aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
commitd98cae64e4a733ff377184d78aa0b1f2b54faede (patch)
treee973e3c93fe7e17741567ac3947f5197bc9d582d /net/mac80211
parent646093a29f85630d8efe2aa38fa585d2c3ea2e46 (diff)
parent4067c666f2dccf56f5db5c182713e68c40d46013 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/wireless/ath/ath9k/Kconfig drivers/net/xen-netback/netback.c net/batman-adv/bat_iv_ogm.c net/wireless/nl80211.c The ath9k Kconfig conflict was a change of a Kconfig option name right next to the deletion of another option. The xen-netback conflict was overlapping changes involving the handling of the notify list in xen_netbk_rx_action(). Batman conflict resolution provided by Antonio Quartulli, basically keep everything in both conflict hunks. The nl80211 conflict is a little more involved. In 'net' we added a dynamic memory allocation to nl80211_dump_wiphy() to fix a race that Linus reported. Meanwhile in 'net-next' the handlers were converted to use pre and post doit handlers which use a flag to determine whether to hold the RTNL mutex around the operation. However, the dump handlers to not use this logic. Instead they have to explicitly do the locking. There were apparent bugs in the conversion of nl80211_dump_wiphy() in that we were not dropping the RTNL mutex in all the return paths, and it seems we very much should be doing so. So I fixed that whilst handling the overlapping changes. To simplify the initial returns, I take the RTNL mutex after we try to allocate 'tb'. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/mlme.c87
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/mac80211/util.c4
5 files changed, 92 insertions, 12 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 30622101d3b5..a1c6e1ceede8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1071,6 +1071,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1071 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1071 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
1072 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 1072 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
1073 1073
1074 if (sdata->wdev.cac_started) {
1075 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
1076 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
1077 GFP_KERNEL);
1078 }
1079
1074 drv_stop_ap(sdata->local, sdata); 1080 drv_stop_ap(sdata->local, sdata);
1075 1081
1076 /* free all potentially still buffered bcast frames */ 1082 /* free all potentially still buffered bcast frames */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9eed6f1d1614..923e1772e8f3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1512,10 +1512,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
1512 ieee80211_tx_skb_tid(sdata, skb, 7); 1512 ieee80211_tx_skb_tid(sdata, skb, 7);
1513} 1513}
1514 1514
1515u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 1515u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1516 struct ieee802_11_elems *elems, 1516 struct ieee802_11_elems *elems,
1517 u64 filter, u32 crc); 1517 u64 filter, u32 crc);
1518static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, 1518static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
1519 bool action,
1519 struct ieee802_11_elems *elems) 1520 struct ieee802_11_elems *elems)
1520{ 1521{
1521 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); 1522 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f44f4caa69ee..118540b16729 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2486,8 +2486,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2486 u16 capab_info, aid; 2486 u16 capab_info, aid;
2487 struct ieee802_11_elems elems; 2487 struct ieee802_11_elems elems;
2488 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 2488 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2489 const struct cfg80211_bss_ies *bss_ies = NULL;
2490 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
2489 u32 changed = 0; 2491 u32 changed = 0;
2490 int err; 2492 int err;
2493 bool ret;
2491 2494
2492 /* AssocResp and ReassocResp have identical structure */ 2495 /* AssocResp and ReassocResp have identical structure */
2493 2496
@@ -2519,21 +2522,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2519 ifmgd->aid = aid; 2522 ifmgd->aid = aid;
2520 2523
2521 /* 2524 /*
2525 * Some APs are erroneously not including some information in their
2526 * (re)association response frames. Try to recover by using the data
2527 * from the beacon or probe response. This seems to afflict mobile
2528 * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
2529 * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
2530 */
2531 if ((assoc_data->wmm && !elems.wmm_param) ||
2532 (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2533 (!elems.ht_cap_elem || !elems.ht_operation)) ||
2534 (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2535 (!elems.vht_cap_elem || !elems.vht_operation))) {
2536 const struct cfg80211_bss_ies *ies;
2537 struct ieee802_11_elems bss_elems;
2538
2539 rcu_read_lock();
2540 ies = rcu_dereference(cbss->ies);
2541 if (ies)
2542 bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
2543 GFP_ATOMIC);
2544 rcu_read_unlock();
2545 if (!bss_ies)
2546 return false;
2547
2548 ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
2549 false, &bss_elems);
2550 if (assoc_data->wmm &&
2551 !elems.wmm_param && bss_elems.wmm_param) {
2552 elems.wmm_param = bss_elems.wmm_param;
2553 sdata_info(sdata,
2554 "AP bug: WMM param missing from AssocResp\n");
2555 }
2556
2557 /*
2558 * Also check if we requested HT/VHT, otherwise the AP doesn't
2559 * have to include the IEs in the (re)association response.
2560 */
2561 if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
2562 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2563 elems.ht_cap_elem = bss_elems.ht_cap_elem;
2564 sdata_info(sdata,
2565 "AP bug: HT capability missing from AssocResp\n");
2566 }
2567 if (!elems.ht_operation && bss_elems.ht_operation &&
2568 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2569 elems.ht_operation = bss_elems.ht_operation;
2570 sdata_info(sdata,
2571 "AP bug: HT operation missing from AssocResp\n");
2572 }
2573 if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
2574 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2575 elems.vht_cap_elem = bss_elems.vht_cap_elem;
2576 sdata_info(sdata,
2577 "AP bug: VHT capa missing from AssocResp\n");
2578 }
2579 if (!elems.vht_operation && bss_elems.vht_operation &&
2580 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2581 elems.vht_operation = bss_elems.vht_operation;
2582 sdata_info(sdata,
2583 "AP bug: VHT operation missing from AssocResp\n");
2584 }
2585 }
2586
2587 /*
2522 * We previously checked these in the beacon/probe response, so 2588 * We previously checked these in the beacon/probe response, so
2523 * they should be present here. This is just a safety net. 2589 * they should be present here. This is just a safety net.
2524 */ 2590 */
2525 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && 2591 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2526 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { 2592 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
2527 sdata_info(sdata, 2593 sdata_info(sdata,
2528 "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); 2594 "HT AP is missing WMM params or HT capability/operation\n");
2529 return false; 2595 ret = false;
2596 goto out;
2530 } 2597 }
2531 2598
2532 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && 2599 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2533 (!elems.vht_cap_elem || !elems.vht_operation)) { 2600 (!elems.vht_cap_elem || !elems.vht_operation)) {
2534 sdata_info(sdata, 2601 sdata_info(sdata,
2535 "VHT AP is missing VHT capability/operation in AssocResp\n"); 2602 "VHT AP is missing VHT capability/operation\n");
2536 return false; 2603 ret = false;
2604 goto out;
2537 } 2605 }
2538 2606
2539 mutex_lock(&sdata->local->sta_mtx); 2607 mutex_lock(&sdata->local->sta_mtx);
@@ -2544,7 +2612,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2544 sta = sta_info_get(sdata, cbss->bssid); 2612 sta = sta_info_get(sdata, cbss->bssid);
2545 if (WARN_ON(!sta)) { 2613 if (WARN_ON(!sta)) {
2546 mutex_unlock(&sdata->local->sta_mtx); 2614 mutex_unlock(&sdata->local->sta_mtx);
2547 return false; 2615 ret = false;
2616 goto out;
2548 } 2617 }
2549 2618
2550 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; 2619 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
@@ -2597,7 +2666,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2597 sta->sta.addr); 2666 sta->sta.addr);
2598 WARN_ON(__sta_info_destroy(sta)); 2667 WARN_ON(__sta_info_destroy(sta));
2599 mutex_unlock(&sdata->local->sta_mtx); 2668 mutex_unlock(&sdata->local->sta_mtx);
2600 return false; 2669 ret = false;
2670 goto out;
2601 } 2671 }
2602 2672
2603 mutex_unlock(&sdata->local->sta_mtx); 2673 mutex_unlock(&sdata->local->sta_mtx);
@@ -2637,7 +2707,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2637 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 2707 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
2638 ieee80211_sta_reset_beacon_monitor(sdata); 2708 ieee80211_sta_reset_beacon_monitor(sdata);
2639 2709
2640 return true; 2710 ret = true;
2711 out:
2712 kfree(bss_ies);
2713 return ret;
2641} 2714}
2642 2715
2643static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, 2716static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index d3f414fe67e0..a02bef35b134 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
615 if (rates[i].idx < 0) 615 if (rates[i].idx < 0)
616 break; 616 break;
617 617
618 rate_idx_match_mask(&rates[i], sband, mask, chan_width, 618 rate_idx_match_mask(&rates[i], sband, chan_width, mask,
619 mcs_mask); 619 mcs_mask);
620 } 620 }
621} 621}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 89a83770d152..c75d3db2a31c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -667,12 +667,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
667} 667}
668EXPORT_SYMBOL(ieee80211_queue_delayed_work); 668EXPORT_SYMBOL(ieee80211_queue_delayed_work);
669 669
670u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 670u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
671 struct ieee802_11_elems *elems, 671 struct ieee802_11_elems *elems,
672 u64 filter, u32 crc) 672 u64 filter, u32 crc)
673{ 673{
674 size_t left = len; 674 size_t left = len;
675 u8 *pos = start; 675 const u8 *pos = start;
676 bool calc_crc = filter != 0; 676 bool calc_crc = filter != 0;
677 DECLARE_BITMAP(seen_elems, 256); 677 DECLARE_BITMAP(seen_elems, 256);
678 const u8 *ie; 678 const u8 *ie;