|
@@ -965,110 +965,124 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
|
|
|
mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
-static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|
|
- struct ieee80211_mgmt *mgmt, size_t len,
|
|
|
- struct ieee80211_rx_status *rx_status,
|
|
|
- struct ieee802_11_elems *elems)
|
|
|
+static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
|
|
|
+ struct ieee80211_mgmt *mgmt, size_t len,
|
|
|
+ struct ieee80211_rx_status *rx_status,
|
|
|
+ struct ieee802_11_elems *elems,
|
|
|
+ struct ieee80211_channel *channel)
|
|
|
{
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
- struct cfg80211_bss *cbss;
|
|
|
- struct ieee80211_bss *bss;
|
|
|
struct sta_info *sta;
|
|
|
- struct ieee80211_channel *channel;
|
|
|
- u64 beacon_timestamp, rx_timestamp;
|
|
|
- u32 supp_rates = 0;
|
|
|
enum ieee80211_band band = rx_status->band;
|
|
|
enum nl80211_bss_scan_width scan_width;
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
|
|
|
bool rates_updated = false;
|
|
|
+ u32 supp_rates = 0;
|
|
|
|
|
|
- channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
|
|
- if (!channel)
|
|
|
+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
|
|
return;
|
|
|
|
|
|
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
|
|
|
- ether_addr_equal(mgmt->bssid, sdata->u.ibss.bssid)) {
|
|
|
+ if (!ether_addr_equal(mgmt->bssid, sdata->u.ibss.bssid))
|
|
|
+ return;
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
- sta = sta_info_get(sdata, mgmt->sa);
|
|
|
-
|
|
|
- if (elems->supp_rates) {
|
|
|
- supp_rates = ieee80211_sta_get_rates(sdata, elems,
|
|
|
- band, NULL);
|
|
|
- if (sta) {
|
|
|
- u32 prev_rates;
|
|
|
-
|
|
|
- prev_rates = sta->sta.supp_rates[band];
|
|
|
- /* make sure mandatory rates are always added */
|
|
|
- scan_width = NL80211_BSS_CHAN_WIDTH_20;
|
|
|
- if (rx_status->flag & RX_FLAG_5MHZ)
|
|
|
- scan_width = NL80211_BSS_CHAN_WIDTH_5;
|
|
|
- if (rx_status->flag & RX_FLAG_10MHZ)
|
|
|
- scan_width = NL80211_BSS_CHAN_WIDTH_10;
|
|
|
-
|
|
|
- sta->sta.supp_rates[band] = supp_rates |
|
|
|
- ieee80211_mandatory_rates(sband,
|
|
|
- scan_width);
|
|
|
- if (sta->sta.supp_rates[band] != prev_rates) {
|
|
|
- ibss_dbg(sdata,
|
|
|
- "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
|
|
|
- sta->sta.addr, prev_rates,
|
|
|
- sta->sta.supp_rates[band]);
|
|
|
- rates_updated = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- rcu_read_unlock();
|
|
|
- sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
|
|
|
- mgmt->sa, supp_rates);
|
|
|
+ rcu_read_lock();
|
|
|
+ sta = sta_info_get(sdata, mgmt->sa);
|
|
|
+
|
|
|
+ if (elems->supp_rates) {
|
|
|
+ supp_rates = ieee80211_sta_get_rates(sdata, elems,
|
|
|
+ band, NULL);
|
|
|
+ if (sta) {
|
|
|
+ u32 prev_rates;
|
|
|
+
|
|
|
+ prev_rates = sta->sta.supp_rates[band];
|
|
|
+ /* make sure mandatory rates are always added */
|
|
|
+ scan_width = NL80211_BSS_CHAN_WIDTH_20;
|
|
|
+ if (rx_status->flag & RX_FLAG_5MHZ)
|
|
|
+ scan_width = NL80211_BSS_CHAN_WIDTH_5;
|
|
|
+ if (rx_status->flag & RX_FLAG_10MHZ)
|
|
|
+ scan_width = NL80211_BSS_CHAN_WIDTH_10;
|
|
|
+
|
|
|
+ sta->sta.supp_rates[band] = supp_rates |
|
|
|
+ ieee80211_mandatory_rates(sband, scan_width);
|
|
|
+ if (sta->sta.supp_rates[band] != prev_rates) {
|
|
|
+ ibss_dbg(sdata,
|
|
|
+ "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
|
|
|
+ sta->sta.addr, prev_rates,
|
|
|
+ sta->sta.supp_rates[band]);
|
|
|
+ rates_updated = true;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ rcu_read_unlock();
|
|
|
+ sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
|
|
|
+ mgmt->sa, supp_rates);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (sta && elems->wmm_info)
|
|
|
- sta->sta.wme = true;
|
|
|
-
|
|
|
- if (sta && elems->ht_operation && elems->ht_cap_elem &&
|
|
|
- sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
|
|
|
- sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 &&
|
|
|
- sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) {
|
|
|
- /* we both use HT */
|
|
|
- struct ieee80211_ht_cap htcap_ie;
|
|
|
- struct cfg80211_chan_def chandef;
|
|
|
-
|
|
|
- ieee80211_ht_oper_to_chandef(channel,
|
|
|
- elems->ht_operation,
|
|
|
- &chandef);
|
|
|
-
|
|
|
- memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
|
|
|
-
|
|
|
- /*
|
|
|
- * fall back to HT20 if we don't use or use
|
|
|
- * the other extension channel
|
|
|
- */
|
|
|
- if (chandef.center_freq1 !=
|
|
|
- sdata->u.ibss.chandef.center_freq1)
|
|
|
- htcap_ie.cap_info &=
|
|
|
- cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
|
|
-
|
|
|
- rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(
|
|
|
- sdata, sband, &htcap_ie, sta);
|
|
|
- }
|
|
|
+ if (sta && elems->wmm_info)
|
|
|
+ sta->sta.wme = true;
|
|
|
|
|
|
- if (sta && rates_updated) {
|
|
|
- u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
|
|
|
- u8 rx_nss = sta->sta.rx_nss;
|
|
|
+ if (sta && elems->ht_operation && elems->ht_cap_elem &&
|
|
|
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
|
|
|
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 &&
|
|
|
+ sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) {
|
|
|
+ /* we both use HT */
|
|
|
+ struct ieee80211_ht_cap htcap_ie;
|
|
|
+ struct cfg80211_chan_def chandef;
|
|
|
|
|
|
- /* Force rx_nss recalculation */
|
|
|
- sta->sta.rx_nss = 0;
|
|
|
- rate_control_rate_init(sta);
|
|
|
- if (sta->sta.rx_nss != rx_nss)
|
|
|
- changed |= IEEE80211_RC_NSS_CHANGED;
|
|
|
+ ieee80211_ht_oper_to_chandef(channel,
|
|
|
+ elems->ht_operation,
|
|
|
+ &chandef);
|
|
|
|
|
|
- drv_sta_rc_update(local, sdata, &sta->sta, changed);
|
|
|
- }
|
|
|
+ memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
|
|
|
|
|
|
- rcu_read_unlock();
|
|
|
+ /*
|
|
|
+ * fall back to HT20 if we don't use or use
|
|
|
+ * the other extension channel
|
|
|
+ */
|
|
|
+ if (chandef.center_freq1 != sdata->u.ibss.chandef.center_freq1)
|
|
|
+ htcap_ie.cap_info &=
|
|
|
+ cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
|
|
+
|
|
|
+ rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
|
|
|
+ &htcap_ie,
|
|
|
+ sta);
|
|
|
}
|
|
|
|
|
|
+ if (sta && rates_updated) {
|
|
|
+ u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
|
|
|
+ u8 rx_nss = sta->sta.rx_nss;
|
|
|
+
|
|
|
+ /* Force rx_nss recalculation */
|
|
|
+ sta->sta.rx_nss = 0;
|
|
|
+ rate_control_rate_init(sta);
|
|
|
+ if (sta->sta.rx_nss != rx_nss)
|
|
|
+ changed |= IEEE80211_RC_NSS_CHANGED;
|
|
|
+
|
|
|
+ drv_sta_rc_update(local, sdata, &sta->sta, changed);
|
|
|
+ }
|
|
|
+
|
|
|
+ rcu_read_unlock();
|
|
|
+}
|
|
|
+
|
|
|
+static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|
|
+ struct ieee80211_mgmt *mgmt, size_t len,
|
|
|
+ struct ieee80211_rx_status *rx_status,
|
|
|
+ struct ieee802_11_elems *elems)
|
|
|
+{
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
+ struct cfg80211_bss *cbss;
|
|
|
+ struct ieee80211_bss *bss;
|
|
|
+ struct ieee80211_channel *channel;
|
|
|
+ u64 beacon_timestamp, rx_timestamp;
|
|
|
+ u32 supp_rates = 0;
|
|
|
+ enum ieee80211_band band = rx_status->band;
|
|
|
+
|
|
|
+ channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
|
|
+ if (!channel)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel);
|
|
|
+
|
|
|
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
|
|
|
channel);
|
|
|
if (!bss)
|