1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "htc_internal.h"
24
25typedef enum _HTC_SEND_QUEUE_RESULT {
26 HTC_SEND_QUEUE_OK = 0,
27 HTC_SEND_QUEUE_DROP = 1,
28} HTC_SEND_QUEUE_RESULT;
29
30#define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q)
31
32
33#define DO_DISTRIBUTION(t,reason,description,pList) \
34{ \
35 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
36 (" calling distribute function (%s) (dfn:0x%lX, ctxt:0x%lX, dist:0x%lX) \n", \
37 (description), \
38 (unsigned long)(t)->DistributeCredits, \
39 (unsigned long)(t)->pCredDistContext, \
40 (unsigned long)pList)); \
41 (t)->DistributeCredits((t)->pCredDistContext, \
42 (pList), \
43 (reason)); \
44}
45
46static void DoSendCompletion(HTC_ENDPOINT *pEndpoint,
47 HTC_PACKET_QUEUE *pQueueToIndicate)
48{
49 do {
50
51 if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
52
53 break;
54 }
55
56 if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) {
57 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n",
58 pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
59
60 pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext,
61 pQueueToIndicate);
62
63 INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
64 } else {
65 HTC_PACKET *pPacket;
66
67 do {
68 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
69 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet 0x%lX \n", \
70 pEndpoint->Id, (unsigned long)(pPacket)));
71 pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
72 } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
73 }
74
75 } while (FALSE);
76
77}
78
79
80static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET *pPacket)
81{
82 pPacket->Completion = NULL;
83
84 if (A_FAILED(pPacket->Status)) {
85 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
86 ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n",
87 pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed));
88
89 LOCK_HTC_TX(target);
90 pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUsed;
91 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
92 DO_DISTRIBUTION(target,
93 HTC_CREDIT_DIST_SEND_COMPLETE,
94 "Send Complete",
95 target->EpCreditDistributionListHead->pNext);
96 UNLOCK_HTC_TX(target);
97 }
98
99 pPacket->pBuffer += HTC_HDR_LENGTH;
100}
101
102
103
104static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
105{
106 HTC_TARGET *target = (HTC_TARGET *)Context;
107 HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
108 HTC_PACKET_QUEUE container;
109
110 CompleteSentPacket(target,pEndpoint,pPacket);
111 INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
112
113 DO_EP_TX_COMPLETION(pEndpoint,&container);
114}
115
116A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
117{
118 A_STATUS status;
119 A_BOOL sync = FALSE;
120
121 if (pPacket->Completion == NULL) {
122
123 sync = TRUE;
124 }
125
126 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
127 ("+-HTCIssueSend: transmit length : %d (%s) \n",
128 pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH,
129 sync ? "SYNC" : "ASYNC" ));
130
131
132 status = DevSendPacket(&target->Device,
133 pPacket,
134 pPacket->ActualLength + HTC_HDR_LENGTH);
135
136 if (sync) {
137
138
139 pPacket->pBuffer += HTC_HDR_LENGTH;
140 }
141
142
143
144
145 return status;
146}
147
148
149static INLINE void GetHTCSendPackets(HTC_TARGET *target,
150 HTC_ENDPOINT *pEndpoint,
151 HTC_PACKET_QUEUE *pQueue)
152{
153 int creditsRequired;
154 int remainder;
155 A_UINT8 sendFlags;
156 HTC_PACKET *pPacket;
157 unsigned int transferLength;
158
159
160 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
161
162
163 while (TRUE) {
164
165 sendFlags = 0;
166
167 pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
168 if (pPacket == NULL) {
169 break;
170 }
171
172 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%lX , Queue Depth: %d\n",
173 (unsigned long)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
174
175 transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->ActualLength + HTC_HDR_LENGTH);
176
177 if (transferLength <= target->TargetCreditSize) {
178 creditsRequired = 1;
179 } else {
180
181 creditsRequired = transferLength / target->TargetCreditSize;
182 remainder = transferLength % target->TargetCreditSize;
183
184 if (remainder) {
185 creditsRequired++;
186 }
187 }
188
189 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
190 creditsRequired, pEndpoint->CreditDist.TxCredits));
191
192 if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
193
194
195 if (pPacket->Endpoint == ENDPOINT_0) {
196
197 break;
198 }
199
200
201
202
203
204
205 pEndpoint->CreditDist.TxCreditsSeek =
206 creditsRequired - pEndpoint->CreditDist.TxCredits;
207 DO_DISTRIBUTION(target,
208 HTC_CREDIT_DIST_SEEK_CREDITS,
209 "Seek Credits",
210 &pEndpoint->CreditDist);
211 pEndpoint->CreditDist.TxCreditsSeek = 0;
212
213 if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
214
215 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
216 (" Not enough credits for ep %d leaving packet in queue..\n",
217 pPacket->Endpoint));
218 break;
219 }
220
221 }
222
223 pEndpoint->CreditDist.TxCredits -= creditsRequired;
224 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
225
226
227 if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
228
229 pEndpoint->CreditDist.TxCreditsSeek =
230 pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits;
231
232 DO_DISTRIBUTION(target,
233 HTC_CREDIT_DIST_SEEK_CREDITS,
234 "Seek Credits",
235 &pEndpoint->CreditDist);
236
237 pEndpoint->CreditDist.TxCreditsSeek = 0;
238
239 if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
240
241 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
242 INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
243 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
244 }
245 }
246
247
248 pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
249
250 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
251
252 pPacket->Completion = HTCSendPktCompletionHandler;
253 pPacket->pContext = target;
254 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
255
256 pPacket->PktInfo.AsTx.SendFlags = sendFlags;
257 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
258 pEndpoint->SeqNo++;
259
260 HTC_PACKET_ENQUEUE(pQueue,pPacket);
261 }
262
263 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n"));
264
265}
266
267static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
268{
269 int i;
270 HTC_PACKET *pPacket;
271 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pScatterReq->Context;
272 HTC_TARGET *target = (HTC_TARGET *)pEndpoint->target;
273 A_STATUS status = A_OK;
274 HTC_PACKET_QUEUE sendCompletes;
275
276 INIT_HTC_PACKET_QUEUE(&sendCompletes);
277
278 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n",
279 pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
280
281 DEV_FINISH_SCATTER_OPERATION(pScatterReq);
282
283 if (A_FAILED(pScatterReq->CompletionStatus)) {
284 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
285 status = A_ERROR;
286 }
287
288
289 for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
290 pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
291 A_ASSERT(pPacket != NULL);
292 pPacket->Status = status;
293 CompleteSentPacket(target,pEndpoint,pPacket);
294
295 HTC_PACKET_ENQUEUE(&sendCompletes, pPacket);
296 }
297
298
299 DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
300
301 DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes);
302
303 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n"));
304}
305
306
307
308
309
310
311
312static void HTCIssueSendBundle(HTC_ENDPOINT *pEndpoint,
313 HTC_PACKET_QUEUE *pQueue,
314 int *pBundlesSent,
315 int *pTotalBundlesPkts)
316{
317 int pktsToScatter;
318 unsigned int scatterSpaceRemaining;
319 HIF_SCATTER_REQ *pScatterReq = NULL;
320 int i, packetsInScatterReq;
321 unsigned int transferLength;
322 HTC_PACKET *pPacket;
323 A_BOOL done = FALSE;
324 int bundlesSent = 0;
325 int totalPktsInBundle = 0;
326 HTC_TARGET *target = pEndpoint->target;
327 int creditRemainder = 0;
328 int creditPad;
329
330 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n"));
331
332 while (!done) {
333
334 pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue);
335 pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
336
337 if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
338
339 break;
340 }
341
342 pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
343
344 if (pScatterReq == NULL) {
345
346 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n"));
347 break;
348 }
349
350 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatter));
351
352 pScatterReq->TotalLength = 0;
353 pScatterReq->ValidScatterEntries = 0;
354
355 packetsInScatterReq = 0;
356 scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device);
357
358 for (i = 0; i < pktsToScatter; i++) {
359
360 pScatterReq->ScatterList[i].pCallerContexts[0] = NULL;
361
362 pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
363 if (pPacket == NULL) {
364 A_ASSERT(FALSE);
365 break;
366 }
367
368 creditPad = 0;
369 transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device,
370 pPacket->ActualLength + HTC_HDR_LENGTH);
371
372 creditRemainder = transferLength % target->TargetCreditSize;
373
374 if (creditRemainder != 0) {
375
376
377
378 if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING) {
379 if (transferLength < target->TargetCreditSize) {
380
381 creditPad = target->TargetCreditSize - transferLength;
382 } else {
383 creditPad = creditRemainder;
384 }
385
386
387 if ((creditPad > 0) && (creditPad <= 255)) {
388
389 transferLength += creditPad;
390 } else {
391
392
393 pPacket = NULL;
394 }
395 } else {
396
397 pPacket = NULL;
398 }
399 }
400
401 if (NULL == pPacket) {
402
403 done = TRUE;
404 break;
405 }
406
407 if (scatterSpaceRemaining < transferLength) {
408
409 break;
410 }
411
412 scatterSpaceRemaining -= transferLength;
413
414 pPacket = HTC_PACKET_DEQUEUE(pQueue);
415
416 pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
417
418 HTC_PREPARE_SEND_PKT(pPacket,
419 pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE,
420 creditPad,
421 pPacket->PktInfo.AsTx.SeqNo);
422 pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
423 pScatterReq->ScatterList[i].Length = transferLength;
424 A_ASSERT(transferLength);
425 pScatterReq->TotalLength += transferLength;
426 pScatterReq->ValidScatterEntries++;
427 packetsInScatterReq++;
428 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%lX, len:%d (remaining space:%d) \n",
429 i, (unsigned long)pPacket,transferLength,scatterSpaceRemaining));
430 }
431
432 if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) {
433
434 pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion;
435 pScatterReq->Context = pEndpoint;
436 bundlesSent++;
437 totalPktsInBundle += packetsInScatterReq;
438 packetsInScatterReq = 0;
439 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , entries: %d\n",
440 pScatterReq->TotalLength,pScatterReq->ValidScatterEntries));
441 DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WRITE, DEV_SCATTER_ASYNC);
442
443 pScatterReq = NULL;
444
445 continue;
446 }
447
448
449 if (pScatterReq != NULL) {
450 if (packetsInScatterReq > 0) {
451
452 for (i = (packetsInScatterReq - 1); i >= 0; i--) {
453 pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
454 if (pPacket != NULL) {
455
456 HTC_UNPREPARE_SEND_PKT(pPacket);
457
458 HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket);
459 }
460 }
461 }
462 DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
463 }
464
465
466 break;
467
468 }
469
470 *pBundlesSent = bundlesSent;
471 *pTotalBundlesPkts = totalPktsInBundle;
472 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSent));
473
474 return;
475}
476
477
478
479
480static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target,
481 HTC_ENDPOINT *pEndpoint,
482 HTC_PACKET_QUEUE *pCallersSendQueue)
483{
484 HTC_PACKET_QUEUE sendQueue;
485 HTC_PACKET *pPacket;
486 int bundlesSent;
487 int pktsInBundles;
488 int overflow;
489 HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
490
491 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%lX Depth:%d)\n",
492 (unsigned long)pCallersSendQueue,
493 (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue)));
494
495
496 INIT_HTC_PACKET_QUEUE(&sendQueue);
497
498 do {
499
500 if (NULL == pCallersSendQueue) {
501
502 break;
503 }
504
505 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
506
507 result = HTC_SEND_QUEUE_DROP;
508 break;
509 }
510
511 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) {
512
513 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
514 } else {
515
516 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
517 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
518
519 overflow -= pEndpoint->MaxTxQueueDepth;
520 }
521
522
523 if (overflow > 0) {
524 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
525 (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n",
526 pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth));
527 }
528 if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) {
529
530
531 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue);
532 } else {
533 int i;
534 int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow;
535
536 A_ASSERT(goodPkts >= 0);
537
538
539 for (i = 0; i < goodPkts; i++) {
540
541 pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue);
542 A_ASSERT(pPacket != NULL);
543
544 HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
545 }
546
547
548
549 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, HTC_PACKET, ListLink) {
550
551 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n",
552 (unsigned long)pPacket));
553 if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext,
554 pPacket) == HTC_SEND_FULL_DROP) {
555
556 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
557
558 } else {
559
560 HTC_PACKET_REMOVE(pCallersSendQueue, pPacket);
561
562 HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
563 }
564
565 } ITERATE_END;
566
567 if (HTC_QUEUE_EMPTY(&sendQueue)) {
568
569 result = HTC_SEND_QUEUE_DROP;
570 break;
571 }
572 }
573
574 } while (FALSE);
575
576 if (result != HTC_SEND_QUEUE_OK) {
577 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
578 return result;
579 }
580
581 LOCK_HTC_TX(target);
582
583 if (!HTC_QUEUE_EMPTY(&sendQueue)) {
584
585 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue);
586 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
587 INIT_HTC_PACKET_QUEUE(&sendQueue);
588 }
589
590
591 pEndpoint->TxProcessCount++;
592 if (pEndpoint->TxProcessCount > 1) {
593
594
595 pEndpoint->TxProcessCount--;
596 UNLOCK_HTC_TX(target);
597 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n"));
598 return HTC_SEND_QUEUE_OK;
599 }
600
601
602
603
604
605 while (TRUE) {
606
607 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
608 break;
609 }
610
611
612 GetHTCSendPackets(target, pEndpoint, &sendQueue);
613
614 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
615
616 break;
617 }
618
619 UNLOCK_HTC_TX(target);
620
621
622
623 bundlesSent = 0;
624 pktsInBundles = 0;
625
626 while (TRUE) {
627
628
629 if ((target->SendBundlingEnabled) &&
630 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
631 int temp1,temp2;
632
633
634 HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2);
635 bundlesSent += temp1;
636 pktsInBundles += temp2;
637 }
638
639
640
641 pPacket = HTC_PACKET_DEQUEUE(&sendQueue);
642 if (NULL == pPacket) {
643
644 break;
645 }
646 HTC_PREPARE_SEND_PKT(pPacket,
647 pPacket->PktInfo.AsTx.SendFlags,
648 0,
649 pPacket->PktInfo.AsTx.SeqNo);
650 HTCIssueSend(target, pPacket);
651
652
653 }
654
655 LOCK_HTC_TX(target);
656
657 INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent);
658 INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles);
659
660 }
661
662
663 pEndpoint->TxProcessCount = 0;
664 UNLOCK_HTC_TX(target);
665
666 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
667
668 return HTC_SEND_QUEUE_OK;
669}
670
671A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
672{
673 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
674 HTC_ENDPOINT *pEndpoint;
675 HTC_PACKET *pPacket;
676
677 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n",
678 (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
679
680
681 pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
682 if (NULL == pPacket) {
683 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
684 return A_EINVAL;
685 }
686
687 AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
688 pEndpoint = &target->EndPoint[pPacket->Endpoint];
689
690 HTCTrySend(target, pEndpoint, pPktQueue);
691
692
693 if (!HTC_QUEUE_EMPTY(pPktQueue)) {
694
695 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
696 if (HTC_STOPPING(target)) {
697 pPacket->Status = A_ECANCELED;
698 } else {
699 pPacket->Status = A_NO_RESOURCE;
700 }
701 } HTC_PACKET_QUEUE_ITERATE_END;
702
703 DO_EP_TX_COMPLETION(pEndpoint,pPktQueue);
704 }
705
706 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
707
708 return A_OK;
709}
710
711
712A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
713{
714 HTC_PACKET_QUEUE queue;
715
716 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
717 ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n",
718 pPacket->Endpoint, (unsigned long)pPacket->pBuffer, pPacket->ActualLength));
719 INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
720 return HTCSendPktsMultiple(HTCHandle, &queue);
721}
722
723
724static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
725{
726 HTC_ENDPOINT *pEndpoint;
727 HTC_ENDPOINT_CREDIT_DIST *pDistItem;
728
729 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
730 pDistItem = target->EpCreditDistributionListHead;
731
732
733
734
735
736 while (pDistItem != NULL) {
737 pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
738
739 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
740 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
741 pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
742
743
744
745
746 HTCTrySend(target, pEndpoint, NULL);
747 }
748
749 pDistItem = pDistItem->pNext;
750 }
751
752 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
753}
754
755
756void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
757{
758 int i;
759 HTC_ENDPOINT *pEndpoint;
760 int totalCredits = 0;
761 A_BOOL doDist = FALSE;
762
763 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
764
765
766 LOCK_HTC_TX(target);
767
768 for (i = 0; i < NumEntries; i++, pRpt++) {
769 if (pRpt->EndpointID >= ENDPOINT_MAX) {
770 AR_DEBUG_ASSERT(FALSE);
771 break;
772 }
773
774 pEndpoint = &target->EndPoint[pRpt->EndpointID];
775
776 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
777 pRpt->EndpointID, pRpt->Credits));
778
779
780#ifdef HTC_EP_STAT_PROFILING
781
782 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
783 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
784
785 if (FromEndpoint == pRpt->EndpointID) {
786
787
788 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
789 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
790 } else if (FromEndpoint == ENDPOINT_0) {
791
792 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
793 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
794 } else {
795
796 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
797 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
798 }
799
800#endif
801
802 if (ENDPOINT_0 == pRpt->EndpointID) {
803
804 pEndpoint->CreditDist.TxCredits += pRpt->Credits;
805 } else {
806
807
808 pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
809
810 doDist = TRUE;
811 }
812
813
814
815 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
816
817 totalCredits += pRpt->Credits;
818 }
819
820 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
821
822 if (doDist) {
823
824
825 DO_DISTRIBUTION(target,
826 HTC_CREDIT_DIST_SEND_COMPLETE,
827 "Send Complete",
828 target->EpCreditDistributionListHead->pNext);
829 }
830
831 UNLOCK_HTC_TX(target);
832
833 if (totalCredits) {
834 HTCCheckEndpointTxQueues(target);
835 }
836
837 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
838}
839
840
841static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
842{
843 HTC_PACKET *pPacket;
844 HTC_PACKET_QUEUE discardQueue;
845 HTC_PACKET_QUEUE container;
846
847
848 INIT_HTC_PACKET_QUEUE(&discardQueue);
849
850 LOCK_HTC_TX(target);
851
852
853 ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, HTC_PACKET, ListLink) {
854
855
856 if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
857
858 HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket);
859
860 HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
861 }
862
863 } ITERATE_END;
864
865 UNLOCK_HTC_TX(target);
866
867
868 while (1) {
869 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
870 if (NULL == pPacket) {
871 break;
872 }
873 pPacket->Status = A_ECANCELED;
874 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%lX, length:%d, ep:%d tag:0x%X \n",
875 (unsigned long)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag));
876 INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
877 DO_EP_TX_COMPLETION(pEndpoint,&container);
878 }
879
880}
881
882void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
883{
884 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n",
885 pEPDist->Endpoint, pEPDist->ServiceID));
886 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%lX next:0x%lX prev:0x%lX\n",
887 (unsigned long)pEPDist, (unsigned long)pEPDist->pNext, (unsigned long)pEPDist->pPrev));
888 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags));
889 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm));
890 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin));
891 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits));
892 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned));
893 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek));
894 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize));
895 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
896 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist));
897 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n",
898 HTC_PACKET_QUEUE_DEPTH(&((HTC_ENDPOINT *)pEPDist->pHTCReserved)->TxQueue)));
899 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
900}
901
902void DumpCreditDistStates(HTC_TARGET *target)
903{
904 HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
905
906 while (pEPList != NULL) {
907 DumpCreditDist(pEPList);
908 pEPList = pEPList->pNext;
909 }
910
911 if (target->DistributeCredits != NULL) {
912 DO_DISTRIBUTION(target,
913 HTC_DUMP_CREDIT_STATE,
914 "Dump State",
915 NULL);
916 }
917}
918
919
920void HTCFlushSendPkts(HTC_TARGET *target)
921{
922 HTC_ENDPOINT *pEndpoint;
923 int i;
924
925 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
926 DumpCreditDistStates(target);
927 }
928
929 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
930 pEndpoint = &target->EndPoint[i];
931 if (pEndpoint->ServiceID == 0) {
932
933 continue;
934 }
935 HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
936 }
937
938
939}
940
941
942void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
943{
944 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
945 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
946
947 if (pEndpoint->ServiceID == 0) {
948 AR_DEBUG_ASSERT(FALSE);
949
950 return;
951 }
952
953 HTCFlushEndpointTX(target, pEndpoint, Tag);
954}
955
956
957void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
958 HTC_ENDPOINT_ID Endpoint,
959 A_BOOL Active)
960{
961 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
962 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
963 A_BOOL doDist = FALSE;
964
965 if (pEndpoint->ServiceID == 0) {
966 AR_DEBUG_ASSERT(FALSE);
967
968 return;
969 }
970
971 LOCK_HTC_TX(target);
972
973 if (Active) {
974 if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
975
976 pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
977 doDist = TRUE;
978 }
979 } else {
980 if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
981
982 pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
983 doDist = TRUE;
984 }
985 }
986
987 if (doDist) {
988
989 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
990
991
992 DO_DISTRIBUTION(target,
993 HTC_CREDIT_DIST_ACTIVITY_CHANGE,
994 "Activity Change",
995 target->EpCreditDistributionListHead->pNext);
996 }
997
998 UNLOCK_HTC_TX(target);
999
1000 if (doDist && !Active) {
1001
1002
1003
1004 HTCCheckEndpointTxQueues(target);
1005 }
1006}
1007
1008A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle,
1009 HTC_ENDPOINT_ID Endpoint)
1010{
1011 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1012 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
1013
1014 if (pEndpoint->ServiceID == 0) {
1015 return FALSE;
1016 }
1017
1018 if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
1019 return TRUE;
1020 }
1021
1022 return FALSE;
1023}
1024