diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 124 |
1 files changed, 105 insertions, 19 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 27d414efa3fd..32f1bc5908c5 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1756,6 +1756,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) bool sched_scan_stopped = false; bool suspended = local->suspended; bool in_reconfig = false; + u32 rts_threshold; lockdep_assert_wiphy(local->hw.wiphy); @@ -1826,13 +1827,20 @@ int ieee80211_reconfig(struct ieee80211_local *local) } /* setup fragmentation threshold */ - drv_set_frag_threshold(local, hw->wiphy->frag_threshold); + drv_set_frag_threshold(local, -1, hw->wiphy->frag_threshold); /* setup RTS threshold */ - drv_set_rts_threshold(local, hw->wiphy->rts_threshold); + if (hw->wiphy->n_radio > 0) { + for (i = 0; i < hw->wiphy->n_radio; i++) { + rts_threshold = hw->wiphy->radio_cfg[i].rts_threshold; + drv_set_rts_threshold(local, i, rts_threshold); + } + } else { + drv_set_rts_threshold(local, -1, hw->wiphy->rts_threshold); + } /* reset coverage class */ - drv_set_coverage_class(local, hw->wiphy->coverage_class); + drv_set_coverage_class(local, -1, hw->wiphy->coverage_class); ieee80211_led_radio(local, true); ieee80211_mod_tpt_led_trig(local, @@ -1890,11 +1898,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) ieee80211_assign_chanctx(local, sdata, &sdata->deflink); /* reconfigure hardware */ - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_LISTEN_INTERVAL | - IEEE80211_CONF_CHANGE_MONITOR | - IEEE80211_CONF_CHANGE_PS | - IEEE80211_CONF_CHANGE_RETRY_LIMITS | - IEEE80211_CONF_CHANGE_IDLE); + ieee80211_hw_config(local, -1, IEEE80211_CONF_CHANGE_LISTEN_INTERVAL | + IEEE80211_CONF_CHANGE_MONITOR | + IEEE80211_CONF_CHANGE_PS | + IEEE80211_CONF_CHANGE_RETRY_LIMITS | + IEEE80211_CONF_CHANGE_IDLE); ieee80211_configure_filter(local); @@ -2144,11 +2152,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) cfg80211_sched_scan_stopped_locked(local->hw.wiphy, 0); wake_up: - - if (local->virt_monitors > 0 && - local->virt_monitors == local->open_count) - ieee80211_add_virtual_monitor(local); - /* * Clear the WLAN_STA_BLOCK_BA flag so new aggregation * sessions can be established after a resume. @@ -2202,6 +2205,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } + if (local->virt_monitors > 0 && + local->virt_monitors == local->open_count) + ieee80211_add_virtual_monitor(local); + if (!suspended) return 0; @@ -2548,6 +2555,23 @@ end: return 0; } +int ieee80211_put_reg_conn(struct sk_buff *skb, + enum ieee80211_channel_flags flags) +{ + u8 reg_conn = IEEE80211_REG_CONN_LPI_VALID | + IEEE80211_REG_CONN_LPI_VALUE | + IEEE80211_REG_CONN_SP_VALID; + + if (!(flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT)) + reg_conn |= IEEE80211_REG_CONN_SP_VALUE; + + skb_put_u8(skb, WLAN_EID_EXTENSION); + skb_put_u8(skb, 1 + sizeof(reg_conn)); + skb_put_u8(skb, WLAN_EID_EXT_NON_AP_STA_REG_CON); + skb_put_u8(skb, reg_conn); + return 0; +} + int ieee80211_put_he_6ghz_cap(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode) @@ -3265,14 +3289,24 @@ int ieee80211_put_srates_elem(struct sk_buff *skb, return 0; } -int ieee80211_ave_rssi(struct ieee80211_vif *vif) +int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_link_data *link_data; if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) return 0; - return -ewma_beacon_signal_read(&sdata->deflink.u.mgd.ave_beacon_signal); + if (link_id < 0) + link_data = &sdata->deflink; + else + link_data = wiphy_dereference(sdata->local->hw.wiphy, + sdata->link[link_id]); + + if (WARN_ON_ONCE(!link_data)) + return -99; + + return -ewma_beacon_signal_read(&link_data->u.mgd.ave_beacon_signal); } EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); @@ -3879,12 +3913,10 @@ int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr, } EXPORT_SYMBOL(ieee80211_parse_p2p_noa); -void ieee80211_recalc_dtim(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) +void ieee80211_recalc_dtim(struct ieee80211_sub_if_data *sdata, u64 tsf) { - u64 tsf = drv_get_tsf(local, sdata); u64 dtim_count = 0; - u16 beacon_int = sdata->vif.bss_conf.beacon_int * 1024; + u32 beacon_int = sdata->vif.bss_conf.beacon_int * 1024; u8 dtim_period = sdata->vif.bss_conf.dtim_period; struct ps_data *ps; u8 bcns_from_dtim; @@ -3920,6 +3952,33 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local, ps->dtim_count = dtim_count; } +/* + * Given a long beacon period, calculate the current index into + * that period to determine the number of TSBTTs until the next TBTT. + * It is completely valid to have a short beacon period that differs + * from the dtim period (i.e a TBTT thats not a DTIM). + */ +void ieee80211_recalc_sb_count(struct ieee80211_sub_if_data *sdata, u64 tsf) +{ + u32 sb_idx; + struct ps_data *ps = &sdata->bss->ps; + u8 lb_period = sdata->vif.bss_conf.s1g_long_beacon_period; + u32 beacon_int = sdata->vif.bss_conf.beacon_int * 1024; + + /* No mesh / IBSS support for short beaconing */ + if (tsf == -1ULL || !lb_period || + (sdata->vif.type != NL80211_IFTYPE_AP && + sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) + return; + + /* find the current TSBTT index in our lb_period */ + do_div(tsf, beacon_int); + sb_idx = do_div(tsf, lb_period); + + /* num TSBTTs until the next TBTT */ + ps->sb_count = sb_idx ? lb_period - sb_idx : 0; +} + static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local, struct ieee80211_chanctx *ctx) { @@ -3953,6 +4012,33 @@ static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local, return radar_detect; } +bool ieee80211_is_radio_idx_in_scan_req(struct wiphy *wiphy, + struct cfg80211_scan_request *scan_req, + int radio_idx) +{ + struct ieee80211_channel *chan; + int i, chan_radio_idx; + + for (i = 0; i < scan_req->n_channels; i++) { + chan = scan_req->channels[i]; + chan_radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan); + /* + * The chan_radio_idx should be valid since it's taken from a + * valid scan request. + * However, if chan_radio_idx is unexpectedly invalid (negative), + * we take a conservative approach and assume the scan request + * might use the specified radio_idx. Hence, return true. + */ + if (WARN_ON(chan_radio_idx < 0)) + return true; + + if (chan_radio_idx == radio_idx) + return true; + } + + return false; +} + static u32 __ieee80211_get_radio_mask(struct ieee80211_sub_if_data *sdata) { |