21 #define HTC_PACKET_CONTAINER_ALLOCATION 32
22 #define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH)
42 if (list_empty(queue_to_indicate)) {
49 "%s: calling ep %d, send complete multiple callback (%d pkts)\n",
51 get_queue_depth(queue_to_indicate));
56 ep->
ep_cb.tx_comp_multi(ep->
target, queue_to_indicate);
61 INIT_LIST_HEAD(queue_to_indicate);
70 "%s: calling ep %d send complete callback on packet 0x%p\n",
71 __func__, ep->
eid, packet);
73 }
while (!list_empty(queue_to_indicate));
83 restore_tx_packet(packet);
84 INIT_LIST_HEAD(&container);
88 do_send_completion(ep, &container);
99 unsigned int transfer_len;
106 if (list_empty(&ep->
txq))
113 "%s: got head packet:0x%p , queue depth: %d\n",
114 __func__, packet, get_queue_depth(&ep->
txq));
118 if (transfer_len <= target->tgt_cred_sz) {
119 credits_required = 1;
122 credits_required = transfer_len / target->
tgt_cred_sz;
130 __func__, credits_required, ep->
cred_dist.credits);
137 credits_required = 0;
141 if (ep->
cred_dist.credits < credits_required)
144 ep->
cred_dist.credits -= credits_required;
145 ep->
ep_st.cred_cosumd += credits_required;
152 ep->
ep_st.cred_low_indicate += 1;
154 "%s: host needs credits\n",
164 packet->
info.
tx.cred_used = credits_required;
166 packet->
info.
tx.flags = send_flags;
175 static void get_htc_packet(
struct htc_target *target,
185 if (list_empty(&ep->
txq))
192 "%s: got packet:0x%p , new queue depth: %d\n",
193 __func__, packet, get_queue_depth(&ep->
txq));
195 packet->
info.
tx.flags = 0;
196 packet->
info.
tx.cred_used = 0;
205 static int htc_issue_packets(
struct htc_target *target,
216 "%s: queue: 0x%p, pkts %d\n", __func__,
217 pkt_queue, get_queue_depth(pkt_queue));
219 while (!list_empty(pkt_queue)) {
247 htc_hdr->
ctrl[0] = 0;
250 spin_lock_bh(&target->
tx_lock);
254 ep->
ep_st.tx_issued += 1;
255 spin_unlock_bh(&target->
tx_lock);
257 status = ath6kl_hif_pipe_send(target->
dev->ar,
268 "%s: failed status:%d\n",
271 spin_lock_bh(&target->
tx_lock);
276 spin_unlock_bh(&target->
tx_lock);
279 list_add(&packet->
list, pkt_queue);
286 while (!list_empty(pkt_queue)) {
289 "%s: failed pkt:0x%p status:%d\n",
290 __func__, packet, status);
297 send_packet_completion(target, packet);
312 int tx_resources,
overflow, txqueue_depth,
i, good_pkts;
317 (txq ==
NULL) ? 0 : get_queue_depth(txq));
320 INIT_LIST_HEAD(&send_queue);
328 if (list_empty(txq)) {
333 spin_lock_bh(&target->
tx_lock);
334 txqueue_depth = get_queue_depth(&ep->
txq);
335 spin_unlock_bh(&target->
tx_lock);
339 overflow = get_queue_depth(txq);
342 overflow = txqueue_depth;
343 overflow += get_queue_depth(txq);
351 "%s: Endpoint %d, TX queue will overflow :%d, Tx Depth:%d, Max:%d\n",
352 __func__, ep->
eid, overflow, txqueue_depth,
355 if ((overflow <= 0) ||
362 list_splice_tail_init(txq, &send_queue);
364 good_pkts = get_queue_depth(txq) -
overflow;
372 for (i = 0; i < good_pkts; i++) {
391 "%s: Indicat overflowed TX pkts: %p\n",
396 ep->
ep_st.tx_dropped += 1;
411 if (list_empty(&send_queue)) {
418 if (!ep->
pipe.tx_credit_flow_enabled) {
420 ath6kl_hif_pipe_get_free_queue_number(ar,
426 spin_lock_bh(&target->
tx_lock);
427 if (!list_empty(&send_queue)) {
429 list_splice_tail_init(&send_queue, &ep->
txq);
430 if (!list_empty(&send_queue)) {
432 spin_unlock_bh(&target->
tx_lock);
435 INIT_LIST_HEAD(&send_queue);
448 spin_unlock_bh(&target->
tx_lock);
460 if (get_queue_depth(&ep->
txq) == 0)
463 if (ep->
pipe.tx_credit_flow_enabled) {
471 get_htc_packet_credit_based(target, ep, &send_queue);
477 get_htc_packet(target, ep, &send_queue, tx_resources);
480 if (get_queue_depth(&send_queue) == 0) {
488 spin_unlock_bh(&target->
tx_lock);
491 htc_issue_packets(target, ep, &send_queue);
493 if (!ep->
pipe.tx_credit_flow_enabled) {
494 pipeid = ep->
pipe.pipeid_ul;
496 ath6kl_hif_pipe_get_free_queue_number(ar, pipeid);
499 spin_lock_bh(&target->
tx_lock);
504 spin_unlock_bh(&target->
tx_lock);
510 static void destroy_htc_txctrl_packet(
struct htc_packet *packet)
520 static struct htc_packet *build_htc_txctrl_packet(
void)
540 static void htc_free_txctrl_packet(
struct htc_target *target,
543 destroy_htc_txctrl_packet(packet);
548 return build_htc_txctrl_packet();
551 static void htc_txctrl_complete(
struct htc_target *target,
554 htc_free_txctrl_packet(target, packet);
557 #define MAX_MESSAGE_SIZE 1536
559 static int htc_setup_target_buffer_assignments(
struct htc_target *target)
561 int status, credits, credit_per_maxmsg,
i;
563 unsigned int hif_usbaudioclass = 0;
572 entry = &target->
pipe.txcredit_alloc[0];
577 if (hif_usbaudioclass) {
579 "%s: For USB Audio Class- Total:%d\n",
650 if (target->
pipe.txcredit_alloc[i].service_id != 0) {
652 "HTC Service Index : %d TX : 0x%2.2X : alloc:%d\n",
654 target->
pipe.txcredit_alloc[i].
656 target->
pipe.txcredit_alloc[i].
665 static void htc_process_credit_report(
struct htc_target *target,
670 int total_credits = 0,
i;
674 spin_lock_bh(&target->
tx_lock);
679 spin_unlock_bh(&target->
tx_lock);
686 if (ep->
cred_dist.credits && get_queue_depth(&ep->
txq)) {
687 spin_unlock_bh(&target->
tx_lock);
688 htc_try_send(target, ep,
NULL);
689 spin_lock_bh(&target->
tx_lock);
695 "Report indicated %d credits to distribute\n",
698 spin_unlock_bh(&target->
tx_lock);
702 static void htc_flush_tx_endpoint(
struct htc_target *target,
707 spin_lock_bh(&target->
tx_lock);
708 while (get_queue_depth(&ep->
txq)) {
712 send_packet_completion(target, packet);
714 spin_unlock_bh(&target->
tx_lock);
730 spin_lock_bh(&target->
tx_lock);
740 if (skb == packet->
skb) {
743 found_packet = packet;
748 spin_unlock_bh(&target->
tx_lock);
753 static int ath6kl_htc_pipe_tx_complete(
struct ath6kl *ar,
struct sk_buff *skb)
767 ep_id = htc_hdr->
eid;
770 packet = htc_lookup_tx_packet(target, ep, skb);
771 if (packet ==
NULL) {
777 send_packet_completion(target, packet);
781 if (!ep->
pipe.tx_credit_flow_enabled) {
787 htc_try_send(target, ep,
NULL);
793 static int htc_send_packets_multiple(
struct htc_target *target,
799 if (list_empty(pkt_queue))
811 htc_try_send(target, ep, pkt_queue);
814 if (!list_empty(pkt_queue)) {
819 do_send_completion(ep, pkt_queue);
829 spin_lock_bh(&target->
rx_lock);
831 if (target->
pipe.htc_packet_pool ==
NULL) {
832 spin_unlock_bh(&target->
rx_lock);
836 packet = target->
pipe.htc_packet_pool;
839 spin_unlock_bh(&target->
rx_lock);
845 static void free_htc_packet_container(
struct htc_target *target,
850 spin_lock_bh(&target->
rx_lock);
852 if (target->
pipe.htc_packet_pool ==
NULL) {
853 target->
pipe.htc_packet_pool = packet;
857 packet->
list.next = lh;
858 target->
pipe.htc_packet_pool = packet;
861 spin_unlock_bh(&target->
rx_lock);
869 u8 *record_buf, *orig_buf;
887 if (record->
len > len) {
890 "invalid length: %d (id:%d) buffer has: %d bytes left\n",
907 htc_process_credit_report(target, report,
908 record->
len /
sizeof(*report),
913 "unhandled record: id:%d length:%d\n",
922 buffer += record->
len;
934 if (list_empty(queue_to_indicate)) {
940 while (!list_empty(queue_to_indicate)) {
950 static void recv_packet_completion(
struct htc_target *target,
955 INIT_LIST_HEAD(&container);
959 do_recv_completion(ep, &container);
962 static int ath6kl_htc_pipe_rx_complete(
struct ath6kl *ar,
struct sk_buff *skb,
966 u8 *netdata, *trailer, hdr_info;
968 u32 netlen, trailerlen = 0;
983 "HTC Rx: invalid EndpointID=%d\n",
993 "HTC Rx: insufficient length, got:%d expected =%u\n",
1000 hdr_info = htc_hdr->
flags;
1003 hdr_info = htc_hdr->
ctrl[0];
1005 (hdr_info > payload_len)) {
1007 "invalid header: payloadlen should be %d, CB[0]: %d\n",
1008 payload_len, hdr_info);
1013 trailerlen = hdr_info;
1016 payload_len - hdr_info;
1017 status = htc_process_trailer(target, trailer, hdr_info,
1023 if (((
int) payload_len - (
int) trailerlen) <= 0) {
1036 "HTC ignores Rx Ctrl after setup complete\n");
1044 netdata = skb->
data;
1047 spin_lock_bh(&target->
rx_lock);
1049 target->
pipe.ctrl_response_valid =
true;
1050 target->
pipe.ctrl_response_len =
min_t(
int, netlen,
1052 memcpy(target->
pipe.ctrl_response_buf, netdata,
1053 target->
pipe.ctrl_response_len);
1055 spin_unlock_bh(&target->
rx_lock);
1067 packet = alloc_htc_packet_container(target);
1068 if (packet ==
NULL) {
1087 recv_packet_completion(target, ep, packet);
1090 free_htc_packet_container(target, packet);
1101 static void htc_flush_rx_queue(
struct htc_target *target,
1107 spin_lock_bh(&target->
rx_lock);
1117 spin_unlock_bh(&target->
rx_lock);
1122 "Flushing RX packet:0x%p, length:%d, ep:%d\n",
1126 INIT_LIST_HEAD(&container);
1130 do_recv_completion(ep, &container);
1131 spin_lock_bh(&target->
rx_lock);
1134 spin_unlock_bh(&target->
rx_lock);
1138 static int htc_wait_recv_ctrl_message(
struct htc_target *target)
1143 spin_lock_bh(&target->
rx_lock);
1145 if (target->
pipe.ctrl_response_valid) {
1146 target->
pipe.ctrl_response_valid =
false;
1147 spin_unlock_bh(&target->
rx_lock);
1151 spin_unlock_bh(&target->
rx_lock);
1170 ath6kl_dbg(
ATH6KL_DBG_HTC,
"%s: invalid call function\n", __func__);
1174 static void reset_endpoint_states(
struct htc_target *target)
1185 INIT_LIST_HEAD(&ep->
txq);
1186 INIT_LIST_HEAD(&ep->
pipe.tx_lookup_queue);
1189 ep->
pipe.tx_credit_flow_enabled = (
bool) 1;
1194 static int htc_config_target_hif_pipe(
struct htc_target *target)
1206 if (target->
pipe.txcredit_alloc[i].service_id == service_id)
1208 target->
pipe.txcredit_alloc[
i].credit_alloc;
1211 if (allocation == 0) {
1213 "HTC Service TX : 0x%2.2X : allocation is zero!\n",
1220 static int ath6kl_htc_pipe_conn_service(
struct htc_target *target,
1229 bool disable_credit_flowctrl =
false;
1230 unsigned int max_msg_size = 0;
1237 if (conn_req->
svc_id == 0) {
1251 tx_alloc = htc_get_credit_alloc(target, conn_req->
svc_id);
1252 if (tx_alloc == 0) {
1258 packet = htc_alloc_txctrl_packet(target);
1260 if (packet ==
NULL) {
1272 if (conn_msg ==
NULL) {
1291 disable_credit_flowctrl =
true;
1294 set_htc_pkt_info(packet,
NULL, (
u8 *) conn_msg,
1298 status = ath6kl_htc_pipe_tx(target, packet);
1306 status = htc_wait_recv_ctrl_message(target);
1314 target->
pipe.ctrl_response_buf;
1317 (target->
pipe.ctrl_response_len <
sizeof(*resp_msg))) {
1325 "%s: service 0x%X conn resp: status: %d ep: %d\n",
1333 "Target failed service 0x%X connect request (status:%d)\n",
1346 if (assigned_epid >= ENDPOINT_MAX) {
1351 if (max_msg_size == 0) {
1356 ep = &target->
endpoint[assigned_epid];
1357 ep->
eid = assigned_epid;
1365 conn_resp->
endpoint = assigned_epid;
1366 conn_resp->
len_max = max_msg_size;
1384 status = ath6kl_hif_pipe_map_service(ar, ep->
svc_id,
1385 &ep->
pipe.pipeid_ul,
1386 &ep->
pipe.pipeid_dl);
1391 "SVC Ready: 0x%4.4X: ULpipe:%d DLpipe:%d id:%d\n",
1395 if (disable_credit_flowctrl && ep->
pipe.tx_credit_flow_enabled) {
1396 ep->
pipe.tx_credit_flow_enabled =
false;
1398 "SVC: 0x%4.4X ep:%d TX flow control off\n",
1399 ep->
svc_id, assigned_epid);
1404 htc_free_txctrl_packet(target, packet);
1409 static void *ath6kl_htc_pipe_create(
struct ath6kl *ar)
1418 if (target ==
NULL) {
1419 ath6kl_err(
"htc create unable to allocate memory\n");
1421 goto fail_htc_create;
1428 reset_endpoint_states(target);
1434 free_htc_packet_container(target, packet);
1441 goto fail_htc_create;
1443 target->
dev->ar =
ar;
1449 ath6kl_hif_pipe_get_default(ar, &ep->
pipe.pipeid_ul,
1450 &ep->
pipe.pipeid_dl);
1457 ath6kl_htc_pipe_cleanup(target);
1465 static void ath6kl_htc_pipe_cleanup(
struct htc_target *target)
1470 packet = alloc_htc_packet_container(target);
1482 static int ath6kl_htc_pipe_start(
struct htc_target *target)
1488 htc_config_target_hif_pipe(target);
1491 packet = htc_alloc_txctrl_packet(target);
1492 if (packet ==
NULL) {
1505 ath6kl_dbg(
ATH6KL_DBG_HTC,
"HTC using TX credit flow control\n");
1507 set_htc_pkt_info(packet,
NULL, (
u8 *) setup,
1513 return ath6kl_htc_pipe_tx(target, packet);
1516 static void ath6kl_htc_pipe_stop(
struct htc_target *target)
1524 htc_flush_rx_queue(target, ep);
1528 reset_endpoint_states(target);
1532 static int ath6kl_htc_pipe_get_rxbuf_num(
struct htc_target *target,
1537 spin_lock_bh(&target->
rx_lock);
1538 num = get_queue_depth(&(target->
endpoint[endpoint].rx_bufq));
1539 spin_unlock_bh(&target->
rx_lock);
1544 static int ath6kl_htc_pipe_tx(
struct htc_target *target,
1550 "%s: endPointId: %d, buffer: 0x%p, length: %d\n",
1554 INIT_LIST_HEAD(&queue);
1557 return htc_send_packets_multiple(target, &queue);
1560 static int ath6kl_htc_pipe_wait_target(
struct htc_target *target)
1567 status = htc_wait_recv_ctrl_message(target);
1572 if (target->
pipe.ctrl_response_len <
sizeof(*ready_msg)) {
1574 target->
pipe.ctrl_response_len);
1587 "Target Ready! : transmit resources : %d size:%d\n",
1597 htc_setup_target_buffer_assignments(target);
1600 memset(&connect, 0,
sizeof(connect));
1602 connect.ep_cb.tx_complete = htc_txctrl_complete;
1603 connect.ep_cb.rx = htc_rxctrl_complete;
1608 status = ath6kl_htc_pipe_conn_service(target, &connect, &
resp);
1613 static void ath6kl_htc_pipe_flush_txep(
struct htc_target *target,
1624 htc_flush_tx_endpoint(target, ep, tag);
1627 static int ath6kl_htc_pipe_add_rxbuf_multiple(
struct htc_target *target,
1634 if (list_empty(pkt_queue))
1639 if (first->
endpoint >= ENDPOINT_MAX) {
1645 __func__, first->
endpoint, get_queue_depth(pkt_queue),
1650 spin_lock_bh(&target->
rx_lock);
1653 list_splice_tail_init(pkt_queue, &ep->
rx_bufq);
1655 spin_unlock_bh(&target->
rx_lock);
1663 do_recv_completion(ep, pkt_queue);
1669 static void ath6kl_htc_pipe_activity_changed(
struct htc_target *target,
1676 static void ath6kl_htc_pipe_flush_rx_buf(
struct htc_target *target)
1681 static int ath6kl_htc_pipe_credit_setup(
struct htc_target *target,
1688 .create = ath6kl_htc_pipe_create,
1689 .wait_target = ath6kl_htc_pipe_wait_target,
1690 .start = ath6kl_htc_pipe_start,
1691 .conn_service = ath6kl_htc_pipe_conn_service,
1692 .tx = ath6kl_htc_pipe_tx,
1693 .stop = ath6kl_htc_pipe_stop,
1694 .cleanup = ath6kl_htc_pipe_cleanup,
1695 .flush_txep = ath6kl_htc_pipe_flush_txep,
1696 .flush_rx_buf = ath6kl_htc_pipe_flush_rx_buf,
1697 .activity_changed = ath6kl_htc_pipe_activity_changed,
1698 .get_rxbuf_num = ath6kl_htc_pipe_get_rxbuf_num,
1699 .add_rxbuf_multiple = ath6kl_htc_pipe_add_rxbuf_multiple,
1700 .credit_setup = ath6kl_htc_pipe_credit_setup,
1701 .tx_complete = ath6kl_htc_pipe_tx_complete,
1702 .rx_complete = ath6kl_htc_pipe_rx_complete,
1707 ar->
htc_ops = &ath6kl_htc_pipe_ops;