diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:18:27 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:19:04 +0200 |
commit | 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch) | |
tree | 021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /net/mac80211/util.c | |
parent | 682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff) | |
parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) |
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree),
to prepare for tooling changes, and also to pick up v3.4 MM
changes that the uprobes code needs to take care of.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9919892575f..32f7a3b3d43 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, size_t left = len; u8 *pos = start; bool calc_crc = filter != 0; + DECLARE_BITMAP(seen_elems, 256); + bitmap_zero(seen_elems, 256); memset(elems, 0, sizeof(*elems)); elems->ie_start = start; elems->total_len = len; while (left >= 2) { u8 id, elen; + bool elem_parse_failed; id = *pos++; elen = *pos++; left -= 2; - if (elen > left) + if (elen > left) { + elems->parse_error = true; break; + } + + if (id != WLAN_EID_VENDOR_SPECIFIC && + id != WLAN_EID_QUIET && + test_bit(id, seen_elems)) { + elems->parse_error = true; + left -= elen; + pos += elen; + continue; + } if (calc_crc && id < 64 && (filter & (1ULL << id))) crc = crc32_be(crc, pos - 2, elen + 2); + elem_parse_failed = false; + switch (id) { case WLAN_EID_SSID: elems->ssid = pos; @@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, if (elen >= sizeof(struct ieee80211_tim_ie)) { elems->tim = (void *)pos; elems->tim_len = elen; - } + } else + elem_parse_failed = true; break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; @@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, case WLAN_EID_HT_CAPABILITY: if (elen >= sizeof(struct ieee80211_ht_cap)) elems->ht_cap_elem = (void *)pos; + else + elem_parse_failed = true; break; case WLAN_EID_HT_INFORMATION: if (elen >= sizeof(struct ieee80211_ht_info)) elems->ht_info_elem = (void *)pos; + else + elem_parse_failed = true; break; case WLAN_EID_MESH_ID: elems->mesh_id = pos; @@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, case WLAN_EID_MESH_CONFIG: if (elen >= sizeof(struct ieee80211_meshconf_ie)) elems->mesh_config = (void *)pos; + else + elem_parse_failed = true; break; case WLAN_EID_PEER_MGMT: elems->peering = pos; @@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, case WLAN_EID_RANN: if (elen >= sizeof(struct ieee80211_rann_ie)) elems->rann = (void *)pos; + else + elem_parse_failed = true; break; case WLAN_EID_CHANNEL_SWITCH: elems->ch_switch_elem = pos; @@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, break; } + if (elem_parse_failed) + elems->parse_error = true; + else + set_bit(id, seen_elems); + left -= elen; pos += elen; } + if (left != 0) + elems->parse_error = true; + return crc; } @@ -737,7 +770,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, ieee802_11_parse_elems_crc(start, len, elems, 0, 0); } -void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) +void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, + bool bss_notify) { struct ieee80211_local *local = sdata->local; struct ieee80211_tx_queue_params qparam; @@ -753,7 +787,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); - for (queue = 0; queue < local_to_hw(local)->queues; queue++) { + for (queue = 0; queue < local->hw.queues; queue++) { /* Set defaults according to 802.11-2007 Table 7-37 */ aCWmax = 1023; if (use_11b) @@ -807,7 +841,9 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { sdata->vif.bss_conf.qos = sdata->vif.type != NL80211_IFTYPE_STATION; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); + if (bss_notify) + ieee80211_bss_info_change_notify(sdata, + BSS_CHANGED_QOS); } } @@ -829,7 +865,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, else sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; - ieee80211_set_wmm_default(sdata); + ieee80211_set_wmm_default(sdata, true); } u32 ieee80211_mandatory_rates(struct ieee80211_local *local, @@ -862,8 +898,8 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, - u8 *extra, size_t extra_len, const u8 *bssid, - const u8 *key, u8 key_len, u8 key_idx) + u8 *extra, size_t extra_len, const u8 *da, + const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb; @@ -881,7 +917,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, memset(mgmt, 0, 24 + 6); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); - memcpy(mgmt->da, bssid, ETH_ALEN); + memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, bssid, ETH_ALEN); mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); @@ -1185,13 +1221,12 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { if (sta->uploaded) { - sdata = sta->sdata; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); + enum ieee80211_sta_state state; - WARN_ON(drv_sta_add(local, sdata, &sta->sta)); + for (state = IEEE80211_STA_NOTEXIST; + state < sta->sta_state - 1; state++) + WARN_ON(drv_sta_state(local, sta->sdata, sta, + state, state + 1)); } } mutex_unlock(&local->sta_mtx); @@ -1272,6 +1307,21 @@ int ieee80211_reconfig(struct ieee80211_local *local) ieee80211_recalc_ps(local, -1); /* + * The sta might be in psm against the ap (e.g. because + * this was the state before a hw restart), so we + * explicitly send a null packet in order to make sure + * it'll sync against the ap (and get out of psm). + */ + if (!(local->hw.conf.flags & IEEE80211_CONF_PS)) { + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_STATION) + continue; + + ieee80211_send_nullfunc(local, sdata, 0); + } + } + + /* * Clear the WLAN_STA_BLOCK_BA flag so new aggregation * sessions can be established after a resume. * |