+ tasklet_kill(&priv->wmi->wmi_event_tasklet);
+ spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
+ __skb_queue_purge(&priv->wmi->wmi_event_queue);
+ spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
+}
+
+void ath9k_wmi_event_tasklet(unsigned long data)
+{
+ struct wmi *wmi = (struct wmi *)data;
+ struct ath9k_htc_priv *priv = wmi->drv_priv;
+ struct wmi_cmd_hdr *hdr;
+ void *wmi_event;
+ struct wmi_event_swba *swba;
+ struct sk_buff *skb = NULL;
+ unsigned long flags;
+ u16 cmd_id;
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+ __be32 txrate;
+#endif
+
+ do {
+ spin_lock_irqsave(&wmi->wmi_lock, flags);
+ skb = __skb_dequeue(&wmi->wmi_event_queue);
+ if (!skb) {
+ spin_unlock_irqrestore(&wmi->wmi_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&wmi->wmi_lock, flags);
+
+ hdr = (struct wmi_cmd_hdr *) skb->data;
+ cmd_id = be16_to_cpu(hdr->command_id);
+ wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+
+ switch (cmd_id) {
+ case WMI_SWBA_EVENTID:
+ swba = (struct wmi_event_swba *) wmi_event;
+ ath9k_htc_swba(priv, swba);
+ break;
+ case WMI_FATAL_EVENTID:
+ ieee80211_queue_work(wmi->drv_priv->hw,
+ &wmi->drv_priv->fatal_work);
+ break;
+ case WMI_TXRATE_EVENTID:
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+ txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
+ wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ kfree_skb(skb);
+ } while (1);