mt76: mt7921: add .set_sar_specs support
A message that is not in the archive (sent off-list or not yet received): YM8NBUZp+/97kiIH@lore-desk--annotate
From: Sean Wang <[email protected]>
Quoted 57 lines
Quoted 57 lines
From: YN Chen <[email protected]>
add .set_sar_specs to allow configuring SAR power limitations on the frequency ranges from the userland.
Co-developed-by Sean Wang <[email protected]>Signed-off-by Sean Wang <[email protected]>Signed-off-by YN Chen <[email protected]>--- drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++ .../net/wireless/mediatek/mt76/mt76_connac.h | 5 +++ .../wireless/mediatek/mt76/mt76_connac_mcu.c | 24 +++++++++- .../net/wireless/mediatek/mt76/mt7921/init.c | 21 +++++++++ .../net/wireless/mediatek/mt76/mt7921/main.c | 45 +++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-)drivers/net/wireless/mediatek/mt76/mt76.h +3
-0@@ -636,6 +636,9 @@ struct mt76_phy {struct sk_buff **tail;u16 seqno; } rx_amsdu[__MT_RXQ_MAX]; + +void *frp_data; +u8 num_frps; };struct mt76_dev {drivers/net/wireless/mediatek/mt76/mt76_connac.h +5
-0@@ -83,6 +83,11 @@ struct mt76_connac_coredump {unsigned long last_activity; }; +struct mt76_connac_freq_range_power { +const struct cfg80211_sar_freq_ranges *range; +s8 power; +}; +extern const struct wiphy_wowlan_support mt76_connac_wowlan_support; static inline bool is_mt7921(struct mt76_dev *dev) diff --git
a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.cb/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.cindex5c3a81e5f559..07f45cb4f500100644drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +0
-0@@ -1749,6 +1749,24 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, } }
Quoted 15 lines
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, · line 1764
Quoted 13 lines
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +13
-0+static s8 mt76_connac_get_sar_power (struct mt76_phy *phy, +struct ieee80211_channel *chan, +s8 target_power) +{ +struct mt76_connac_freq_range_power *frp = phy->frp_data; +int freq, i; + + freq =ieee80211_channel_to_frequency (chan->hw_value, chan->band); +for (i =0 ; i < phy->num_frps; i++) { +if (frp[i].range && + freq >= frp[i].range->start_freq && + freq < frp[i].range->end_freq) + target_power =min_t (s8, frp[i].power, target_power);can we have overlapping freq range? if not I guess you can add a break here.
It is supposed to be there is no overlapping freq range for the real use case. I will add a break in the next version.
Quoted 54 lines
Quoted 54 lines
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +10
-1+ } + +return target_power; +} +static int mt76_connac_mcu_rate_txpower_band (struct mt76_phy *phy,enum nl80211_band band)@@ -1816,9 +1834,13 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, .hw_value = ch_list[idx], .band = band, }; +s8 sar_power; + + sar_power =mt76_connac_get_sar_power (phy, &chan, + tx_power);mt76_get_rate_power_limits (phy, &chan, &limits, - tx_power); + sar_power); tx_power_tlv.last_msg = ch_list[idx] == last_ch; sku_tlbv.channel = ch_list[idx];drivers/net/wireless/mediatek/mt76/mt7921/init.c +12
-0@@ -24,6 +24,20 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; +const struct cfg80211_sar_freq_ranges mt7921_sar_freq_ranges[] = { + { .start_freq =2402 , .end_freq =2494 , }, + { .start_freq =5150 , .end_freq =5350 , }, + { .start_freq =5350 , .end_freq =5470 , }, + { .start_freq =5470 , .end_freq =5725 , }, + { .start_freq =5725 , .end_freq =5950 , }, }; + +static const struct cfg80211_sar_capa mt7921_sar_capa = { + .type =NL80211_SAR_TYPE_POWER , + .num_freq_ranges =ARRAY_SIZE (mt7921_sar_freq_ranges), + .freq_ranges = &mt7921_sar_freq_ranges[0 ], }; +static void mt7921_regd_notifier (struct wiphy *wiphy, struct regulatory_request *request) @@ -75,6 +89,13 @@
mt7921_init_wiphy(struct ieee80211_hw *hw)wiphy->max_sched_scan_reqs = 1; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->reg_notifier = mt7921_regd_notifier;drivers/net/wireless/mediatek/mt76/mt7921/init.c +1
-0+ wiphy->sar_capa = &mt7921_sar_capa;
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/mt7921/init.c
Quoted 5 lines
drivers/net/wireless/mediatek/mt76/mt7921/init.c +5
-0+ + phy->mt76->frp_data =devm_kcalloc (dev->mt76.dev, + wiphy->sar_capa->num_freq_ranges, +sizeof (struct mt76_connac_freq_range_power ), +GFP_KERNEL );Here I guess we need to check if
devm_kcallocfails returning an int frommt7921_init_wiphy()
Sure, will do it.
Quoted 23 lines
Quoted 23 lines
drivers/net/wireless/mediatek/mt76/mt7921/init.c +1
-0+ phy->mt76->num_frps = wiphy->sar_capa->num_freq_ranges;wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;drivers/net/wireless/mediatek/mt76/mt7921/main.c +10
-0@@ -1171,6 +1171,50 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, MCU_UNI_CMD_STA_REC_UPDATE); } +static int mt7921_set_sar_specs (struct ieee80211_hw *hw, +const struct cfg80211_sar_specs *sar) { +const struct cfg80211_sar_capa *capa = hw->wiphy->sar_capa; +struct mt76_connac_freq_range_power *frp_data, *frp; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; +int err; +u32 i; + +mt7921_mutex_acquire (dev);
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, · line 1188
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c +6
-0+ +if (!sar || sar->type !=NL80211_SAR_TYPE_POWER || + sar->num_sub_specs ==0 ) { + err = -EINVAL ; + goto out; + }I guess you can move this out of the lock
Sure, will do it.
Quoted 10 lines
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c +10
-0+ + frp_data = mphy->frp_data; + +for (i =0 ; i < sar->num_sub_specs; i++) { +u32 index = sar->sub_specs[i].freq_range_index; +/* SAR specifies power limitaton in 0.25dbm */ +s32 power = sar->sub_specs[i].power >>1 ; + +if (power >127 || power <-127 ) + power =127 ;
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, · line 1204
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c +6
-0+ +if (index >= mphy->num_frps) +continue ; + + frp = &frp_data[index]; + frp->range = &capa->freq_ranges[index];I guess there is an use-after-free here since sar is freed at the end of
nl80211_set_sar_specs, right?
Nope, there is no use-after-free case happens here because frp->range just points to an entry of const struct cfg80211_sar_specs table, not the one created from nl80211_set_sar_specs.
Quoted 17 lines
Regards,
LorenzoQuoted 14 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c +11
-0+ frp->power = power; + } + + err =mt76_connac_mcu_set_rate_txpower (mphy); + +out: +mt7921_mutex_release (dev); + +return err; +} +const struct ieee80211_ops mt7921_ops = { .tx = mt7921_tx, .start = mt7921_start,
Quoted 8 lines
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/mt7921/main.c +1
-1@@ -1209,4 +1253,5 @@ const struct ieee80211_ops mt7921_ops = { .set_rekey_data = mt7921_set_rekey_data, #endif /* CONFIG_PM */ .flush = mt7921_flush, + .set_sar_specs = mt7921_set_sar_specs, }; --2.25.1
_______________________________________________
Linux-mediatek mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-mediatek
[...]
Quoted 5 lines
Quoted 3 lines
I guess there is an use-after-free here since sar is freed at the end of
nl80211_set_sar_specs, right?Nope, there is no use-after-free case happens here because
frp->rangejust points to an entry of const structcfg80211_sar_specstable, not the one created fromnl80211_set_sar_specs.
ack, right. I misread the code.
Regards,
Lorenzo
Quoted 26 lines
Quoted 26 lines
Regards,
LorenzoQuoted 22 lines
(quoted diff) +11
-0+ frp->power = power; + } + + err = mt76_connac_mcu_set_rate_txpower(mphy); + +out: + mt7921_mutex_release(dev); + + return err; +} + const struct ieee80211_ops mt7921_ops = {.tx = mt7921_tx, .start = mt7921_start,(quoted diff) +1
-1@@ -1209,4 +1253,5 @@ const struct ieee80211_ops mt7921_ops = { .set_rekey_data = mt7921_set_rekey_data, #endif /* CONFIG_PM */ .flush = mt7921_flush, + .set_sar_specs = mt7921_set_sar_specs, }; --2.25.1