htc_send.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. //------------------------------------------------------------------------------
  2. // <copyright file="htc_send.c" company="Atheros">
  3. // Copyright (c) 2007-2008 Atheros Corporation. All rights reserved.
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License version 2 as
  7. // published by the Free Software Foundation;
  8. //
  9. // Software distributed under the License is distributed on an "AS
  10. // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11. // implied. See the License for the specific language governing
  12. // rights and limitations under the License.
  13. //
  14. //
  15. //------------------------------------------------------------------------------
  16. //==============================================================================
  17. // Author(s): ="Atheros"
  18. //==============================================================================
  19. #include "htc_internal.h"
  20. typedef enum _HTC_SEND_QUEUE_RESULT {
  21. HTC_SEND_QUEUE_OK = 0, /* packet was queued */
  22. HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
  23. } HTC_SEND_QUEUE_RESULT;
  24. #define DO_EP_TX_COMPLETION(ep,p) \
  25. { \
  26. (p)->Completion = NULL; \
  27. (ep)->EpCallBacks.EpTxComplete((ep)->EpCallBacks.pContext,(p)); \
  28. }
  29. /* call the distribute credits callback with the distribution */
  30. #define DO_DISTRIBUTION(t,reason,description,pList) \
  31. { \
  32. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
  33. (" calling distribute function (%s) (dfn:0x%X, ctxt:0x%X, dist:0x%X) \n", \
  34. (description), \
  35. (A_UINT32)(t)->DistributeCredits, \
  36. (A_UINT32)(t)->pCredDistContext, \
  37. (A_UINT32)pList)); \
  38. (t)->DistributeCredits((t)->pCredDistContext, \
  39. (pList), \
  40. (reason)); \
  41. }
  42. /* our internal send packet completion handler when packets are submited to the AR6K device
  43. * layer */
  44. static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
  45. {
  46. HTC_TARGET *target = (HTC_TARGET *)Context;
  47. HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
  48. if (A_FAILED(pPacket->Status)) {
  49. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  50. ("HTCSendPktCompletionHandler: request failed (status:%d, ep:%d) \n",
  51. pPacket->Status, pPacket->Endpoint));
  52. }
  53. /* first, fixup the head room we allocated */
  54. pPacket->pBuffer += HTC_HDR_LENGTH;
  55. /* do completion */
  56. DO_EP_TX_COMPLETION(pEndpoint,pPacket);
  57. }
  58. A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 SendFlags)
  59. {
  60. A_STATUS status;
  61. A_UINT8 *pHdrBuf;
  62. A_BOOL sync = FALSE;
  63. /* caller always provides headrooom */
  64. pPacket->pBuffer -= HTC_HDR_LENGTH;
  65. pHdrBuf = pPacket->pBuffer;
  66. /* setup frame header */
  67. A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)pPacket->ActualLength);
  68. A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,SendFlags);
  69. A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)pPacket->Endpoint);
  70. if (pPacket->Completion == NULL) {
  71. /* mark that this request was synchronously issued */
  72. sync = TRUE;
  73. }
  74. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
  75. ("+-HTCIssueSend: transmit length : %d (%s) \n",
  76. pPacket->ActualLength + HTC_HDR_LENGTH,
  77. sync ? "SYNC" : "ASYNC" ));
  78. /* send message to device */
  79. status = DevSendPacket(&target->Device,
  80. pPacket,
  81. pPacket->ActualLength + HTC_HDR_LENGTH);
  82. if (sync) {
  83. /* use local sync variable. If this was issued asynchronously, pPacket is no longer
  84. * safe to access. */
  85. pPacket->pBuffer += HTC_HDR_LENGTH;
  86. }
  87. /* if this request was asynchronous, the packet completion routine will be invoked by
  88. * the device layer when the HIF layer completes the request */
  89. return status;
  90. }
  91. /* try to send the current packet or a packet at the head of the TX queue,
  92. * if there are no credits, the packet remains in the queue.
  93. * this function returns the result of the attempt to send the HTC packet */
  94. static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target,
  95. HTC_ENDPOINT *pEndpoint,
  96. HTC_PACKET *pPacketToSend)
  97. {
  98. HTC_PACKET *pPacket;
  99. int creditsRequired;
  100. int remainder;
  101. A_UINT8 sendFlags;
  102. HTC_SEND_QUEUE_RESULT result;
  103. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (pPkt:0x%X)\n",(A_UINT32)pPacketToSend));
  104. if (pPacketToSend != NULL) {
  105. /* see if adding this packet hits the max depth */
  106. if ((pEndpoint->CurrentTxQueueDepth + 1) >= pEndpoint->MaxTxQueueDepth) {
  107. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX queue is full, Depth:%d, Max:%d \n",
  108. pPacketToSend->Endpoint, pEndpoint->CurrentTxQueueDepth, pEndpoint->MaxTxQueueDepth));
  109. /* queue will be full, invoke any callbacks to determine what action to take */
  110. if (pEndpoint->EpCallBacks.EpSendFull != NULL) {
  111. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Calling driver's send full callback.... \n"));
  112. if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext,
  113. pPacketToSend) == HTC_SEND_FULL_DROP) {
  114. /* callback wants the packet dropped */
  115. INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
  116. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
  117. return HTC_SEND_QUEUE_DROP;
  118. }
  119. }
  120. }
  121. }
  122. LOCK_HTC_TX(target);
  123. result = HTC_SEND_QUEUE_OK;
  124. if (pPacketToSend != NULL) {
  125. /* packet was supplied to be queued */
  126. HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue,pPacketToSend);
  127. pEndpoint->CurrentTxQueueDepth++;
  128. }
  129. pEndpoint->TxProcessCount++;
  130. if (pEndpoint->TxProcessCount > 1) {
  131. /* another thread is draining the queues, get out */
  132. pEndpoint->TxProcessCount--;
  133. UNLOCK_HTC_TX(target);
  134. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
  135. return HTC_SEND_QUEUE_OK;
  136. }
  137. /* at this point, only 1 thread may enter to drain this endpoint queue */
  138. /* now drain the TX queue for transmission as long as we have enough
  139. * credits */
  140. while (1) {
  141. if (HTC_QUEUE_EMPTY(&pEndpoint->TxQueue)) {
  142. /* nothing in the queue */
  143. break;
  144. }
  145. if (HTC_STOPPING(target)) {
  146. if (pPacketToSend != NULL) {
  147. HTC_PACKET_REMOVE(pPacketToSend);
  148. pEndpoint->CurrentTxQueueDepth--;
  149. result = HTC_SEND_QUEUE_DROP;
  150. }
  151. break;
  152. }
  153. sendFlags = 0;
  154. /* get packet at head, but don't remove it */
  155. pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
  156. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%X , Queue Depth: %d\n",
  157. (A_UINT32)pPacket, pEndpoint->CurrentTxQueueDepth));
  158. /* figure out how many credits this message requires */
  159. creditsRequired = (pPacket->ActualLength + HTC_HDR_LENGTH) / target->TargetCreditSize;
  160. remainder = (pPacket->ActualLength + HTC_HDR_LENGTH) % target->TargetCreditSize;
  161. if (remainder) {
  162. creditsRequired++;
  163. }
  164. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
  165. creditsRequired, pEndpoint->CreditDist.TxCredits));
  166. if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
  167. /* not enough credits */
  168. if (pPacket->Endpoint == ENDPOINT_0) {
  169. /* leave it in the queue */
  170. break;
  171. }
  172. /* invoke the registered distribution function only if this is not
  173. * endpoint 0, we let the driver layer provide more credits if it can.
  174. * We pass the credit distribution list starting at the endpoint in question
  175. * */
  176. /* set how many credits we need */
  177. pEndpoint->CreditDist.TxCreditsSeek =
  178. creditsRequired - pEndpoint->CreditDist.TxCredits;
  179. DO_DISTRIBUTION(target,
  180. HTC_CREDIT_DIST_SEEK_CREDITS,
  181. "Seek Credits",
  182. &pEndpoint->CreditDist);
  183. pEndpoint->CreditDist.TxCreditsSeek = 0;
  184. if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
  185. /* still not enough credits to send, leave packet in the queue */
  186. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
  187. (" Not enough credits for ep %d leaving packet in queue..\n",
  188. pPacket->Endpoint));
  189. break;
  190. }
  191. }
  192. pEndpoint->CreditDist.TxCredits -= creditsRequired;
  193. INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
  194. /* check if we need credits back from the target */
  195. if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
  196. /* we are getting low on credits, see if we can ask for more from the distribution function */
  197. pEndpoint->CreditDist.TxCreditsSeek =
  198. pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits;
  199. DO_DISTRIBUTION(target,
  200. HTC_CREDIT_DIST_SEEK_CREDITS,
  201. "Seek Credits",
  202. &pEndpoint->CreditDist);
  203. pEndpoint->CreditDist.TxCreditsSeek = 0;
  204. /* see if we were successful in getting more */
  205. if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
  206. /* tell the target we need credits ASAP! */
  207. sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
  208. INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
  209. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
  210. }
  211. }
  212. /* now we can fully dequeue */
  213. pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
  214. pEndpoint->CurrentTxQueueDepth--;
  215. INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
  216. UNLOCK_HTC_TX(target);
  217. HTCIssueSend(target, pPacket, sendFlags);
  218. LOCK_HTC_TX(target);
  219. /* go back and check for more messages */
  220. }
  221. /* we're done, clear count */
  222. pEndpoint->TxProcessCount = 0;
  223. UNLOCK_HTC_TX(target);
  224. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
  225. return result;
  226. }
  227. /* HTC API - HTCSendPkt */
  228. A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
  229. {
  230. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  231. HTC_ENDPOINT *pEndpoint;
  232. HTC_ENDPOINT_ID ep;
  233. A_STATUS status = A_OK;
  234. HTC_SEND_QUEUE_RESULT result;
  235. AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
  236. ("+HTCSendPkt: Enter endPointId: %d, buffer: 0x%X, length: %d \n",
  237. pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->ActualLength));
  238. ep = pPacket->Endpoint;
  239. AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
  240. pEndpoint = &target->EndPoint[ep];
  241. do {
  242. /* everything sent through this interface is asynchronous */
  243. /* fill in HTC completion routines */
  244. pPacket->Completion = HTCSendPktCompletionHandler;
  245. pPacket->pContext = target;
  246. result = HTCTrySend(target, pEndpoint, pPacket);
  247. if (HTC_SEND_QUEUE_DROP == result) {
  248. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX packet dropped \n", ep));
  249. if (HTC_STOPPING(target)) {
  250. status = A_ECANCELED;
  251. } else {
  252. status = A_NO_RESOURCE;
  253. }
  254. }
  255. } while (FALSE);
  256. if (A_FAILED(status)) {
  257. pPacket->Status = status;
  258. DO_EP_TX_COMPLETION(pEndpoint,pPacket);
  259. }
  260. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n"));
  261. return status;
  262. }
  263. /* check TX queues to drain because of credit distribution update */
  264. static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
  265. {
  266. HTC_ENDPOINT *pEndpoint;
  267. HTC_ENDPOINT_CREDIT_DIST *pDistItem;
  268. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
  269. pDistItem = target->EpCreditDistributionListHead;
  270. /* run through the credit distribution list to see
  271. * if there are packets queued
  272. * NOTE: no locks need to be taken since the distribution list
  273. * is not dynamic (cannot be re-ordered) and we are not modifying any state */
  274. while (pDistItem != NULL) {
  275. pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
  276. if (pEndpoint->CurrentTxQueueDepth > 0) {
  277. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
  278. pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, pEndpoint->CurrentTxQueueDepth));
  279. /* try to start the stalled queue, this list is ordered by priority.
  280. * Highest priority queue get's processed first, if there are credits available the
  281. * highest priority queue will get a chance to reclaim credits from lower priority
  282. * ones */
  283. HTCTrySend(target, pEndpoint, NULL);
  284. }
  285. pDistItem = pDistItem->pNext;
  286. }
  287. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
  288. }
  289. /* process credit reports and call distribution function */
  290. void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
  291. {
  292. int i;
  293. HTC_ENDPOINT *pEndpoint;
  294. int totalCredits = 0;
  295. A_BOOL doDist = FALSE;
  296. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
  297. /* lock out TX while we update credits */
  298. LOCK_HTC_TX(target);
  299. for (i = 0; i < NumEntries; i++, pRpt++) {
  300. if (pRpt->EndpointID >= ENDPOINT_MAX) {
  301. AR_DEBUG_ASSERT(FALSE);
  302. break;
  303. }
  304. pEndpoint = &target->EndPoint[pRpt->EndpointID];
  305. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
  306. pRpt->EndpointID, pRpt->Credits));
  307. #ifdef HTC_EP_STAT_PROFILING
  308. INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
  309. INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
  310. if (FromEndpoint == pRpt->EndpointID) {
  311. /* this credit report arrived on the same endpoint indicating it arrived in an RX
  312. * packet */
  313. INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
  314. INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
  315. } else if (FromEndpoint == ENDPOINT_0) {
  316. /* this credit arrived on endpoint 0 as a NULL message */
  317. INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
  318. INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
  319. } else {
  320. /* arrived on another endpoint */
  321. INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
  322. INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
  323. }
  324. #endif
  325. if (ENDPOINT_0 == pRpt->EndpointID) {
  326. /* always give endpoint 0 credits back */
  327. pEndpoint->CreditDist.TxCredits += pRpt->Credits;
  328. } else {
  329. /* for all other endpoints, update credits to distribute, the distribution function
  330. * will handle giving out credits back to the endpoints */
  331. pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
  332. /* flag that we have to do the distribution */
  333. doDist = TRUE;
  334. }
  335. /* refresh tx depth for distribution function that will recover these credits
  336. * NOTE: this is only valid when there are credits to recover! */
  337. pEndpoint->CreditDist.TxQueueDepth = pEndpoint->CurrentTxQueueDepth;
  338. totalCredits += pRpt->Credits;
  339. }
  340. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
  341. if (doDist) {
  342. /* this was a credit return based on a completed send operations
  343. * note, this is done with the lock held */
  344. DO_DISTRIBUTION(target,
  345. HTC_CREDIT_DIST_SEND_COMPLETE,
  346. "Send Complete",
  347. target->EpCreditDistributionListHead->pNext);
  348. }
  349. UNLOCK_HTC_TX(target);
  350. if (totalCredits) {
  351. HTCCheckEndpointTxQueues(target);
  352. }
  353. AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
  354. }
  355. /* flush endpoint TX queue */
  356. static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
  357. {
  358. HTC_PACKET *pPacket;
  359. HTC_PACKET_QUEUE discardQueue;
  360. /* initialize the discard queue */
  361. INIT_HTC_PACKET_QUEUE(&discardQueue);
  362. LOCK_HTC_TX(target);
  363. /* interate from the front of the TX queue and flush out packets */
  364. ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue, pPacket, HTC_PACKET, ListLink) {
  365. /* check for removal */
  366. if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
  367. /* remove from queue */
  368. HTC_PACKET_REMOVE(pPacket);
  369. /* add it to the discard pile */
  370. HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
  371. pEndpoint->CurrentTxQueueDepth--;
  372. }
  373. } ITERATE_END;
  374. UNLOCK_HTC_TX(target);
  375. /* empty the discard queue */
  376. while (1) {
  377. pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
  378. if (NULL == pPacket) {
  379. break;
  380. }
  381. pPacket->Status = A_ECANCELED;
  382. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%X, length:%d, ep:%d tag:0x%X \n",
  383. (A_UINT32)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag));
  384. DO_EP_TX_COMPLETION(pEndpoint,pPacket);
  385. }
  386. }
  387. void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
  388. {
  389. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n",
  390. pEPDist->Endpoint, pEPDist->ServiceID));
  391. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%X next:0x%X prev:0x%X\n",
  392. (A_UINT32)pEPDist, (A_UINT32)pEPDist->pNext, (A_UINT32)pEPDist->pPrev));
  393. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags));
  394. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm));
  395. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin));
  396. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits));
  397. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned));
  398. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek));
  399. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize));
  400. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
  401. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist));
  402. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n",
  403. ((HTC_ENDPOINT *) pEPDist->pHTCReserved)->CurrentTxQueueDepth));
  404. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
  405. }
  406. void DumpCreditDistStates(HTC_TARGET *target)
  407. {
  408. HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
  409. while (pEPList != NULL) {
  410. DumpCreditDist(pEPList);
  411. pEPList = pEPList->pNext;
  412. }
  413. if (target->DistributeCredits != NULL) {
  414. DO_DISTRIBUTION(target,
  415. HTC_DUMP_CREDIT_STATE,
  416. "Dump State",
  417. NULL);
  418. }
  419. }
  420. /* flush all send packets from all endpoint queues */
  421. void HTCFlushSendPkts(HTC_TARGET *target)
  422. {
  423. HTC_ENDPOINT *pEndpoint;
  424. int i;
  425. DumpCreditDistStates(target);
  426. for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
  427. pEndpoint = &target->EndPoint[i];
  428. if (pEndpoint->ServiceID == 0) {
  429. /* not in use.. */
  430. continue;
  431. }
  432. HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
  433. }
  434. }
  435. /* HTC API to flush an endpoint's TX queue*/
  436. void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
  437. {
  438. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  439. HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
  440. if (pEndpoint->ServiceID == 0) {
  441. AR_DEBUG_ASSERT(FALSE);
  442. /* not in use.. */
  443. return;
  444. }
  445. HTCFlushEndpointTX(target, pEndpoint, Tag);
  446. }
  447. /* HTC API to indicate activity to the credit distribution function */
  448. void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
  449. HTC_ENDPOINT_ID Endpoint,
  450. A_BOOL Active)
  451. {
  452. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  453. HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
  454. A_BOOL doDist = FALSE;
  455. if (pEndpoint->ServiceID == 0) {
  456. AR_DEBUG_ASSERT(FALSE);
  457. /* not in use.. */
  458. return;
  459. }
  460. LOCK_HTC_TX(target);
  461. if (Active) {
  462. if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
  463. /* mark active now */
  464. pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
  465. doDist = TRUE;
  466. }
  467. } else {
  468. if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
  469. /* mark inactive now */
  470. pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
  471. doDist = TRUE;
  472. }
  473. }
  474. if (doDist) {
  475. /* indicate current Tx Queue depth to the credit distribution function */
  476. pEndpoint->CreditDist.TxQueueDepth = pEndpoint->CurrentTxQueueDepth;
  477. /* do distribution again based on activity change
  478. * note, this is done with the lock held */
  479. DO_DISTRIBUTION(target,
  480. HTC_CREDIT_DIST_ACTIVITY_CHANGE,
  481. "Activity Change",
  482. target->EpCreditDistributionListHead->pNext);
  483. }
  484. UNLOCK_HTC_TX(target);
  485. if (doDist && !Active) {
  486. /* if a stream went inactive and this resulted in a credit distribution change,
  487. * some credits may now be available for HTC packets that are stuck in
  488. * HTC queues */
  489. HTCCheckEndpointTxQueues(target);
  490. }
  491. }