diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/driver-ops.h | 14 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/iface.c | 9 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 9 |
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 | ||
13 | static inline int drv_start(struct ieee80211_local *local) | 13 | static 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 | ||
26 | static inline int drv_add_interface(struct ieee80211_local *local, | 38 | static 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 || |