diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 23 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 34 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 52 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 22 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 18 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 17 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 14 | ||||
-rw-r--r-- | net/mac80211/pm.c | 10 | ||||
-rw-r--r-- | net/mac80211/rx.c | 4 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 731 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 32 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 16 |
13 files changed, 511 insertions, 464 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index facf233843e0..a362523d8eb7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -747,9 +747,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
747 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 747 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
748 | sdata->vif.type == NL80211_IFTYPE_AP; | 748 | sdata->vif.type == NL80211_IFTYPE_AP; |
749 | 749 | ||
750 | rcu_read_lock(); | 750 | err = sta_info_insert_rcu(sta); |
751 | |||
752 | err = sta_info_insert(sta); | ||
753 | if (err) { | 751 | if (err) { |
754 | rcu_read_unlock(); | 752 | rcu_read_unlock(); |
755 | return err; | 753 | return err; |
@@ -768,26 +766,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
768 | { | 766 | { |
769 | struct ieee80211_local *local = wiphy_priv(wiphy); | 767 | struct ieee80211_local *local = wiphy_priv(wiphy); |
770 | struct ieee80211_sub_if_data *sdata; | 768 | struct ieee80211_sub_if_data *sdata; |
771 | struct sta_info *sta; | ||
772 | 769 | ||
773 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 770 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
774 | 771 | ||
775 | if (mac) { | 772 | if (mac) |
776 | rcu_read_lock(); | 773 | return sta_info_destroy_addr_bss(sdata, mac); |
777 | |||
778 | sta = sta_info_get_bss(sdata, mac); | ||
779 | if (!sta) { | ||
780 | rcu_read_unlock(); | ||
781 | return -ENOENT; | ||
782 | } | ||
783 | |||
784 | sta_info_unlink(&sta); | ||
785 | rcu_read_unlock(); | ||
786 | |||
787 | sta_info_destroy(sta); | ||
788 | } else | ||
789 | sta_info_flush(local, sdata); | ||
790 | 774 | ||
775 | sta_info_flush(local, sdata); | ||
791 | return 0; | 776 | return 0; |
792 | } | 777 | } |
793 | 778 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6c31f38ac7f5..855e85b55061 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -243,6 +243,40 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
243 | trace_drv_sta_notify(local, sdata, cmd, sta); | 243 | trace_drv_sta_notify(local, sdata, cmd, sta); |
244 | } | 244 | } |
245 | 245 | ||
246 | static inline int drv_sta_add(struct ieee80211_local *local, | ||
247 | struct ieee80211_sub_if_data *sdata, | ||
248 | struct ieee80211_sta *sta) | ||
249 | { | ||
250 | int ret = 0; | ||
251 | |||
252 | might_sleep(); | ||
253 | |||
254 | if (local->ops->sta_add) | ||
255 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | ||
256 | else if (local->ops->sta_notify) | ||
257 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
258 | STA_NOTIFY_ADD, sta); | ||
259 | |||
260 | trace_drv_sta_add(local, sdata, sta, ret); | ||
261 | |||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static inline void drv_sta_remove(struct ieee80211_local *local, | ||
266 | struct ieee80211_sub_if_data *sdata, | ||
267 | struct ieee80211_sta *sta) | ||
268 | { | ||
269 | might_sleep(); | ||
270 | |||
271 | if (local->ops->sta_remove) | ||
272 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | ||
273 | else if (local->ops->sta_notify) | ||
274 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
275 | STA_NOTIFY_REMOVE, sta); | ||
276 | |||
277 | trace_drv_sta_remove(local, sdata, sta); | ||
278 | } | ||
279 | |||
246 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 280 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
247 | const struct ieee80211_tx_queue_params *params) | 281 | const struct ieee80211_tx_queue_params *params) |
248 | { | 282 | { |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 502424b2538a..c984910bf275 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -545,6 +545,58 @@ TRACE_EVENT(drv_sta_notify, | |||
545 | ) | 545 | ) |
546 | ); | 546 | ); |
547 | 547 | ||
548 | TRACE_EVENT(drv_sta_add, | ||
549 | TP_PROTO(struct ieee80211_local *local, | ||
550 | struct ieee80211_sub_if_data *sdata, | ||
551 | struct ieee80211_sta *sta, int ret), | ||
552 | |||
553 | TP_ARGS(local, sdata, sta, ret), | ||
554 | |||
555 | TP_STRUCT__entry( | ||
556 | LOCAL_ENTRY | ||
557 | VIF_ENTRY | ||
558 | STA_ENTRY | ||
559 | __field(int, ret) | ||
560 | ), | ||
561 | |||
562 | TP_fast_assign( | ||
563 | LOCAL_ASSIGN; | ||
564 | VIF_ASSIGN; | ||
565 | STA_ASSIGN; | ||
566 | __entry->ret = ret; | ||
567 | ), | ||
568 | |||
569 | TP_printk( | ||
570 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", | ||
571 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret | ||
572 | ) | ||
573 | ); | ||
574 | |||
575 | TRACE_EVENT(drv_sta_remove, | ||
576 | TP_PROTO(struct ieee80211_local *local, | ||
577 | struct ieee80211_sub_if_data *sdata, | ||
578 | struct ieee80211_sta *sta), | ||
579 | |||
580 | TP_ARGS(local, sdata, sta), | ||
581 | |||
582 | TP_STRUCT__entry( | ||
583 | LOCAL_ENTRY | ||
584 | VIF_ENTRY | ||
585 | STA_ENTRY | ||
586 | ), | ||
587 | |||
588 | TP_fast_assign( | ||
589 | LOCAL_ASSIGN; | ||
590 | VIF_ASSIGN; | ||
591 | STA_ASSIGN; | ||
592 | ), | ||
593 | |||
594 | TP_printk( | ||
595 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, | ||
596 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG | ||
597 | ) | ||
598 | ); | ||
599 | |||
548 | TRACE_EVENT(drv_conf_tx, | 600 | TRACE_EVENT(drv_conf_tx, |
549 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 601 | TP_PROTO(struct ieee80211_local *local, u16 queue, |
550 | const struct ieee80211_tx_queue_params *params, | 602 | const struct ieee80211_tx_queue_params *params, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 85c4ba14c77d..f3e942486749 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -275,10 +275,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
275 | (unsigned long long) supp_rates, | 275 | (unsigned long long) supp_rates, |
276 | (unsigned long long) sta->sta.supp_rates[band]); | 276 | (unsigned long long) sta->sta.supp_rates[band]); |
277 | #endif | 277 | #endif |
278 | } else | 278 | rcu_read_unlock(); |
279 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 279 | } else { |
280 | 280 | rcu_read_unlock(); | |
281 | rcu_read_unlock(); | 281 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
282 | supp_rates, GFP_KERNEL); | ||
283 | } | ||
282 | } | 284 | } |
283 | 285 | ||
284 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 286 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
@@ -368,7 +370,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
368 | sdata->name, mgmt->bssid); | 370 | sdata->name, mgmt->bssid); |
369 | #endif | 371 | #endif |
370 | ieee80211_sta_join_ibss(sdata, bss); | 372 | ieee80211_sta_join_ibss(sdata, bss); |
371 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 373 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
374 | supp_rates, GFP_KERNEL); | ||
372 | } | 375 | } |
373 | 376 | ||
374 | put_bss: | 377 | put_bss: |
@@ -381,7 +384,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
381 | * must be callable in atomic context. | 384 | * must be callable in atomic context. |
382 | */ | 385 | */ |
383 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 386 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
384 | u8 *bssid,u8 *addr, u32 supp_rates) | 387 | u8 *bssid,u8 *addr, u32 supp_rates, |
388 | gfp_t gfp) | ||
385 | { | 389 | { |
386 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 390 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
387 | struct ieee80211_local *local = sdata->local; | 391 | struct ieee80211_local *local = sdata->local; |
@@ -410,7 +414,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
410 | wiphy_name(local->hw.wiphy), addr, sdata->name); | 414 | wiphy_name(local->hw.wiphy), addr, sdata->name); |
411 | #endif | 415 | #endif |
412 | 416 | ||
413 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 417 | sta = sta_info_alloc(sdata, addr, gfp); |
414 | if (!sta) | 418 | if (!sta) |
415 | return NULL; | 419 | return NULL; |
416 | 420 | ||
@@ -422,9 +426,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
422 | 426 | ||
423 | rate_control_rate_init(sta); | 427 | rate_control_rate_init(sta); |
424 | 428 | ||
429 | /* If it fails, maybe we raced another insertion? */ | ||
425 | if (sta_info_insert(sta)) | 430 | if (sta_info_insert(sta)) |
426 | return NULL; | 431 | return sta_info_get(sdata, addr); |
427 | |||
428 | return sta; | 432 | return sta; |
429 | } | 433 | } |
430 | 434 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3067fbd69d63..a5911191f224 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -688,15 +688,18 @@ struct ieee80211_local { | |||
688 | 688 | ||
689 | /* Station data */ | 689 | /* Station data */ |
690 | /* | 690 | /* |
691 | * The lock only protects the list, hash, timer and counter | 691 | * The mutex only protects the list and counter, |
692 | * against manipulation, reads are done in RCU. Additionally, | 692 | * reads are done in RCU. |
693 | * the lock protects each BSS's TIM bitmap. | 693 | * Additionally, the lock protects the hash table, |
694 | * the pending list and each BSS's TIM bitmap. | ||
694 | */ | 695 | */ |
696 | struct mutex sta_mtx; | ||
695 | spinlock_t sta_lock; | 697 | spinlock_t sta_lock; |
696 | unsigned long num_sta; | 698 | unsigned long num_sta; |
697 | struct list_head sta_list; | 699 | struct list_head sta_list, sta_pending_list; |
698 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 700 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
699 | struct timer_list sta_cleanup; | 701 | struct timer_list sta_cleanup; |
702 | struct work_struct sta_finish_work; | ||
700 | int sta_generation; | 703 | int sta_generation; |
701 | 704 | ||
702 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 705 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
@@ -770,10 +773,6 @@ struct ieee80211_local { | |||
770 | assoc_led_name[32], radio_led_name[32]; | 773 | assoc_led_name[32], radio_led_name[32]; |
771 | #endif | 774 | #endif |
772 | 775 | ||
773 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
774 | struct work_struct sta_debugfs_add; | ||
775 | #endif | ||
776 | |||
777 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 776 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
778 | /* TX/RX handler statistics */ | 777 | /* TX/RX handler statistics */ |
779 | unsigned int tx_handlers_drop; | 778 | unsigned int tx_handlers_drop; |
@@ -985,7 +984,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | |||
985 | ieee80211_rx_result | 984 | ieee80211_rx_result |
986 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 985 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
987 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 986 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
988 | u8 *bssid, u8 *addr, u32 supp_rates); | 987 | u8 *bssid, u8 *addr, u32 supp_rates, |
988 | gfp_t gfp); | ||
989 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 989 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
990 | struct cfg80211_ibss_params *params); | 990 | struct cfg80211_ibss_params *params); |
991 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 991 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7985e5150898..bc4e20e57ff5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
102 | if (local->num_sta >= MESH_MAX_PLINKS) | 102 | if (local->num_sta >= MESH_MAX_PLINKS) |
103 | return NULL; | 103 | return NULL; |
104 | 104 | ||
105 | sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); | 105 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); |
106 | if (!sta) | 106 | if (!sta) |
107 | return NULL; | 107 | return NULL; |
108 | 108 | ||
@@ -236,12 +236,12 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
236 | 236 | ||
237 | sta = sta_info_get(sdata, hw_addr); | 237 | sta = sta_info_get(sdata, hw_addr); |
238 | if (!sta) { | 238 | if (!sta) { |
239 | rcu_read_unlock(); | ||
240 | |||
239 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 241 | sta = mesh_plink_alloc(sdata, hw_addr, rates); |
240 | if (!sta) { | 242 | if (!sta) |
241 | rcu_read_unlock(); | ||
242 | return; | 243 | return; |
243 | } | 244 | if (sta_info_insert_rcu(sta)) { |
244 | if (sta_info_insert(sta)) { | ||
245 | rcu_read_unlock(); | 245 | rcu_read_unlock(); |
246 | return; | 246 | return; |
247 | } | 247 | } |
@@ -485,9 +485,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
485 | } else if (!sta) { | 485 | } else if (!sta) { |
486 | /* ftype == PLINK_OPEN */ | 486 | /* ftype == PLINK_OPEN */ |
487 | u32 rates; | 487 | u32 rates; |
488 | |||
489 | rcu_read_unlock(); | ||
490 | |||
488 | if (!mesh_plink_free_count(sdata)) { | 491 | if (!mesh_plink_free_count(sdata)) { |
489 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 492 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
490 | rcu_read_unlock(); | ||
491 | return; | 493 | return; |
492 | } | 494 | } |
493 | 495 | ||
@@ -495,10 +497,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
495 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 497 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); |
496 | if (!sta) { | 498 | if (!sta) { |
497 | mpl_dbg("Mesh plink error: plink table full\n"); | 499 | mpl_dbg("Mesh plink error: plink table full\n"); |
498 | rcu_read_unlock(); | ||
499 | return; | 500 | return; |
500 | } | 501 | } |
501 | if (sta_info_insert(sta)) { | 502 | if (sta_info_insert_rcu(sta)) { |
502 | rcu_read_unlock(); | 503 | rcu_read_unlock(); |
503 | return; | 504 | return; |
504 | } | 505 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f437284830ef..ac9429e8d72b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -822,19 +822,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
822 | changed |= BSS_CHANGED_BSSID; | 822 | changed |= BSS_CHANGED_BSSID; |
823 | ieee80211_bss_info_change_notify(sdata, changed); | 823 | ieee80211_bss_info_change_notify(sdata, changed); |
824 | 824 | ||
825 | rcu_read_lock(); | 825 | sta_info_destroy_addr(sdata, bssid); |
826 | |||
827 | sta = sta_info_get(sdata, bssid); | ||
828 | if (!sta) { | ||
829 | rcu_read_unlock(); | ||
830 | return; | ||
831 | } | ||
832 | |||
833 | sta_info_unlink(&sta); | ||
834 | |||
835 | rcu_read_unlock(); | ||
836 | |||
837 | sta_info_destroy(sta); | ||
838 | } | 826 | } |
839 | 827 | ||
840 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 828 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 47f818959ad7..0e64484e861c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -11,7 +11,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 13 | struct sta_info *sta; |
14 | unsigned long flags; | ||
15 | 14 | ||
16 | ieee80211_scan_cancel(local); | 15 | ieee80211_scan_cancel(local); |
17 | 16 | ||
@@ -55,22 +54,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
55 | rcu_read_unlock(); | 54 | rcu_read_unlock(); |
56 | 55 | ||
57 | /* remove STAs */ | 56 | /* remove STAs */ |
58 | spin_lock_irqsave(&local->sta_lock, flags); | 57 | mutex_lock(&local->sta_mtx); |
59 | list_for_each_entry(sta, &local->sta_list, list) { | 58 | list_for_each_entry(sta, &local->sta_list, list) { |
60 | if (local->ops->sta_notify) { | 59 | if (sta->uploaded) { |
61 | sdata = sta->sdata; | 60 | sdata = sta->sdata; |
62 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 61 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
63 | sdata = container_of(sdata->bss, | 62 | sdata = container_of(sdata->bss, |
64 | struct ieee80211_sub_if_data, | 63 | struct ieee80211_sub_if_data, |
65 | u.ap); | 64 | u.ap); |
66 | 65 | ||
67 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, | 66 | drv_sta_remove(local, sdata, &sta->sta); |
68 | &sta->sta); | ||
69 | } | 67 | } |
70 | 68 | ||
71 | mesh_plink_quiesce(sta); | 69 | mesh_plink_quiesce(sta); |
72 | } | 70 | } |
73 | spin_unlock_irqrestore(&local->sta_lock, flags); | 71 | mutex_unlock(&local->sta_mtx); |
74 | 72 | ||
75 | /* remove all interfaces */ | 73 | /* remove all interfaces */ |
76 | list_for_each_entry(sdata, &local->interfaces, list) { | 74 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5709307fcb9b..01dba7618397 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2244,8 +2244,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2244 | rate_idx = 0; /* TODO: HT rates */ | 2244 | rate_idx = 0; /* TODO: HT rates */ |
2245 | else | 2245 | else |
2246 | rate_idx = status->rate_idx; | 2246 | rate_idx = status->rate_idx; |
2247 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 2247 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, |
2248 | BIT(rate_idx)); | 2248 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); |
2249 | } | 2249 | } |
2250 | break; | 2250 | break; |
2251 | case NL80211_IFTYPE_MESH_POINT: | 2251 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f735826f055c..211c475f73c6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -32,49 +32,33 @@ | |||
32 | * for faster lookup and a list for iteration. They are managed using | 32 | * for faster lookup and a list for iteration. They are managed using |
33 | * RCU, i.e. access to the list and hash table is protected by RCU. | 33 | * RCU, i.e. access to the list and hash table is protected by RCU. |
34 | * | 34 | * |
35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller owns | 35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller |
36 | * that structure. It must then either destroy it using sta_info_destroy() | 36 | * owns that structure. It must then insert it into the hash table using |
37 | * (which is pretty useless) or insert it into the hash table using | 37 | * either sta_info_insert() or sta_info_insert_rcu(); only in the latter |
38 | * sta_info_insert() which demotes the reference from ownership to a regular | 38 | * case (which acquires an rcu read section but must not be called from |
39 | * RCU-protected reference; if the function is called without protection by an | 39 | * within one) will the pointer still be valid after the call. Note that |
40 | * RCU critical section the reference is instantly invalidated. Note that the | 40 | * the caller may not do much with the STA info before inserting it, in |
41 | * caller may not do much with the STA info before inserting it, in particular, | 41 | * particular, it may not start any mesh peer link management or add |
42 | * it may not start any mesh peer link management or add encryption keys. | 42 | * encryption keys. |
43 | * | 43 | * |
44 | * When the insertion fails (sta_info_insert()) returns non-zero), the | 44 | * When the insertion fails (sta_info_insert()) returns non-zero), the |
45 | * structure will have been freed by sta_info_insert()! | 45 | * structure will have been freed by sta_info_insert()! |
46 | * | 46 | * |
47 | * sta entries are added by mac80211 when you establish a link with a | 47 | * Station entries are added by mac80211 when you establish a link with a |
48 | * peer. This means different things for the different type of interfaces | 48 | * peer. This means different things for the different type of interfaces |
49 | * we support. For a regular station this mean we add the AP sta when we | 49 | * we support. For a regular station this mean we add the AP sta when we |
50 | * receive an assocation response from the AP. For IBSS this occurs when | 50 | * receive an assocation response from the AP. For IBSS this occurs when |
51 | * we receive a probe response or a beacon from target IBSS network. For | 51 | * get to know about a peer on the same IBSS. For WDS we add the sta for |
52 | * WDS we add the sta for the peer imediately upon device open. When using | 52 | * the peer imediately upon device open. When using AP mode we add stations |
53 | * AP mode we add stations for each respective station upon request from | 53 | * for each respective station upon request from userspace through nl80211. |
54 | * userspace through nl80211. | ||
55 | * | 54 | * |
56 | * Because there are debugfs entries for each station, and adding those | 55 | * In order to remove a STA info structure, various sta_info_destroy_*() |
57 | * must be able to sleep, it is also possible to "pin" a station entry, | 56 | * calls are available. |
58 | * that means it can be removed from the hash table but not be freed. | ||
59 | * See the comment in __sta_info_unlink() for more information, this is | ||
60 | * an internal capability only. | ||
61 | * | 57 | * |
62 | * In order to remove a STA info structure, the caller needs to first | 58 | * There is no concept of ownership on a STA entry, each structure is |
63 | * unlink it (sta_info_unlink()) from the list and hash tables and | 59 | * owned by the global hash table/list until it is removed. All users of |
64 | * then destroy it; sta_info_destroy() will wait for an RCU grace period | 60 | * the structure need to be RCU protected so that the structure won't be |
65 | * to elapse before actually freeing it. Due to the pinning and the | 61 | * freed before they are done using it. |
66 | * possibility of multiple callers trying to remove the same STA info at | ||
67 | * the same time, sta_info_unlink() can clear the STA info pointer it is | ||
68 | * passed to indicate that the STA info is owned by somebody else now. | ||
69 | * | ||
70 | * If sta_info_unlink() did not clear the pointer then the caller owns | ||
71 | * the STA info structure now and is responsible of destroying it with | ||
72 | * a call to sta_info_destroy(). | ||
73 | * | ||
74 | * In all other cases, there is no concept of ownership on a STA entry, | ||
75 | * each structure is owned by the global hash table/list until it is | ||
76 | * removed. All users of the structure need to be RCU protected so that | ||
77 | * the structure won't be freed before they are done using it. | ||
78 | */ | 62 | */ |
79 | 63 | ||
80 | /* Caller must hold local->sta_lock */ | 64 | /* Caller must hold local->sta_lock */ |
@@ -185,101 +169,6 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
185 | kfree(sta); | 169 | kfree(sta); |
186 | } | 170 | } |
187 | 171 | ||
188 | void sta_info_destroy(struct sta_info *sta) | ||
189 | { | ||
190 | struct ieee80211_local *local; | ||
191 | struct sk_buff *skb; | ||
192 | int i; | ||
193 | |||
194 | might_sleep(); | ||
195 | |||
196 | if (!sta) | ||
197 | return; | ||
198 | |||
199 | local = sta->local; | ||
200 | |||
201 | cancel_work_sync(&sta->drv_unblock_wk); | ||
202 | |||
203 | rate_control_remove_sta_debugfs(sta); | ||
204 | ieee80211_sta_debugfs_remove(sta); | ||
205 | |||
206 | #ifdef CONFIG_MAC80211_MESH | ||
207 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
208 | mesh_plink_deactivate(sta); | ||
209 | #endif | ||
210 | |||
211 | /* | ||
212 | * We have only unlinked the key, and actually destroying it | ||
213 | * may mean it is removed from hardware which requires that | ||
214 | * the key->sta pointer is still valid, so flush the key todo | ||
215 | * list here. | ||
216 | * | ||
217 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
218 | * nothing can reference this sta struct any more. | ||
219 | */ | ||
220 | ieee80211_key_todo(); | ||
221 | |||
222 | #ifdef CONFIG_MAC80211_MESH | ||
223 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
224 | del_timer_sync(&sta->plink_timer); | ||
225 | #endif | ||
226 | |||
227 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
228 | local->total_ps_buffered--; | ||
229 | dev_kfree_skb_any(skb); | ||
230 | } | ||
231 | |||
232 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
233 | dev_kfree_skb_any(skb); | ||
234 | |||
235 | for (i = 0; i < STA_TID_NUM; i++) { | ||
236 | struct tid_ampdu_rx *tid_rx; | ||
237 | struct tid_ampdu_tx *tid_tx; | ||
238 | |||
239 | spin_lock_bh(&sta->lock); | ||
240 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
241 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
242 | if (tid_rx) | ||
243 | tid_rx->shutdown = true; | ||
244 | |||
245 | spin_unlock_bh(&sta->lock); | ||
246 | |||
247 | /* | ||
248 | * Outside spinlock - shutdown is true now so that the timer | ||
249 | * won't free tid_rx, we have to do that now. Can't let the | ||
250 | * timer do it because we have to sync the timer outside the | ||
251 | * lock that it takes itself. | ||
252 | */ | ||
253 | if (tid_rx) { | ||
254 | del_timer_sync(&tid_rx->session_timer); | ||
255 | kfree(tid_rx); | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * No need to do such complications for TX agg sessions, the | ||
260 | * path leading to freeing the tid_tx struct goes via a call | ||
261 | * from the driver, and thus needs to look up the sta struct | ||
262 | * again, which cannot be found when we get here. Hence, we | ||
263 | * just need to delete the timer and free the aggregation | ||
264 | * info; we won't be telling the peer about it then but that | ||
265 | * doesn't matter if we're not talking to it again anyway. | ||
266 | */ | ||
267 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
268 | if (tid_tx) { | ||
269 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
270 | /* | ||
271 | * STA removed while aggregation session being | ||
272 | * started? Bit odd, but purge frames anyway. | ||
273 | */ | ||
274 | skb_queue_purge(&tid_tx->pending); | ||
275 | kfree(tid_tx); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | __sta_info_free(local, sta); | ||
280 | } | ||
281 | |||
282 | |||
283 | /* Caller must hold local->sta_lock */ | 172 | /* Caller must hold local->sta_lock */ |
284 | static void sta_info_hash_add(struct ieee80211_local *local, | 173 | static void sta_info_hash_add(struct ieee80211_local *local, |
285 | struct sta_info *sta) | 174 | struct sta_info *sta) |
@@ -376,7 +265,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
376 | return sta; | 265 | return sta; |
377 | } | 266 | } |
378 | 267 | ||
379 | int sta_info_insert(struct sta_info *sta) | 268 | static int sta_info_finish_insert(struct sta_info *sta, bool async) |
380 | { | 269 | { |
381 | struct ieee80211_local *local = sta->local; | 270 | struct ieee80211_local *local = sta->local; |
382 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 271 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -384,6 +273,91 @@ int sta_info_insert(struct sta_info *sta) | |||
384 | unsigned long flags; | 273 | unsigned long flags; |
385 | int err = 0; | 274 | int err = 0; |
386 | 275 | ||
276 | WARN_ON(!mutex_is_locked(&local->sta_mtx)); | ||
277 | |||
278 | /* notify driver */ | ||
279 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
280 | sdata = container_of(sdata->bss, | ||
281 | struct ieee80211_sub_if_data, | ||
282 | u.ap); | ||
283 | err = drv_sta_add(local, sdata, &sta->sta); | ||
284 | if (err) { | ||
285 | if (!async) | ||
286 | return err; | ||
287 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" | ||
288 | " - keeping it anyway.\n", | ||
289 | sdata->name, sta->sta.addr, err); | ||
290 | } else { | ||
291 | sta->uploaded = true; | ||
292 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
293 | if (async) | ||
294 | printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", | ||
295 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
296 | #endif | ||
297 | } | ||
298 | |||
299 | sdata = sta->sdata; | ||
300 | |||
301 | if (!async) { | ||
302 | local->num_sta++; | ||
303 | local->sta_generation++; | ||
304 | smp_mb(); | ||
305 | |||
306 | /* make the station visible */ | ||
307 | spin_lock_irqsave(&local->sta_lock, flags); | ||
308 | sta_info_hash_add(local, sta); | ||
309 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
310 | } | ||
311 | |||
312 | list_add(&sta->list, &local->sta_list); | ||
313 | |||
314 | ieee80211_sta_debugfs_add(sta); | ||
315 | rate_control_add_sta_debugfs(sta); | ||
316 | |||
317 | sinfo.filled = 0; | ||
318 | sinfo.generation = local->sta_generation; | ||
319 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
320 | |||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static void sta_info_finish_pending(struct ieee80211_local *local) | ||
326 | { | ||
327 | struct sta_info *sta; | ||
328 | unsigned long flags; | ||
329 | |||
330 | spin_lock_irqsave(&local->sta_lock, flags); | ||
331 | while (!list_empty(&local->sta_pending_list)) { | ||
332 | sta = list_first_entry(&local->sta_pending_list, | ||
333 | struct sta_info, list); | ||
334 | list_del(&sta->list); | ||
335 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
336 | |||
337 | sta_info_finish_insert(sta, true); | ||
338 | |||
339 | spin_lock_irqsave(&local->sta_lock, flags); | ||
340 | } | ||
341 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
342 | } | ||
343 | |||
344 | static void sta_info_finish_work(struct work_struct *work) | ||
345 | { | ||
346 | struct ieee80211_local *local = | ||
347 | container_of(work, struct ieee80211_local, sta_finish_work); | ||
348 | |||
349 | mutex_lock(&local->sta_mtx); | ||
350 | sta_info_finish_pending(local); | ||
351 | mutex_unlock(&local->sta_mtx); | ||
352 | } | ||
353 | |||
354 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | ||
355 | { | ||
356 | struct ieee80211_local *local = sta->local; | ||
357 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
358 | unsigned long flags; | ||
359 | int err = 0; | ||
360 | |||
387 | /* | 361 | /* |
388 | * Can't be a WARN_ON because it can be triggered through a race: | 362 | * Can't be a WARN_ON because it can be triggered through a race: |
389 | * something inserts a STA (on one CPU) without holding the RTNL | 363 | * something inserts a STA (on one CPU) without holding the RTNL |
@@ -391,36 +365,87 @@ int sta_info_insert(struct sta_info *sta) | |||
391 | */ | 365 | */ |
392 | if (unlikely(!ieee80211_sdata_running(sdata))) { | 366 | if (unlikely(!ieee80211_sdata_running(sdata))) { |
393 | err = -ENETDOWN; | 367 | err = -ENETDOWN; |
368 | rcu_read_lock(); | ||
394 | goto out_free; | 369 | goto out_free; |
395 | } | 370 | } |
396 | 371 | ||
397 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || | 372 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || |
398 | is_multicast_ether_addr(sta->sta.addr))) { | 373 | is_multicast_ether_addr(sta->sta.addr))) { |
399 | err = -EINVAL; | 374 | err = -EINVAL; |
375 | rcu_read_lock(); | ||
400 | goto out_free; | 376 | goto out_free; |
401 | } | 377 | } |
402 | 378 | ||
379 | /* | ||
380 | * In ad-hoc mode, we sometimes need to insert stations | ||
381 | * from tasklet context from the RX path. To avoid races, | ||
382 | * always do so in that case -- see the comment below. | ||
383 | */ | ||
384 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
385 | spin_lock_irqsave(&local->sta_lock, flags); | ||
386 | /* check if STA exists already */ | ||
387 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | ||
388 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
389 | rcu_read_lock(); | ||
390 | err = -EEXIST; | ||
391 | goto out_free; | ||
392 | } | ||
393 | |||
394 | local->num_sta++; | ||
395 | local->sta_generation++; | ||
396 | smp_mb(); | ||
397 | sta_info_hash_add(local, sta); | ||
398 | |||
399 | list_add_tail(&sta->list, &local->sta_pending_list); | ||
400 | |||
401 | rcu_read_lock(); | ||
402 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
403 | |||
404 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
405 | printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", | ||
406 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
407 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
408 | |||
409 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * On first glance, this will look racy, because the code | ||
416 | * below this point, which inserts a station with sleeping, | ||
417 | * unlocks the sta_lock between checking existence in the | ||
418 | * hash table and inserting into it. | ||
419 | * | ||
420 | * However, it is not racy against itself because it keeps | ||
421 | * the mutex locked. It still seems to race against the | ||
422 | * above code that atomically inserts the station... That, | ||
423 | * however, is not true because the above code can only | ||
424 | * be invoked for IBSS interfaces, and the below code will | ||
425 | * not be -- and the two do not race against each other as | ||
426 | * the hash table also keys off the interface. | ||
427 | */ | ||
428 | |||
429 | might_sleep(); | ||
430 | |||
431 | mutex_lock(&local->sta_mtx); | ||
432 | |||
403 | spin_lock_irqsave(&local->sta_lock, flags); | 433 | spin_lock_irqsave(&local->sta_lock, flags); |
404 | /* check if STA exists already */ | 434 | /* check if STA exists already */ |
405 | if (sta_info_get(sdata, sta->sta.addr)) { | 435 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
406 | spin_unlock_irqrestore(&local->sta_lock, flags); | 436 | spin_unlock_irqrestore(&local->sta_lock, flags); |
437 | rcu_read_lock(); | ||
407 | err = -EEXIST; | 438 | err = -EEXIST; |
408 | goto out_free; | 439 | goto out_free; |
409 | } | 440 | } |
410 | list_add(&sta->list, &local->sta_list); | ||
411 | local->sta_generation++; | ||
412 | local->num_sta++; | ||
413 | sta_info_hash_add(local, sta); | ||
414 | 441 | ||
415 | /* notify driver */ | 442 | spin_unlock_irqrestore(&local->sta_lock, flags); |
416 | if (local->ops->sta_notify) { | ||
417 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
418 | sdata = container_of(sdata->bss, | ||
419 | struct ieee80211_sub_if_data, | ||
420 | u.ap); | ||
421 | 443 | ||
422 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); | 444 | err = sta_info_finish_insert(sta, false); |
423 | sdata = sta->sdata; | 445 | if (err) { |
446 | mutex_unlock(&local->sta_mtx); | ||
447 | rcu_read_lock(); | ||
448 | goto out_free; | ||
424 | } | 449 | } |
425 | 450 | ||
426 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 451 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -428,22 +453,9 @@ int sta_info_insert(struct sta_info *sta) | |||
428 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 453 | wiphy_name(local->hw.wiphy), sta->sta.addr); |
429 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 454 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
430 | 455 | ||
431 | spin_unlock_irqrestore(&local->sta_lock, flags); | 456 | /* move reference to rcu-protected */ |
432 | 457 | rcu_read_lock(); | |
433 | sinfo.filled = 0; | 458 | mutex_unlock(&local->sta_mtx); |
434 | sinfo.generation = local->sta_generation; | ||
435 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); | ||
436 | |||
437 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
438 | /* | ||
439 | * Debugfs entry adding might sleep, so schedule process | ||
440 | * context task for adding entry for STAs that do not yet | ||
441 | * have one. | ||
442 | * NOTE: due to auto-freeing semantics this may only be done | ||
443 | * if the insertion is successful! | ||
444 | */ | ||
445 | schedule_work(&local->sta_debugfs_add); | ||
446 | #endif | ||
447 | 459 | ||
448 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 460 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
449 | mesh_accept_plinks_update(sdata); | 461 | mesh_accept_plinks_update(sdata); |
@@ -455,6 +467,15 @@ int sta_info_insert(struct sta_info *sta) | |||
455 | return err; | 467 | return err; |
456 | } | 468 | } |
457 | 469 | ||
470 | int sta_info_insert(struct sta_info *sta) | ||
471 | { | ||
472 | int err = sta_info_insert_rcu(sta); | ||
473 | |||
474 | rcu_read_unlock(); | ||
475 | |||
476 | return err; | ||
477 | } | ||
478 | |||
458 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 479 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
459 | { | 480 | { |
460 | /* | 481 | /* |
@@ -523,108 +544,6 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
523 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 544 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
524 | } | 545 | } |
525 | 546 | ||
526 | static void __sta_info_unlink(struct sta_info **sta) | ||
527 | { | ||
528 | struct ieee80211_local *local = (*sta)->local; | ||
529 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | ||
530 | /* | ||
531 | * pull caller's reference if we're already gone. | ||
532 | */ | ||
533 | if (sta_info_hash_del(local, *sta)) { | ||
534 | *sta = NULL; | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | if ((*sta)->key) { | ||
539 | ieee80211_key_free((*sta)->key); | ||
540 | WARN_ON((*sta)->key); | ||
541 | } | ||
542 | |||
543 | list_del(&(*sta)->list); | ||
544 | (*sta)->dead = true; | ||
545 | |||
546 | if (test_and_clear_sta_flags(*sta, | ||
547 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
548 | BUG_ON(!sdata->bss); | ||
549 | |||
550 | atomic_dec(&sdata->bss->num_sta_ps); | ||
551 | __sta_info_clear_tim_bit(sdata->bss, *sta); | ||
552 | } | ||
553 | |||
554 | local->num_sta--; | ||
555 | local->sta_generation++; | ||
556 | |||
557 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
558 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
559 | |||
560 | if (local->ops->sta_notify) { | ||
561 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
562 | sdata = container_of(sdata->bss, | ||
563 | struct ieee80211_sub_if_data, | ||
564 | u.ap); | ||
565 | |||
566 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, | ||
567 | &(*sta)->sta); | ||
568 | sdata = (*sta)->sdata; | ||
569 | } | ||
570 | |||
571 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
572 | mesh_accept_plinks_update(sdata); | ||
573 | #ifdef CONFIG_MAC80211_MESH | ||
574 | del_timer(&(*sta)->plink_timer); | ||
575 | #endif | ||
576 | } | ||
577 | |||
578 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
579 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
580 | wiphy_name(local->hw.wiphy), (*sta)->sta.addr); | ||
581 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
582 | |||
583 | /* | ||
584 | * Finally, pull caller's reference if the STA is pinned by the | ||
585 | * task that is adding the debugfs entries. In that case, we | ||
586 | * leave the STA "to be freed". | ||
587 | * | ||
588 | * The rules are not trivial, but not too complex either: | ||
589 | * (1) pin_status is only modified under the sta_lock | ||
590 | * (2) STAs may only be pinned under the RTNL so that | ||
591 | * sta_info_flush() is guaranteed to actually destroy | ||
592 | * all STAs that are active for a given interface, this | ||
593 | * is required for correctness because otherwise we | ||
594 | * could notify a driver that an interface is going | ||
595 | * away and only after that (!) notify it about a STA | ||
596 | * on that interface going away. | ||
597 | * (3) sta_info_debugfs_add_work() will set the status | ||
598 | * to PINNED when it found an item that needs a new | ||
599 | * debugfs directory created. In that case, that item | ||
600 | * must not be freed although all *RCU* users are done | ||
601 | * with it. Hence, we tell the caller of _unlink() | ||
602 | * that the item is already gone (as can happen when | ||
603 | * two tasks try to unlink/destroy at the same time) | ||
604 | * (4) We set the pin_status to DESTROY here when we | ||
605 | * find such an item. | ||
606 | * (5) sta_info_debugfs_add_work() will reset the pin_status | ||
607 | * from PINNED to NORMAL when it is done with the item, | ||
608 | * but will check for DESTROY before resetting it in | ||
609 | * which case it will free the item. | ||
610 | */ | ||
611 | if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { | ||
612 | (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; | ||
613 | *sta = NULL; | ||
614 | return; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | void sta_info_unlink(struct sta_info **sta) | ||
619 | { | ||
620 | struct ieee80211_local *local = (*sta)->local; | ||
621 | unsigned long flags; | ||
622 | |||
623 | spin_lock_irqsave(&local->sta_lock, flags); | ||
624 | __sta_info_unlink(sta); | ||
625 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
626 | } | ||
627 | |||
628 | static int sta_info_buffer_expired(struct sta_info *sta, | 547 | static int sta_info_buffer_expired(struct sta_info *sta, |
629 | struct sk_buff *skb) | 548 | struct sk_buff *skb) |
630 | { | 549 | { |
@@ -681,109 +600,209 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
681 | } | 600 | } |
682 | } | 601 | } |
683 | 602 | ||
684 | 603 | static int __must_check __sta_info_destroy(struct sta_info *sta) | |
685 | static void sta_info_cleanup(unsigned long data) | ||
686 | { | 604 | { |
687 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 605 | struct ieee80211_local *local; |
688 | struct sta_info *sta; | 606 | struct ieee80211_sub_if_data *sdata; |
607 | struct sk_buff *skb; | ||
608 | unsigned long flags; | ||
609 | int ret, i; | ||
689 | 610 | ||
690 | rcu_read_lock(); | 611 | might_sleep(); |
691 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
692 | sta_info_cleanup_expire_buffered(local, sta); | ||
693 | rcu_read_unlock(); | ||
694 | 612 | ||
695 | if (local->quiescing) | 613 | if (!sta) |
696 | return; | 614 | return -ENOENT; |
697 | 615 | ||
698 | local->sta_cleanup.expires = | 616 | local = sta->local; |
699 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 617 | sdata = sta->sdata; |
700 | add_timer(&local->sta_cleanup); | ||
701 | } | ||
702 | 618 | ||
703 | #ifdef CONFIG_MAC80211_DEBUGFS | 619 | spin_lock_irqsave(&local->sta_lock, flags); |
704 | /* | 620 | ret = sta_info_hash_del(local, sta); |
705 | * See comment in __sta_info_unlink, | 621 | /* this might still be the pending list ... which is fine */ |
706 | * caller must hold local->sta_lock. | 622 | if (!ret) |
707 | */ | 623 | list_del(&sta->list); |
708 | static void __sta_info_pin(struct sta_info *sta) | 624 | spin_unlock_irqrestore(&local->sta_lock, flags); |
709 | { | 625 | if (ret) |
710 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); | 626 | return ret; |
711 | sta->pin_status = STA_INFO_PIN_STAT_PINNED; | 627 | |
628 | if (sta->key) { | ||
629 | ieee80211_key_free(sta->key); | ||
630 | /* | ||
631 | * We have only unlinked the key, and actually destroying it | ||
632 | * may mean it is removed from hardware which requires that | ||
633 | * the key->sta pointer is still valid, so flush the key todo | ||
634 | * list here. | ||
635 | * | ||
636 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
637 | * nothing can reference this sta struct any more. | ||
638 | */ | ||
639 | ieee80211_key_todo(); | ||
640 | |||
641 | WARN_ON(sta->key); | ||
642 | } | ||
643 | |||
644 | sta->dead = true; | ||
645 | |||
646 | if (test_and_clear_sta_flags(sta, | ||
647 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
648 | BUG_ON(!sdata->bss); | ||
649 | |||
650 | atomic_dec(&sdata->bss->num_sta_ps); | ||
651 | __sta_info_clear_tim_bit(sdata->bss, sta); | ||
652 | } | ||
653 | |||
654 | local->num_sta--; | ||
655 | local->sta_generation++; | ||
656 | |||
657 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
658 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
659 | |||
660 | if (sta->uploaded) { | ||
661 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
662 | sdata = container_of(sdata->bss, | ||
663 | struct ieee80211_sub_if_data, | ||
664 | u.ap); | ||
665 | drv_sta_remove(local, sdata, &sta->sta); | ||
666 | sdata = sta->sdata; | ||
667 | } | ||
668 | |||
669 | #ifdef CONFIG_MAC80211_MESH | ||
670 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
671 | mesh_accept_plinks_update(sdata); | ||
672 | del_timer(&sta->plink_timer); | ||
673 | } | ||
674 | #endif | ||
675 | |||
676 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
677 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
678 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
679 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
680 | cancel_work_sync(&sta->drv_unblock_wk); | ||
681 | |||
682 | rate_control_remove_sta_debugfs(sta); | ||
683 | ieee80211_sta_debugfs_remove(sta); | ||
684 | |||
685 | #ifdef CONFIG_MAC80211_MESH | ||
686 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { | ||
687 | mesh_plink_deactivate(sta); | ||
688 | del_timer_sync(&sta->plink_timer); | ||
689 | } | ||
690 | #endif | ||
691 | |||
692 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
693 | local->total_ps_buffered--; | ||
694 | dev_kfree_skb_any(skb); | ||
695 | } | ||
696 | |||
697 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
698 | dev_kfree_skb_any(skb); | ||
699 | |||
700 | for (i = 0; i < STA_TID_NUM; i++) { | ||
701 | struct tid_ampdu_rx *tid_rx; | ||
702 | struct tid_ampdu_tx *tid_tx; | ||
703 | |||
704 | spin_lock_bh(&sta->lock); | ||
705 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
706 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
707 | if (tid_rx) | ||
708 | tid_rx->shutdown = true; | ||
709 | |||
710 | spin_unlock_bh(&sta->lock); | ||
711 | |||
712 | /* | ||
713 | * Outside spinlock - shutdown is true now so that the timer | ||
714 | * won't free tid_rx, we have to do that now. Can't let the | ||
715 | * timer do it because we have to sync the timer outside the | ||
716 | * lock that it takes itself. | ||
717 | */ | ||
718 | if (tid_rx) { | ||
719 | del_timer_sync(&tid_rx->session_timer); | ||
720 | kfree(tid_rx); | ||
721 | } | ||
722 | |||
723 | /* | ||
724 | * No need to do such complications for TX agg sessions, the | ||
725 | * path leading to freeing the tid_tx struct goes via a call | ||
726 | * from the driver, and thus needs to look up the sta struct | ||
727 | * again, which cannot be found when we get here. Hence, we | ||
728 | * just need to delete the timer and free the aggregation | ||
729 | * info; we won't be telling the peer about it then but that | ||
730 | * doesn't matter if we're not talking to it again anyway. | ||
731 | */ | ||
732 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
733 | if (tid_tx) { | ||
734 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
735 | /* | ||
736 | * STA removed while aggregation session being | ||
737 | * started? Bit odd, but purge frames anyway. | ||
738 | */ | ||
739 | skb_queue_purge(&tid_tx->pending); | ||
740 | kfree(tid_tx); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | __sta_info_free(local, sta); | ||
745 | |||
746 | return 0; | ||
712 | } | 747 | } |
713 | 748 | ||
714 | /* | 749 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) |
715 | * See comment in __sta_info_unlink, returns sta if it | ||
716 | * needs to be destroyed. | ||
717 | */ | ||
718 | static struct sta_info *__sta_info_unpin(struct sta_info *sta) | ||
719 | { | 750 | { |
720 | struct sta_info *ret = NULL; | 751 | struct sta_info *sta; |
721 | unsigned long flags; | 752 | int ret; |
722 | 753 | ||
723 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 754 | mutex_lock(&sdata->local->sta_mtx); |
724 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && | 755 | sta = sta_info_get(sdata, addr); |
725 | sta->pin_status != STA_INFO_PIN_STAT_PINNED); | 756 | ret = __sta_info_destroy(sta); |
726 | if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) | 757 | mutex_unlock(&sdata->local->sta_mtx); |
727 | ret = sta; | ||
728 | sta->pin_status = STA_INFO_PIN_STAT_NORMAL; | ||
729 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
730 | 758 | ||
731 | return ret; | 759 | return ret; |
732 | } | 760 | } |
733 | 761 | ||
734 | static void sta_info_debugfs_add_work(struct work_struct *work) | 762 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
763 | const u8 *addr) | ||
735 | { | 764 | { |
736 | struct ieee80211_local *local = | 765 | struct sta_info *sta; |
737 | container_of(work, struct ieee80211_local, sta_debugfs_add); | 766 | int ret; |
738 | struct sta_info *sta, *tmp; | ||
739 | unsigned long flags; | ||
740 | 767 | ||
741 | /* We need to keep the RTNL across the whole pinned status. */ | 768 | mutex_lock(&sdata->local->sta_mtx); |
742 | rtnl_lock(); | 769 | sta = sta_info_get_bss(sdata, addr); |
743 | while (1) { | 770 | ret = __sta_info_destroy(sta); |
744 | sta = NULL; | 771 | mutex_unlock(&sdata->local->sta_mtx); |
745 | 772 | ||
746 | spin_lock_irqsave(&local->sta_lock, flags); | 773 | return ret; |
747 | list_for_each_entry(tmp, &local->sta_list, list) { | 774 | } |
748 | /* | ||
749 | * debugfs.add_has_run will be set by | ||
750 | * ieee80211_sta_debugfs_add regardless | ||
751 | * of what else it does. | ||
752 | */ | ||
753 | if (!tmp->debugfs.add_has_run) { | ||
754 | sta = tmp; | ||
755 | __sta_info_pin(sta); | ||
756 | break; | ||
757 | } | ||
758 | } | ||
759 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
760 | 775 | ||
761 | if (!sta) | 776 | static void sta_info_cleanup(unsigned long data) |
762 | break; | 777 | { |
778 | struct ieee80211_local *local = (struct ieee80211_local *) data; | ||
779 | struct sta_info *sta; | ||
780 | |||
781 | rcu_read_lock(); | ||
782 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
783 | sta_info_cleanup_expire_buffered(local, sta); | ||
784 | rcu_read_unlock(); | ||
763 | 785 | ||
764 | ieee80211_sta_debugfs_add(sta); | 786 | if (local->quiescing) |
765 | rate_control_add_sta_debugfs(sta); | 787 | return; |
766 | 788 | ||
767 | sta = __sta_info_unpin(sta); | 789 | local->sta_cleanup.expires = |
768 | sta_info_destroy(sta); | 790 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
769 | } | 791 | add_timer(&local->sta_cleanup); |
770 | rtnl_unlock(); | ||
771 | } | 792 | } |
772 | #endif | ||
773 | 793 | ||
774 | void sta_info_init(struct ieee80211_local *local) | 794 | void sta_info_init(struct ieee80211_local *local) |
775 | { | 795 | { |
776 | spin_lock_init(&local->sta_lock); | 796 | spin_lock_init(&local->sta_lock); |
797 | mutex_init(&local->sta_mtx); | ||
777 | INIT_LIST_HEAD(&local->sta_list); | 798 | INIT_LIST_HEAD(&local->sta_list); |
799 | INIT_LIST_HEAD(&local->sta_pending_list); | ||
800 | INIT_WORK(&local->sta_finish_work, sta_info_finish_work); | ||
778 | 801 | ||
779 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 802 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
780 | (unsigned long)local); | 803 | (unsigned long)local); |
781 | local->sta_cleanup.expires = | 804 | local->sta_cleanup.expires = |
782 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 805 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
783 | |||
784 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
785 | INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); | ||
786 | #endif | ||
787 | } | 806 | } |
788 | 807 | ||
789 | int sta_info_start(struct ieee80211_local *local) | 808 | int sta_info_start(struct ieee80211_local *local) |
@@ -795,16 +814,6 @@ int sta_info_start(struct ieee80211_local *local) | |||
795 | void sta_info_stop(struct ieee80211_local *local) | 814 | void sta_info_stop(struct ieee80211_local *local) |
796 | { | 815 | { |
797 | del_timer(&local->sta_cleanup); | 816 | del_timer(&local->sta_cleanup); |
798 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
799 | /* | ||
800 | * Make sure the debugfs adding work isn't pending after this | ||
801 | * because we're about to be destroyed. It doesn't matter | ||
802 | * whether it ran or not since we're going to flush all STAs | ||
803 | * anyway. | ||
804 | */ | ||
805 | cancel_work_sync(&local->sta_debugfs_add); | ||
806 | #endif | ||
807 | |||
808 | sta_info_flush(local, NULL); | 817 | sta_info_flush(local, NULL); |
809 | } | 818 | } |
810 | 819 | ||
@@ -820,26 +829,19 @@ int sta_info_flush(struct ieee80211_local *local, | |||
820 | struct ieee80211_sub_if_data *sdata) | 829 | struct ieee80211_sub_if_data *sdata) |
821 | { | 830 | { |
822 | struct sta_info *sta, *tmp; | 831 | struct sta_info *sta, *tmp; |
823 | LIST_HEAD(tmp_list); | ||
824 | int ret = 0; | 832 | int ret = 0; |
825 | unsigned long flags; | ||
826 | 833 | ||
827 | might_sleep(); | 834 | might_sleep(); |
828 | 835 | ||
829 | spin_lock_irqsave(&local->sta_lock, flags); | 836 | mutex_lock(&local->sta_mtx); |
837 | |||
838 | sta_info_finish_pending(local); | ||
839 | |||
830 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 840 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
831 | if (!sdata || sdata == sta->sdata) { | 841 | if (!sdata || sdata == sta->sdata) |
832 | __sta_info_unlink(&sta); | 842 | WARN_ON(__sta_info_destroy(sta)); |
833 | if (sta) { | ||
834 | list_add_tail(&sta->list, &tmp_list); | ||
835 | ret++; | ||
836 | } | ||
837 | } | ||
838 | } | 843 | } |
839 | spin_unlock_irqrestore(&local->sta_lock, flags); | 844 | mutex_unlock(&local->sta_mtx); |
840 | |||
841 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
842 | sta_info_destroy(sta); | ||
843 | 845 | ||
844 | return ret; | 846 | return ret; |
845 | } | 847 | } |
@@ -849,24 +851,17 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
849 | { | 851 | { |
850 | struct ieee80211_local *local = sdata->local; | 852 | struct ieee80211_local *local = sdata->local; |
851 | struct sta_info *sta, *tmp; | 853 | struct sta_info *sta, *tmp; |
852 | LIST_HEAD(tmp_list); | ||
853 | unsigned long flags; | ||
854 | 854 | ||
855 | spin_lock_irqsave(&local->sta_lock, flags); | 855 | mutex_lock(&local->sta_mtx); |
856 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 856 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) |
857 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 857 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
858 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 858 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
859 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 859 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |
860 | sdata->name, sta->sta.addr); | 860 | sdata->name, sta->sta.addr); |
861 | #endif | 861 | #endif |
862 | __sta_info_unlink(&sta); | 862 | WARN_ON(__sta_info_destroy(sta)); |
863 | if (sta) | ||
864 | list_add(&sta->list, &tmp_list); | ||
865 | } | 863 | } |
866 | spin_unlock_irqrestore(&local->sta_lock, flags); | 864 | mutex_unlock(&local->sta_mtx); |
867 | |||
868 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
869 | sta_info_destroy(sta); | ||
870 | } | 865 | } |
871 | 866 | ||
872 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | 867 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f79bba5706e..5ff611a35979 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -162,11 +162,6 @@ struct sta_ampdu_mlme { | |||
162 | }; | 162 | }; |
163 | 163 | ||
164 | 164 | ||
165 | /* see __sta_info_unlink */ | ||
166 | #define STA_INFO_PIN_STAT_NORMAL 0 | ||
167 | #define STA_INFO_PIN_STAT_PINNED 1 | ||
168 | #define STA_INFO_PIN_STAT_DESTROY 2 | ||
169 | |||
170 | /** | 165 | /** |
171 | * struct sta_info - STA information | 166 | * struct sta_info - STA information |
172 | * | 167 | * |
@@ -187,7 +182,6 @@ struct sta_ampdu_mlme { | |||
187 | * @flaglock: spinlock for flags accesses | 182 | * @flaglock: spinlock for flags accesses |
188 | * @drv_unblock_wk: used for driver PS unblocking | 183 | * @drv_unblock_wk: used for driver PS unblocking |
189 | * @listen_interval: listen interval of this station, when we're acting as AP | 184 | * @listen_interval: listen interval of this station, when we're acting as AP |
190 | * @pin_status: used internally for pinning a STA struct into memory | ||
191 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 185 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
192 | * @ps_tx_buf: buffer of frames to transmit to this station | 186 | * @ps_tx_buf: buffer of frames to transmit to this station |
193 | * when it leaves power saving state | 187 | * when it leaves power saving state |
@@ -226,6 +220,7 @@ struct sta_ampdu_mlme { | |||
226 | * @debugfs: debug filesystem info | 220 | * @debugfs: debug filesystem info |
227 | * @sta: station information we share with the driver | 221 | * @sta: station information we share with the driver |
228 | * @dead: set to true when sta is unlinked | 222 | * @dead: set to true when sta is unlinked |
223 | * @uploaded: set to true when sta is uploaded to the driver | ||
229 | */ | 224 | */ |
230 | struct sta_info { | 225 | struct sta_info { |
231 | /* General information, mostly static */ | 226 | /* General information, mostly static */ |
@@ -245,11 +240,7 @@ struct sta_info { | |||
245 | 240 | ||
246 | bool dead; | 241 | bool dead; |
247 | 242 | ||
248 | /* | 243 | bool uploaded; |
249 | * for use by the internal lifetime management, | ||
250 | * see __sta_info_unlink | ||
251 | */ | ||
252 | u8 pin_status; | ||
253 | 244 | ||
254 | /* | 245 | /* |
255 | * frequently updated, locked with own spinlock (flaglock), | 246 | * frequently updated, locked with own spinlock (flaglock), |
@@ -449,18 +440,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
449 | * Insert STA info into hash table/list, returns zero or a | 440 | * Insert STA info into hash table/list, returns zero or a |
450 | * -EEXIST if (if the same MAC address is already present). | 441 | * -EEXIST if (if the same MAC address is already present). |
451 | * | 442 | * |
452 | * Calling this without RCU protection makes the caller | 443 | * Calling the non-rcu version makes the caller relinquish, |
453 | * relinquish its reference to @sta. | 444 | * the _rcu version calls read_lock_rcu() and must be called |
445 | * without it held. | ||
454 | */ | 446 | */ |
455 | int sta_info_insert(struct sta_info *sta); | 447 | int sta_info_insert(struct sta_info *sta); |
456 | /* | 448 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
457 | * Unlink a STA info from the hash table/list. | 449 | int sta_info_insert_atomic(struct sta_info *sta); |
458 | * This can NULL the STA pointer if somebody else | 450 | |
459 | * has already unlinked it. | 451 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
460 | */ | 452 | const u8 *addr); |
461 | void sta_info_unlink(struct sta_info **sta); | 453 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
454 | const u8 *addr); | ||
462 | 455 | ||
463 | void sta_info_destroy(struct sta_info *sta); | ||
464 | void sta_info_set_tim_bit(struct sta_info *sta); | 456 | void sta_info_set_tim_bit(struct sta_info *sta); |
465 | void sta_info_clear_tim_bit(struct sta_info *sta); | 457 | void sta_info_clear_tim_bit(struct sta_info *sta); |
466 | 458 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e392820a4c33..cbe53ed4fb0b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -571,7 +571,7 @@ ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) | |||
571 | { | 571 | { |
572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
573 | 573 | ||
574 | if (tx->sta) | 574 | if (tx->sta && tx->sta->uploaded) |
575 | info->control.sta = &tx->sta->sta; | 575 | info->control.sta = &tx->sta->sta; |
576 | 576 | ||
577 | return TX_CONTINUE; | 577 | return TX_CONTINUE; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ca170b417da6..3af439a85b33 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1082,7 +1082,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1082 | struct ieee80211_hw *hw = &local->hw; | 1082 | struct ieee80211_hw *hw = &local->hw; |
1083 | struct ieee80211_sub_if_data *sdata; | 1083 | struct ieee80211_sub_if_data *sdata; |
1084 | struct sta_info *sta; | 1084 | struct sta_info *sta; |
1085 | unsigned long flags; | ||
1086 | int res; | 1085 | int res; |
1087 | 1086 | ||
1088 | if (local->suspended) | 1087 | if (local->suspended) |
@@ -1116,20 +1115,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1116 | } | 1115 | } |
1117 | 1116 | ||
1118 | /* add STAs back */ | 1117 | /* add STAs back */ |
1119 | if (local->ops->sta_notify) { | 1118 | mutex_lock(&local->sta_mtx); |
1120 | spin_lock_irqsave(&local->sta_lock, flags); | 1119 | list_for_each_entry(sta, &local->sta_list, list) { |
1121 | list_for_each_entry(sta, &local->sta_list, list) { | 1120 | if (sta->uploaded) { |
1122 | sdata = sta->sdata; | 1121 | sdata = sta->sdata; |
1123 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1122 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1124 | sdata = container_of(sdata->bss, | 1123 | sdata = container_of(sdata->bss, |
1125 | struct ieee80211_sub_if_data, | 1124 | struct ieee80211_sub_if_data, |
1126 | u.ap); | 1125 | u.ap); |
1127 | 1126 | ||
1128 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, | 1127 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1129 | &sta->sta); | ||
1130 | } | 1128 | } |
1131 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1132 | } | 1129 | } |
1130 | mutex_unlock(&local->sta_mtx); | ||
1133 | 1131 | ||
1134 | /* Clear Suspend state so that ADDBA requests can be processed */ | 1132 | /* Clear Suspend state so that ADDBA requests can be processed */ |
1135 | 1133 | ||
@@ -1219,10 +1217,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1219 | 1217 | ||
1220 | add_timer(&local->sta_cleanup); | 1218 | add_timer(&local->sta_cleanup); |
1221 | 1219 | ||
1222 | spin_lock_irqsave(&local->sta_lock, flags); | 1220 | mutex_lock(&local->sta_mtx); |
1223 | list_for_each_entry(sta, &local->sta_list, list) | 1221 | list_for_each_entry(sta, &local->sta_list, list) |
1224 | mesh_plink_restart(sta); | 1222 | mesh_plink_restart(sta); |
1225 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1223 | mutex_unlock(&local->sta_mtx); |
1226 | #else | 1224 | #else |
1227 | WARN_ON(1); | 1225 | WARN_ON(1); |
1228 | #endif | 1226 | #endif |