aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/driver-ops.h14
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c9
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/rx.c9
5 files changed, 26 insertions, 11 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index d231c9323ad1..020a94a31106 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -12,7 +12,11 @@ static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
12 12
13static inline int drv_start(struct ieee80211_local *local) 13static inline int drv_start(struct ieee80211_local *local)
14{ 14{
15 int ret = local->ops->start(&local->hw); 15 int ret;
16
17 local->started = true;
18 smp_mb();
19 ret = local->ops->start(&local->hw);
16 trace_drv_start(local, ret); 20 trace_drv_start(local, ret);
17 return ret; 21 return ret;
18} 22}
@@ -21,6 +25,14 @@ static inline void drv_stop(struct ieee80211_local *local)
21{ 25{
22 local->ops->stop(&local->hw); 26 local->ops->stop(&local->hw);
23 trace_drv_stop(local); 27 trace_drv_stop(local);
28
29 /* sync away all work on the tasklet before clearing started */
30 tasklet_disable(&local->tasklet);
31 tasklet_enable(&local->tasklet);
32
33 barrier();
34
35 local->started = false;
24} 36}
25 37
26static inline int drv_add_interface(struct ieee80211_local *local, 38static inline int drv_add_interface(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fa930e01295f..dbd8411cc1bd 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -667,6 +667,9 @@ struct ieee80211_local {
667 */ 667 */
668 bool quiescing; 668 bool quiescing;
669 669
670 /* device is started */
671 bool started;
672
670 int tx_headroom; /* required headroom for hardware/radiotap */ 673 int tx_headroom; /* required headroom for hardware/radiotap */
671 674
672 /* Tasklet and skb queue to process calls from IRQ mode. All frames 675 /* Tasklet and skb queue to process calls from IRQ mode. All frames
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5940e69fa33c..d134bd79972f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -277,11 +277,6 @@ static int ieee80211_open(struct net_device *dev)
277 } 277 }
278 } 278 }
279 279
280 if (local->open_count == 0) {
281 tasklet_enable(&local->tx_pending_tasklet);
282 tasklet_enable(&local->tasklet);
283 }
284
285 /* 280 /*
286 * set_multicast_list will be invoked by the networking core 281 * set_multicast_list will be invoked by the networking core
287 * which will check whether any increments here were done in 282 * which will check whether any increments here were done in
@@ -552,11 +547,9 @@ static int ieee80211_stop(struct net_device *dev)
552 ieee80211_recalc_ps(local, -1); 547 ieee80211_recalc_ps(local, -1);
553 548
554 if (local->open_count == 0) { 549 if (local->open_count == 0) {
550 ieee80211_clear_tx_pending(local);
555 ieee80211_stop_device(local); 551 ieee80211_stop_device(local);
556 552
557 tasklet_disable(&local->tx_pending_tasklet);
558 tasklet_disable(&local->tasklet);
559
560 /* no reconfiguring after stop! */ 553 /* no reconfiguring after stop! */
561 hw_reconf_flags = 0; 554 hw_reconf_flags = 0;
562 } 555 }
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index dd3b0816614d..797f53942e5f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -715,12 +715,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
715 skb_queue_head_init(&local->pending[i]); 715 skb_queue_head_init(&local->pending[i]);
716 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 716 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
717 (unsigned long)local); 717 (unsigned long)local);
718 tasklet_disable(&local->tx_pending_tasklet);
719 718
720 tasklet_init(&local->tasklet, 719 tasklet_init(&local->tasklet,
721 ieee80211_tasklet_handler, 720 ieee80211_tasklet_handler,
722 (unsigned long) local); 721 (unsigned long) local);
723 tasklet_disable(&local->tasklet);
724 722
725 skb_queue_head_init(&local->skb_queue); 723 skb_queue_head_init(&local->skb_queue);
726 skb_queue_head_init(&local->skb_queue_unreliable); 724 skb_queue_head_init(&local->skb_queue_unreliable);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index dff2239db6e2..b98f1afbfebf 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2471,6 +2471,15 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
2471 return; 2471 return;
2472 } 2472 }
2473 2473
2474 /*
2475 * The same happens when we're not even started,
2476 * but that's worth a warning.
2477 */
2478 if (WARN_ON(!local->started)) {
2479 kfree_skb(skb);
2480 return;
2481 }
2482
2474 if (status->flag & RX_FLAG_HT) { 2483 if (status->flag & RX_FLAG_HT) {
2475 /* rate_idx is MCS index */ 2484 /* rate_idx is MCS index */
2476 if (WARN_ON(status->rate_idx < 0 || 2485 if (WARN_ON(status->rate_idx < 0 ||