Message ID | 20230919071724.15505-7-quic_aisr@quicinc.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kalle Valo |
Headers | show |
Series | wifi: ath12k: add support for 6 GHz AP for various power modes | expand |
On 9/19/2023 12:17 AM, Aishwarya R wrote: > Prepare the parameters which is needed for wmi cmd > vdev_set_tpc_power. > > Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 > > Signed-off-by: Aishwarya R <quic_aisr@quicinc.com> > --- > drivers/net/wireless/ath/ath12k/core.h | 1 + > drivers/net/wireless/ath/ath12k/mac.c | 273 +++++++++++++++++++++++++ > drivers/net/wireless/ath/ath12k/mac.h | 3 + > drivers/net/wireless/ath/ath12k/wmi.c | 1 + > drivers/net/wireless/ath/ath12k/wmi.h | 1 + > 5 files changed, 279 insertions(+) > > diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h > index 01768fe79bd6..e9bf87f740cd 100644 > --- a/drivers/net/wireless/ath/ath12k/core.h > +++ b/drivers/net/wireless/ath/ath12k/core.h > @@ -606,6 +606,7 @@ struct ath12k { > bool monitor_vdev_created; > bool monitor_started; > int monitor_vdev_id; > + s8 max_allowed_tx_power; > }; > > struct ath12k_band_cap { > diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c > index 0683b22137b0..35bd472267c1 100644 > --- a/drivers/net/wireless/ath/ath12k/mac.c > +++ b/drivers/net/wireless/ath/ath12k/mac.c > @@ -5883,6 +5883,279 @@ static u8 ath12k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def) > return num_pwr_levels; > } > > +static u16 ath12k_mac_get_6ghz_start_frequency(struct cfg80211_chan_def *chan_def) > +{ > + u16 diff_seq; > + > + /* It is to get the lowest channel number's center frequency of the chan. s/It is to // also suggest any function documentation should appear before the function, and if the function requires documentation, that kernel-doc format be used same guidance applies to the functions that follow > + * For example, > + * bandwidth=40 MHz, center frequency is 5965, lowest channel is 1 > + * with center frequency 5955, its diff is 5965 - 5955 = 10. > + * bandwidth=80 MHz, center frequency is 5985, lowest channel is 1 > + * with center frequency 5955, its diff is 5985 - 5955 = 30. > + * bandwidth=160 MHz, center frequency is 6025, lowest channel is 1 > + * with center frequency 5955, its diff is 6025 - 5955 = 70. > + */ > + switch (chan_def->width) { > + case NL80211_CHAN_WIDTH_160: > + diff_seq = 70; > + break; > + case NL80211_CHAN_WIDTH_80: > + case NL80211_CHAN_WIDTH_80P80: > + diff_seq = 30; > + break; > + case NL80211_CHAN_WIDTH_40: > + diff_seq = 10; > + break; > + default: > + diff_seq = 0; > + } > + > + return chan_def->center_freq1 - diff_seq; > +} > + > +static u16 ath12k_mac_get_seg_freq(struct cfg80211_chan_def *chan_def, > + u16 start_seq, u8 seq) > +{ > + u16 seg_seq; > + > + /* It is to get the center frequency of the specific bandwidth. > + * start_seq means the lowest channel number's center frequency. > + * seq 0/1/2/3 means 20 MHz/40 MHz/80 MHz/160 MHz & 80P80. > + * For example, > + * lowest channel is 1, its center frequency 5955, > + * center frequency is 5955 when bandwidth=20 MHz, its diff is 5955 - 5955 = 0. > + * lowest channel is 1, its center frequency 5955, > + * center frequency is 5965 when bandwidth=40 MHz, its diff is 5965 - 5955 = 10. > + * lowest channel is 1, its center frequency 5955, > + * center frequency is 5985 when bandwidth=80 MHz, its diff is 5985 - 5955 = 30. > + * lowest channel is 1, its center frequency 5955, > + * center frequency is 6025 when bandwidth=160 MHz, its diff is 6025 - 5955 = 70. > + */ > + if (chan_def->width == NL80211_CHAN_WIDTH_80P80 && seq == 3) > + return chan_def->center_freq2; > + > + seg_seq = 10 * (BIT(seq) - 1); > + return seg_seq + start_seq; > +} > + > +static void ath12k_mac_get_psd_channel(struct ath12k *ar, > + u16 step_freq, > + u16 *start_freq, > + u16 *center_freq, > + u8 i, > + struct ieee80211_channel **temp_chan, > + s8 *tx_power) > +{ > + /* It is to get the center frequency for each 20 MHz. > + * For example, if the chan is 160 MHz and center frequency is 6025, > + * then it include 8 channels, they are 1/5/9/13/17/21/25/29, > + * channel number 1's center frequency is 5955, it is parameter start_freq. > + * parameter i is the step of the 8 channels. i is 0~7 for the 8 channels. > + * the channel 1/5/9/13/17/21/25/29 maps i=0/1/2/3/4/5/6/7, > + * and maps its center frequency is 5955/5975/5995/6015/6035/6055/6075/6095, > + * the gap is 20 for each channel, parameter step_freq means the gap. > + * after get the center frequency of each channel, it is easy to find the > + * struct ieee80211_channel of it and get the max_reg_power. > + */ > + *center_freq = *start_freq + i * step_freq; > + *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq); > + *tx_power = (*temp_chan)->max_reg_power; > +} > + > +static void ath12k_mac_get_eirp_power(struct ath12k *ar, > + u16 *start_freq, > + u16 *center_freq, > + u8 i, > + struct ieee80211_channel **temp_chan, > + struct cfg80211_chan_def *def, > + s8 *tx_power) > +{ > + /* It is to get the center frequency for 20 MHz/40 MHz/80 MHz/ > + * 160 MHz & 80P80 bandwidth, and then plus 10 to the center frequency, > + * it is the center frequency of a channel number. > + * For example, when configured channel number is 1. > + * center frequency is 5965 when bandwidth=40 MHz, after plus 10, it is 5975, > + * then it is channel number 5. > + * center frequency is 5985 when bandwidth=80 MHz, after plus 10, it is 5995, > + * then it is channel number 9. > + * center frequency is 6025 when bandwidth=160 MHz, after plus 10, it is 6035, > + * then it is channel number 17. > + * after get the center frequency of each channel, it is easy to find the > + * struct ieee80211_channel of it and get the max_reg_power. > + */ > + *center_freq = ath12k_mac_get_seg_freq(def, *start_freq, i); > + *center_freq += 10; > + *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq); > + *tx_power = (*temp_chan)->max_reg_power; > +} > + > +void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, > + struct ieee80211_vif *vif, > + struct ieee80211_chanctx_conf *ctx) > +{ > + struct ath12k_base *ab = ar->ab; > + struct ath12k_vif *arvif = (void *)vif->drv_priv; > + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; > + struct ath12k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info; > + struct ieee80211_channel *chan, *temp_chan; > + u8 pwr_lvl_idx, num_pwr_levels, pwr_reduction; > + bool is_psd_power = false, is_tpe_present = false; > + s8 max_tx_power[IEEE80211_MAX_NUM_PWR_LEVEL], > + psd_power, tx_power = 0, eirp_power = 0; > + u16 start_freq = 0, center_freq = 0; > + > + chan = ctx->def.chan; > + start_freq = ath12k_mac_get_6ghz_start_frequency(&ctx->def); > + pwr_reduction = bss_conf->pwr_reduction; > + > + if (arvif->vdev_type == WMI_VDEV_TYPE_STA && > + arvif->reg_tpc_info.num_pwr_levels) { > + is_tpe_present = true; > + num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels; > + } else { > + num_pwr_levels = ath12k_mac_get_num_pwr_levels(&ctx->def); > + } > + > + for (pwr_lvl_idx = 0; pwr_lvl_idx < num_pwr_levels; pwr_lvl_idx++) { > + /* STA received TPE IE*/ > + if (is_tpe_present) { > + /* local power is PSD power*/ > + if (chan->flags & IEEE80211_CHAN_PSD) { > + /* Connecting AP is psd power */ > + if (reg_tpc_info->is_psd_power) { > + is_psd_power = true; > + ath12k_mac_get_psd_channel(ar, 20, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &tx_power); > + psd_power = temp_chan->psd; > + eirp_power = tx_power; > + max_tx_power[pwr_lvl_idx] = > + min_t(s8, > + psd_power, > + reg_tpc_info->tpe[pwr_lvl_idx]); > + /* Connecting AP is not psd power */ > + } else { > + ath12k_mac_get_eirp_power(ar, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &ctx->def, > + &tx_power); > + psd_power = temp_chan->psd; > + /* convert psd power to EIRP power based > + * on channel width > + */ > + tx_power = > + min_t(s8, tx_power, > + psd_power + 13 + pwr_lvl_idx * 3); > + max_tx_power[pwr_lvl_idx] = > + min_t(s8, > + tx_power, > + reg_tpc_info->tpe[pwr_lvl_idx]); > + } bad brace placement? > + /* local power is not PSD power */ > + } else { > + /* Connecting AP is psd power */ > + if (reg_tpc_info->is_psd_power) { > + is_psd_power = true; > + ath12k_mac_get_psd_channel(ar, 20, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &tx_power); > + eirp_power = tx_power; > + max_tx_power[pwr_lvl_idx] = > + reg_tpc_info->tpe[pwr_lvl_idx]; > + /* Connecting AP is not psd power */ > + } else { > + ath12k_mac_get_eirp_power(ar, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &ctx->def, > + &tx_power); > + max_tx_power[pwr_lvl_idx] = > + min_t(s8, > + tx_power, > + reg_tpc_info->tpe[pwr_lvl_idx]); > + } > + } bad brace placement? > + /* STA not received TPE IE */ > + } else { > + /* local power is PSD power*/ > + if (chan->flags & IEEE80211_CHAN_PSD) { > + is_psd_power = true; > + ath12k_mac_get_psd_channel(ar, 20, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &tx_power); > + psd_power = temp_chan->psd; > + eirp_power = tx_power; > + max_tx_power[pwr_lvl_idx] = psd_power; > + } else { > + ath12k_mac_get_eirp_power(ar, > + &start_freq, > + ¢er_freq, > + pwr_lvl_idx, > + &temp_chan, > + &ctx->def, > + &tx_power); > + max_tx_power[pwr_lvl_idx] = tx_power; > + } > + } > + > + if (is_psd_power) { > + /* If AP local power constraint is present */ > + if (pwr_reduction) > + eirp_power = eirp_power - pwr_reduction; > + > + /* If FW updated max tx power is non zero, then take the min of > + * firmware updated ap tx power > + * and max power derived from above mentioned parameters. > + */ > + ath12k_dbg(ab, ATH12K_DBG_MAC, > + "eirp power : %d firmware report power : %d\n", > + eirp_power, ar->max_allowed_tx_power); > + if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) > + eirp_power = min_t(s8, > + eirp_power, > + ar->max_allowed_tx_power); > + } else { > + /* If AP local power constraint is present */ > + if (pwr_reduction) > + max_tx_power[pwr_lvl_idx] = > + max_tx_power[pwr_lvl_idx] - pwr_reduction; > + /* If FW updated max tx power is non zero, then take the min of > + * firmware updated ap tx power > + * and max power derived from above mentioned parameters. > + */ > + if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) > + max_tx_power[pwr_lvl_idx] = > + min_t(s8, > + max_tx_power[pwr_lvl_idx], > + ar->max_allowed_tx_power); > + } > + reg_tpc_info->chan_power_info[pwr_lvl_idx].chan_cfreq = center_freq; > + reg_tpc_info->chan_power_info[pwr_lvl_idx].tx_power = > + max_tx_power[pwr_lvl_idx]; > + } > + > + reg_tpc_info->num_pwr_levels = num_pwr_levels; > + reg_tpc_info->is_psd_power = is_psd_power; > + reg_tpc_info->eirp_power = eirp_power; > + reg_tpc_info->power_type_6ghz = > + ath12k_ieee80211_ap_pwr_type_convert(vif->bss_conf.power_type); > +} > + > static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, > struct ieee80211_vif *vif, > struct ieee80211_chanctx_conf *ctx) > diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h > index 82f590004d05..ce2ce7f324d7 100644 > --- a/drivers/net/wireless/ath/ath12k/mac.h > +++ b/drivers/net/wireless/ath/ath12k/mac.h > @@ -68,6 +68,9 @@ struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id) > struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); > enum wmi_vdev_type ath12k_mac_get_ar_vdev_type(struct ath12k *ar); > > +void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, > + struct ieee80211_vif *vif, > + struct ieee80211_chanctx_conf *ctx); > void ath12k_mac_drain_tx(struct ath12k *ar); > void ath12k_mac_peer_cleanup_all(struct ath12k *ar); > int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); > diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c > index 211bdb915173..5bfca2513730 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.c > +++ b/drivers/net/wireless/ath/ath12k/wmi.c > @@ -5588,6 +5588,7 @@ static void ath12k_vdev_start_resp_event(struct ath12k_base *ab, struct sk_buff > } > > ar->last_wmi_vdev_start_status = 0; > + ar->max_allowed_tx_power = le32_to_cpu(vdev_start_resp.max_allowed_tx_power); > > status = le32_to_cpu(vdev_start_resp.status); > > diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h > index c3b110af1272..9f24f8ded52f 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.h > +++ b/drivers/net/wireless/ath/ath12k/wmi.h > @@ -3796,6 +3796,7 @@ struct wmi_vdev_start_resp_event { > }; > __le32 cfgd_tx_streams; > __le32 cfgd_rx_streams; > + __le32 max_allowed_tx_power; > } __packed; > > /* VDEV start response status codes */
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 01768fe79bd6..e9bf87f740cd 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -606,6 +606,7 @@ struct ath12k { bool monitor_vdev_created; bool monitor_started; int monitor_vdev_id; + s8 max_allowed_tx_power; }; struct ath12k_band_cap { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 0683b22137b0..35bd472267c1 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -5883,6 +5883,279 @@ static u8 ath12k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def) return num_pwr_levels; } +static u16 ath12k_mac_get_6ghz_start_frequency(struct cfg80211_chan_def *chan_def) +{ + u16 diff_seq; + + /* It is to get the lowest channel number's center frequency of the chan. + * For example, + * bandwidth=40 MHz, center frequency is 5965, lowest channel is 1 + * with center frequency 5955, its diff is 5965 - 5955 = 10. + * bandwidth=80 MHz, center frequency is 5985, lowest channel is 1 + * with center frequency 5955, its diff is 5985 - 5955 = 30. + * bandwidth=160 MHz, center frequency is 6025, lowest channel is 1 + * with center frequency 5955, its diff is 6025 - 5955 = 70. + */ + switch (chan_def->width) { + case NL80211_CHAN_WIDTH_160: + diff_seq = 70; + break; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + diff_seq = 30; + break; + case NL80211_CHAN_WIDTH_40: + diff_seq = 10; + break; + default: + diff_seq = 0; + } + + return chan_def->center_freq1 - diff_seq; +} + +static u16 ath12k_mac_get_seg_freq(struct cfg80211_chan_def *chan_def, + u16 start_seq, u8 seq) +{ + u16 seg_seq; + + /* It is to get the center frequency of the specific bandwidth. + * start_seq means the lowest channel number's center frequency. + * seq 0/1/2/3 means 20 MHz/40 MHz/80 MHz/160 MHz & 80P80. + * For example, + * lowest channel is 1, its center frequency 5955, + * center frequency is 5955 when bandwidth=20 MHz, its diff is 5955 - 5955 = 0. + * lowest channel is 1, its center frequency 5955, + * center frequency is 5965 when bandwidth=40 MHz, its diff is 5965 - 5955 = 10. + * lowest channel is 1, its center frequency 5955, + * center frequency is 5985 when bandwidth=80 MHz, its diff is 5985 - 5955 = 30. + * lowest channel is 1, its center frequency 5955, + * center frequency is 6025 when bandwidth=160 MHz, its diff is 6025 - 5955 = 70. + */ + if (chan_def->width == NL80211_CHAN_WIDTH_80P80 && seq == 3) + return chan_def->center_freq2; + + seg_seq = 10 * (BIT(seq) - 1); + return seg_seq + start_seq; +} + +static void ath12k_mac_get_psd_channel(struct ath12k *ar, + u16 step_freq, + u16 *start_freq, + u16 *center_freq, + u8 i, + struct ieee80211_channel **temp_chan, + s8 *tx_power) +{ + /* It is to get the center frequency for each 20 MHz. + * For example, if the chan is 160 MHz and center frequency is 6025, + * then it include 8 channels, they are 1/5/9/13/17/21/25/29, + * channel number 1's center frequency is 5955, it is parameter start_freq. + * parameter i is the step of the 8 channels. i is 0~7 for the 8 channels. + * the channel 1/5/9/13/17/21/25/29 maps i=0/1/2/3/4/5/6/7, + * and maps its center frequency is 5955/5975/5995/6015/6035/6055/6075/6095, + * the gap is 20 for each channel, parameter step_freq means the gap. + * after get the center frequency of each channel, it is easy to find the + * struct ieee80211_channel of it and get the max_reg_power. + */ + *center_freq = *start_freq + i * step_freq; + *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq); + *tx_power = (*temp_chan)->max_reg_power; +} + +static void ath12k_mac_get_eirp_power(struct ath12k *ar, + u16 *start_freq, + u16 *center_freq, + u8 i, + struct ieee80211_channel **temp_chan, + struct cfg80211_chan_def *def, + s8 *tx_power) +{ + /* It is to get the center frequency for 20 MHz/40 MHz/80 MHz/ + * 160 MHz & 80P80 bandwidth, and then plus 10 to the center frequency, + * it is the center frequency of a channel number. + * For example, when configured channel number is 1. + * center frequency is 5965 when bandwidth=40 MHz, after plus 10, it is 5975, + * then it is channel number 5. + * center frequency is 5985 when bandwidth=80 MHz, after plus 10, it is 5995, + * then it is channel number 9. + * center frequency is 6025 when bandwidth=160 MHz, after plus 10, it is 6035, + * then it is channel number 17. + * after get the center frequency of each channel, it is easy to find the + * struct ieee80211_channel of it and get the max_reg_power. + */ + *center_freq = ath12k_mac_get_seg_freq(def, *start_freq, i); + *center_freq += 10; + *temp_chan = ieee80211_get_channel(ar->hw->wiphy, *center_freq); + *tx_power = (*temp_chan)->max_reg_power; +} + +void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *ctx) +{ + struct ath12k_base *ab = ar->ab; + struct ath12k_vif *arvif = (void *)vif->drv_priv; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ath12k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info; + struct ieee80211_channel *chan, *temp_chan; + u8 pwr_lvl_idx, num_pwr_levels, pwr_reduction; + bool is_psd_power = false, is_tpe_present = false; + s8 max_tx_power[IEEE80211_MAX_NUM_PWR_LEVEL], + psd_power, tx_power = 0, eirp_power = 0; + u16 start_freq = 0, center_freq = 0; + + chan = ctx->def.chan; + start_freq = ath12k_mac_get_6ghz_start_frequency(&ctx->def); + pwr_reduction = bss_conf->pwr_reduction; + + if (arvif->vdev_type == WMI_VDEV_TYPE_STA && + arvif->reg_tpc_info.num_pwr_levels) { + is_tpe_present = true; + num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels; + } else { + num_pwr_levels = ath12k_mac_get_num_pwr_levels(&ctx->def); + } + + for (pwr_lvl_idx = 0; pwr_lvl_idx < num_pwr_levels; pwr_lvl_idx++) { + /* STA received TPE IE*/ + if (is_tpe_present) { + /* local power is PSD power*/ + if (chan->flags & IEEE80211_CHAN_PSD) { + /* Connecting AP is psd power */ + if (reg_tpc_info->is_psd_power) { + is_psd_power = true; + ath12k_mac_get_psd_channel(ar, 20, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &tx_power); + psd_power = temp_chan->psd; + eirp_power = tx_power; + max_tx_power[pwr_lvl_idx] = + min_t(s8, + psd_power, + reg_tpc_info->tpe[pwr_lvl_idx]); + /* Connecting AP is not psd power */ + } else { + ath12k_mac_get_eirp_power(ar, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &ctx->def, + &tx_power); + psd_power = temp_chan->psd; + /* convert psd power to EIRP power based + * on channel width + */ + tx_power = + min_t(s8, tx_power, + psd_power + 13 + pwr_lvl_idx * 3); + max_tx_power[pwr_lvl_idx] = + min_t(s8, + tx_power, + reg_tpc_info->tpe[pwr_lvl_idx]); + } + /* local power is not PSD power */ + } else { + /* Connecting AP is psd power */ + if (reg_tpc_info->is_psd_power) { + is_psd_power = true; + ath12k_mac_get_psd_channel(ar, 20, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &tx_power); + eirp_power = tx_power; + max_tx_power[pwr_lvl_idx] = + reg_tpc_info->tpe[pwr_lvl_idx]; + /* Connecting AP is not psd power */ + } else { + ath12k_mac_get_eirp_power(ar, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &ctx->def, + &tx_power); + max_tx_power[pwr_lvl_idx] = + min_t(s8, + tx_power, + reg_tpc_info->tpe[pwr_lvl_idx]); + } + } + /* STA not received TPE IE */ + } else { + /* local power is PSD power*/ + if (chan->flags & IEEE80211_CHAN_PSD) { + is_psd_power = true; + ath12k_mac_get_psd_channel(ar, 20, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &tx_power); + psd_power = temp_chan->psd; + eirp_power = tx_power; + max_tx_power[pwr_lvl_idx] = psd_power; + } else { + ath12k_mac_get_eirp_power(ar, + &start_freq, + ¢er_freq, + pwr_lvl_idx, + &temp_chan, + &ctx->def, + &tx_power); + max_tx_power[pwr_lvl_idx] = tx_power; + } + } + + if (is_psd_power) { + /* If AP local power constraint is present */ + if (pwr_reduction) + eirp_power = eirp_power - pwr_reduction; + + /* If FW updated max tx power is non zero, then take the min of + * firmware updated ap tx power + * and max power derived from above mentioned parameters. + */ + ath12k_dbg(ab, ATH12K_DBG_MAC, + "eirp power : %d firmware report power : %d\n", + eirp_power, ar->max_allowed_tx_power); + if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) + eirp_power = min_t(s8, + eirp_power, + ar->max_allowed_tx_power); + } else { + /* If AP local power constraint is present */ + if (pwr_reduction) + max_tx_power[pwr_lvl_idx] = + max_tx_power[pwr_lvl_idx] - pwr_reduction; + /* If FW updated max tx power is non zero, then take the min of + * firmware updated ap tx power + * and max power derived from above mentioned parameters. + */ + if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) + max_tx_power[pwr_lvl_idx] = + min_t(s8, + max_tx_power[pwr_lvl_idx], + ar->max_allowed_tx_power); + } + reg_tpc_info->chan_power_info[pwr_lvl_idx].chan_cfreq = center_freq; + reg_tpc_info->chan_power_info[pwr_lvl_idx].tx_power = + max_tx_power[pwr_lvl_idx]; + } + + reg_tpc_info->num_pwr_levels = num_pwr_levels; + reg_tpc_info->is_psd_power = is_psd_power; + reg_tpc_info->eirp_power = eirp_power; + reg_tpc_info->power_type_6ghz = + ath12k_ieee80211_ap_pwr_type_convert(vif->bss_conf.power_type); +} + static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx) diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 82f590004d05..ce2ce7f324d7 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -68,6 +68,9 @@ struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id) struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); enum wmi_vdev_type ath12k_mac_get_ar_vdev_type(struct ath12k *ar); +void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *ctx); void ath12k_mac_drain_tx(struct ath12k *ar); void ath12k_mac_peer_cleanup_all(struct ath12k *ar); int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 211bdb915173..5bfca2513730 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -5588,6 +5588,7 @@ static void ath12k_vdev_start_resp_event(struct ath12k_base *ab, struct sk_buff } ar->last_wmi_vdev_start_status = 0; + ar->max_allowed_tx_power = le32_to_cpu(vdev_start_resp.max_allowed_tx_power); status = le32_to_cpu(vdev_start_resp.status); diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index c3b110af1272..9f24f8ded52f 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -3796,6 +3796,7 @@ struct wmi_vdev_start_resp_event { }; __le32 cfgd_tx_streams; __le32 cfgd_rx_streams; + __le32 max_allowed_tx_power; } __packed; /* VDEV start response status codes */
Prepare the parameters which is needed for wmi cmd vdev_set_tpc_power. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aishwarya R <quic_aisr@quicinc.com> --- drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/mac.c | 273 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/mac.h | 3 + drivers/net/wireless/ath/ath12k/wmi.c | 1 + drivers/net/wireless/ath/ath12k/wmi.h | 1 + 5 files changed, 279 insertions(+)