--- x/net/mac80211/ieee80211_i.h +++ y/net/mac80211/ieee80211_i.h @@ -1437,6 +1437,7 @@ struct ieee80211_local { * queues increases over the limit. */ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 struct tasklet_struct tasklet; + struct work_struct tlw; struct sk_buff_head skb_queue; struct sk_buff_head skb_queue_unreliable; --- x/net/mac80211/main.c +++ y/net/mac80211/main.c @@ -423,9 +423,9 @@ u64 ieee80211_reset_erp_info(struct ieee BSS_CHANGED_ERP_SLOT; } -static void ieee80211_tasklet_handler(struct tasklet_struct *t) +static void ieee80211_tlw_fn(struct work_struct *w) { - struct ieee80211_local *local = from_tasklet(local, t, tasklet); + struct ieee80211_local *local = container_of(w, struct ieee80211_local, tlw); struct sk_buff *skb; while ((skb = skb_dequeue(&local->skb_queue)) || @@ -450,6 +450,13 @@ static void ieee80211_tasklet_handler(st } } +static void ieee80211_tasklet_handler(struct tasklet_struct *t) +{ + struct ieee80211_local *local = from_tasklet(local, t, tasklet); + + schedule_work(&local->tlw); +} + static void ieee80211_restart_work(struct work_struct *work) { struct ieee80211_local *local = @@ -989,6 +996,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending); tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs); tasklet_setup(&local->tasklet, ieee80211_tasklet_handler); + INIT_WORK(&local->tlw, ieee80211_tlw_fn); skb_queue_head_init(&local->skb_queue); skb_queue_head_init(&local->skb_queue_unreliable); @@ -1634,6 +1642,7 @@ void ieee80211_unregister_hw(struct ieee tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); + flush_work(&local->tlw); #ifdef CONFIG_INET unregister_inetaddr_notifier(&local->ifa_notifier);