@@ -7608,6 +7608,192 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
76087608 return 0 ;
76097609}
76107610
7611+ static u8 ath11k_mac_get_tpe_count (u8 txpwr_intrprt , u8 txpwr_cnt )
7612+ {
7613+ switch (txpwr_intrprt ) {
7614+ /* Refer "Table 9-276-Meaning of Maximum Transmit Power Count subfield
7615+ * if the Maximum Transmit Power Interpretation subfield is 0 or 2" of
7616+ * "IEEE Std 802.11ax 2021".
7617+ */
7618+ case IEEE80211_TPE_LOCAL_EIRP :
7619+ case IEEE80211_TPE_REG_CLIENT_EIRP :
7620+ txpwr_cnt = txpwr_cnt <= 3 ? txpwr_cnt : 3 ;
7621+ txpwr_cnt = txpwr_cnt + 1 ;
7622+ break ;
7623+ /* Refer "Table 9-277-Meaning of Maximum Transmit Power Count subfield
7624+ * if Maximum Transmit Power Interpretation subfield is 1 or 3" of
7625+ * "IEEE Std 802.11ax 2021".
7626+ */
7627+ case IEEE80211_TPE_LOCAL_EIRP_PSD :
7628+ case IEEE80211_TPE_REG_CLIENT_EIRP_PSD :
7629+ txpwr_cnt = txpwr_cnt <= 4 ? txpwr_cnt : 4 ;
7630+ txpwr_cnt = txpwr_cnt ? (BIT (txpwr_cnt - 1 )) : 1 ;
7631+ break ;
7632+ }
7633+
7634+ return txpwr_cnt ;
7635+ }
7636+
7637+ static u8 ath11k_mac_get_num_pwr_levels (struct cfg80211_chan_def * chan_def )
7638+ {
7639+ if (chan_def -> chan -> flags & IEEE80211_CHAN_PSD ) {
7640+ switch (chan_def -> width ) {
7641+ case NL80211_CHAN_WIDTH_20 :
7642+ return 1 ;
7643+ case NL80211_CHAN_WIDTH_40 :
7644+ return 2 ;
7645+ case NL80211_CHAN_WIDTH_80 :
7646+ return 4 ;
7647+ case NL80211_CHAN_WIDTH_80P80 :
7648+ case NL80211_CHAN_WIDTH_160 :
7649+ return 8 ;
7650+ default :
7651+ return 1 ;
7652+ }
7653+ } else {
7654+ switch (chan_def -> width ) {
7655+ case NL80211_CHAN_WIDTH_20 :
7656+ return 1 ;
7657+ case NL80211_CHAN_WIDTH_40 :
7658+ return 2 ;
7659+ case NL80211_CHAN_WIDTH_80 :
7660+ return 3 ;
7661+ case NL80211_CHAN_WIDTH_80P80 :
7662+ case NL80211_CHAN_WIDTH_160 :
7663+ return 4 ;
7664+ default :
7665+ return 1 ;
7666+ }
7667+ }
7668+ }
7669+
7670+ static void ath11k_mac_parse_tx_pwr_env (struct ath11k * ar ,
7671+ struct ieee80211_vif * vif ,
7672+ struct ieee80211_chanctx_conf * ctx )
7673+ {
7674+ struct ath11k_base * ab = ar -> ab ;
7675+ struct ath11k_vif * arvif = (void * )vif -> drv_priv ;
7676+ struct ieee80211_bss_conf * bss_conf = & vif -> bss_conf ;
7677+ struct ieee80211_tx_pwr_env * single_tpe ;
7678+ enum wmi_reg_6ghz_client_type client_type ;
7679+ struct cur_regulatory_info * reg_info ;
7680+ int i ;
7681+ u8 pwr_count , pwr_interpret , pwr_category ;
7682+ u8 psd_index = 0 , non_psd_index = 0 , local_tpe_count = 0 , reg_tpe_count = 0 ;
7683+ bool use_local_tpe , non_psd_set = false, psd_set = false;
7684+
7685+ reg_info = & ab -> reg_info_store [ar -> pdev_idx ];
7686+ client_type = reg_info -> client_type ;
7687+
7688+ for (i = 0 ; i < bss_conf -> tx_pwr_env_num ; i ++ ) {
7689+ single_tpe = & bss_conf -> tx_pwr_env [i ];
7690+ pwr_category = u8_get_bits (single_tpe -> tx_power_info ,
7691+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY );
7692+ pwr_interpret = u8_get_bits (single_tpe -> tx_power_info ,
7693+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET );
7694+
7695+ if (pwr_category == client_type ) {
7696+ if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP ||
7697+ pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD )
7698+ local_tpe_count ++ ;
7699+ else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP ||
7700+ pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD )
7701+ reg_tpe_count ++ ;
7702+ }
7703+ }
7704+
7705+ if (!reg_tpe_count && !local_tpe_count ) {
7706+ ath11k_warn (ab ,
7707+ "no transmit power envelope match client power type %d\n" ,
7708+ client_type );
7709+ return ;
7710+ } else if (!reg_tpe_count ) {
7711+ use_local_tpe = true;
7712+ } else {
7713+ use_local_tpe = false;
7714+ }
7715+
7716+ for (i = 0 ; i < bss_conf -> tx_pwr_env_num ; i ++ ) {
7717+ single_tpe = & bss_conf -> tx_pwr_env [i ];
7718+ pwr_category = u8_get_bits (single_tpe -> tx_power_info ,
7719+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY );
7720+ pwr_interpret = u8_get_bits (single_tpe -> tx_power_info ,
7721+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET );
7722+
7723+ if (pwr_category != client_type )
7724+ continue ;
7725+
7726+ /* get local transmit power envelope */
7727+ if (use_local_tpe ) {
7728+ if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP ) {
7729+ non_psd_index = i ;
7730+ non_psd_set = true;
7731+ } else if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD ) {
7732+ psd_index = i ;
7733+ psd_set = true;
7734+ }
7735+ /* get regulatory transmit power envelope */
7736+ } else {
7737+ if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP ) {
7738+ non_psd_index = i ;
7739+ non_psd_set = true;
7740+ } else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD ) {
7741+ psd_index = i ;
7742+ psd_set = true;
7743+ }
7744+ }
7745+ }
7746+
7747+ if (non_psd_set && !psd_set ) {
7748+ single_tpe = & bss_conf -> tx_pwr_env [non_psd_index ];
7749+ pwr_count = u8_get_bits (single_tpe -> tx_power_info ,
7750+ IEEE80211_TX_PWR_ENV_INFO_COUNT );
7751+ pwr_interpret = u8_get_bits (single_tpe -> tx_power_info ,
7752+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET );
7753+ arvif -> reg_tpc_info .is_psd_power = false;
7754+ arvif -> reg_tpc_info .eirp_power = 0 ;
7755+
7756+ arvif -> reg_tpc_info .num_pwr_levels =
7757+ ath11k_mac_get_tpe_count (pwr_interpret , pwr_count );
7758+
7759+ for (i = 0 ; i < arvif -> reg_tpc_info .num_pwr_levels ; i ++ ) {
7760+ ath11k_dbg (ab , ATH11K_DBG_MAC ,
7761+ "non PSD power[%d] : %d\n" ,
7762+ i , single_tpe -> tx_power [i ]);
7763+ arvif -> reg_tpc_info .tpe [i ] = single_tpe -> tx_power [i ] / 2 ;
7764+ }
7765+ }
7766+
7767+ if (psd_set ) {
7768+ single_tpe = & bss_conf -> tx_pwr_env [psd_index ];
7769+ pwr_count = u8_get_bits (single_tpe -> tx_power_info ,
7770+ IEEE80211_TX_PWR_ENV_INFO_COUNT );
7771+ pwr_interpret = u8_get_bits (single_tpe -> tx_power_info ,
7772+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET );
7773+ arvif -> reg_tpc_info .is_psd_power = true;
7774+
7775+ if (pwr_count == 0 ) {
7776+ ath11k_dbg (ab , ATH11K_DBG_MAC ,
7777+ "TPE PSD power : %d\n" , single_tpe -> tx_power [0 ]);
7778+ arvif -> reg_tpc_info .num_pwr_levels =
7779+ ath11k_mac_get_num_pwr_levels (& ctx -> def );
7780+
7781+ for (i = 0 ; i < arvif -> reg_tpc_info .num_pwr_levels ; i ++ )
7782+ arvif -> reg_tpc_info .tpe [i ] = single_tpe -> tx_power [0 ] / 2 ;
7783+ } else {
7784+ arvif -> reg_tpc_info .num_pwr_levels =
7785+ ath11k_mac_get_tpe_count (pwr_interpret , pwr_count );
7786+
7787+ for (i = 0 ; i < arvif -> reg_tpc_info .num_pwr_levels ; i ++ ) {
7788+ ath11k_dbg (ab , ATH11K_DBG_MAC ,
7789+ "TPE PSD power[%d] : %d\n" ,
7790+ i , single_tpe -> tx_power [i ]);
7791+ arvif -> reg_tpc_info .tpe [i ] = single_tpe -> tx_power [i ] / 2 ;
7792+ }
7793+ }
7794+ }
7795+ }
7796+
76117797static int
76127798ath11k_mac_op_assign_vif_chanctx (struct ieee80211_hw * hw ,
76137799 struct ieee80211_vif * vif ,
@@ -7642,6 +7828,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
76427828 }
76437829
76447830 ath11k_reg_handle_chan_list (ab , reg_info , power_type );
7831+
7832+ ath11k_mac_parse_tx_pwr_env (ar , vif , ctx );
76457833 }
76467834
76477835 /* for QCA6390 bss peer must be created before vdev_start */
0 commit comments