aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-04-13 01:56:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-13 15:24:20 -0400
commit27876a29de221186c9d5883e5fe5f6da18ef9a45 (patch)
treef47eb4d749e7bc49c8248171177c61d9bbe9952f /drivers/net/wireless/ath
parent84c9e164468bd707e52b440e1c34bc3c85299332 (diff)
ath9k_htc: Add support for TX completion
Now that the infrastructure is in place, process WMI TX status events and complete packets. 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')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c208
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.h4
5 files changed, 207 insertions, 31 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 41823fd6d9ad..6c103edf890a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -266,11 +266,17 @@ struct ath9k_htc_rx {
266#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) 266#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE)
267 267
268#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) 268#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0)
269#define ATH9K_HTC_OP_TX_DRAIN BIT(1)
269 270
270struct ath9k_htc_tx { 271struct ath9k_htc_tx {
271 u8 flags; 272 u8 flags;
272 int queued_cnt; 273 int queued_cnt;
273 struct sk_buff_head tx_queue; 274 struct sk_buff_head mgmt_ep_queue;
275 struct sk_buff_head cab_ep_queue;
276 struct sk_buff_head data_be_queue;
277 struct sk_buff_head data_bk_queue;
278 struct sk_buff_head data_vi_queue;
279 struct sk_buff_head data_vo_queue;
274 struct sk_buff_head tx_failed; 280 struct sk_buff_head tx_failed;
275 DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); 281 DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
276 spinlock_t tx_lock; 282 spinlock_t tx_lock;
@@ -465,8 +471,8 @@ struct ath9k_htc_priv {
465 471
466 struct tasklet_struct swba_tasklet; 472 struct tasklet_struct swba_tasklet;
467 struct tasklet_struct rx_tasklet; 473 struct tasklet_struct rx_tasklet;
468 struct tasklet_struct tx_tasklet;
469 struct delayed_work ani_work; 474 struct delayed_work ani_work;
475 struct tasklet_struct tx_failed_tasklet;
470 struct work_struct ps_work; 476 struct work_struct ps_work;
471 struct work_struct fatal_work; 477 struct work_struct fatal_work;
472 478
@@ -533,7 +539,6 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
533void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); 539void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
534 540
535int ath9k_tx_init(struct ath9k_htc_priv *priv); 541int ath9k_tx_init(struct ath9k_htc_priv *priv);
536void ath9k_tx_tasklet(unsigned long data);
537int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, 542int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
538 struct sk_buff *skb, u8 slot, bool is_cab); 543 struct sk_buff *skb, u8 slot, bool is_cab);
539void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); 544void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
@@ -547,6 +552,9 @@ void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv);
547int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); 552int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
548void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); 553void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
549void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); 554void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
555void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
556void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv);
557void ath9k_tx_failed_tasklet(unsigned long data);
550 558
551int ath9k_rx_init(struct ath9k_htc_priv *priv); 559int ath9k_rx_init(struct ath9k_htc_priv *priv);
552void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); 560void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index c270da7be10f..afceeaa6b916 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
678 mutex_init(&priv->htc_pm_lock); 678 mutex_init(&priv->htc_pm_lock);
679 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 679 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
680 (unsigned long)priv); 680 (unsigned long)priv);
681 tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, 681 tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
682 (unsigned long)priv); 682 (unsigned long)priv);
683 INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); 683 INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
684 INIT_WORK(&priv->ps_work, ath9k_ps_work); 684 INIT_WORK(&priv->ps_work, ath9k_ps_work);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 0790070a7f63..a9b6bb1ef287 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -99,8 +99,8 @@ void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot)
99 spin_unlock_bh(&priv->tx.tx_lock); 99 spin_unlock_bh(&priv->tx.tx_lock);
100} 100}
101 101
102static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, 102static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
103 u16 qnum) 103 u16 qnum)
104{ 104{
105 enum htc_endpoint_id epid; 105 enum htc_endpoint_id epid;
106 106
@@ -127,6 +127,30 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
127 return epid; 127 return epid;
128} 128}
129 129
130static inline struct sk_buff_head*
131get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid)
132{
133 struct ath_common *common = ath9k_hw_common(priv->ah);
134 struct sk_buff_head *epid_queue = NULL;
135
136 if (epid == priv->mgmt_ep)
137 epid_queue = &priv->tx.mgmt_ep_queue;
138 else if (epid == priv->cab_ep)
139 epid_queue = &priv->tx.cab_ep_queue;
140 else if (epid == priv->data_be_ep)
141 epid_queue = &priv->tx.data_be_queue;
142 else if (epid == priv->data_bk_ep)
143 epid_queue = &priv->tx.data_bk_queue;
144 else if (epid == priv->data_vi_ep)
145 epid_queue = &priv->tx.data_vi_queue;
146 else if (epid == priv->data_vo_ep)
147 epid_queue = &priv->tx.data_vo_queue;
148 else
149 ath_err(common, "Invalid EPID: %d\n", epid);
150
151 return epid_queue;
152}
153
130/* 154/*
131 * Removes the driver header and returns the TX slot number 155 * Removes the driver header and returns the TX slot number
132 */ 156 */
@@ -387,11 +411,15 @@ static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
387} 411}
388 412
389static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, 413static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
390 struct sk_buff *skb) 414 struct sk_buff *skb,
415 struct __wmi_event_txstatus *txs)
391{ 416{
392 struct ieee80211_vif *vif; 417 struct ieee80211_vif *vif;
393 struct ath9k_htc_tx_ctl *tx_ctl; 418 struct ath9k_htc_tx_ctl *tx_ctl;
394 struct ieee80211_tx_info *tx_info; 419 struct ieee80211_tx_info *tx_info;
420 struct ieee80211_tx_rate *rate;
421 struct ieee80211_conf *cur_conf = &priv->hw->conf;
422 struct ieee80211_supported_band *sband;
395 bool txok; 423 bool txok;
396 int slot; 424 int slot;
397 425
@@ -405,6 +433,8 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
405 txok = tx_ctl->txok; 433 txok = tx_ctl->txok;
406 tx_info = IEEE80211_SKB_CB(skb); 434 tx_info = IEEE80211_SKB_CB(skb);
407 vif = tx_info->control.vif; 435 vif = tx_info->control.vif;
436 rate = &tx_info->status.rates[0];
437 sband = priv->hw->wiphy->bands[cur_conf->channel->band];
408 438
409 memset(&tx_info->status, 0, sizeof(tx_info->status)); 439 memset(&tx_info->status, 0, sizeof(tx_info->status));
410 440
@@ -412,10 +442,32 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
412 * URB submission failed for this frame, it never reached 442 * URB submission failed for this frame, it never reached
413 * the target. 443 * the target.
414 */ 444 */
415 if (!txok || !vif) 445 if (!txok || !vif || !txs)
416 goto send_mac80211; 446 goto send_mac80211;
417 447
418 tx_info->flags |= IEEE80211_TX_STAT_ACK; 448 if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK)
449 tx_info->flags |= IEEE80211_TX_STAT_ACK;
450
451 if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT)
452 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
453
454 if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS)
455 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
456
457 rate->count = 1;
458 rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE);
459
460 if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) {
461 rate->flags |= IEEE80211_TX_RC_MCS;
462
463 if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40)
464 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
465 if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
466 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
467 } else {
468 if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
469 rate->idx += 4; /* No CCK rates */
470 }
419 471
420 ath9k_htc_check_tx_aggr(priv, vif, skb); 472 ath9k_htc_check_tx_aggr(priv, vif, skb);
421 473
@@ -431,37 +483,130 @@ send_mac80211:
431 ieee80211_tx_status(priv->hw, skb); 483 ieee80211_tx_status(priv->hw, skb);
432} 484}
433 485
486static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv,
487 struct sk_buff_head *queue)
488{
489 struct sk_buff *skb;
490
491 while ((skb = skb_dequeue(queue)) != NULL) {
492 ath9k_htc_tx_process(priv, skb, NULL);
493 }
494}
495
434void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) 496void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv)
435{ 497{
436 struct sk_buff *skb = NULL; 498 spin_lock_bh(&priv->tx.tx_lock);
499 priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN;
500 spin_unlock_bh(&priv->tx.tx_lock);
437 501
438 /* 502 /*
439 * Ensure that all pending TX frames are flushed, 503 * Ensure that all pending TX frames are flushed,
440 * and that the TX completion tasklet is killed. 504 * and that the TX completion/failed tasklets is killed.
441 */ 505 */
442 htc_stop(priv->htc); 506 htc_stop(priv->htc);
443 tasklet_kill(&priv->tx_tasklet); 507 tasklet_kill(&priv->wmi->wmi_event_tasklet);
508 tasklet_kill(&priv->tx_failed_tasklet);
444 509
445 while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { 510 ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue);
446 ath9k_htc_tx_process(priv, skb); 511 ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue);
447 } 512 ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue);
513 ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue);
514 ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue);
515 ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue);
516 ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
448 517
449 while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { 518 spin_lock_bh(&priv->tx.tx_lock);
450 ath9k_htc_tx_process(priv, skb); 519 priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN;
451 } 520 spin_unlock_bh(&priv->tx.tx_lock);
452} 521}
453 522
454void ath9k_tx_tasklet(unsigned long data) 523void ath9k_tx_failed_tasklet(unsigned long data)
455{ 524{
456 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; 525 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
457 struct sk_buff *skb = NULL;
458 526
459 while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { 527 spin_lock_bh(&priv->tx.tx_lock);
460 ath9k_htc_tx_process(priv, skb); 528 if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
529 spin_unlock_bh(&priv->tx.tx_lock);
530 return;
461 } 531 }
532 spin_unlock_bh(&priv->tx.tx_lock);
462 533
463 while ((skb = skb_dequeue(&priv->tx.tx_failed)) != NULL) { 534 ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
464 ath9k_htc_tx_process(priv, skb); 535}
536
537static inline bool check_cookie(struct ath9k_htc_priv *priv,
538 struct sk_buff *skb,
539 u8 cookie, u8 epid)
540{
541 u8 fcookie = 0;
542
543 if (epid == priv->mgmt_ep) {
544 struct tx_mgmt_hdr *hdr;
545 hdr = (struct tx_mgmt_hdr *) skb->data;
546 fcookie = hdr->cookie;
547 } else if ((epid == priv->data_bk_ep) ||
548 (epid == priv->data_be_ep) ||
549 (epid == priv->data_vi_ep) ||
550 (epid == priv->data_vo_ep) ||
551 (epid == priv->cab_ep)) {
552 struct tx_frame_hdr *hdr;
553 hdr = (struct tx_frame_hdr *) skb->data;
554 fcookie = hdr->cookie;
555 }
556
557 if (fcookie == cookie)
558 return true;
559
560 return false;
561}
562
563static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv,
564 struct __wmi_event_txstatus *txs)
565{
566 struct ath_common *common = ath9k_hw_common(priv->ah);
567 struct sk_buff_head *epid_queue;
568 struct sk_buff *skb, *tmp;
569 unsigned long flags;
570 u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID);
571
572 epid_queue = get_htc_epid_queue(priv, epid);
573 if (!epid_queue)
574 return NULL;
575
576 spin_lock_irqsave(&epid_queue->lock, flags);
577 skb_queue_walk_safe(epid_queue, skb, tmp) {
578 if (check_cookie(priv, skb, txs->cookie, epid)) {
579 __skb_unlink(skb, epid_queue);
580 spin_unlock_irqrestore(&epid_queue->lock, flags);
581 return skb;
582 }
583 }
584 spin_unlock_irqrestore(&epid_queue->lock, flags);
585
586 ath_dbg(common, ATH_DBG_XMIT,
587 "No matching packet for cookie: %d, epid: %d\n",
588 txs->cookie, epid);
589
590 return NULL;
591}
592
593void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event)
594{
595 struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event;
596 struct __wmi_event_txstatus *__txs;
597 struct sk_buff *skb;
598 int i;
599
600 for (i = 0; i < txs->cnt; i++) {
601 WARN_ON(txs->cnt > HTC_MAX_TX_STATUS);
602
603 __txs = &txs->txstatus[i];
604
605 skb = ath9k_htc_tx_get_packet(priv, __txs);
606 if (!skb)
607 continue;
608
609 ath9k_htc_tx_process(priv, skb, __txs);
465 } 610 }
466 611
467 /* Wake TX queues if needed */ 612 /* Wake TX queues if needed */
@@ -473,21 +618,34 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
473{ 618{
474 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; 619 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
475 struct ath9k_htc_tx_ctl *tx_ctl; 620 struct ath9k_htc_tx_ctl *tx_ctl;
621 struct sk_buff_head *epid_queue;
476 622
477 tx_ctl = HTC_SKB_CB(skb); 623 tx_ctl = HTC_SKB_CB(skb);
478 tx_ctl->txok = txok; 624 tx_ctl->txok = txok;
479 625
480 if (txok) 626 if (!txok) {
481 skb_queue_tail(&priv->tx.tx_queue, skb);
482 else
483 skb_queue_tail(&priv->tx.tx_failed, skb); 627 skb_queue_tail(&priv->tx.tx_failed, skb);
628 tasklet_schedule(&priv->tx_failed_tasklet);
629 return;
630 }
631
632 epid_queue = get_htc_epid_queue(priv, ep_id);
633 if (!epid_queue) {
634 dev_kfree_skb_any(skb);
635 return;
636 }
484 637
485 tasklet_schedule(&priv->tx_tasklet); 638 skb_queue_tail(epid_queue, skb);
486} 639}
487 640
488int ath9k_tx_init(struct ath9k_htc_priv *priv) 641int ath9k_tx_init(struct ath9k_htc_priv *priv)
489{ 642{
490 skb_queue_head_init(&priv->tx.tx_queue); 643 skb_queue_head_init(&priv->tx.mgmt_ep_queue);
644 skb_queue_head_init(&priv->tx.cab_ep_queue);
645 skb_queue_head_init(&priv->tx.data_be_queue);
646 skb_queue_head_init(&priv->tx.data_bk_queue);
647 skb_queue_head_init(&priv->tx.data_vi_queue);
648 skb_queue_head_init(&priv->tx.data_vo_queue);
491 skb_queue_head_init(&priv->tx.tx_failed); 649 skb_queue_head_init(&priv->tx.tx_failed);
492 return 0; 650 return 0;
493} 651}
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index e66f6c333028..3f5a4d1fe077 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -163,6 +163,16 @@ void ath9k_wmi_event_tasklet(unsigned long data)
163 wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); 163 wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
164#endif 164#endif
165 break; 165 break;
166 case WMI_TXSTATUS_EVENTID:
167 spin_lock_bh(&priv->tx.tx_lock);
168 if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
169 spin_unlock_bh(&priv->tx.tx_lock);
170 break;
171 }
172 spin_unlock_bh(&priv->tx.tx_lock);
173
174 ath9k_htc_txstatus(priv, wmi_event);
175 break;
166 default: 176 default:
167 break; 177 break;
168 } 178 }
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index 8c877dc2e2e0..44b17385374f 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -45,9 +45,9 @@ struct wmi_event_swba {
45/* 45/*
46 * 64 - HTC header - WMI header - 1 / txstatus 46 * 64 - HTC header - WMI header - 1 / txstatus
47 * And some other hdr. space is also accounted for. 47 * And some other hdr. space is also accounted for.
48 * 13 seems to be the magic number. 48 * 12 seems to be the magic number.
49 */ 49 */
50#define HTC_MAX_TX_STATUS 13 50#define HTC_MAX_TX_STATUS 12
51 51
52#define ATH9K_HTC_TXSTAT_ACK BIT(0) 52#define ATH9K_HTC_TXSTAT_ACK BIT(0)
53#define ATH9K_HTC_TXSTAT_FILT BIT(1) 53#define ATH9K_HTC_TXSTAT_FILT BIT(1)