summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/hif_usb.c
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-04-13 05:56:11 (GMT)
committerJohn W. Linville <linville@tuxdriver.com>2011-04-13 19:24:16 (GMT)
commit84c9e164468bd707e52b440e1c34bc3c85299332 (patch)
tree3abb317396af9864ccbe185f2d204471c50d89db /drivers/net/wireless/ath/ath9k/hif_usb.c
parente1fe7c38d39f8f6ebdffc3a55e2ec6e2ec0d1872 (diff)
downloadlinux-84c9e164468bd707e52b440e1c34bc3c85299332.tar.xz
ath9k_htc: Drain packets on station removal
When a station entry is removed, there could still be pending packets destined for that station in the HIF layer. Sending these to the target is not necessary, so drain them in the driver itself. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hif_usb.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index b3f23c2..7fae79d 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -363,6 +363,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
return ret;
}
+static inline bool check_index(struct sk_buff *skb, u8 idx)
+{
+ struct ath9k_htc_tx_ctl *tx_ctl;
+
+ tx_ctl = HTC_SKB_CB(skb);
+
+ if ((tx_ctl->type == ATH9K_HTC_AMPDU) &&
+ (tx_ctl->sta_idx == idx))
+ return true;
+
+ return false;
+}
+
+static void hif_usb_sta_drain(void *hif_handle, u8 idx)
+{
+ struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
+ struct sk_buff *skb, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+
+ skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) {
+ if (check_index(skb, idx)) {
+ __skb_unlink(skb, &hif_dev->tx.tx_skb_queue);
+ ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
+ skb, false);
+ hif_dev->tx.tx_skb_cnt--;
+ TX_STAT_INC(skb_failed);
+ }
+ }
+
+ spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+}
+
static struct ath9k_htc_hif hif_usb = {
.transport = ATH9K_HIF_USB,
.name = "ath9k_hif_usb",
@@ -372,6 +406,7 @@ static struct ath9k_htc_hif hif_usb = {
.start = hif_usb_start,
.stop = hif_usb_stop,
+ .sta_drain = hif_usb_sta_drain,
.send = hif_usb_send,
};