blob: d40bb14a2dac0ae76eade0efb020f838fcf56e2c [file] [log] [blame]
Vipin Mehta30295c82010-09-01 12:06:33 -07001//------------------------------------------------------------------------------
2// <copyright file="htc.c" company="Atheros">
3// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
4//
5//
6// Permission to use, copy, modify, and/or distribute this software for any
7// purpose with or without fee is hereby granted, provided that the above
8// copyright notice and this permission notice appear in all copies.
9//
10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17//
18//
19//------------------------------------------------------------------------------
20//==============================================================================
21// Author(s): ="Atheros"
22//==============================================================================
23#include "htc_internal.h"
24
25#ifdef ATH_DEBUG_MODULE
Luis R. Rodriguez090f8072011-03-10 18:55:44 -080026static struct ath_debug_mask_description g_HTCDebugDescription[] = {
Vipin Mehta30295c82010-09-01 12:06:33 -070027 { ATH_DEBUG_SEND , "Send"},
28 { ATH_DEBUG_RECV , "Recv"},
29 { ATH_DEBUG_SYNC , "Sync"},
30 { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"},
31 { ATH_DEBUG_IRQ , "Interrupt Processing"}
32};
33
34ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
35 "htc",
36 "Host Target Communications",
37 ATH_DEBUG_MASK_DEFAULTS,
38 ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription),
39 g_HTCDebugDescription);
40
41#endif
42
43static void HTCReportFailure(void *Context);
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -070044static void ResetEndpointStates(struct htc_target *target);
Vipin Mehta30295c82010-09-01 12:06:33 -070045
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -070046void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList)
Vipin Mehta30295c82010-09-01 12:06:33 -070047{
48 LOCK_HTC(target);
49 HTC_PACKET_ENQUEUE(pList,pPacket);
50 UNLOCK_HTC(target);
51}
52
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -070053struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList)
Vipin Mehta30295c82010-09-01 12:06:33 -070054{
Luis R. Rodriguezc6528e22011-03-14 10:58:57 -070055 struct htc_packet *pPacket;
Vipin Mehta30295c82010-09-01 12:06:33 -070056
57 LOCK_HTC(target);
58 pPacket = HTC_PACKET_DEQUEUE(pList);
59 UNLOCK_HTC(target);
60
61 return pPacket;
62}
63
64/* cleanup the HTC instance */
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -070065static void HTCCleanup(struct htc_target *target)
Vipin Mehta30295c82010-09-01 12:06:33 -070066{
Joe Perchesf68057e2011-02-02 14:05:55 -080067 s32 i;
Vipin Mehta30295c82010-09-01 12:06:33 -070068
69 DevCleanup(&target->Device);
70
71 for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
72 if (target->HTCControlBuffers[i].Buffer) {
73 A_FREE(target->HTCControlBuffers[i].Buffer);
74 }
75 }
76
77 if (A_IS_MUTEX_VALID(&target->HTCLock)) {
78 A_MUTEX_DELETE(&target->HTCLock);
79 }
80
81 if (A_IS_MUTEX_VALID(&target->HTCRxLock)) {
82 A_MUTEX_DELETE(&target->HTCRxLock);
83 }
84
85 if (A_IS_MUTEX_VALID(&target->HTCTxLock)) {
86 A_MUTEX_DELETE(&target->HTCTxLock);
87 }
88 /* free our instance */
89 A_FREE(target);
90}
91
92/* registered target arrival callback from the HIF layer */
Luis R. Rodriguez4f0cce92011-03-14 10:58:56 -070093HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo)
Vipin Mehta30295c82010-09-01 12:06:33 -070094{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -070095 struct htc_target *target = NULL;
Joe Perches4f69cef2011-02-02 14:05:57 -080096 int status = 0;
Vipin Mehta30295c82010-09-01 12:06:33 -070097 int i;
Joe Perchese1ce2a32011-02-02 14:05:51 -080098 u32 ctrl_bufsz;
99 u32 blocksizes[HTC_MAILBOX_NUM_MAX];
Vipin Mehta30295c82010-09-01 12:06:33 -0700100
101 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n"));
102
103 A_REGISTER_MODULE_DEBUG_INFO(htc);
104
105 do {
106
107 /* allocate target memory */
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700108 if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700109 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
110 status = A_ERROR;
111 break;
112 }
113
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700114 A_MEMZERO(target, sizeof(struct htc_target));
Vipin Mehta30295c82010-09-01 12:06:33 -0700115 A_MUTEX_INIT(&target->HTCLock);
116 A_MUTEX_INIT(&target->HTCRxLock);
117 A_MUTEX_INIT(&target->HTCTxLock);
118 INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
119 INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList);
120
121 /* give device layer the hif device handle */
122 target->Device.HIFDevice = hif_handle;
123 /* give the device layer our context (for event processing)
124 * the device layer will register it's own context with HIF
125 * so we need to set this so we can fetch it in the target remove handler */
126 target->Device.HTCContext = target;
127 /* set device layer target failure callback */
128 target->Device.TargetFailureCallback = HTCReportFailure;
129 /* set device layer recv message pending callback */
130 target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
131 target->EpWaitingForBuffers = ENDPOINT_MAX;
132
Luis R. Rodriguez4f0cce92011-03-14 10:58:56 -0700133 memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info));
Vipin Mehta30295c82010-09-01 12:06:33 -0700134
135 ResetEndpointStates(target);
136
137 /* setup device layer */
138 status = DevSetup(&target->Device);
139
Joe Perches391bb212011-01-27 20:04:21 -0800140 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700141 break;
142 }
143
144
145 /* get the block sizes */
146 status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
147 blocksizes, sizeof(blocksizes));
Joe Perches391bb212011-01-27 20:04:21 -0800148 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700149 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n"));
150 break;
151 }
152
153 /* Set the control buffer size based on the block size */
154 if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) {
155 ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH;
156 } else {
157 ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH;
158 }
159 for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
160 target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz);
161 if (target->HTCControlBuffers[i].Buffer == NULL) {
162 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
163 status = A_ERROR;
164 break;
165 }
166 }
167
Joe Perches391bb212011-01-27 20:04:21 -0800168 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700169 break;
170 }
171
172 /* carve up buffers/packets for control messages */
173 for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
Luis R. Rodriguezc6528e22011-03-14 10:58:57 -0700174 struct htc_packet *pControlPacket;
Vipin Mehta30295c82010-09-01 12:06:33 -0700175 pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
176 SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
177 target,
178 target->HTCControlBuffers[i].Buffer,
179 ctrl_bufsz,
180 ENDPOINT_0);
181 HTC_FREE_CONTROL_RX(target,pControlPacket);
182 }
183
184 for (;i < NUM_CONTROL_BUFFERS;i++) {
Luis R. Rodriguezc6528e22011-03-14 10:58:57 -0700185 struct htc_packet *pControlPacket;
Vipin Mehta30295c82010-09-01 12:06:33 -0700186 pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
187 INIT_HTC_PACKET_INFO(pControlPacket,
188 target->HTCControlBuffers[i].Buffer,
189 ctrl_bufsz);
190 HTC_FREE_CONTROL_TX(target,pControlPacket);
191 }
192
Joe Perches1071a132011-02-02 14:05:47 -0800193 } while (false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700194
Joe Perches391bb212011-01-27 20:04:21 -0800195 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700196 if (target != NULL) {
197 HTCCleanup(target);
198 target = NULL;
199 }
200 }
201
202 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n"));
203
204 return target;
205}
206
207void HTCDestroy(HTC_HANDLE HTCHandle)
208{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700209 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Vipin Mehta30295c82010-09-01 12:06:33 -0700210 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%lX \n",(unsigned long)target));
211 HTCCleanup(target);
212 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
213}
214
215/* get the low level HIF device for the caller , the caller may wish to do low level
216 * HIF requests */
217void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
218{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700219 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Vipin Mehta30295c82010-09-01 12:06:33 -0700220 return target->Device.HIFDevice;
221}
222
223/* wait for the target to arrive (sends HTC Ready message)
224 * this operation is fully synchronous and the message is polled for */
Joe Perches1f4c34b2011-01-27 20:04:19 -0800225int HTCWaitTarget(HTC_HANDLE HTCHandle)
Vipin Mehta30295c82010-09-01 12:06:33 -0700226{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700227 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Joe Perches1f4c34b2011-01-27 20:04:19 -0800228 int status;
Luis R. Rodriguezc6528e22011-03-14 10:58:57 -0700229 struct htc_packet *pPacket = NULL;
Vipin Mehta30295c82010-09-01 12:06:33 -0700230 HTC_READY_EX_MSG *pRdyMsg;
231
Luis R. Rodriguez3d82b15e2011-03-14 10:59:00 -0700232 struct htc_service_connect_req connect;
Luis R. Rodriguezcb3ea092011-03-14 10:59:01 -0700233 struct htc_service_connect_resp resp;
Vipin Mehta30295c82010-09-01 12:06:33 -0700234
235 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target));
236
237 do {
238
239#ifdef MBOXHW_UNIT_TEST
240
241 status = DoMboxHWTest(&target->Device);
242
Joe Perchesa1d46522011-02-02 14:05:56 -0800243 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700244 break;
245 }
246
247#endif
248
249 /* we should be getting 1 control message that the target is ready */
250 status = HTCWaitforControlMessage(target, &pPacket);
251
Joe Perches391bb212011-01-27 20:04:21 -0800252 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700253 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
254 break;
255 }
256
257 /* we controlled the buffer creation so it has to be properly aligned */
258 pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer;
259
260 if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) ||
261 (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
262 /* this message is not valid */
Joe Perches1071a132011-02-02 14:05:47 -0800263 AR_DEBUG_ASSERT(false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700264 status = A_EPROTO;
265 break;
266 }
267
268
269 if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) {
270 /* this message is not valid */
Joe Perches1071a132011-02-02 14:05:47 -0800271 AR_DEBUG_ASSERT(false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700272 status = A_EPROTO;
273 break;
274 }
275
276 target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount;
277 target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize;
278
279 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size: %d\n",
280 target->TargetCredits, target->TargetCreditSize));
281
282 /* check if this is an extended ready message */
283 if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) {
284 /* this is an extended message */
285 target->HTCTargetVersion = pRdyMsg->HTCVersion;
286 target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle;
287 } else {
288 /* legacy */
289 target->HTCTargetVersion = HTC_VERSION_2P0;
290 target->MaxMsgPerBundle = 0;
291 }
292
293#ifdef HTC_FORCE_LEGACY_2P0
294 /* for testing and comparison...*/
295 target->HTCTargetVersion = HTC_VERSION_2P0;
296 target->MaxMsgPerBundle = 0;
297#endif
298
299 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
300 ("Using HTC Protocol Version : %s (%d)\n ",
301 (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
302 target->HTCTargetVersion));
303
304 if (target->MaxMsgPerBundle > 0) {
305 /* limit what HTC can handle */
306 target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle);
307 /* target supports message bundling, setup device layer */
Joe Perches391bb212011-01-27 20:04:21 -0800308 if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700309 /* device layer can't handle bundling */
310 target->MaxMsgPerBundle = 0;
311 } else {
312 /* limit bundle what the device layer can handle */
313 target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target->Device),
314 target->MaxMsgPerBundle);
315 }
316 }
317
318 if (target->MaxMsgPerBundle > 0) {
319 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
320 (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle));
321
322 if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) {
Joe Perches1071a132011-02-02 14:05:47 -0800323 target->SendBundlingEnabled = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700324 }
325 if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) {
Joe Perches1071a132011-02-02 14:05:47 -0800326 target->RecvBundlingEnabled = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700327 }
328
329 if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) {
330 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not block aligned! Disabling send bundling \n",
331 target->TargetCreditSize));
332 /* disallow send bundling since the credit size is not aligned to a block size
333 * the I/O block padding will spill into the next credit buffer which is fatal */
Joe Perches1071a132011-02-02 14:05:47 -0800334 target->SendBundlingEnabled = false;
Vipin Mehta30295c82010-09-01 12:06:33 -0700335 }
336 }
337
338 /* setup our pseudo HTC control endpoint connection */
339 A_MEMZERO(&connect,sizeof(connect));
340 A_MEMZERO(&resp,sizeof(resp));
341 connect.EpCallbacks.pContext = target;
342 connect.EpCallbacks.EpTxComplete = HTCControlTxComplete;
343 connect.EpCallbacks.EpRecv = HTCControlRecv;
344 connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */
345 connect.EpCallbacks.EpSendFull = NULL; /* not nedded */
346 connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS;
347 connect.ServiceID = HTC_CTRL_RSVD_SVC;
348
349 /* connect fake service */
350 status = HTCConnectService((HTC_HANDLE)target,
351 &connect,
352 &resp);
353
Joe Perches391bb212011-01-27 20:04:21 -0800354 if (!status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700355 break;
356 }
357
Joe Perches1071a132011-02-02 14:05:47 -0800358 } while (false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700359
360 if (pPacket != NULL) {
361 HTC_FREE_CONTROL_RX(target,pPacket);
362 }
363
364 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n"));
365
366 return status;
367}
368
369
370
371/* Start HTC, enable interrupts and let the target know host has finished setup */
Joe Perches1f4c34b2011-01-27 20:04:19 -0800372int HTCStart(HTC_HANDLE HTCHandle)
Vipin Mehta30295c82010-09-01 12:06:33 -0700373{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700374 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Luis R. Rodriguezc6528e22011-03-14 10:58:57 -0700375 struct htc_packet *pPacket;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800376 int status;
Vipin Mehta30295c82010-09-01 12:06:33 -0700377
378 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
379
380 /* make sure interrupts are disabled at the chip level,
381 * this function can be called again from a reboot of the target without shutting down HTC */
382 DevDisableInterrupts(&target->Device);
383 /* make sure state is cleared again */
384 target->OpStateFlags = 0;
385 target->RecvStateFlags = 0;
386
387 /* now that we are starting, push control receive buffers into the
388 * HTC control endpoint */
389
390 while (1) {
391 pPacket = HTC_ALLOC_CONTROL_RX(target);
392 if (NULL == pPacket) {
393 break;
394 }
395 HTCAddReceivePkt((HTC_HANDLE)target,pPacket);
396 }
397
398 do {
399
400 AR_DEBUG_ASSERT(target->InitCredits != NULL);
401 AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL);
402 AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL);
403
404 /* call init credits callback to do the distribution ,
405 * NOTE: the first entry in the distribution list is ENDPOINT_0, so
406 * we pass the start of the list after this one. */
407 target->InitCredits(target->pCredDistContext,
408 target->EpCreditDistributionListHead->pNext,
409 target->TargetCredits);
410
411#ifdef ATH_DEBUG_MODULE
412
413 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
414 DumpCreditDistStates(target);
415 }
416#endif
417
418 /* the caller is done connecting to services, so we can indicate to the
419 * target that the setup phase is complete */
420 status = HTCSendSetupComplete(target);
421
Joe Perches391bb212011-01-27 20:04:21 -0800422 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700423 break;
424 }
425
426 /* unmask interrupts */
427 status = DevUnmaskInterrupts(&target->Device);
428
Joe Perches391bb212011-01-27 20:04:21 -0800429 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700430 HTCStop(target);
431 }
432
Joe Perches1071a132011-02-02 14:05:47 -0800433 } while (false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700434
435 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
436 return status;
437}
438
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700439static void ResetEndpointStates(struct htc_target *target)
Vipin Mehta30295c82010-09-01 12:06:33 -0700440{
Luis R. Rodriguezdf5a7182011-03-14 10:58:51 -0700441 struct htc_endpoint *pEndpoint;
Vipin Mehta30295c82010-09-01 12:06:33 -0700442 int i;
443
444 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
445 pEndpoint = &target->EndPoint[i];
446
447 A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist));
448 pEndpoint->ServiceID = 0;
449 pEndpoint->MaxMsgLength = 0;
450 pEndpoint->MaxTxQueueDepth = 0;
451#ifdef HTC_EP_STAT_PROFILING
452 A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats));
453#endif
454 INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers);
455 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
456 INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue);
457 pEndpoint->target = target;
458 }
459 /* reset distribution list */
460 target->EpCreditDistributionListHead = NULL;
461}
462
463/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
464void HTCStop(HTC_HANDLE HTCHandle)
465{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700466 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Vipin Mehta30295c82010-09-01 12:06:33 -0700467 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
468
469 LOCK_HTC(target);
470 /* mark that we are shutting down .. */
471 target->OpStateFlags |= HTC_OP_STATE_STOPPING;
472 UNLOCK_HTC(target);
473
474 /* Masking interrupts is a synchronous operation, when this function returns
475 * all pending HIF I/O has completed, we can safely flush the queues */
476 DevMaskInterrupts(&target->Device);
477
478#ifdef THREAD_X
479 //
480 // Is this delay required
481 //
482 A_MDELAY(200); // wait for IRQ process done
483#endif
484 /* flush all send packets */
485 HTCFlushSendPkts(target);
486 /* flush all recv buffers */
487 HTCFlushRecvBuffers(target);
488
Vipin Mehta774c1fe2011-02-18 13:13:09 -0800489 DevCleanupMsgBundling(&target->Device);
490
Vipin Mehta30295c82010-09-01 12:06:33 -0700491 ResetEndpointStates(target);
492
493 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
494}
495
496#ifdef ATH_DEBUG_MODULE
497void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
498{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700499 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Vipin Mehta30295c82010-09-01 12:06:33 -0700500
501 LOCK_HTC_TX(target);
502
503 DumpCreditDistStates(target);
504
505 UNLOCK_HTC_TX(target);
506
507 DumpAR6KDevState(&target->Device);
508}
509#endif
510/* report a target failure from the device, this is a callback from the device layer
511 * which uses a mechanism to report errors from the target (i.e. special interrupts) */
512static void HTCReportFailure(void *Context)
513{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700514 struct htc_target *target = (struct htc_target *)Context;
Vipin Mehta30295c82010-09-01 12:06:33 -0700515
Joe Perches1071a132011-02-02 14:05:47 -0800516 target->TargetFailure = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700517
518 if (target->HTCInitInfo.TargetFailure != NULL) {
519 /* let upper layer know, it needs to call HTCStop() */
520 target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR);
521 }
522}
523
Joe Perches1071a132011-02-02 14:05:47 -0800524bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
Vipin Mehta30295c82010-09-01 12:06:33 -0700525 HTC_ENDPOINT_ID Endpoint,
526 HTC_ENDPOINT_STAT_ACTION Action,
Luis R. Rodriguez84efc7f2011-03-14 10:58:53 -0700527 struct htc_endpoint_stats *pStats)
Vipin Mehta30295c82010-09-01 12:06:33 -0700528{
529
530#ifdef HTC_EP_STAT_PROFILING
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700531 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Joe Perches1071a132011-02-02 14:05:47 -0800532 bool clearStats = false;
533 bool sample = false;
Vipin Mehta30295c82010-09-01 12:06:33 -0700534
535 switch (Action) {
536 case HTC_EP_STAT_SAMPLE :
Joe Perches1071a132011-02-02 14:05:47 -0800537 sample = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700538 break;
539 case HTC_EP_STAT_SAMPLE_AND_CLEAR :
Joe Perches1071a132011-02-02 14:05:47 -0800540 sample = true;
541 clearStats = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700542 break;
543 case HTC_EP_STAT_CLEAR :
Joe Perches1071a132011-02-02 14:05:47 -0800544 clearStats = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700545 break;
546 default:
547 break;
548 }
549
550 A_ASSERT(Endpoint < ENDPOINT_MAX);
551
552 /* lock out TX and RX while we sample and/or clear */
553 LOCK_HTC_TX(target);
554 LOCK_HTC_RX(target);
555
556 if (sample) {
557 A_ASSERT(pStats != NULL);
558 /* return the stats to the caller */
Luis R. Rodriguez84efc7f2011-03-14 10:58:53 -0700559 memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
Vipin Mehta30295c82010-09-01 12:06:33 -0700560 }
561
562 if (clearStats) {
563 /* reset stats */
Luis R. Rodriguez84efc7f2011-03-14 10:58:53 -0700564 A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
Vipin Mehta30295c82010-09-01 12:06:33 -0700565 }
566
567 UNLOCK_HTC_RX(target);
568 UNLOCK_HTC_TX(target);
569
Joe Perches1071a132011-02-02 14:05:47 -0800570 return true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700571#else
Joe Perches1071a132011-02-02 14:05:47 -0800572 return false;
Vipin Mehta30295c82010-09-01 12:06:33 -0700573#endif
574}
575
Luis R. Rodriguez495abc72011-03-10 18:55:36 -0800576struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle)
Vipin Mehta30295c82010-09-01 12:06:33 -0700577{
Luis R. Rodriguezc1ebe362011-03-14 10:59:02 -0700578 struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Vipin Mehta30295c82010-09-01 12:06:33 -0700579 return &target->Device;
580}
581