aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorChilam Ng <chilamng@qca.qualcomm.com>2012-02-07 04:33:00 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2012-02-08 04:33:49 -0500
commitb29072cc7b0e08ace48ab709c40cf6246fb2e8b0 (patch)
treea360185622713df0934983e90d7a9277eaeb661a /drivers/net/wireless
parent1b2df4073447234034e2329f0df584c6346a8ec3 (diff)
ath6kl: prioritize Tx bundling based on AC priorities
Tx bundling is the more efficient use of SDIO bus and allows more packet transfers with fewer bus transactions, and is a way to improve overall throughput. However, Tx bundling has only 4 scatter request resources available. When there are multiple traffic streams of different priorities, it's possible that lower priority traffic may hog all the scatter requests and lock out the higher prioirty traffic from bundling. Tx bundling is now enabled per AC. When an AC do a scatter request and the remaining scatter request resources is lower than a configurable threshold, it will disable Tx bundling for all AC's of lower priorities. When an AC has Tx bundling disabled and has no Tx bundles sent in a consecutive and configurable number of packets, Tx bundling will be re-enabled for that AC. Signed-off-by: Chilam Ng <chilamng@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c77
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.h7
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c2
4 files changed, 80 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
index fb4186f5d432..904458ab484b 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.h
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -198,6 +198,8 @@ struct hif_scatter_req {
198 u8 *virt_dma_buf; 198 u8 *virt_dma_buf;
199 199
200 struct hif_scatter_item scat_list[1]; 200 struct hif_scatter_item scat_list[1];
201
202 u32 scat_q_depth;
201}; 203};
202 204
203struct ath6kl_irq_proc_registers { 205struct ath6kl_irq_proc_registers {
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 1385f719ad07..c703ef9c5313 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -23,6 +23,9 @@
23 23
24#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) 24#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
25 25
26/* threshold to re-enable Tx bundling for an AC*/
27#define TX_RESUME_BUNDLE_THRESHOLD 1500
28
26/* Functions for Tx credit handling */ 29/* Functions for Tx credit handling */
27static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info, 30static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info,
28 struct htc_endpoint_credit_dist *ep_dist, 31 struct htc_endpoint_credit_dist *ep_dist,
@@ -745,6 +748,12 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
745 struct hif_scatter_req *scat_req = NULL; 748 struct hif_scatter_req *scat_req = NULL;
746 int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; 749 int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
747 int status; 750 int status;
751 u32 txb_mask;
752 u8 ac = WMM_NUM_AC;
753
754 if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
755 (WMI_CONTROL_SVC != endpoint->svc_id))
756 ac = target->dev->ar->ep2ac_map[endpoint->eid];
748 757
749 while (true) { 758 while (true) {
750 status = 0; 759 status = 0;
@@ -764,6 +773,31 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
764 break; 773 break;
765 } 774 }
766 775
776 if ((ac < WMM_NUM_AC) && (ac != WMM_AC_BK)) {
777 if (WMM_AC_BE == ac)
778 /*
779 * BE, BK have priorities and bit
780 * positions reversed
781 */
782 txb_mask = (1 << WMM_AC_BK);
783 else
784 /*
785 * any AC with priority lower than
786 * itself
787 */
788 txb_mask = ((1 << ac) - 1);
789 /*
790 * when the scatter request resources drop below a
791 * certain threshold, disable Tx bundling for all
792 * AC's with priority lower than the current requesting
793 * AC. Otherwise re-enable Tx bundling for them
794 */
795 if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS)
796 target->tx_bndl_mask &= ~txb_mask;
797 else
798 target->tx_bndl_mask |= txb_mask;
799 }
800
767 ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", 801 ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n",
768 n_scat); 802 n_scat);
769 803
@@ -807,6 +841,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
807 struct htc_packet *packet; 841 struct htc_packet *packet;
808 int bundle_sent; 842 int bundle_sent;
809 int n_pkts_bundle; 843 int n_pkts_bundle;
844 u8 ac = WMM_NUM_AC;
810 845
811 spin_lock_bh(&target->tx_lock); 846 spin_lock_bh(&target->tx_lock);
812 847
@@ -824,6 +859,10 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
824 */ 859 */
825 INIT_LIST_HEAD(&txq); 860 INIT_LIST_HEAD(&txq);
826 861
862 if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
863 (WMI_CONTROL_SVC != endpoint->svc_id))
864 ac = target->dev->ar->ep2ac_map[endpoint->eid];
865
827 while (true) { 866 while (true) {
828 867
829 if (list_empty(&endpoint->txq)) 868 if (list_empty(&endpoint->txq))
@@ -841,15 +880,18 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
841 880
842 while (true) { 881 while (true) {
843 /* try to send a bundle on each pass */ 882 /* try to send a bundle on each pass */
844 if ((target->tx_bndl_enable) && 883 if ((target->tx_bndl_mask) &&
845 (get_queue_depth(&txq) >= 884 (get_queue_depth(&txq) >=
846 HTC_MIN_HTC_MSGS_TO_BUNDLE)) { 885 HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
847 int temp1 = 0, temp2 = 0; 886 int temp1 = 0, temp2 = 0;
848 887
849 ath6kl_htc_tx_bundle(endpoint, &txq, 888 /* check if bundling is enabled for an AC */
850 &temp1, &temp2); 889 if (target->tx_bndl_mask & (1 << ac)) {
851 bundle_sent += temp1; 890 ath6kl_htc_tx_bundle(endpoint, &txq,
852 n_pkts_bundle += temp2; 891 &temp1, &temp2);
892 bundle_sent += temp1;
893 n_pkts_bundle += temp2;
894 }
853 } 895 }
854 896
855 if (list_empty(&txq)) 897 if (list_empty(&txq))
@@ -868,6 +910,26 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
868 910
869 endpoint->ep_st.tx_bundles += bundle_sent; 911 endpoint->ep_st.tx_bundles += bundle_sent;
870 endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle; 912 endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle;
913
914 /*
915 * if an AC has bundling disabled and no tx bundling
916 * has occured continously for a certain number of TX,
917 * enable tx bundling for this AC
918 */
919 if (!bundle_sent) {
920 if (!(target->tx_bndl_mask & (1 << ac)) &&
921 (ac < WMM_NUM_AC)) {
922 if (++target->ac_tx_count[ac] >=
923 TX_RESUME_BUNDLE_THRESHOLD) {
924 target->ac_tx_count[ac] = 0;
925 target->tx_bndl_mask |= (1 << ac);
926 }
927 }
928 } else {
929 /* tx bundling will reset the counter */
930 if (ac < WMM_NUM_AC)
931 target->ac_tx_count[ac] = 0;
932 }
871 } 933 }
872 934
873 endpoint->tx_proc_cnt = 0; 935 endpoint->tx_proc_cnt = 0;
@@ -2518,7 +2580,8 @@ static void htc_setup_msg_bndl(struct htc_target *target)
2518 target->max_rx_bndl_sz, target->max_tx_bndl_sz); 2580 target->max_rx_bndl_sz, target->max_tx_bndl_sz);
2519 2581
2520 if (target->max_tx_bndl_sz) 2582 if (target->max_tx_bndl_sz)
2521 target->tx_bndl_enable = true; 2583 /* tx_bndl_mask is enabled per AC, each has 1 bit */
2584 target->tx_bndl_mask = (1 << WMM_NUM_AC) - 1;
2522 2585
2523 if (target->max_rx_bndl_sz) 2586 if (target->max_rx_bndl_sz)
2524 target->rx_bndl_enable = true; 2587 target->rx_bndl_enable = true;
@@ -2533,7 +2596,7 @@ static void htc_setup_msg_bndl(struct htc_target *target)
2533 * padding will spill into the next credit buffer 2596 * padding will spill into the next credit buffer
2534 * which is fatal. 2597 * which is fatal.
2535 */ 2598 */
2536 target->tx_bndl_enable = false; 2599 target->tx_bndl_mask = 0;
2537 } 2600 }
2538} 2601}
2539 2602
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h
index 84a2ab52aa68..519766571334 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.h
+++ b/drivers/net/wireless/ath/ath6kl/htc.h
@@ -88,6 +88,8 @@
88#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) 88#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
89#define WMI_MAX_SERVICES 5 89#define WMI_MAX_SERVICES 5
90 90
91#define WMM_NUM_AC 4
92
91/* reserved and used to flush ALL packets */ 93/* reserved and used to flush ALL packets */
92#define HTC_TX_PACKET_TAG_ALL 0 94#define HTC_TX_PACKET_TAG_ALL 0
93#define HTC_SERVICE_TX_PACKET_TAG 1 95#define HTC_SERVICE_TX_PACKET_TAG 1
@@ -532,7 +534,7 @@ struct htc_target {
532 /* max messages per bundle for HTC */ 534 /* max messages per bundle for HTC */
533 int msg_per_bndl_max; 535 int msg_per_bndl_max;
534 536
535 bool tx_bndl_enable; 537 u32 tx_bndl_mask;
536 int rx_bndl_enable; 538 int rx_bndl_enable;
537 int max_rx_bndl_sz; 539 int max_rx_bndl_sz;
538 int max_tx_bndl_sz; 540 int max_tx_bndl_sz;
@@ -544,6 +546,9 @@ struct htc_target {
544 int max_xfer_szper_scatreq; 546 int max_xfer_szper_scatreq;
545 547
546 int chk_irq_status_cnt; 548 int chk_irq_status_cnt;
549
550 /* counts the number of Tx without bundling continously per AC */
551 u32 ac_tx_count[WMM_NUM_AC];
547}; 552};
548 553
549void *ath6kl_htc_create(struct ath6kl *ar); 554void *ath6kl_htc_create(struct ath6kl *ar);
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 2826613b1933..cae446bf2129 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -602,6 +602,8 @@ static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
602 node = list_first_entry(&ar_sdio->scat_req, 602 node = list_first_entry(&ar_sdio->scat_req,
603 struct hif_scatter_req, list); 603 struct hif_scatter_req, list);
604 list_del(&node->list); 604 list_del(&node->list);
605
606 node->scat_q_depth = get_queue_depth(&ar_sdio->scat_req);
605 } 607 }
606 608
607 spin_unlock_bh(&ar_sdio->scat_lock); 609 spin_unlock_bh(&ar_sdio->scat_lock);