diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/htc.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc.c | 202 |
1 files changed, 145 insertions, 57 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index 2d721903640b..4849d99cce77 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007-2011 Atheros Communications Inc. | 2 | * Copyright (c) 2007-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -22,6 +23,9 @@ | |||
22 | 23 | ||
23 | #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)) |
24 | 25 | ||
26 | /* threshold to re-enable Tx bundling for an AC*/ | ||
27 | #define TX_RESUME_BUNDLE_THRESHOLD 1500 | ||
28 | |||
25 | /* Functions for Tx credit handling */ | 29 | /* Functions for Tx credit handling */ |
26 | static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info, | 30 | static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info, |
27 | struct htc_endpoint_credit_dist *ep_dist, | 31 | struct htc_endpoint_credit_dist *ep_dist, |
@@ -168,31 +172,29 @@ static void ath6kl_credit_reduce(struct ath6kl_htc_credit_info *cred_info, | |||
168 | static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info, | 172 | static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info, |
169 | struct list_head *epdist_list) | 173 | struct list_head *epdist_list) |
170 | { | 174 | { |
171 | struct htc_endpoint_credit_dist *cur_dist_list; | 175 | struct htc_endpoint_credit_dist *cur_list; |
172 | 176 | ||
173 | list_for_each_entry(cur_dist_list, epdist_list, list) { | 177 | list_for_each_entry(cur_list, epdist_list, list) { |
174 | if (cur_dist_list->endpoint == ENDPOINT_0) | 178 | if (cur_list->endpoint == ENDPOINT_0) |
175 | continue; | 179 | continue; |
176 | 180 | ||
177 | if (cur_dist_list->cred_to_dist > 0) { | 181 | if (cur_list->cred_to_dist > 0) { |
178 | cur_dist_list->credits += | 182 | cur_list->credits += cur_list->cred_to_dist; |
179 | cur_dist_list->cred_to_dist; | 183 | cur_list->cred_to_dist = 0; |
180 | cur_dist_list->cred_to_dist = 0; | 184 | |
181 | if (cur_dist_list->credits > | 185 | if (cur_list->credits > cur_list->cred_assngd) |
182 | cur_dist_list->cred_assngd) | ||
183 | ath6kl_credit_reduce(cred_info, | 186 | ath6kl_credit_reduce(cred_info, |
184 | cur_dist_list, | 187 | cur_list, |
185 | cur_dist_list->cred_assngd); | 188 | cur_list->cred_assngd); |
186 | 189 | ||
187 | if (cur_dist_list->credits > | 190 | if (cur_list->credits > cur_list->cred_norm) |
188 | cur_dist_list->cred_norm) | 191 | ath6kl_credit_reduce(cred_info, cur_list, |
189 | ath6kl_credit_reduce(cred_info, cur_dist_list, | 192 | cur_list->cred_norm); |
190 | cur_dist_list->cred_norm); | ||
191 | 193 | ||
192 | if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) { | 194 | if (!(cur_list->dist_flags & HTC_EP_ACTIVE)) { |
193 | if (cur_dist_list->txq_depth == 0) | 195 | if (cur_list->txq_depth == 0) |
194 | ath6kl_credit_reduce(cred_info, | 196 | ath6kl_credit_reduce(cred_info, |
195 | cur_dist_list, 0); | 197 | cur_list, 0); |
196 | } | 198 | } |
197 | } | 199 | } |
198 | } | 200 | } |
@@ -460,8 +462,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target, | |||
460 | INIT_LIST_HEAD(&tx_compq); | 462 | INIT_LIST_HEAD(&tx_compq); |
461 | 463 | ||
462 | ath6kl_dbg(ATH6KL_DBG_HTC, | 464 | ath6kl_dbg(ATH6KL_DBG_HTC, |
463 | "htc tx scat complete len %d entries %d\n", | 465 | "htc tx scat complete len %d entries %d\n", |
464 | scat_req->len, scat_req->scat_entries); | 466 | scat_req->len, scat_req->scat_entries); |
465 | 467 | ||
466 | if (scat_req->status) | 468 | if (scat_req->status) |
467 | ath6kl_err("send scatter req failed: %d\n", scat_req->status); | 469 | ath6kl_err("send scatter req failed: %d\n", scat_req->status); |
@@ -599,8 +601,8 @@ static void ath6kl_htc_tx_pkts_get(struct htc_target *target, | |||
599 | list); | 601 | list); |
600 | 602 | ||
601 | ath6kl_dbg(ATH6KL_DBG_HTC, | 603 | ath6kl_dbg(ATH6KL_DBG_HTC, |
602 | "htc tx got packet 0x%p queue depth %d\n", | 604 | "htc tx got packet 0x%p queue depth %d\n", |
603 | packet, get_queue_depth(&endpoint->txq)); | 605 | packet, get_queue_depth(&endpoint->txq)); |
604 | 606 | ||
605 | len = CALC_TXRX_PADDED_LEN(target, | 607 | len = CALC_TXRX_PADDED_LEN(target, |
606 | packet->act_len + HTC_HDR_LENGTH); | 608 | packet->act_len + HTC_HDR_LENGTH); |
@@ -670,6 +672,7 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, | |||
670 | struct htc_packet *packet; | 672 | struct htc_packet *packet; |
671 | int i, len, rem_scat, cred_pad; | 673 | int i, len, rem_scat, cred_pad; |
672 | int status = 0; | 674 | int status = 0; |
675 | u8 flags; | ||
673 | 676 | ||
674 | rem_scat = target->max_tx_bndl_sz; | 677 | rem_scat = target->max_tx_bndl_sz; |
675 | 678 | ||
@@ -696,9 +699,9 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, | |||
696 | 699 | ||
697 | scat_req->scat_list[i].packet = packet; | 700 | scat_req->scat_list[i].packet = packet; |
698 | /* prepare packet and flag message as part of a send bundle */ | 701 | /* prepare packet and flag message as part of a send bundle */ |
699 | ath6kl_htc_tx_prep_pkt(packet, | 702 | flags = packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE; |
700 | packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, | 703 | ath6kl_htc_tx_prep_pkt(packet, flags, |
701 | cred_pad, packet->info.tx.seqno); | 704 | cred_pad, packet->info.tx.seqno); |
702 | /* Make sure the buffer is 4-byte aligned */ | 705 | /* Make sure the buffer is 4-byte aligned */ |
703 | ath6kl_htc_tx_buf_align(&packet->buf, | 706 | ath6kl_htc_tx_buf_align(&packet->buf, |
704 | packet->act_len + HTC_HDR_LENGTH); | 707 | packet->act_len + HTC_HDR_LENGTH); |
@@ -744,6 +747,12 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
744 | struct hif_scatter_req *scat_req = NULL; | 747 | struct hif_scatter_req *scat_req = NULL; |
745 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; | 748 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; |
746 | int status; | 749 | int status; |
750 | u32 txb_mask; | ||
751 | u8 ac = WMM_NUM_AC; | ||
752 | |||
753 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | ||
754 | (WMI_CONTROL_SVC != endpoint->svc_id)) | ||
755 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | ||
747 | 756 | ||
748 | while (true) { | 757 | while (true) { |
749 | status = 0; | 758 | status = 0; |
@@ -759,10 +768,35 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
759 | if (!scat_req) { | 768 | if (!scat_req) { |
760 | /* no scatter resources */ | 769 | /* no scatter resources */ |
761 | ath6kl_dbg(ATH6KL_DBG_HTC, | 770 | ath6kl_dbg(ATH6KL_DBG_HTC, |
762 | "htc tx no more scatter resources\n"); | 771 | "htc tx no more scatter resources\n"); |
763 | break; | 772 | break; |
764 | } | 773 | } |
765 | 774 | ||
775 | if ((ac < WMM_NUM_AC) && (ac != WMM_AC_BK)) { | ||
776 | if (WMM_AC_BE == ac) | ||
777 | /* | ||
778 | * BE, BK have priorities and bit | ||
779 | * positions reversed | ||
780 | */ | ||
781 | txb_mask = (1 << WMM_AC_BK); | ||
782 | else | ||
783 | /* | ||
784 | * any AC with priority lower than | ||
785 | * itself | ||
786 | */ | ||
787 | txb_mask = ((1 << ac) - 1); | ||
788 | /* | ||
789 | * when the scatter request resources drop below a | ||
790 | * certain threshold, disable Tx bundling for all | ||
791 | * AC's with priority lower than the current requesting | ||
792 | * AC. Otherwise re-enable Tx bundling for them | ||
793 | */ | ||
794 | if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) | ||
795 | target->tx_bndl_mask &= ~txb_mask; | ||
796 | else | ||
797 | target->tx_bndl_mask |= txb_mask; | ||
798 | } | ||
799 | |||
766 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", | 800 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", |
767 | n_scat); | 801 | n_scat); |
768 | 802 | ||
@@ -806,6 +840,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
806 | struct htc_packet *packet; | 840 | struct htc_packet *packet; |
807 | int bundle_sent; | 841 | int bundle_sent; |
808 | int n_pkts_bundle; | 842 | int n_pkts_bundle; |
843 | u8 ac = WMM_NUM_AC; | ||
809 | 844 | ||
810 | spin_lock_bh(&target->tx_lock); | 845 | spin_lock_bh(&target->tx_lock); |
811 | 846 | ||
@@ -823,6 +858,10 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
823 | */ | 858 | */ |
824 | INIT_LIST_HEAD(&txq); | 859 | INIT_LIST_HEAD(&txq); |
825 | 860 | ||
861 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | ||
862 | (WMI_CONTROL_SVC != endpoint->svc_id)) | ||
863 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | ||
864 | |||
826 | while (true) { | 865 | while (true) { |
827 | 866 | ||
828 | if (list_empty(&endpoint->txq)) | 867 | if (list_empty(&endpoint->txq)) |
@@ -840,15 +879,18 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
840 | 879 | ||
841 | while (true) { | 880 | while (true) { |
842 | /* try to send a bundle on each pass */ | 881 | /* try to send a bundle on each pass */ |
843 | if ((target->tx_bndl_enable) && | 882 | if ((target->tx_bndl_mask) && |
844 | (get_queue_depth(&txq) >= | 883 | (get_queue_depth(&txq) >= |
845 | HTC_MIN_HTC_MSGS_TO_BUNDLE)) { | 884 | HTC_MIN_HTC_MSGS_TO_BUNDLE)) { |
846 | int temp1 = 0, temp2 = 0; | 885 | int temp1 = 0, temp2 = 0; |
847 | 886 | ||
848 | ath6kl_htc_tx_bundle(endpoint, &txq, | 887 | /* check if bundling is enabled for an AC */ |
849 | &temp1, &temp2); | 888 | if (target->tx_bndl_mask & (1 << ac)) { |
850 | bundle_sent += temp1; | 889 | ath6kl_htc_tx_bundle(endpoint, &txq, |
851 | n_pkts_bundle += temp2; | 890 | &temp1, &temp2); |
891 | bundle_sent += temp1; | ||
892 | n_pkts_bundle += temp2; | ||
893 | } | ||
852 | } | 894 | } |
853 | 895 | ||
854 | if (list_empty(&txq)) | 896 | if (list_empty(&txq)) |
@@ -867,6 +909,26 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
867 | 909 | ||
868 | endpoint->ep_st.tx_bundles += bundle_sent; | 910 | endpoint->ep_st.tx_bundles += bundle_sent; |
869 | endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle; | 911 | endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle; |
912 | |||
913 | /* | ||
914 | * if an AC has bundling disabled and no tx bundling | ||
915 | * has occured continously for a certain number of TX, | ||
916 | * enable tx bundling for this AC | ||
917 | */ | ||
918 | if (!bundle_sent) { | ||
919 | if (!(target->tx_bndl_mask & (1 << ac)) && | ||
920 | (ac < WMM_NUM_AC)) { | ||
921 | if (++target->ac_tx_count[ac] >= | ||
922 | TX_RESUME_BUNDLE_THRESHOLD) { | ||
923 | target->ac_tx_count[ac] = 0; | ||
924 | target->tx_bndl_mask |= (1 << ac); | ||
925 | } | ||
926 | } | ||
927 | } else { | ||
928 | /* tx bundling will reset the counter */ | ||
929 | if (ac < WMM_NUM_AC) | ||
930 | target->ac_tx_count[ac] = 0; | ||
931 | } | ||
870 | } | 932 | } |
871 | 933 | ||
872 | endpoint->tx_proc_cnt = 0; | 934 | endpoint->tx_proc_cnt = 0; |
@@ -979,8 +1041,8 @@ static int htc_setup_tx_complete(struct htc_target *target) | |||
979 | memcpy(&setup_comp_ext->flags, &flags, | 1041 | memcpy(&setup_comp_ext->flags, &flags, |
980 | sizeof(setup_comp_ext->flags)); | 1042 | sizeof(setup_comp_ext->flags)); |
981 | set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext, | 1043 | set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext, |
982 | sizeof(struct htc_setup_comp_ext_msg), | 1044 | sizeof(struct htc_setup_comp_ext_msg), |
983 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); | 1045 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); |
984 | 1046 | ||
985 | } else { | 1047 | } else { |
986 | struct htc_setup_comp_msg *setup_comp; | 1048 | struct htc_setup_comp_msg *setup_comp; |
@@ -988,8 +1050,8 @@ static int htc_setup_tx_complete(struct htc_target *target) | |||
988 | memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg)); | 1050 | memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg)); |
989 | setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID); | 1051 | setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID); |
990 | set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp, | 1052 | set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp, |
991 | sizeof(struct htc_setup_comp_msg), | 1053 | sizeof(struct htc_setup_comp_msg), |
992 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); | 1054 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); |
993 | } | 1055 | } |
994 | 1056 | ||
995 | /* we want synchronous operation */ | 1057 | /* we want synchronous operation */ |
@@ -1088,9 +1150,9 @@ void ath6kl_htc_flush_txep(struct htc_target *target, | |||
1088 | packet->status = -ECANCELED; | 1150 | packet->status = -ECANCELED; |
1089 | list_del(&packet->list); | 1151 | list_del(&packet->list); |
1090 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1152 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1091 | "htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n", | 1153 | "htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n", |
1092 | packet, packet->act_len, | 1154 | packet, packet->act_len, |
1093 | packet->endpoint, packet->info.tx.tag); | 1155 | packet->endpoint, packet->info.tx.tag); |
1094 | 1156 | ||
1095 | INIT_LIST_HEAD(&container); | 1157 | INIT_LIST_HEAD(&container); |
1096 | list_add_tail(&packet->list, &container); | 1158 | list_add_tail(&packet->list, &container); |
@@ -1490,7 +1552,7 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets) | |||
1490 | 1552 | ||
1491 | if (packets->act_len > 0) { | 1553 | if (packets->act_len > 0) { |
1492 | ath6kl_err("htc_ctrl_rx, got message with len:%zu\n", | 1554 | ath6kl_err("htc_ctrl_rx, got message with len:%zu\n", |
1493 | packets->act_len + HTC_HDR_LENGTH); | 1555 | packets->act_len + HTC_HDR_LENGTH); |
1494 | 1556 | ||
1495 | ath6kl_dbg_dump(ATH6KL_DBG_HTC, | 1557 | ath6kl_dbg_dump(ATH6KL_DBG_HTC, |
1496 | "htc rx unexpected endpoint 0 message", "", | 1558 | "htc rx unexpected endpoint 0 message", "", |
@@ -1609,8 +1671,8 @@ static int htc_parse_trailer(struct htc_target *target, | |||
1609 | } | 1671 | } |
1610 | 1672 | ||
1611 | lk_ahd = (struct htc_lookahead_report *) record_buf; | 1673 | lk_ahd = (struct htc_lookahead_report *) record_buf; |
1612 | if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) | 1674 | if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) && |
1613 | && next_lk_ahds) { | 1675 | next_lk_ahds) { |
1614 | 1676 | ||
1615 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1677 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1616 | "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n", | 1678 | "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n", |
@@ -2038,13 +2100,13 @@ fail_rx: | |||
2038 | list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) { | 2100 | list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) { |
2039 | list_del(&packet->list); | 2101 | list_del(&packet->list); |
2040 | htc_reclaim_rxbuf(target, packet, | 2102 | htc_reclaim_rxbuf(target, packet, |
2041 | &target->endpoint[packet->endpoint]); | 2103 | &target->endpoint[packet->endpoint]); |
2042 | } | 2104 | } |
2043 | 2105 | ||
2044 | list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) { | 2106 | list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) { |
2045 | list_del(&packet->list); | 2107 | list_del(&packet->list); |
2046 | htc_reclaim_rxbuf(target, packet, | 2108 | htc_reclaim_rxbuf(target, packet, |
2047 | &target->endpoint[packet->endpoint]); | 2109 | &target->endpoint[packet->endpoint]); |
2048 | } | 2110 | } |
2049 | 2111 | ||
2050 | return status; | 2112 | return status; |
@@ -2176,11 +2238,11 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) | |||
2176 | u32 look_ahead; | 2238 | u32 look_ahead; |
2177 | 2239 | ||
2178 | if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead, | 2240 | if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead, |
2179 | HTC_TARGET_RESPONSE_TIMEOUT)) | 2241 | HTC_TARGET_RESPONSE_TIMEOUT)) |
2180 | return NULL; | 2242 | return NULL; |
2181 | 2243 | ||
2182 | ath6kl_dbg(ATH6KL_DBG_HTC, | 2244 | ath6kl_dbg(ATH6KL_DBG_HTC, |
2183 | "htc rx wait ctrl look_ahead 0x%X\n", look_ahead); | 2245 | "htc rx wait ctrl look_ahead 0x%X\n", look_ahead); |
2184 | 2246 | ||
2185 | htc_hdr = (struct htc_frame_hdr *)&look_ahead; | 2247 | htc_hdr = (struct htc_frame_hdr *)&look_ahead; |
2186 | 2248 | ||
@@ -2245,7 +2307,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | |||
2245 | depth = get_queue_depth(pkt_queue); | 2307 | depth = get_queue_depth(pkt_queue); |
2246 | 2308 | ||
2247 | ath6kl_dbg(ATH6KL_DBG_HTC, | 2309 | ath6kl_dbg(ATH6KL_DBG_HTC, |
2248 | "htc rx add multiple ep id %d cnt %d len %d\n", | 2310 | "htc rx add multiple ep id %d cnt %d len %d\n", |
2249 | first_pkt->endpoint, depth, first_pkt->buf_len); | 2311 | first_pkt->endpoint, depth, first_pkt->buf_len); |
2250 | 2312 | ||
2251 | endpoint = &target->endpoint[first_pkt->endpoint]; | 2313 | endpoint = &target->endpoint[first_pkt->endpoint]; |
@@ -2271,8 +2333,8 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | |||
2271 | if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) { | 2333 | if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) { |
2272 | if (target->ep_waiting == first_pkt->endpoint) { | 2334 | if (target->ep_waiting == first_pkt->endpoint) { |
2273 | ath6kl_dbg(ATH6KL_DBG_HTC, | 2335 | ath6kl_dbg(ATH6KL_DBG_HTC, |
2274 | "htc rx blocked on ep %d, unblocking\n", | 2336 | "htc rx blocked on ep %d, unblocking\n", |
2275 | target->ep_waiting); | 2337 | target->ep_waiting); |
2276 | target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS; | 2338 | target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS; |
2277 | target->ep_waiting = ENDPOINT_MAX; | 2339 | target->ep_waiting = ENDPOINT_MAX; |
2278 | rx_unblock = true; | 2340 | rx_unblock = true; |
@@ -2309,7 +2371,21 @@ void ath6kl_htc_flush_rx_buf(struct htc_target *target) | |||
2309 | "htc rx flush pkt 0x%p len %d ep %d\n", | 2371 | "htc rx flush pkt 0x%p len %d ep %d\n", |
2310 | packet, packet->buf_len, | 2372 | packet, packet->buf_len, |
2311 | packet->endpoint); | 2373 | packet->endpoint); |
2312 | dev_kfree_skb(packet->pkt_cntxt); | 2374 | /* |
2375 | * packets in rx_bufq of endpoint 0 have originally | ||
2376 | * been queued from target->free_ctrl_rxbuf where | ||
2377 | * packet and packet->buf_start are allocated | ||
2378 | * separately using kmalloc(). For other endpoint | ||
2379 | * rx_bufq, it is allocated as skb where packet is | ||
2380 | * skb->head. Take care of this difference while freeing | ||
2381 | * the memory. | ||
2382 | */ | ||
2383 | if (packet->endpoint == ENDPOINT_0) { | ||
2384 | kfree(packet->buf_start); | ||
2385 | kfree(packet); | ||
2386 | } else { | ||
2387 | dev_kfree_skb(packet->pkt_cntxt); | ||
2388 | } | ||
2313 | spin_lock_bh(&target->rx_lock); | 2389 | spin_lock_bh(&target->rx_lock); |
2314 | } | 2390 | } |
2315 | spin_unlock_bh(&target->rx_lock); | 2391 | spin_unlock_bh(&target->rx_lock); |
@@ -2328,6 +2404,7 @@ int ath6kl_htc_conn_service(struct htc_target *target, | |||
2328 | enum htc_endpoint_id assigned_ep = ENDPOINT_MAX; | 2404 | enum htc_endpoint_id assigned_ep = ENDPOINT_MAX; |
2329 | unsigned int max_msg_sz = 0; | 2405 | unsigned int max_msg_sz = 0; |
2330 | int status = 0; | 2406 | int status = 0; |
2407 | u16 msg_id; | ||
2331 | 2408 | ||
2332 | ath6kl_dbg(ATH6KL_DBG_HTC, | 2409 | ath6kl_dbg(ATH6KL_DBG_HTC, |
2333 | "htc connect service target 0x%p service id 0x%x\n", | 2410 | "htc connect service target 0x%p service id 0x%x\n", |
@@ -2371,9 +2448,10 @@ int ath6kl_htc_conn_service(struct htc_target *target, | |||
2371 | } | 2448 | } |
2372 | 2449 | ||
2373 | resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf; | 2450 | resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf; |
2451 | msg_id = le16_to_cpu(resp_msg->msg_id); | ||
2374 | 2452 | ||
2375 | if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID) | 2453 | if ((msg_id != HTC_MSG_CONN_SVC_RESP_ID) || |
2376 | || (rx_pkt->act_len < sizeof(*resp_msg))) { | 2454 | (rx_pkt->act_len < sizeof(*resp_msg))) { |
2377 | status = -ENOMEM; | 2455 | status = -ENOMEM; |
2378 | goto fail_tx; | 2456 | goto fail_tx; |
2379 | } | 2457 | } |
@@ -2420,6 +2498,15 @@ int ath6kl_htc_conn_service(struct htc_target *target, | |||
2420 | endpoint->cred_dist.endpoint = assigned_ep; | 2498 | endpoint->cred_dist.endpoint = assigned_ep; |
2421 | endpoint->cred_dist.cred_sz = target->tgt_cred_sz; | 2499 | endpoint->cred_dist.cred_sz = target->tgt_cred_sz; |
2422 | 2500 | ||
2501 | switch (endpoint->svc_id) { | ||
2502 | case WMI_DATA_BK_SVC: | ||
2503 | endpoint->tx_drop_packet_threshold = MAX_DEF_COOKIE_NUM / 3; | ||
2504 | break; | ||
2505 | default: | ||
2506 | endpoint->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM; | ||
2507 | break; | ||
2508 | } | ||
2509 | |||
2423 | if (conn_req->max_rxmsg_sz) { | 2510 | if (conn_req->max_rxmsg_sz) { |
2424 | /* | 2511 | /* |
2425 | * Override cred_per_msg calculation, this optimizes | 2512 | * Override cred_per_msg calculation, this optimizes |
@@ -2517,7 +2604,8 @@ static void htc_setup_msg_bndl(struct htc_target *target) | |||
2517 | target->max_rx_bndl_sz, target->max_tx_bndl_sz); | 2604 | target->max_rx_bndl_sz, target->max_tx_bndl_sz); |
2518 | 2605 | ||
2519 | if (target->max_tx_bndl_sz) | 2606 | if (target->max_tx_bndl_sz) |
2520 | target->tx_bndl_enable = true; | 2607 | /* tx_bndl_mask is enabled per AC, each has 1 bit */ |
2608 | target->tx_bndl_mask = (1 << WMM_NUM_AC) - 1; | ||
2521 | 2609 | ||
2522 | if (target->max_rx_bndl_sz) | 2610 | if (target->max_rx_bndl_sz) |
2523 | target->rx_bndl_enable = true; | 2611 | target->rx_bndl_enable = true; |
@@ -2532,7 +2620,7 @@ static void htc_setup_msg_bndl(struct htc_target *target) | |||
2532 | * padding will spill into the next credit buffer | 2620 | * padding will spill into the next credit buffer |
2533 | * which is fatal. | 2621 | * which is fatal. |
2534 | */ | 2622 | */ |
2535 | target->tx_bndl_enable = false; | 2623 | target->tx_bndl_mask = 0; |
2536 | } | 2624 | } |
2537 | } | 2625 | } |
2538 | 2626 | ||
@@ -2589,8 +2677,8 @@ int ath6kl_htc_wait_target(struct htc_target *target) | |||
2589 | } | 2677 | } |
2590 | 2678 | ||
2591 | ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n", | 2679 | ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n", |
2592 | (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", | 2680 | (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", |
2593 | target->htc_tgt_ver); | 2681 | target->htc_tgt_ver); |
2594 | 2682 | ||
2595 | if (target->msg_per_bndl_max > 0) | 2683 | if (target->msg_per_bndl_max > 0) |
2596 | htc_setup_msg_bndl(target); | 2684 | htc_setup_msg_bndl(target); |
@@ -2784,14 +2872,14 @@ void ath6kl_htc_cleanup(struct htc_target *target) | |||
2784 | ath6kl_hif_cleanup_scatter(target->dev->ar); | 2872 | ath6kl_hif_cleanup_scatter(target->dev->ar); |
2785 | 2873 | ||
2786 | list_for_each_entry_safe(packet, tmp_packet, | 2874 | list_for_each_entry_safe(packet, tmp_packet, |
2787 | &target->free_ctrl_txbuf, list) { | 2875 | &target->free_ctrl_txbuf, list) { |
2788 | list_del(&packet->list); | 2876 | list_del(&packet->list); |
2789 | kfree(packet->buf_start); | 2877 | kfree(packet->buf_start); |
2790 | kfree(packet); | 2878 | kfree(packet); |
2791 | } | 2879 | } |
2792 | 2880 | ||
2793 | list_for_each_entry_safe(packet, tmp_packet, | 2881 | list_for_each_entry_safe(packet, tmp_packet, |
2794 | &target->free_ctrl_rxbuf, list) { | 2882 | &target->free_ctrl_rxbuf, list) { |
2795 | list_del(&packet->list); | 2883 | list_del(&packet->list); |
2796 | kfree(packet->buf_start); | 2884 | kfree(packet->buf_start); |
2797 | kfree(packet); | 2885 | kfree(packet); |