diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-01-30 14:22:19 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-30 14:22:19 -0500 |
commit | 20fb9e50338199d9e88512703af4c560ab53bad4 (patch) | |
tree | 2d0913749141e9e8e0df774426a658b52fddabbf /net/mac80211 | |
parent | 0f496df2d9ba48faa808b5fa330de0da1a2d29d7 (diff) | |
parent | 3b4797bce0050570e84bedd10e1b14e9320a3551 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-rx.c | 14 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 61 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 36 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/iface.c | 3 | ||||
-rw-r--r-- | net/mac80211/key.c | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 64 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 168 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 42 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 5 | ||||
-rw-r--r-- | net/mac80211/trace.h | 53 | ||||
-rw-r--r-- | net/mac80211/tx.c | 8 |
12 files changed, 304 insertions, 158 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 808338a1bce5..31bf2586fb84 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -83,8 +83,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
83 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 83 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
84 | &sta->sta, tid, NULL, 0)) | 84 | &sta->sta, tid, NULL, 0)) |
85 | sdata_info(sta->sdata, | 85 | sdata_info(sta->sdata, |
86 | "HW problem - can not stop rx aggregation for tid %d\n", | 86 | "HW problem - can not stop rx aggregation for %pM tid %d\n", |
87 | tid); | 87 | sta->sta.addr, tid); |
88 | 88 | ||
89 | /* check if this is a self generated aggregation halt */ | 89 | /* check if this is a self generated aggregation halt */ |
90 | if (initiator == WLAN_BACK_RECIPIENT && tx) | 90 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
@@ -159,7 +159,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
159 | } | 159 | } |
160 | rcu_read_unlock(); | 160 | rcu_read_unlock(); |
161 | 161 | ||
162 | ht_dbg(sta->sdata, "rx session timer expired on tid %d\n", (u16)*ptid); | 162 | ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n", |
163 | sta->sta.addr, (u16)*ptid); | ||
163 | 164 | ||
164 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); | 165 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); |
165 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 166 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
@@ -247,7 +248,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
247 | status = WLAN_STATUS_REQUEST_DECLINED; | 248 | status = WLAN_STATUS_REQUEST_DECLINED; |
248 | 249 | ||
249 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 250 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
250 | ht_dbg(sta->sdata, "Suspend in progress - Denying ADDBA request\n"); | 251 | ht_dbg(sta->sdata, |
252 | "Suspend in progress - Denying ADDBA request (%pM tid %d)\n", | ||
253 | sta->sta.addr, tid); | ||
251 | goto end_no_lock; | 254 | goto end_no_lock; |
252 | } | 255 | } |
253 | 256 | ||
@@ -317,7 +320,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
317 | 320 | ||
318 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 321 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
319 | &sta->sta, tid, &start_seq_num, 0); | 322 | &sta->sta, tid, &start_seq_num, 0); |
320 | ht_dbg(sta->sdata, "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 323 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", |
324 | sta->sta.addr, tid, ret); | ||
321 | if (ret) { | 325 | if (ret) { |
322 | kfree(tid_agg_rx->reorder_buf); | 326 | kfree(tid_agg_rx->reorder_buf); |
323 | kfree(tid_agg_rx->reorder_time); | 327 | kfree(tid_agg_rx->reorder_time); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 2f0ccbc5f13e..13b7683de5a4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -296,7 +296,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
296 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, | 296 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, |
297 | &sta->sta, tid, NULL, 0); | 297 | &sta->sta, tid, NULL, 0); |
298 | WARN_ON_ONCE(ret); | 298 | WARN_ON_ONCE(ret); |
299 | goto remove_tid_tx; | 299 | return 0; |
300 | } | 300 | } |
301 | 301 | ||
302 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 302 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
@@ -354,12 +354,15 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
354 | */ | 354 | */ |
355 | } | 355 | } |
356 | 356 | ||
357 | if (reason == AGG_STOP_DESTROY_STA) { | 357 | /* |
358 | remove_tid_tx: | 358 | * In the case of AGG_STOP_DESTROY_STA, the driver won't |
359 | spin_lock_bh(&sta->lock); | 359 | * necessarily call ieee80211_stop_tx_ba_cb(), so this may |
360 | ieee80211_remove_tid_tx(sta, tid); | 360 | * seem like we can leave the tid_tx data pending forever. |
361 | spin_unlock_bh(&sta->lock); | 361 | * This is true, in a way, but "forever" is only until the |
362 | } | 362 | * station struct is actually destroyed. In the meantime, |
363 | * leaving it around ensures that we don't transmit packets | ||
364 | * to the driver on this TID which might confuse it. | ||
365 | */ | ||
363 | 366 | ||
364 | return 0; | 367 | return 0; |
365 | } | 368 | } |
@@ -387,12 +390,13 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
387 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { | 390 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { |
388 | rcu_read_unlock(); | 391 | rcu_read_unlock(); |
389 | ht_dbg(sta->sdata, | 392 | ht_dbg(sta->sdata, |
390 | "timer expired on tid %d but we are not (or no longer) expecting addBA response there\n", | 393 | "timer expired on %pM tid %d but we are not (or no longer) expecting addBA response there\n", |
391 | tid); | 394 | sta->sta.addr, tid); |
392 | return; | 395 | return; |
393 | } | 396 | } |
394 | 397 | ||
395 | ht_dbg(sta->sdata, "addBA response timer expired on tid %d\n", tid); | 398 | ht_dbg(sta->sdata, "addBA response timer expired on %pM tid %d\n", |
399 | sta->sta.addr, tid); | ||
396 | 400 | ||
397 | ieee80211_stop_tx_ba_session(&sta->sta, tid); | 401 | ieee80211_stop_tx_ba_session(&sta->sta, tid); |
398 | rcu_read_unlock(); | 402 | rcu_read_unlock(); |
@@ -429,7 +433,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
429 | &sta->sta, tid, &start_seq_num, 0); | 433 | &sta->sta, tid, &start_seq_num, 0); |
430 | if (ret) { | 434 | if (ret) { |
431 | ht_dbg(sdata, | 435 | ht_dbg(sdata, |
432 | "BA request denied - HW unavailable for tid %d\n", tid); | 436 | "BA request denied - HW unavailable for %pM tid %d\n", |
437 | sta->sta.addr, tid); | ||
433 | spin_lock_bh(&sta->lock); | 438 | spin_lock_bh(&sta->lock); |
434 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); | 439 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
435 | ieee80211_assign_tid_tx(sta, tid, NULL); | 440 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -442,7 +447,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
442 | 447 | ||
443 | /* activate the timer for the recipient's addBA response */ | 448 | /* activate the timer for the recipient's addBA response */ |
444 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 449 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
445 | ht_dbg(sdata, "activated addBA response timer on tid %d\n", tid); | 450 | ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n", |
451 | sta->sta.addr, tid); | ||
446 | 452 | ||
447 | spin_lock_bh(&sta->lock); | 453 | spin_lock_bh(&sta->lock); |
448 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; | 454 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; |
@@ -489,7 +495,8 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
489 | 495 | ||
490 | rcu_read_unlock(); | 496 | rcu_read_unlock(); |
491 | 497 | ||
492 | ht_dbg(sta->sdata, "tx session timer expired on tid %d\n", (u16)*ptid); | 498 | ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n", |
499 | sta->sta.addr, (u16)*ptid); | ||
493 | 500 | ||
494 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); | 501 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); |
495 | } | 502 | } |
@@ -525,7 +532,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
525 | 532 | ||
526 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 533 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
527 | ht_dbg(sdata, | 534 | ht_dbg(sdata, |
528 | "BA sessions blocked - Denying BA session request\n"); | 535 | "BA sessions blocked - Denying BA session request %pM tid %d\n", |
536 | sta->sta.addr, tid); | ||
529 | return -EINVAL; | 537 | return -EINVAL; |
530 | } | 538 | } |
531 | 539 | ||
@@ -566,8 +574,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
566 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + | 574 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + |
567 | HT_AGG_RETRIES_PERIOD)) { | 575 | HT_AGG_RETRIES_PERIOD)) { |
568 | ht_dbg(sdata, | 576 | ht_dbg(sdata, |
569 | "BA request denied - waiting a grace period after %d failed requests on tid %u\n", | 577 | "BA request denied - waiting a grace period after %d failed requests on %pM tid %u\n", |
570 | sta->ampdu_mlme.addba_req_num[tid], tid); | 578 | sta->ampdu_mlme.addba_req_num[tid], sta->sta.addr, tid); |
571 | ret = -EBUSY; | 579 | ret = -EBUSY; |
572 | goto err_unlock_sta; | 580 | goto err_unlock_sta; |
573 | } | 581 | } |
@@ -576,8 +584,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
576 | /* check if the TID is not in aggregation flow already */ | 584 | /* check if the TID is not in aggregation flow already */ |
577 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { | 585 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
578 | ht_dbg(sdata, | 586 | ht_dbg(sdata, |
579 | "BA request denied - session is not idle on tid %u\n", | 587 | "BA request denied - session is not idle on %pM tid %u\n", |
580 | tid); | 588 | sta->sta.addr, tid); |
581 | ret = -EAGAIN; | 589 | ret = -EAGAIN; |
582 | goto err_unlock_sta; | 590 | goto err_unlock_sta; |
583 | } | 591 | } |
@@ -632,7 +640,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
632 | 640 | ||
633 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 641 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
634 | 642 | ||
635 | ht_dbg(sta->sdata, "Aggregation is on for tid %d\n", tid); | 643 | ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n", |
644 | sta->sta.addr, tid); | ||
636 | 645 | ||
637 | drv_ampdu_action(local, sta->sdata, | 646 | drv_ampdu_action(local, sta->sdata, |
638 | IEEE80211_AMPDU_TX_OPERATIONAL, | 647 | IEEE80211_AMPDU_TX_OPERATIONAL, |
@@ -802,7 +811,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
802 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 811 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
803 | 812 | ||
804 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 813 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
805 | ht_dbg(sdata, "unexpected callback to A-MPDU stop\n"); | 814 | ht_dbg(sdata, |
815 | "unexpected callback to A-MPDU stop for %pM tid %d\n", | ||
816 | sta->sta.addr, tid); | ||
806 | goto unlock_sta; | 817 | goto unlock_sta; |
807 | } | 818 | } |
808 | 819 | ||
@@ -861,13 +872,15 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
861 | goto out; | 872 | goto out; |
862 | 873 | ||
863 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { | 874 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { |
864 | ht_dbg(sta->sdata, "wrong addBA response token, tid %d\n", tid); | 875 | ht_dbg(sta->sdata, "wrong addBA response token, %pM tid %d\n", |
876 | sta->sta.addr, tid); | ||
865 | goto out; | 877 | goto out; |
866 | } | 878 | } |
867 | 879 | ||
868 | del_timer_sync(&tid_tx->addba_resp_timer); | 880 | del_timer_sync(&tid_tx->addba_resp_timer); |
869 | 881 | ||
870 | ht_dbg(sta->sdata, "switched off addBA timer for tid %d\n", tid); | 882 | ht_dbg(sta->sdata, "switched off addBA timer for %pM tid %d\n", |
883 | sta->sta.addr, tid); | ||
871 | 884 | ||
872 | /* | 885 | /* |
873 | * addba_resp_timer may have fired before we got here, and | 886 | * addba_resp_timer may have fired before we got here, and |
@@ -877,8 +890,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
877 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | 890 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || |
878 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 891 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
879 | ht_dbg(sta->sdata, | 892 | ht_dbg(sta->sdata, |
880 | "got addBA resp for tid %d but we already gave up\n", | 893 | "got addBA resp for %pM tid %d but we already gave up\n", |
881 | tid); | 894 | sta->sta.addr, tid); |
882 | goto out; | 895 | goto out; |
883 | } | 896 | } |
884 | 897 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 0c07f94c5378..434b3c4f31b5 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -569,7 +569,8 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local, | |||
569 | check_sdata_in_driver(sdata); | 569 | check_sdata_in_driver(sdata); |
570 | 570 | ||
571 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | 571 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && |
572 | sdata->vif.type != NL80211_IFTYPE_ADHOC); | 572 | (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
573 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); | ||
573 | 574 | ||
574 | trace_drv_sta_rc_update(local, sdata, sta, changed); | 575 | trace_drv_sta_rc_update(local, sdata, sta, changed); |
575 | if (local->ops->sta_rc_update) | 576 | if (local->ops->sta_rc_update) |
@@ -845,11 +846,12 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, | |||
845 | } | 846 | } |
846 | 847 | ||
847 | static inline void drv_rssi_callback(struct ieee80211_local *local, | 848 | static inline void drv_rssi_callback(struct ieee80211_local *local, |
849 | struct ieee80211_sub_if_data *sdata, | ||
848 | const enum ieee80211_rssi_event event) | 850 | const enum ieee80211_rssi_event event) |
849 | { | 851 | { |
850 | trace_drv_rssi_callback(local, event); | 852 | trace_drv_rssi_callback(local, sdata, event); |
851 | if (local->ops->rssi_callback) | 853 | if (local->ops->rssi_callback) |
852 | local->ops->rssi_callback(&local->hw, event); | 854 | local->ops->rssi_callback(&local->hw, &sdata->vif, event); |
853 | trace_drv_return_void(local); | 855 | trace_drv_return_void(local); |
854 | } | 856 | } |
855 | 857 | ||
@@ -1020,4 +1022,32 @@ static inline void drv_restart_complete(struct ieee80211_local *local) | |||
1020 | trace_drv_return_void(local); | 1022 | trace_drv_return_void(local); |
1021 | } | 1023 | } |
1022 | 1024 | ||
1025 | static inline void | ||
1026 | drv_set_default_unicast_key(struct ieee80211_local *local, | ||
1027 | struct ieee80211_sub_if_data *sdata, | ||
1028 | int key_idx) | ||
1029 | { | ||
1030 | check_sdata_in_driver(sdata); | ||
1031 | |||
1032 | WARN_ON_ONCE(key_idx < -1 || key_idx > 3); | ||
1033 | |||
1034 | trace_drv_set_default_unicast_key(local, sdata, key_idx); | ||
1035 | if (local->ops->set_default_unicast_key) | ||
1036 | local->ops->set_default_unicast_key(&local->hw, &sdata->vif, | ||
1037 | key_idx); | ||
1038 | trace_drv_return_void(local); | ||
1039 | } | ||
1040 | |||
1041 | #if IS_ENABLED(CONFIG_IPV6) | ||
1042 | static inline void drv_ipv6_addr_change(struct ieee80211_local *local, | ||
1043 | struct ieee80211_sub_if_data *sdata, | ||
1044 | struct inet6_dev *idev) | ||
1045 | { | ||
1046 | trace_drv_ipv6_addr_change(local, sdata); | ||
1047 | if (local->ops->ipv6_addr_change) | ||
1048 | local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev); | ||
1049 | trace_drv_return_void(local); | ||
1050 | } | ||
1051 | #endif | ||
1052 | |||
1023 | #endif /* __MAC80211_DRIVER_OPS */ | 1053 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 63f0430c131e..5fba867d9e2e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -747,8 +747,6 @@ struct ieee80211_sub_if_data { | |||
747 | struct work_struct work; | 747 | struct work_struct work; |
748 | struct sk_buff_head skb_queue; | 748 | struct sk_buff_head skb_queue; |
749 | 749 | ||
750 | bool arp_filter_state; | ||
751 | |||
752 | u8 needed_rx_chains; | 750 | u8 needed_rx_chains; |
753 | enum ieee80211_smps_mode smps_mode; | 751 | enum ieee80211_smps_mode smps_mode; |
754 | 752 | ||
@@ -1129,6 +1127,7 @@ struct ieee80211_local { | |||
1129 | struct timer_list dynamic_ps_timer; | 1127 | struct timer_list dynamic_ps_timer; |
1130 | struct notifier_block network_latency_notifier; | 1128 | struct notifier_block network_latency_notifier; |
1131 | struct notifier_block ifa_notifier; | 1129 | struct notifier_block ifa_notifier; |
1130 | struct notifier_block ifa6_notifier; | ||
1132 | 1131 | ||
1133 | /* | 1132 | /* |
1134 | * The dynamic ps timeout configured from user space via WEXT - | 1133 | * The dynamic ps timeout configured from user space via WEXT - |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 06fac2991d40..0a36dc6346bb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1574,9 +1574,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1574 | /* initialise type-independent data */ | 1574 | /* initialise type-independent data */ |
1575 | sdata->wdev.wiphy = local->hw.wiphy; | 1575 | sdata->wdev.wiphy = local->hw.wiphy; |
1576 | sdata->local = local; | 1576 | sdata->local = local; |
1577 | #ifdef CONFIG_INET | ||
1578 | sdata->arp_filter_state = true; | ||
1579 | #endif | ||
1580 | 1577 | ||
1581 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 1578 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
1582 | skb_queue_head_init(&sdata->fragments[i].skb_list); | 1579 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 619c5d697999..ef252eb58c36 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -204,8 +204,11 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
204 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 204 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
205 | key = key_mtx_dereference(sdata->local, sdata->keys[idx]); | 205 | key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
206 | 206 | ||
207 | if (uni) | 207 | if (uni) { |
208 | rcu_assign_pointer(sdata->default_unicast_key, key); | 208 | rcu_assign_pointer(sdata->default_unicast_key, key); |
209 | drv_set_default_unicast_key(sdata->local, sdata, idx); | ||
210 | } | ||
211 | |||
209 | if (multi) | 212 | if (multi) |
210 | rcu_assign_pointer(sdata->default_multicast_key, key); | 213 | rcu_assign_pointer(sdata->default_multicast_key, key); |
211 | 214 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 39cfe8f10ad2..2bdd454e8bcf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/inetdevice.h> | 23 | #include <linux/inetdevice.h> |
24 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
25 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
26 | #include <net/addrconf.h> | ||
26 | 27 | ||
27 | #include "ieee80211_i.h" | 28 | #include "ieee80211_i.h" |
28 | #include "driver-ops.h" | 29 | #include "driver-ops.h" |
@@ -349,27 +350,19 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
349 | 350 | ||
350 | /* Copy the addresses to the bss_conf list */ | 351 | /* Copy the addresses to the bss_conf list */ |
351 | ifa = idev->ifa_list; | 352 | ifa = idev->ifa_list; |
352 | while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) { | 353 | while (ifa) { |
353 | bss_conf->arp_addr_list[c] = ifa->ifa_address; | 354 | if (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN) |
355 | bss_conf->arp_addr_list[c] = ifa->ifa_address; | ||
354 | ifa = ifa->ifa_next; | 356 | ifa = ifa->ifa_next; |
355 | c++; | 357 | c++; |
356 | } | 358 | } |
357 | 359 | ||
358 | /* If not all addresses fit the list, disable filtering */ | ||
359 | if (ifa) { | ||
360 | sdata->arp_filter_state = false; | ||
361 | c = 0; | ||
362 | } else { | ||
363 | sdata->arp_filter_state = true; | ||
364 | } | ||
365 | bss_conf->arp_addr_cnt = c; | 360 | bss_conf->arp_addr_cnt = c; |
366 | 361 | ||
367 | /* Configure driver only if associated (which also implies it is up) */ | 362 | /* Configure driver only if associated (which also implies it is up) */ |
368 | if (ifmgd->associated) { | 363 | if (ifmgd->associated) |
369 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | ||
370 | ieee80211_bss_info_change_notify(sdata, | 364 | ieee80211_bss_info_change_notify(sdata, |
371 | BSS_CHANGED_ARP_FILTER); | 365 | BSS_CHANGED_ARP_FILTER); |
372 | } | ||
373 | 366 | ||
374 | mutex_unlock(&ifmgd->mtx); | 367 | mutex_unlock(&ifmgd->mtx); |
375 | 368 | ||
@@ -377,6 +370,37 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
377 | } | 370 | } |
378 | #endif | 371 | #endif |
379 | 372 | ||
373 | #if IS_ENABLED(CONFIG_IPV6) | ||
374 | static int ieee80211_ifa6_changed(struct notifier_block *nb, | ||
375 | unsigned long data, void *arg) | ||
376 | { | ||
377 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg; | ||
378 | struct inet6_dev *idev = ifa->idev; | ||
379 | struct net_device *ndev = ifa->idev->dev; | ||
380 | struct ieee80211_local *local = | ||
381 | container_of(nb, struct ieee80211_local, ifa6_notifier); | ||
382 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
383 | struct ieee80211_sub_if_data *sdata; | ||
384 | |||
385 | /* Make sure it's our interface that got changed */ | ||
386 | if (!wdev || wdev->wiphy != local->hw.wiphy) | ||
387 | return NOTIFY_DONE; | ||
388 | |||
389 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | ||
390 | |||
391 | /* | ||
392 | * For now only support station mode. This is mostly because | ||
393 | * doing AP would have to handle AP_VLAN in some way ... | ||
394 | */ | ||
395 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
396 | return NOTIFY_DONE; | ||
397 | |||
398 | drv_ipv6_addr_change(local, sdata, idev); | ||
399 | |||
400 | return NOTIFY_DONE; | ||
401 | } | ||
402 | #endif | ||
403 | |||
380 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | 404 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) |
381 | { | 405 | { |
382 | struct ieee80211_local *local = | 406 | struct ieee80211_local *local = |
@@ -985,12 +1009,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
985 | goto fail_ifa; | 1009 | goto fail_ifa; |
986 | #endif | 1010 | #endif |
987 | 1011 | ||
1012 | #if IS_ENABLED(CONFIG_IPV6) | ||
1013 | local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; | ||
1014 | result = register_inet6addr_notifier(&local->ifa6_notifier); | ||
1015 | if (result) | ||
1016 | goto fail_ifa6; | ||
1017 | #endif | ||
1018 | |||
988 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | 1019 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, |
989 | local->hw.napi_weight); | 1020 | local->hw.napi_weight); |
990 | 1021 | ||
991 | return 0; | 1022 | return 0; |
992 | 1023 | ||
1024 | #if IS_ENABLED(CONFIG_IPV6) | ||
1025 | fail_ifa6: | ||
993 | #ifdef CONFIG_INET | 1026 | #ifdef CONFIG_INET |
1027 | unregister_inetaddr_notifier(&local->ifa_notifier); | ||
1028 | #endif | ||
1029 | #endif | ||
1030 | #if defined(CONFIG_INET) || defined(CONFIG_IPV6) | ||
994 | fail_ifa: | 1031 | fail_ifa: |
995 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, | 1032 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, |
996 | &local->network_latency_notifier); | 1033 | &local->network_latency_notifier); |
@@ -1026,6 +1063,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1026 | #ifdef CONFIG_INET | 1063 | #ifdef CONFIG_INET |
1027 | unregister_inetaddr_notifier(&local->ifa_notifier); | 1064 | unregister_inetaddr_notifier(&local->ifa_notifier); |
1028 | #endif | 1065 | #endif |
1066 | #if IS_ENABLED(CONFIG_IPV6) | ||
1067 | unregister_inet6addr_notifier(&local->ifa6_notifier); | ||
1068 | #endif | ||
1029 | 1069 | ||
1030 | rtnl_lock(); | 1070 | rtnl_lock(); |
1031 | 1071 | ||
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9e0416696a83..81e612682bc3 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -55,30 +55,6 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
55 | sta->plink_retries = 0; | 55 | sta->plink_retries = 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | /* | ||
59 | * Allocate mesh sta entry and insert into station table | ||
60 | */ | ||
61 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | ||
62 | u8 *hw_addr) | ||
63 | { | ||
64 | struct sta_info *sta; | ||
65 | |||
66 | if (sdata->local->num_sta >= MESH_MAX_PLINKS) | ||
67 | return NULL; | ||
68 | |||
69 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); | ||
70 | if (!sta) | ||
71 | return NULL; | ||
72 | |||
73 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
74 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
75 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
76 | |||
77 | set_sta_flag(sta, WLAN_STA_WME); | ||
78 | |||
79 | return sta; | ||
80 | } | ||
81 | |||
82 | /** | 58 | /** |
83 | * mesh_set_ht_prot_mode - set correct HT protection mode | 59 | * mesh_set_ht_prot_mode - set correct HT protection mode |
84 | * | 60 | * |
@@ -309,53 +285,27 @@ free: | |||
309 | return err; | 285 | return err; |
310 | } | 286 | } |
311 | 287 | ||
312 | /** | 288 | static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, |
313 | * mesh_peer_init - initialize new mesh peer and return resulting sta_info | 289 | struct sta_info *sta, |
314 | * | 290 | struct ieee802_11_elems *elems, bool insert) |
315 | * @sdata: local meshif | ||
316 | * @addr: peer's address | ||
317 | * @elems: IEs from beacon or mesh peering frame | ||
318 | * | ||
319 | * call under RCU | ||
320 | */ | ||
321 | static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | ||
322 | u8 *addr, | ||
323 | struct ieee802_11_elems *elems) | ||
324 | { | 291 | { |
325 | struct ieee80211_local *local = sdata->local; | 292 | struct ieee80211_local *local = sdata->local; |
326 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 293 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
327 | struct ieee80211_supported_band *sband; | 294 | struct ieee80211_supported_band *sband; |
328 | u32 rates, basic_rates = 0; | 295 | u32 rates, basic_rates = 0, changed = 0; |
329 | struct sta_info *sta; | ||
330 | bool insert = false; | ||
331 | 296 | ||
332 | sband = local->hw.wiphy->bands[band]; | 297 | sband = local->hw.wiphy->bands[band]; |
333 | rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); | 298 | rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); |
334 | 299 | ||
335 | sta = sta_info_get(sdata, addr); | ||
336 | if (!sta) { | ||
337 | /* Userspace handles peer allocation when security is enabled */ | ||
338 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) { | ||
339 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, | ||
340 | elems->ie_start, | ||
341 | elems->total_len, | ||
342 | GFP_ATOMIC); | ||
343 | return NULL; | ||
344 | } | ||
345 | |||
346 | sta = mesh_plink_alloc(sdata, addr); | ||
347 | if (!sta) | ||
348 | return NULL; | ||
349 | insert = true; | ||
350 | } | ||
351 | |||
352 | spin_lock_bh(&sta->lock); | 300 | spin_lock_bh(&sta->lock); |
353 | sta->last_rx = jiffies; | 301 | sta->last_rx = jiffies; |
354 | if (sta->plink_state == NL80211_PLINK_ESTAB) { | ||
355 | spin_unlock_bh(&sta->lock); | ||
356 | return sta; | ||
357 | } | ||
358 | 302 | ||
303 | /* rates and capabilities don't change during peering */ | ||
304 | if (sta->plink_state == NL80211_PLINK_ESTAB) | ||
305 | goto out; | ||
306 | |||
307 | if (sta->sta.supp_rates[band] != rates) | ||
308 | changed |= IEEE80211_RC_SUPP_RATES_CHANGED; | ||
359 | sta->sta.supp_rates[band] = rates; | 309 | sta->sta.supp_rates[band] = rates; |
360 | if (elems->ht_cap_elem && | 310 | if (elems->ht_cap_elem && |
361 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) | 311 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) |
@@ -374,27 +324,115 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
374 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 324 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
375 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 325 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
376 | elems->ht_operation, &chandef); | 326 | elems->ht_operation, &chandef); |
327 | if (sta->ch_width != chandef.width) | ||
328 | changed |= IEEE80211_RC_BW_CHANGED; | ||
377 | sta->ch_width = chandef.width; | 329 | sta->ch_width = chandef.width; |
378 | } | 330 | } |
379 | 331 | ||
380 | if (insert) | 332 | if (insert) |
381 | rate_control_rate_init(sta); | 333 | rate_control_rate_init(sta); |
334 | else | ||
335 | rate_control_rate_update(local, sband, sta, changed); | ||
336 | out: | ||
382 | spin_unlock_bh(&sta->lock); | 337 | spin_unlock_bh(&sta->lock); |
338 | } | ||
339 | |||
340 | static struct sta_info * | ||
341 | __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) | ||
342 | { | ||
343 | struct sta_info *sta; | ||
383 | 344 | ||
384 | if (insert && sta_info_insert(sta)) | 345 | if (sdata->local->num_sta >= MESH_MAX_PLINKS) |
385 | return NULL; | 346 | return NULL; |
386 | 347 | ||
348 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); | ||
349 | if (!sta) | ||
350 | return NULL; | ||
351 | |||
352 | sta->plink_state = NL80211_PLINK_LISTEN; | ||
353 | init_timer(&sta->plink_timer); | ||
354 | |||
355 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
356 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
357 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
358 | |||
359 | set_sta_flag(sta, WLAN_STA_WME); | ||
360 | |||
361 | return sta; | ||
362 | } | ||
363 | |||
364 | static struct sta_info * | ||
365 | mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, | ||
366 | struct ieee802_11_elems *elems) | ||
367 | { | ||
368 | struct sta_info *sta = NULL; | ||
369 | |||
370 | /* Userspace handles peer allocation when security is enabled */ | ||
371 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | ||
372 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, | ||
373 | elems->ie_start, | ||
374 | elems->total_len, | ||
375 | GFP_KERNEL); | ||
376 | else | ||
377 | sta = __mesh_sta_info_alloc(sdata, addr); | ||
378 | |||
379 | return sta; | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * mesh_sta_info_get - return mesh sta info entry for @addr. | ||
384 | * | ||
385 | * @sdata: local meshif | ||
386 | * @addr: peer's address | ||
387 | * @elems: IEs from beacon or mesh peering frame. | ||
388 | * | ||
389 | * Return existing or newly allocated sta_info under RCU read lock. | ||
390 | * (re)initialize with given IEs. | ||
391 | */ | ||
392 | static struct sta_info * | ||
393 | mesh_sta_info_get(struct ieee80211_sub_if_data *sdata, | ||
394 | u8 *addr, struct ieee802_11_elems *elems) __acquires(RCU) | ||
395 | { | ||
396 | struct sta_info *sta = NULL; | ||
397 | |||
398 | rcu_read_lock(); | ||
399 | sta = sta_info_get(sdata, addr); | ||
400 | if (sta) { | ||
401 | mesh_sta_info_init(sdata, sta, elems, false); | ||
402 | } else { | ||
403 | rcu_read_unlock(); | ||
404 | /* can't run atomic */ | ||
405 | sta = mesh_sta_info_alloc(sdata, addr, elems); | ||
406 | if (!sta) { | ||
407 | rcu_read_lock(); | ||
408 | return NULL; | ||
409 | } | ||
410 | |||
411 | mesh_sta_info_init(sdata, sta, elems, true); | ||
412 | |||
413 | if (sta_info_insert_rcu(sta)) | ||
414 | return NULL; | ||
415 | } | ||
416 | |||
387 | return sta; | 417 | return sta; |
388 | } | 418 | } |
389 | 419 | ||
420 | /* | ||
421 | * mesh_neighbour_update - update or initialize new mesh neighbor. | ||
422 | * | ||
423 | * @sdata: local meshif | ||
424 | * @addr: peer's address | ||
425 | * @elems: IEs from beacon or mesh peering frame | ||
426 | * | ||
427 | * Initiates peering if appropriate. | ||
428 | */ | ||
390 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | 429 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, |
391 | u8 *hw_addr, | 430 | u8 *hw_addr, |
392 | struct ieee802_11_elems *elems) | 431 | struct ieee802_11_elems *elems) |
393 | { | 432 | { |
394 | struct sta_info *sta; | 433 | struct sta_info *sta; |
395 | 434 | ||
396 | rcu_read_lock(); | 435 | sta = mesh_sta_info_get(sdata, hw_addr, elems); |
397 | sta = mesh_peer_init(sdata, hw_addr, elems); | ||
398 | if (!sta) | 436 | if (!sta) |
399 | goto out; | 437 | goto out; |
400 | 438 | ||
@@ -632,6 +670,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
632 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) | 670 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) |
633 | memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); | 671 | memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); |
634 | 672 | ||
673 | /* WARNING: Only for sta pointer, is dropped & re-acquired */ | ||
635 | rcu_read_lock(); | 674 | rcu_read_lock(); |
636 | 675 | ||
637 | sta = sta_info_get(sdata, mgmt->sa); | 676 | sta = sta_info_get(sdata, mgmt->sa); |
@@ -735,8 +774,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
735 | } | 774 | } |
736 | 775 | ||
737 | if (event == OPN_ACPT) { | 776 | if (event == OPN_ACPT) { |
777 | rcu_read_unlock(); | ||
738 | /* allocate sta entry if necessary and update info */ | 778 | /* allocate sta entry if necessary and update info */ |
739 | sta = mesh_peer_init(sdata, mgmt->sa, &elems); | 779 | sta = mesh_sta_info_get(sdata, mgmt->sa, &elems); |
740 | if (!sta) { | 780 | if (!sta) { |
741 | mpl_dbg(sdata, "Mesh plink: failed to init peer!\n"); | 781 | mpl_dbg(sdata, "Mesh plink: failed to init peer!\n"); |
742 | rcu_read_unlock(); | 782 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e930175771ff..5913fb924b12 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1465,10 +1465,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1465 | bss_info_changed |= BSS_CHANGED_CQM; | 1465 | bss_info_changed |= BSS_CHANGED_CQM; |
1466 | 1466 | ||
1467 | /* Enable ARP filtering */ | 1467 | /* Enable ARP filtering */ |
1468 | if (bss_conf->arp_filter_enabled != sdata->arp_filter_state) { | 1468 | if (bss_conf->arp_addr_cnt) |
1469 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | ||
1470 | bss_info_changed |= BSS_CHANGED_ARP_FILTER; | 1469 | bss_info_changed |= BSS_CHANGED_ARP_FILTER; |
1471 | } | ||
1472 | 1470 | ||
1473 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 1471 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
1474 | 1472 | ||
@@ -1489,7 +1487,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1489 | { | 1487 | { |
1490 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1488 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1491 | struct ieee80211_local *local = sdata->local; | 1489 | struct ieee80211_local *local = sdata->local; |
1492 | struct sta_info *sta; | ||
1493 | u32 changed = 0; | 1490 | u32 changed = 0; |
1494 | 1491 | ||
1495 | ASSERT_MGD_MTX(ifmgd); | 1492 | ASSERT_MGD_MTX(ifmgd); |
@@ -1521,14 +1518,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1521 | netif_tx_stop_all_queues(sdata->dev); | 1518 | netif_tx_stop_all_queues(sdata->dev); |
1522 | netif_carrier_off(sdata->dev); | 1519 | netif_carrier_off(sdata->dev); |
1523 | 1520 | ||
1524 | mutex_lock(&local->sta_mtx); | ||
1525 | sta = sta_info_get(sdata, ifmgd->bssid); | ||
1526 | if (sta) { | ||
1527 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | ||
1528 | ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); | ||
1529 | } | ||
1530 | mutex_unlock(&local->sta_mtx); | ||
1531 | |||
1532 | /* | 1521 | /* |
1533 | * if we want to get out of ps before disassoc (why?) we have | 1522 | * if we want to get out of ps before disassoc (why?) we have |
1534 | * to do it before sending disassoc, as otherwise the null-packet | 1523 | * to do it before sending disassoc, as otherwise the null-packet |
@@ -1582,10 +1571,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1582 | cancel_work_sync(&local->dynamic_ps_enable_work); | 1571 | cancel_work_sync(&local->dynamic_ps_enable_work); |
1583 | 1572 | ||
1584 | /* Disable ARP filtering */ | 1573 | /* Disable ARP filtering */ |
1585 | if (sdata->vif.bss_conf.arp_filter_enabled) { | 1574 | if (sdata->vif.bss_conf.arp_addr_cnt) |
1586 | sdata->vif.bss_conf.arp_filter_enabled = false; | ||
1587 | changed |= BSS_CHANGED_ARP_FILTER; | 1575 | changed |= BSS_CHANGED_ARP_FILTER; |
1588 | } | ||
1589 | 1576 | ||
1590 | sdata->vif.bss_conf.qos = false; | 1577 | sdata->vif.bss_conf.qos = false; |
1591 | changed |= BSS_CHANGED_QOS; | 1578 | changed |= BSS_CHANGED_QOS; |
@@ -2608,12 +2595,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2608 | if (sig > ifmgd->rssi_max_thold && | 2595 | if (sig > ifmgd->rssi_max_thold && |
2609 | (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { | 2596 | (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { |
2610 | ifmgd->last_ave_beacon_signal = sig; | 2597 | ifmgd->last_ave_beacon_signal = sig; |
2611 | drv_rssi_callback(local, RSSI_EVENT_HIGH); | 2598 | drv_rssi_callback(local, sdata, RSSI_EVENT_HIGH); |
2612 | } else if (sig < ifmgd->rssi_min_thold && | 2599 | } else if (sig < ifmgd->rssi_min_thold && |
2613 | (last_sig >= ifmgd->rssi_max_thold || | 2600 | (last_sig >= ifmgd->rssi_max_thold || |
2614 | last_sig == 0)) { | 2601 | last_sig == 0)) { |
2615 | ifmgd->last_ave_beacon_signal = sig; | 2602 | ifmgd->last_ave_beacon_signal = sig; |
2616 | drv_rssi_callback(local, RSSI_EVENT_LOW); | 2603 | drv_rssi_callback(local, sdata, RSSI_EVENT_LOW); |
2617 | } | 2604 | } |
2618 | } | 2605 | } |
2619 | 2606 | ||
@@ -3169,23 +3156,22 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
3169 | { | 3156 | { |
3170 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3157 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3171 | 3158 | ||
3172 | if (!ifmgd->associated) | 3159 | mutex_lock(&ifmgd->mtx); |
3160 | if (!ifmgd->associated) { | ||
3161 | mutex_unlock(&ifmgd->mtx); | ||
3173 | return; | 3162 | return; |
3163 | } | ||
3174 | 3164 | ||
3175 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | 3165 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { |
3176 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | 3166 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; |
3177 | mutex_lock(&ifmgd->mtx); | 3167 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); |
3178 | if (ifmgd->associated) { | 3168 | ieee80211_sta_connection_lost(sdata, |
3179 | mlme_dbg(sdata, | 3169 | ifmgd->associated->bssid, |
3180 | "driver requested disconnect after resume\n"); | 3170 | WLAN_REASON_UNSPECIFIED); |
3181 | ieee80211_sta_connection_lost(sdata, | ||
3182 | ifmgd->associated->bssid, | ||
3183 | WLAN_REASON_UNSPECIFIED); | ||
3184 | mutex_unlock(&ifmgd->mtx); | ||
3185 | return; | ||
3186 | } | ||
3187 | mutex_unlock(&ifmgd->mtx); | 3171 | mutex_unlock(&ifmgd->mtx); |
3172 | return; | ||
3188 | } | 3173 | } |
3174 | mutex_unlock(&ifmgd->mtx); | ||
3189 | 3175 | ||
3190 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | 3176 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) |
3191 | add_timer(&ifmgd->timer); | 3177 | add_timer(&ifmgd->timer); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 9d864ed5f3da..227233c3ff7f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -380,11 +380,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
380 | 380 | ||
381 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); | 381 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); |
382 | 382 | ||
383 | #ifdef CONFIG_MAC80211_MESH | ||
384 | sta->plink_state = NL80211_PLINK_LISTEN; | ||
385 | init_timer(&sta->plink_timer); | ||
386 | #endif | ||
387 | |||
388 | return sta; | 383 | return sta; |
389 | } | 384 | } |
390 | 385 | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 41861b91daa3..6ca53d64cb28 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -347,8 +347,11 @@ TRACE_EVENT(drv_bss_info_changed, | |||
347 | __field(s32, cqm_rssi_hyst); | 347 | __field(s32, cqm_rssi_hyst); |
348 | __field(u32, channel_width); | 348 | __field(u32, channel_width); |
349 | __field(u32, channel_cfreq1); | 349 | __field(u32, channel_cfreq1); |
350 | __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); | 350 | __dynamic_array(u32, arp_addr_list, |
351 | __field(bool, arp_filter_enabled); | 351 | info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ? |
352 | IEEE80211_BSS_ARP_ADDR_LIST_LEN : | ||
353 | info->arp_addr_cnt); | ||
354 | __field(int, arp_addr_cnt); | ||
352 | __field(bool, qos); | 355 | __field(bool, qos); |
353 | __field(bool, idle); | 356 | __field(bool, idle); |
354 | __field(bool, ps); | 357 | __field(bool, ps); |
@@ -384,9 +387,11 @@ TRACE_EVENT(drv_bss_info_changed, | |||
384 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; | 387 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; |
385 | __entry->channel_width = info->chandef.width; | 388 | __entry->channel_width = info->chandef.width; |
386 | __entry->channel_cfreq1 = info->chandef.center_freq1; | 389 | __entry->channel_cfreq1 = info->chandef.center_freq1; |
390 | __entry->arp_addr_cnt = info->arp_addr_cnt; | ||
387 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, | 391 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, |
388 | sizeof(u32) * info->arp_addr_cnt); | 392 | sizeof(u32) * (info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ? |
389 | __entry->arp_filter_enabled = info->arp_filter_enabled; | 393 | IEEE80211_BSS_ARP_ADDR_LIST_LEN : |
394 | info->arp_addr_cnt)); | ||
390 | __entry->qos = info->qos; | 395 | __entry->qos = info->qos; |
391 | __entry->idle = info->idle; | 396 | __entry->idle = info->idle; |
392 | __entry->ps = info->ps; | 397 | __entry->ps = info->ps; |
@@ -1184,23 +1189,26 @@ TRACE_EVENT(drv_set_rekey_data, | |||
1184 | 1189 | ||
1185 | TRACE_EVENT(drv_rssi_callback, | 1190 | TRACE_EVENT(drv_rssi_callback, |
1186 | TP_PROTO(struct ieee80211_local *local, | 1191 | TP_PROTO(struct ieee80211_local *local, |
1192 | struct ieee80211_sub_if_data *sdata, | ||
1187 | enum ieee80211_rssi_event rssi_event), | 1193 | enum ieee80211_rssi_event rssi_event), |
1188 | 1194 | ||
1189 | TP_ARGS(local, rssi_event), | 1195 | TP_ARGS(local, sdata, rssi_event), |
1190 | 1196 | ||
1191 | TP_STRUCT__entry( | 1197 | TP_STRUCT__entry( |
1192 | LOCAL_ENTRY | 1198 | LOCAL_ENTRY |
1199 | VIF_ENTRY | ||
1193 | __field(u32, rssi_event) | 1200 | __field(u32, rssi_event) |
1194 | ), | 1201 | ), |
1195 | 1202 | ||
1196 | TP_fast_assign( | 1203 | TP_fast_assign( |
1197 | LOCAL_ASSIGN; | 1204 | LOCAL_ASSIGN; |
1205 | VIF_ASSIGN; | ||
1198 | __entry->rssi_event = rssi_event; | 1206 | __entry->rssi_event = rssi_event; |
1199 | ), | 1207 | ), |
1200 | 1208 | ||
1201 | TP_printk( | 1209 | TP_printk( |
1202 | LOCAL_PR_FMT " rssi_event:%d", | 1210 | LOCAL_PR_FMT VIF_PR_FMT " rssi_event:%d", |
1203 | LOCAL_PR_ARG, __entry->rssi_event | 1211 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->rssi_event |
1204 | ) | 1212 | ) |
1205 | ); | 1213 | ); |
1206 | 1214 | ||
@@ -1432,6 +1440,14 @@ DEFINE_EVENT(local_only_evt, drv_restart_complete, | |||
1432 | TP_ARGS(local) | 1440 | TP_ARGS(local) |
1433 | ); | 1441 | ); |
1434 | 1442 | ||
1443 | #if IS_ENABLED(CONFIG_IPV6) | ||
1444 | DEFINE_EVENT(local_sdata_evt, drv_ipv6_addr_change, | ||
1445 | TP_PROTO(struct ieee80211_local *local, | ||
1446 | struct ieee80211_sub_if_data *sdata), | ||
1447 | TP_ARGS(local, sdata) | ||
1448 | ); | ||
1449 | #endif | ||
1450 | |||
1435 | /* | 1451 | /* |
1436 | * Tracing for API calls that drivers call. | 1452 | * Tracing for API calls that drivers call. |
1437 | */ | 1453 | */ |
@@ -1821,6 +1837,29 @@ TRACE_EVENT(stop_queue, | |||
1821 | ) | 1837 | ) |
1822 | ); | 1838 | ); |
1823 | 1839 | ||
1840 | TRACE_EVENT(drv_set_default_unicast_key, | ||
1841 | TP_PROTO(struct ieee80211_local *local, | ||
1842 | struct ieee80211_sub_if_data *sdata, | ||
1843 | int key_idx), | ||
1844 | |||
1845 | TP_ARGS(local, sdata, key_idx), | ||
1846 | |||
1847 | TP_STRUCT__entry( | ||
1848 | LOCAL_ENTRY | ||
1849 | VIF_ENTRY | ||
1850 | __field(int, key_idx) | ||
1851 | ), | ||
1852 | |||
1853 | TP_fast_assign( | ||
1854 | LOCAL_ASSIGN; | ||
1855 | VIF_ASSIGN; | ||
1856 | __entry->key_idx = key_idx; | ||
1857 | ), | ||
1858 | |||
1859 | TP_printk(LOCAL_PR_FMT VIF_PR_FMT " key_idx:%d", | ||
1860 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->key_idx) | ||
1861 | ); | ||
1862 | |||
1824 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING | 1863 | #ifdef CONFIG_MAC80211_MESSAGE_TRACING |
1825 | #undef TRACE_SYSTEM | 1864 | #undef TRACE_SYSTEM |
1826 | #define TRACE_SYSTEM mac80211_msg | 1865 | #define TRACE_SYSTEM mac80211_msg |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f32d68186dbc..a2cb6a302cc7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1787,16 +1787,16 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1787 | break; | 1787 | break; |
1788 | /* fall through */ | 1788 | /* fall through */ |
1789 | case NL80211_IFTYPE_AP: | 1789 | case NL80211_IFTYPE_AP: |
1790 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1791 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1792 | if (!chanctx_conf) | ||
1793 | goto fail_rcu; | ||
1790 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1794 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1791 | /* DA BSSID SA */ | 1795 | /* DA BSSID SA */ |
1792 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1796 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1793 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); | 1797 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1794 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1798 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1795 | hdrlen = 24; | 1799 | hdrlen = 24; |
1796 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1797 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1798 | if (!chanctx_conf) | ||
1799 | goto fail_rcu; | ||
1800 | band = chanctx_conf->def.chan->band; | 1800 | band = chanctx_conf->def.chan->band; |
1801 | break; | 1801 | break; |
1802 | case NL80211_IFTYPE_WDS: | 1802 | case NL80211_IFTYPE_WDS: |