aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c35
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.h2
6 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index b3f23c2be73..7fae79d1666 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)
363 return ret; 363 return ret;
364} 364}
365 365
366static inline bool check_index(struct sk_buff *skb, u8 idx)
367{
368 struct ath9k_htc_tx_ctl *tx_ctl;
369
370 tx_ctl = HTC_SKB_CB(skb);
371
372 if ((tx_ctl->type == ATH9K_HTC_AMPDU) &&
373 (tx_ctl->sta_idx == idx))
374 return true;
375
376 return false;
377}
378
379static void hif_usb_sta_drain(void *hif_handle, u8 idx)
380{
381 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
382 struct sk_buff *skb, *tmp;
383 unsigned long flags;
384
385 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
386
387 skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) {
388 if (check_index(skb, idx)) {
389 __skb_unlink(skb, &hif_dev->tx.tx_skb_queue);
390 ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
391 skb, false);
392 hif_dev->tx.tx_skb_cnt--;
393 TX_STAT_INC(skb_failed);
394 }
395 }
396
397 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
398}
399
366static struct ath9k_htc_hif hif_usb = { 400static struct ath9k_htc_hif hif_usb = {
367 .transport = ATH9K_HIF_USB, 401 .transport = ATH9K_HIF_USB,
368 .name = "ath9k_hif_usb", 402 .name = "ath9k_hif_usb",
@@ -372,6 +406,7 @@ static struct ath9k_htc_hif hif_usb = {
372 406
373 .start = hif_usb_start, 407 .start = hif_usb_start,
374 .stop = hif_usb_stop, 408 .stop = hif_usb_stop,
409 .sta_drain = hif_usb_sta_drain,
375 .send = hif_usb_send, 410 .send = hif_usb_send,
376}; 411};
377 412
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 0d2e2b10358..41823fd6d9a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -280,6 +280,7 @@ struct ath9k_htc_tx_ctl {
280 u8 type; /* ATH9K_HTC_* */ 280 u8 type; /* ATH9K_HTC_* */
281 u8 epid; 281 u8 epid;
282 u8 txok; 282 u8 txok;
283 u8 sta_idx;
283}; 284};
284 285
285static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) 286static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index fb9ff1188a0..ae85cc4373f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1303,10 +1303,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
1303 struct ieee80211_sta *sta) 1303 struct ieee80211_sta *sta)
1304{ 1304{
1305 struct ath9k_htc_priv *priv = hw->priv; 1305 struct ath9k_htc_priv *priv = hw->priv;
1306 struct ath9k_htc_sta *ista;
1306 int ret; 1307 int ret;
1307 1308
1308 mutex_lock(&priv->mutex); 1309 mutex_lock(&priv->mutex);
1309 ath9k_htc_ps_wakeup(priv); 1310 ath9k_htc_ps_wakeup(priv);
1311 ista = (struct ath9k_htc_sta *) sta->drv_priv;
1312 htc_sta_drain(priv->htc, ista->index);
1310 ret = ath9k_htc_remove_station(priv, vif, sta); 1313 ret = ath9k_htc_remove_station(priv, vif, sta);
1311 ath9k_htc_ps_restore(priv); 1314 ath9k_htc_ps_restore(priv);
1312 mutex_unlock(&priv->mutex); 1315 mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 9e0c34b0a79..0790070a7f6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -248,6 +248,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
248 tx_hdr.vif_idx = vif_idx; 248 tx_hdr.vif_idx = vif_idx;
249 tx_hdr.cookie = slot; 249 tx_hdr.cookie = slot;
250 250
251 /*
252 * This is a bit redundant but it helps to get
253 * the per-packet index quickly when draining the
254 * TX queue in the HIF layer. Otherwise we would
255 * have to parse the packet contents ...
256 */
257 tx_ctl->sta_idx = sta_idx;
258
251 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { 259 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
252 tx_ctl->type = ATH9K_HTC_AMPDU; 260 tx_ctl->type = ATH9K_HTC_AMPDU;
253 tx_hdr.data_type = ATH9K_HTC_AMPDU; 261 tx_hdr.data_type = ATH9K_HTC_AMPDU;
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 7ced8ab1ae4..5c76352b131 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -310,6 +310,11 @@ void htc_start(struct htc_target *target)
310 target->hif->start(target->hif_dev); 310 target->hif->start(target->hif_dev);
311} 311}
312 312
313void htc_sta_drain(struct htc_target *target, u8 idx)
314{
315 target->hif->sta_drain(target->hif_dev, idx);
316}
317
313void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, 318void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
314 struct sk_buff *skb, bool txok) 319 struct sk_buff *skb, bool txok)
315{ 320{
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index 191e3c0837a..cb9174ade53 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -35,6 +35,7 @@ struct ath9k_htc_hif {
35 35
36 void (*start) (void *hif_handle); 36 void (*start) (void *hif_handle);
37 void (*stop) (void *hif_handle); 37 void (*stop) (void *hif_handle);
38 void (*sta_drain) (void *hif_handle, u8 idx);
38 int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); 39 int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf);
39}; 40};
40 41
@@ -209,6 +210,7 @@ int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
209 enum htc_endpoint_id epid); 210 enum htc_endpoint_id epid);
210void htc_stop(struct htc_target *target); 211void htc_stop(struct htc_target *target);
211void htc_start(struct htc_target *target); 212void htc_start(struct htc_target *target);
213void htc_sta_drain(struct htc_target *target, u8 idx);
212 214
213void ath9k_htc_rx_msg(struct htc_target *htc_handle, 215void ath9k_htc_rx_msg(struct htc_target *htc_handle,
214 struct sk_buff *skb, u32 len, u8 pipe_id); 216 struct sk_buff *skb, u32 len, u8 pipe_id);