Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: chromeos/drivers/ath6kl/htc2/htc_send.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromeos/drivers/ath6kl/htc2/htc_recv.c ('k') | chromeos/drivers/ath6kl/htc2/htc_services.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
21 typedef enum _HTC_SEND_QUEUE_RESULT {
22 HTC_SEND_QUEUE_OK = 0, /* packet was queued */
23 HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
24 } HTC_SEND_QUEUE_RESULT;
25
26 #define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q)
27
28 /* call the distribute credits callback with the distribution */
29 #define DO_DISTRIBUTION(t,reason,description,pList) \
30 { \
31 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
32 (" calling distribute function (%s) (dfn:0x%X, ctxt:0x%X, dist:0x%X) \n ", \
33 (description), \
34 (A_UINT32)(t)->DistributeCredits, \
35 (A_UINT32)(t)->pCredDistContext, \
36 (A_UINT32)pList)); \
37 (t)->DistributeCredits((t)->pCredDistContext, \
38 (pList), \
39 (reason)); \
40 }
41
42 static void DoSendCompletion(HTC_ENDPOINT *pEndpoint,
43 HTC_PACKET_QUEUE *pQueueToIndicate)
44 {
45 do {
46
47 if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
48 /* nothing to indicate */
49 break;
50 }
51
52 if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) {
53 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n",
54 pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
55 /* a multiple send complete handler is being used, pass the queu e to the handler */
56 pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.p Context,
57 pQueueToIndicate);
58 /* all packets are now owned by the callback, reset queue to be safe */
59 INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
60 } else {
61 HTC_PACKET *pPacket;
62 /* using legacy EpTxComplete */
63 do {
64 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
65 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send comple te callback on packet 0x%X \n", \
66 pEndpoint->Id, (A_UINT32)(pPacket)));
67 pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pCont ext, pPacket);
68 } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
69 }
70
71 } while (FALSE);
72
73 }
74
75 /* do final completion on sent packet */
76 static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoin t, HTC_PACKET *pPacket)
77 {
78 pPacket->Completion = NULL;
79
80 if (A_FAILED(pPacket->Status)) {
81 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
82 ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d cr eds:%d) \n",
83 pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPack et->PktInfo.AsTx.CreditsUsed));
84 /* on failure to submit, reclaim credits for this packet */
85 LOCK_HTC_TX(target);
86 pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUs ed;
87 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> TxQueue);
88 DO_DISTRIBUTION(target,
89 HTC_CREDIT_DIST_SEND_COMPLETE,
90 "Send Complete",
91 target->EpCreditDistributionListHead->pNext);
92 UNLOCK_HTC_TX(target);
93 }
94 /* first, fixup the head room we allocated */
95 pPacket->pBuffer += HTC_HDR_LENGTH;
96 }
97
98 /* our internal send packet completion handler when packets are submited to the AR6K device
99 * layer */
100 static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
101 {
102 HTC_TARGET *target = (HTC_TARGET *)Context;
103 HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
104 HTC_PACKET_QUEUE container;
105
106 CompleteSentPacket(target,pEndpoint,pPacket);
107 INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
108 /* do completion */
109 DO_EP_TX_COMPLETION(pEndpoint,&container);
110 }
111
112 A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
113 {
114 A_STATUS status;
115 A_BOOL sync = FALSE;
116
117 if (pPacket->Completion == NULL) {
118 /* mark that this request was synchronously issued */
119 sync = TRUE;
120 }
121
122 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
123 ("+-HTCIssueSend: transmit length : %d (%s) \n",
124 pPacket->ActualLength + HTC_HDR_LENGTH,
125 sync ? "SYNC" : "ASYNC" ));
126
127 /* send message to device */
128 status = DevSendPacket(&target->Device,
129 pPacket,
130 pPacket->ActualLength + HTC_HDR_LENGTH);
131
132 if (sync) {
133 /* use local sync variable. If this was issued asynchronously, pPac ket is no longer
134 * safe to access. */
135 pPacket->pBuffer += HTC_HDR_LENGTH;
136 }
137
138 /* if this request was asynchronous, the packet completion routine will be i nvoked by
139 * the device layer when the HIF layer completes the request */
140
141 return status;
142 }
143
144 /* get HTC send packets from the TX queue on an endpoint */
145 static INLINE void GetHTCSendPackets(HTC_TARGET *target,
146 HTC_ENDPOINT *pEndpoint,
147 HTC_PACKET_QUEUE *pQueue)
148 {
149 int creditsRequired;
150 int remainder;
151 A_UINT8 sendFlags;
152 HTC_PACKET *pPacket;
153 int transferLength;
154
155 /****** NOTE : the TX lock is held when this function is called ************ *****/
156 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
157
158 /* loop until we can grab as many packets out of the queue as we can */
159 while (TRUE) {
160
161 sendFlags = 0;
162 /* get packet at head, but don't remove it */
163 pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
164 if (pPacket == NULL) {
165 break;
166 }
167
168 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%X , Queue Depth: %d \n",
169 (A_UINT32)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))) ;
170
171 transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->Actu alLength + HTC_HDR_LENGTH);
172
173 if (transferLength <= target->TargetCreditSize) {
174 creditsRequired = 1;
175 } else {
176 /* figure out how many credits this message requires */
177 creditsRequired = transferLength / target->TargetCreditSize;
178 remainder = transferLength % target->TargetCreditSize;
179
180 if (remainder) {
181 creditsRequired++;
182 }
183 }
184
185 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
186 creditsRequired, pEndpoint->CreditDist.TxCredits));
187
188 if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
189
190 /* not enough credits */
191 if (pPacket->Endpoint == ENDPOINT_0) {
192 /* leave it in the queue */
193 break;
194 }
195 /* invoke the registered distribution function only if this is n ot
196 * endpoint 0, we let the driver layer provide more credits if i t can.
197 * We pass the credit distribution list starting at the endpoint in question
198 * */
199
200 /* set how many credits we need */
201 pEndpoint->CreditDist.TxCreditsSeek =
202 creditsRequired - pEndpoint->CreditDist.TxCr edits;
203 DO_DISTRIBUTION(target,
204 HTC_CREDIT_DIST_SEEK_CREDITS,
205 "Seek Credits",
206 &pEndpoint->CreditDist);
207 pEndpoint->CreditDist.TxCreditsSeek = 0;
208
209 if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
210 /* still not enough credits to send, leave packet in the que ue */
211 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
212 (" Not enough credits for ep %d leaving packet in queue..\n" ,
213 pPacket->Endpoint));
214 break;
215 }
216
217 }
218
219 pEndpoint->CreditDist.TxCredits -= creditsRequired;
220 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
221
222 /* check if we need credits back from the target */
223 if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPer MaxMsg) {
224 /* we are getting low on credits, see if we can ask for more fro m the distribution function */
225 pEndpoint->CreditDist.TxCreditsSeek =
226 pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->Cr editDist.TxCredits;
227
228 DO_DISTRIBUTION(target,
229 HTC_CREDIT_DIST_SEEK_CREDITS,
230 "Seek Credits",
231 &pEndpoint->CreditDist);
232
233 pEndpoint->CreditDist.TxCreditsSeek = 0;
234 /* see if we were successful in getting more */
235 if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCredit sPerMaxMsg) {
236 /* tell the target we need credits ASAP! */
237 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
238 INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
239 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
240 }
241 }
242
243 /* now we can fully dequeue */
244 pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
245 /* save the number of credits this packet consumed */
246 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
247 /* all TX packets are handled asynchronously */
248 pPacket->Completion = HTCSendPktCompletionHandler;
249 pPacket->pContext = target;
250 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
251 /* save send flags */
252 pPacket->PktInfo.AsTx.SendFlags = sendFlags;
253 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
254 pEndpoint->SeqNo++;
255 /* queue this packet into the caller's queue */
256 HTC_PACKET_ENQUEUE(pQueue,pPacket);
257 }
258
259 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n"));
260
261 }
262
263 static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
264 {
265 int i;
266 HTC_PACKET *pPacket;
267 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pScatterReq->Context;
268 HTC_TARGET *target = (HTC_TARGET *)pEndpoint->target;
269 A_STATUS status = A_OK;
270 HTC_PACKET_QUEUE sendCompletes;
271
272 INIT_HTC_PACKET_QUEUE(&sendCompletes);
273
274 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n",
275 pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
276
277 DEV_FINISH_SCATTER_OPERATION(pScatterReq);
278
279 if (A_FAILED(pScatterReq->CompletionStatus)) {
280 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",p ScatterReq->CompletionStatus));
281 status = A_ERROR;
282 }
283
284 /* walk through the scatter list and process */
285 for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
286 pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]) ;
287 A_ASSERT(pPacket != NULL);
288 pPacket->Status = status;
289 CompleteSentPacket(target,pEndpoint,pPacket);
290 /* add it to the completion queue */
291 HTC_PACKET_ENQUEUE(&sendCompletes, pPacket);
292 }
293
294 /* free scatter request */
295 DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
296 /* complete all packets */
297 DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes);
298
299 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n"));
300 }
301
302 /* drain a queue and send as bundles
303 * this function may return without fully draining the queue under the follo wing conditions :
304 * - scatter resources are exhausted
305 * - a message that will consume a partial credit will stop the bundling process early
306 * - we drop below the minimum number of messages for a bundle
307 * */
308 static void HTCIssueSendBundle(HTC_ENDPOINT *pEndpoint,
309 HTC_PACKET_QUEUE *pQueue,
310 int *pBundlesSent,
311 int *pTotalBundlesPkts)
312 {
313 int pktsToScatter;
314 int scatterSpaceRemaining;
315 HIF_SCATTER_REQ *pScatterReq = NULL;
316 int i, packetsInScatterReq;
317 int transferLength;
318 HTC_PACKET *pPacket;
319 A_BOOL done = FALSE;
320 int bundlesSent = 0;
321 int totalPktsInBundle = 0;
322 HTC_TARGET *target = pEndpoint->target;
323 int creditRemainder = 0;
324 int creditPad;
325
326 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n"));
327
328 while (!done) {
329
330 pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue);
331 pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
332
333 if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
334 /* not enough to bundle */
335 break;
336 }
337
338 pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
339
340 if (pScatterReq == NULL) {
341 /* no scatter resources */
342 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n"));
343 break;
344 }
345
346 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatt er));
347
348 pScatterReq->TotalLength = 0;
349 pScatterReq->ValidScatterEntries = 0;
350
351 packetsInScatterReq = 0;
352 scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device);
353
354 for (i = 0; i < pktsToScatter; i++) {
355
356 pScatterReq->ScatterList[i].pCallerContexts[0] = NULL;
357
358 pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
359 if (pPacket == NULL) {
360 A_ASSERT(FALSE);
361 break;
362 }
363
364 creditPad = 0;
365 transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device,
366 pPacket->ActualLength + HT C_HDR_LENGTH);
367 /* see if the padded transfer length falls on a credit boundary */
368 creditRemainder = transferLength % target->TargetCreditSize;
369
370 if (creditRemainder != 0) {
371 /* the transfer consumes a "partial" credit, this packet can not be bundled unless
372 * we add additional "dummy" padding (max 255 bytes) to cons ume the entire credit
373 *** NOTE: only allow the send padding if the endpoint is al lowed to */
374 if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABL E_SEND_BUNDLE_PADDING) {
375 if (transferLength < target->TargetCreditSize) {
376 /* special case where the transfer is less than a cr edit */
377 creditPad = target->TargetCreditSize - transferLength;
378 } else {
379 creditPad = creditRemainder;
380 }
381
382 /* now check to see if we can indicate padding in the HT C header */
383 if ((creditPad > 0) && (creditPad <= 255)) {
384 /* adjust the transferlength of this packet with the new credit padding */
385 transferLength += creditPad;
386 } else {
387 /* the amount to pad is too large, bail on this pack et, we have to
388 * send it using the non-bundled method */
389 pPacket = NULL;
390 }
391 } else {
392 /* bail on this packet, user does not want padding appli ed */
393 pPacket = NULL;
394 }
395 }
396
397 if (NULL == pPacket) {
398 /* can't bundle */
399 done = TRUE;
400 break;
401 }
402
403 if ((scatterSpaceRemaining - transferLength) < 0) {
404 /* exceeds what we can transfer */
405 break;
406 }
407
408 scatterSpaceRemaining -= transferLength;
409 /* now remove it from the queue */
410 pPacket = HTC_PACKET_DEQUEUE(pQueue);
411 /* save it in the scatter list */
412 pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
413 /* prepare packet and flag message as part of a send bundle */
414 HTC_PREPARE_SEND_PKT(pPacket,
415 pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEN D_BUNDLE,
416 creditPad,
417 pPacket->PktInfo.AsTx.SeqNo);
418 pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
419 pScatterReq->ScatterList[i].Length = transferLength;
420 A_ASSERT(transferLength);
421 pScatterReq->TotalLength += transferLength;
422 pScatterReq->ValidScatterEntries++;
423 packetsInScatterReq++;
424 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%X, len:%d (remaining space:%d) \n",
425 i, (A_UINT32)pPacket,transferLength,scatterSpaceRemaining));
426 }
427
428 if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) {
429 /* send path is always asynchronous */
430 pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion;
431 pScatterReq->Context = pEndpoint;
432 bundlesSent++;
433 totalPktsInBundle += packetsInScatterReq;
434 packetsInScatterReq = 0;
435 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , ent ries: %d\n",
436 pScatterReq->TotalLength,pScatterReq->ValidScatt erEntries));
437 DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WR ITE, DEV_SCATTER_ASYNC);
438 /* we don't own this anymore */
439 pScatterReq = NULL;
440 /* try to send some more */
441 continue;
442 }
443
444 /* not enough packets to use the scatter request, cleanup */
445 if (pScatterReq != NULL) {
446 if (packetsInScatterReq > 0) {
447 /* work backwards to requeue requests */
448 for (i = (packetsInScatterReq - 1); i >= 0; i--) {
449 pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCaller Contexts[0]);
450 if (pPacket != NULL) {
451 /* undo any prep */
452 HTC_UNPREPARE_SEND_PKT(pPacket);
453 /* queue back to the head */
454 HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket);
455 }
456 }
457 }
458 DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
459 }
460
461 /* if we get here, we sent all that we could, get out */
462 break;
463
464 }
465
466 *pBundlesSent = bundlesSent;
467 *pTotalBundlesPkts = totalPktsInBundle;
468 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSe nt));
469
470 return;
471 }
472
473 /*
474 * if there are no credits, the packet(s) remains in the queue.
475 * this function returns the result of the attempt to send a queue of HTC packet s */
476 static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target,
477 HTC_ENDPOINT *pEndpoint,
478 HTC_PACKET_QUEUE *pCallersSendQueue)
479 {
480 HTC_PACKET_QUEUE sendQueue; /* temp queue to hold packets at various st ages */
481 HTC_PACKET *pPacket;
482 int bundlesSent;
483 int pktsInBundles;
484 int overflow;
485 HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
486
487 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%X Depth:%d)\n",
488 (A_UINT32)pCallersSendQueue,
489 (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSen dQueue)));
490
491 /* init the local send queue */
492 INIT_HTC_PACKET_QUEUE(&sendQueue);
493
494 do {
495
496 if (NULL == pCallersSendQueue) {
497 /* caller didn't provide a queue, just wants us to check queues and send */
498 break;
499 }
500
501 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
502 /* empty queue */
503 result = HTC_SEND_QUEUE_DROP;
504 break;
505 }
506
507 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueue Depth) {
508 /* we've already overflowed */
509 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
510 } else {
511 /* figure out how much we will overflow by */
512 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
513 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
514 /* figure out how much we will overflow the TX queue by */
515 overflow -= pEndpoint->MaxTxQueueDepth;
516 }
517
518 /* if overflow is negative or zero, we are okay */
519 if (overflow > 0) {
520 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
521 (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n",
522 pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQu eue), pEndpoint->MaxTxQueueDepth));
523 }
524 if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) {
525 /* all packets will fit or caller did not provide send full indi cation handler
526 * -- just move all of them to the local sendQueue object */
527 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue);
528 } else {
529 int i;
530 int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueu e) - overflow;
531
532 A_ASSERT(goodPkts >= 0);
533 /* we have overflowed, and a callback is provided */
534 /* dequeue all non-overflow packets into the sendqueue */
535 for (i = 0; i < goodPkts; i++) {
536 /* pop off caller's queue*/
537 pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue);
538 A_ASSERT(pPacket != NULL);
539 /* insert into local queue */
540 HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
541 }
542
543 /* the caller's queue has all the packets that won't fit*/
544 /* walk through the caller's queue and indicate each one to the send full handler */
545 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacke t, HTC_PACKET, ListLink) {
546
547 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX pack et: 0x%X \n",
548 (A_UINT32)pPacket));
549 if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pCo ntext,
550 pPacket) == HTC_SEND_FULL_ DROP) {
551 /* callback wants the packet dropped */
552 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
553 /* leave this one in the caller's queue for cleanup */
554 } else {
555 /* callback wants to keep this packet, remove from calle r's queue */
556 HTC_PACKET_REMOVE(pCallersSendQueue, pPacket);
557 /* put it in the send queue */
558 HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
559 }
560
561 } ITERATE_END;
562
563 if (HTC_QUEUE_EMPTY(&sendQueue)) {
564 /* no packets made it in, caller will cleanup */
565 result = HTC_SEND_QUEUE_DROP;
566 break;
567 }
568 }
569
570 } while (FALSE);
571
572 if (result != HTC_SEND_QUEUE_OK) {
573 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
574 return result;
575 }
576
577 LOCK_HTC_TX(target);
578
579 if (!HTC_QUEUE_EMPTY(&sendQueue)) {
580 /* transfer packets */
581 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue);
582 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
583 INIT_HTC_PACKET_QUEUE(&sendQueue);
584 }
585
586 /* increment tx processing count on entry */
587 pEndpoint->TxProcessCount++;
588 if (pEndpoint->TxProcessCount > 1) {
589 /* another thread or task is draining the TX queues on this endpoint
590 * that thread will reset the tx processing count when the queue is drained */
591 pEndpoint->TxProcessCount--;
592 UNLOCK_HTC_TX(target);
593 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n"));
594 return HTC_SEND_QUEUE_OK;
595 }
596
597 /***** beyond this point only 1 thread may enter ******/
598
599 /* now drain the endpoint TX queue for transmission as long as we have e nough
600 * credits */
601 while (TRUE) {
602
603 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
604 break;
605 }
606
607 /* get all the packets for this endpoint that we can for this pass * /
608 GetHTCSendPackets(target, pEndpoint, &sendQueue);
609
610 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
611 /* didn't get any packets due to a lack of credits */
612 break;
613 }
614
615 UNLOCK_HTC_TX(target);
616
617 /* any packets to send are now in our local send queue */
618
619 bundlesSent = 0;
620 pktsInBundles = 0;
621
622 while (TRUE) {
623
624 /* try to send a bundle on each pass */
625 if ((target->SendBundlingEnabled) &&
626 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_B UNDLE)) {
627 int temp1,temp2;
628 /* bundling is enabled and there is at least a minimum numbe r of packets in the send queue
629 * send what we can in this pass */
630 HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2);
631 bundlesSent += temp1;
632 pktsInBundles += temp2;
633 }
634
635 /* if not bundling or there was a packet that could not be place d in a bundle, pull it out
636 * and send it the normal way */
637 pPacket = HTC_PACKET_DEQUEUE(&sendQueue);
638 if (NULL == pPacket) {
639 /* local queue is fully drained */
640 break;
641 }
642 HTC_PREPARE_SEND_PKT(pPacket,
643 pPacket->PktInfo.AsTx.SendFlags,
644 0,
645 pPacket->PktInfo.AsTx.SeqNo);
646 HTCIssueSend(target, pPacket);
647
648 /* go back and see if we can bundle some more */
649 }
650
651 LOCK_HTC_TX(target);
652
653 INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent);
654 INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles);
655
656 }
657
658 /* done with this endpoint, we can clear the count */
659 pEndpoint->TxProcessCount = 0;
660 UNLOCK_HTC_TX(target);
661
662 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
663
664 return HTC_SEND_QUEUE_OK;
665 }
666
667 A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
668 {
669 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
670 HTC_ENDPOINT *pEndpoint;
671 HTC_PACKET *pPacket;
672
673 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%X, Pkts %d \n",
674 (A_UINT32)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
675
676 /* get packet at head to figure out which endpoint these packets will go into */
677 pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
678 if (NULL == pPacket) {
679 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
680 return A_EINVAL;
681 }
682
683 AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
684 pEndpoint = &target->EndPoint[pPacket->Endpoint];
685
686 HTCTrySend(target, pEndpoint, pPktQueue);
687
688 /* do completion on any packets that couldn't get in */
689 if (!HTC_QUEUE_EMPTY(pPktQueue)) {
690
691 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
692 if (HTC_STOPPING(target)) {
693 pPacket->Status = A_ECANCELED;
694 } else {
695 pPacket->Status = A_NO_RESOURCE;
696 }
697 } HTC_PACKET_QUEUE_ITERATE_END;
698
699 DO_EP_TX_COMPLETION(pEndpoint,pPktQueue);
700 }
701
702 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
703
704 return A_OK;
705 }
706
707 /* HTC API - HTCSendPkt */
708 A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
709 {
710 HTC_PACKET_QUEUE queue;
711
712 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
713 ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%X, length: %d \n",
714 pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->Actu alLength));
715 INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
716 return HTCSendPktsMultiple(HTCHandle, &queue);
717 }
718
719 /* check TX queues to drain because of credit distribution update */
720 static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
721 {
722 HTC_ENDPOINT *pEndpoint;
723 HTC_ENDPOINT_CREDIT_DIST *pDistItem;
724
725 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
726 pDistItem = target->EpCreditDistributionListHead;
727
728 /* run through the credit distribution list to see
729 * if there are packets queued
730 * NOTE: no locks need to be taken since the distribution list
731 * is not dynamic (cannot be re-ordered) and we are not modifying any st ate */
732 while (pDistItem != NULL) {
733 pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
734
735 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
736 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packe ts in TX Queue \n",
737 pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PA CKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
738 /* try to start the stalled queue, this list is ordered by prior ity.
739 * Highest priority queue get's processed first, if there are cr edits available the
740 * highest priority queue will get a chance to reclaim credits f rom lower priority
741 * ones */
742 HTCTrySend(target, pEndpoint, NULL);
743 }
744
745 pDistItem = pDistItem->pNext;
746 }
747
748 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
749 }
750
751 /* process credit reports and call distribution function */
752 void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEnt ries, HTC_ENDPOINT_ID FromEndpoint)
753 {
754 int i;
755 HTC_ENDPOINT *pEndpoint;
756 int totalCredits = 0;
757 A_BOOL doDist = FALSE;
758
759 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entrie s:%d \n", NumEntries));
760
761 /* lock out TX while we update credits */
762 LOCK_HTC_TX(target);
763
764 for (i = 0; i < NumEntries; i++, pRpt++) {
765 if (pRpt->EndpointID >= ENDPOINT_MAX) {
766 AR_DEBUG_ASSERT(FALSE);
767 break;
768 }
769
770 pEndpoint = &target->EndPoint[pRpt->EndpointID];
771
772 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
773 pRpt->EndpointID, pRpt->Credits));
774
775
776 #ifdef HTC_EP_STAT_PROFILING
777
778 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
779 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
780
781 if (FromEndpoint == pRpt->EndpointID) {
782 /* this credit report arrived on the same endpoint indicating it arrived in an RX
783 * packet */
784 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
785 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
786 } else if (FromEndpoint == ENDPOINT_0) {
787 /* this credit arrived on endpoint 0 as a NULL message */
788 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
789 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
790 } else {
791 /* arrived on another endpoint */
792 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
793 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
794 }
795
796 #endif
797
798 if (ENDPOINT_0 == pRpt->EndpointID) {
799 /* always give endpoint 0 credits back */
800 pEndpoint->CreditDist.TxCredits += pRpt->Credits;
801 } else {
802 /* for all other endpoints, update credits to distribute, the di stribution function
803 * will handle giving out credits back to the endpoints */
804 pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
805 /* flag that we have to do the distribution */
806 doDist = TRUE;
807 }
808
809 /* refresh tx depth for distribution function that will recover thes e credits
810 * NOTE: this is only valid when there are credits to recover! */
811 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> TxQueue);
812
813 totalCredits += pRpt->Credits;
814 }
815
816 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribut e \n", totalCredits));
817
818 if (doDist) {
819 /* this was a credit return based on a completed send operations
820 * note, this is done with the lock held */
821 DO_DISTRIBUTION(target,
822 HTC_CREDIT_DIST_SEND_COMPLETE,
823 "Send Complete",
824 target->EpCreditDistributionListHead->pNext);
825 }
826
827 UNLOCK_HTC_TX(target);
828
829 if (totalCredits) {
830 HTCCheckEndpointTxQueues(target);
831 }
832
833 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
834 }
835
836 /* flush endpoint TX queue */
837 static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_ TX_TAG Tag)
838 {
839 HTC_PACKET *pPacket;
840 HTC_PACKET_QUEUE discardQueue;
841 HTC_PACKET_QUEUE container;
842
843 /* initialize the discard queue */
844 INIT_HTC_PACKET_QUEUE(&discardQueue);
845
846 LOCK_HTC_TX(target);
847
848 /* interate from the front of the TX queue and flush out packets */
849 ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, HTC_P ACKET, ListLink) {
850
851 /* check for removal */
852 if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag) ) {
853 /* remove from queue */
854 HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket);
855 /* add it to the discard pile */
856 HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
857 }
858
859 } ITERATE_END;
860
861 UNLOCK_HTC_TX(target);
862
863 /* empty the discard queue */
864 while (1) {
865 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
866 if (NULL == pPacket) {
867 break;
868 }
869 pPacket->Status = A_ECANCELED;
870 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%X, length:%d, e p:%d tag:0x%X \n",
871 (A_UINT32)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPa cket->PktInfo.AsTx.Tag));
872 INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
873 DO_EP_TX_COMPLETION(pEndpoint,&container);
874 }
875
876 }
877
878 void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
879 {
880 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X ----------- ---\n",
881 pEPDist->Endpoint, pEPDist->ServiceID));
882 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%X next:0x%X prev:0x%X\n",
883 (A_UINT32)pEPDist, (A_UINT32)pEPDist->pNext, (A_UINT32)pEPDist-> pPrev));
884 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->Di stFlags));
885 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCr editsNorm));
886 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCr editsMin));
887 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCr edits));
888 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCr editsAssigned));
889 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCr editsSeek));
890 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCr editSize));
891 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCr editsPerMaxMsg));
892 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCr editsToDist));
893 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n",
894 HTC_PACKET_QUEUE_DEPTH(&((HTC_ENDPOINT *)pEPDist->pHTCReserv ed)->TxQueue)));
895 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("------------------------------------------- ---------\n"));
896 }
897
898 void DumpCreditDistStates(HTC_TARGET *target)
899 {
900 HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
901
902 while (pEPList != NULL) {
903 DumpCreditDist(pEPList);
904 pEPList = pEPList->pNext;
905 }
906
907 if (target->DistributeCredits != NULL) {
908 DO_DISTRIBUTION(target,
909 HTC_DUMP_CREDIT_STATE,
910 "Dump State",
911 NULL);
912 }
913 }
914
915 /* flush all send packets from all endpoint queues */
916 void HTCFlushSendPkts(HTC_TARGET *target)
917 {
918 HTC_ENDPOINT *pEndpoint;
919 int i;
920
921 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
922 DumpCreditDistStates(target);
923 }
924
925 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
926 pEndpoint = &target->EndPoint[i];
927 if (pEndpoint->ServiceID == 0) {
928 /* not in use.. */
929 continue;
930 }
931 HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
932 }
933
934
935 }
936
937 /* HTC API to flush an endpoint's TX queue*/
938 void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
939 {
940 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
941 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
942
943 if (pEndpoint->ServiceID == 0) {
944 AR_DEBUG_ASSERT(FALSE);
945 /* not in use.. */
946 return;
947 }
948
949 HTCFlushEndpointTX(target, pEndpoint, Tag);
950 }
951
952 /* HTC API to indicate activity to the credit distribution function */
953 void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
954 HTC_ENDPOINT_ID Endpoint,
955 A_BOOL Active)
956 {
957 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
958 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
959 A_BOOL doDist = FALSE;
960
961 if (pEndpoint->ServiceID == 0) {
962 AR_DEBUG_ASSERT(FALSE);
963 /* not in use.. */
964 return;
965 }
966
967 LOCK_HTC_TX(target);
968
969 if (Active) {
970 if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
971 /* mark active now */
972 pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
973 doDist = TRUE;
974 }
975 } else {
976 if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
977 /* mark inactive now */
978 pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
979 doDist = TRUE;
980 }
981 }
982
983 if (doDist) {
984 /* indicate current Tx Queue depth to the credit distribution functi on */
985 pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> TxQueue);
986 /* do distribution again based on activity change
987 * note, this is done with the lock held */
988 DO_DISTRIBUTION(target,
989 HTC_CREDIT_DIST_ACTIVITY_CHANGE,
990 "Activity Change",
991 target->EpCreditDistributionListHead->pNext);
992 }
993
994 UNLOCK_HTC_TX(target);
995
996 if (doDist && !Active) {
997 /* if a stream went inactive and this resulted in a credit distribution change,
998 * some credits may now be available for HTC packets that are stuck in
999 * HTC queues */
1000 HTCCheckEndpointTxQueues(target);
1001 }
1002 }
1003
1004 A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle,
1005 HTC_ENDPOINT_ID Endpoint)
1006 {
1007 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1008 HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
1009
1010 if (pEndpoint->ServiceID == 0) {
1011 return FALSE;
1012 }
1013
1014 if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
1015 return TRUE;
1016 }
1017
1018 return FALSE;
1019 }
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/htc2/htc_recv.c ('k') | chromeos/drivers/ath6kl/htc2/htc_services.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698