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

Side by Side Diff: chromeos/drivers/ath6kl/htc2/AR6000/ar6k_events.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
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------
2 // <copyright file="ar6k_events.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 // AR6K Driver layer event handling (i.e. interrupts, message polling)
18 //
19 // Author(s): ="Atheros"
20 //==============================================================================
21 #include "a_config.h"
22 #include "athdefs.h"
23 #include "a_types.h"
24 #include "AR6002/hw2.0/hw/mbox_host_reg.h"
25 #include "a_osapi.h"
26 #include "../htc_debug.h"
27 #include "hif.h"
28 #include "htc_packet.h"
29 #include "ar6k.h"
30
31 extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
32 extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
33
34 static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
35
36 #define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */
37
38 /* completion routine for ALL HIF layer async I/O */
39 A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
40 {
41 HTC_PACKET *pPacket = (HTC_PACKET *)context;
42
43 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
44 ("+DevRWCompletionHandler (Pkt:0x%X) , Status: %d \n",
45 (A_UINT32)pPacket,
46 status));
47
48 COMPLETE_HTC_PACKET(pPacket,status);
49
50 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
51 ("-DevRWCompletionHandler\n"));
52
53 return A_OK;
54 }
55
56 /* mailbox recv message polling */
57 A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
58 A_UINT32 *pLookAhead,
59 int TimeoutMS)
60 {
61 A_STATUS status = A_OK;
62 int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
63
64 A_ASSERT(timeout > 0);
65
66 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
67
68 while (TRUE) {
69
70 if (pDev->GetPendingEventsFunc != NULL) {
71
72 HIF_PENDING_EVENTS_INFO events;
73
74 /* the HIF layer uses a special mechanism to get events, do this
75 * synchronously */
76 status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
77 &events,
78 NULL);
79 if (A_FAILED(status))
80 {
81 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n" ));
82 break;
83 }
84
85 if (events.Events & HIF_RECV_MSG_AVAIL)
86 {
87 /* there is a message available, the lookahead should be va lid now */
88 *pLookAhead = events.LookAhead;
89
90 break;
91 }
92 } else {
93
94 /* this is the standard HIF way.... */
95 /* load the register table */
96 status = HIFReadWrite(pDev->HIFDevice,
97 HOST_INT_STATUS_ADDRESS,
98 (A_UINT8 *)&pDev->IrqProcRegisters,
99 AR6K_IRQ_PROC_REGS_SIZE,
100 HIF_RD_SYNC_BYTE_INC,
101 NULL);
102
103 if (A_FAILED(status)){
104 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n "));
105 break;
106 }
107
108 /* check for MBOX data and valid lookahead */
109 if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) {
110 if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBO X))
111 {
112 /* mailbox has a message and the look ahead is valid */
113 *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBO X];
114 break;
115 }
116 }
117
118 }
119
120 timeout--;
121
122 if (timeout <= 0) {
123 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \ n"));
124 status = A_ERROR;
125
126 /* check if the target asserted */
127 if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_I NTR_MASK) {
128 /* target signaled an assert, process this pending interrupt
129 * this will call the target failure handler */
130 DevServiceDebugInterrupt(pDev);
131 }
132
133 break;
134 }
135
136 /* delay a little */
137 A_MDELAY(DELAY_PER_INTERVAL_MS);
138 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout));
139 }
140
141 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));
142
143 return status;
144 }
145
146 static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
147 {
148 A_STATUS status;
149 A_UINT8 cpu_int_status;
150 A_UINT8 regBuffer[4];
151
152 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
153 cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
154 pDev->IrqEnableRegisters.cpu_int_status_enable;
155 A_ASSERT(cpu_int_status);
156 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
157 ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
158 cpu_int_status));
159
160 /* Clear the interrupt */
161 pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */
162
163 /* set up the register transfer buffer to hit the register 4 times , thi s is done
164 * to make the access 4-byte aligned to mitigate issues with host bus in terconnects that
165 * restrict bus transfer lengths to be a multiple of 4-bytes */
166
167 /* set W1C value to clear the interrupt, this hits the register first */
168 regBuffer[0] = cpu_int_status;
169 /* the remaining 4 values are set to zero which have no-effect */
170 regBuffer[1] = 0;
171 regBuffer[2] = 0;
172 regBuffer[3] = 0;
173
174 status = HIFReadWrite(pDev->HIFDevice,
175 CPU_INT_STATUS_ADDRESS,
176 regBuffer,
177 4,
178 HIF_WR_SYNC_BYTE_FIX,
179 NULL);
180
181 A_ASSERT(status == A_OK);
182 return status;
183 }
184
185
186 static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
187 {
188 A_STATUS status;
189 A_UINT8 error_int_status;
190 A_UINT8 regBuffer[4];
191
192 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
193 error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
194 A_ASSERT(error_int_status);
195 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
196 ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
197 error_int_status));
198
199 if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
200 /* Wakeup */
201 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
202 }
203
204 if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) {
205 /* Rx Underflow */
206 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n"));
207 }
208
209 if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) {
210 /* Tx Overflow */
211 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n"));
212 }
213
214 /* Clear the interrupt */
215 pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */
216
217 /* set up the register transfer buffer to hit the register 4 times , thi s is done
218 * to make the access 4-byte aligned to mitigate issues with host bus in terconnects that
219 * restrict bus transfer lengths to be a multiple of 4-bytes */
220
221 /* set W1C value to clear the interrupt, this hits the register first */
222 regBuffer[0] = error_int_status;
223 /* the remaining 4 values are set to zero which have no-effect */
224 regBuffer[1] = 0;
225 regBuffer[2] = 0;
226 regBuffer[3] = 0;
227
228 status = HIFReadWrite(pDev->HIFDevice,
229 ERROR_INT_STATUS_ADDRESS,
230 regBuffer,
231 4,
232 HIF_WR_SYNC_BYTE_FIX,
233 NULL);
234
235 A_ASSERT(status == A_OK);
236 return status;
237 }
238
239 static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
240 {
241 A_UINT32 dummy;
242 A_STATUS status;
243
244 /* Send a target failure event to the application */
245 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
246
247 if (pDev->TargetFailureCallback != NULL) {
248 pDev->TargetFailureCallback(pDev->HTCContext);
249 }
250
251 if (pDev->GMboxEnabled) {
252 DevNotifyGMboxTargetFailure(pDev);
253 }
254
255 /* clear the interrupt , the debug error interrupt is
256 * counter 0 */
257 /* read counter to clear interrupt */
258 status = HIFReadWrite(pDev->HIFDevice,
259 COUNT_DEC_ADDRESS,
260 (A_UINT8 *)&dummy,
261 4,
262 HIF_RD_SYNC_BYTE_INC,
263 NULL);
264
265 A_ASSERT(status == A_OK);
266 return status;
267 }
268
269 static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
270 {
271 A_UINT8 counter_int_status;
272
273 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
274
275 counter_int_status = pDev->IrqProcRegisters.counter_int_status &
276 pDev->IrqEnableRegisters.counter_int_status_enable;
277
278 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
279 ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
280 counter_int_status));
281
282 /* Check if the debug interrupt is pending
283 * NOTE: other modules like GMBOX may use the counter interrupt for
284 * credit flow control on other counters, we only need to check for the debug assertion
285 * counter interrupt */
286 if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
287 return DevServiceDebugInterrupt(pDev);
288 }
289
290 return A_OK;
291 }
292
293 /* callback when our fetch to get interrupt status registers completes */
294 static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
295 {
296 AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
297 A_UINT32 lookAhead = 0;
298 A_BOOL otherInts = FALSE;
299
300 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%X)\n", (A _UINT32)pDev));
301
302 do {
303
304 if (A_FAILED(pPacket->Status)) {
305 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
306 (" GetEvents I/O request failed, status:%d \n", pPacket->Sta tus));
307 /* bail out, don't unmask HIF interrupt */
308 break;
309 }
310
311 if (pDev->GetPendingEventsFunc != NULL) {
312 /* the HIF layer collected the information for us */
313 HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacke t->pBuffer;
314 if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
315 lookAhead = pEvents->LookAhead;
316 if (0 == lookAhead) {
317 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, l ookAhead is zero! \n"));
318 }
319 }
320 if (pEvents->Events & HIF_OTHER_EVENTS) {
321 otherInts = TRUE;
322 }
323 } else {
324 /* standard interrupt table handling.... */
325 AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket-> pBuffer;
326 A_UINT8 host_int_status;
327
328 host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.i nt_status_enable;
329
330 if (host_int_status & (1 << HTC_MAILBOX)) {
331 host_int_status &= ~(1 << HTC_MAILBOX);
332 if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) {
333 /* mailbox has a message and the look ahead is valid */
334 lookAhead = pReg->rx_lookahead[HTC_MAILBOX];
335 if (0 == lookAhead) {
336 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler 2, lookAhead is zero! \n"));
337 }
338 }
339 }
340
341 if (host_int_status) {
342 /* there are other interrupts to handle */
343 otherInts = TRUE;
344 }
345 }
346
347 if (otherInts || (lookAhead == 0)) {
348 /* if there are other interrupts to process, we cannot do this in th e async handler so
349 * ack the interrupt which will cause our sync handler to run again
350 * if however there are no more messages, we can now ack the interru pt */
351 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
352 (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n",
353 otherInts, lookAhead));
354 HIFAckInterrupt(pDev->HIFDevice);
355 } else {
356 int fetched = 0;
357 A_STATUS status;
358
359 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
360 (" DevGetEventAsyncHandler : detected another message, looka head :0x%X \n",
361 lookAhead));
362 /* lookahead is non-zero and there are no other interrupts to se rvice,
363 * go get the next message */
364 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched);
365
366 if (A_SUCCESS(status) && !fetched) {
367 /* HTC layer could not pull out messages due to lack of reso urces, stop IRQ processing */
368 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not p ull any messages, force-ack \n"));
369 DevAsyncIrqProcessComplete(pDev);
370 }
371 }
372
373 } while (FALSE);
374
375 /* free this IO packet */
376 AR6KFreeIOPacket(pDev,pPacket);
377 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n"));
378 }
379
380 /* called by the HTC layer when it wants us to check if the device has any more pending
381 * recv messages, this starts off a series of async requests to read interrupt r egisters */
382 A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
383 {
384 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
385 A_STATUS status = A_OK;
386 HTC_PACKET *pIOPacket;
387
388 /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
389 * cause us to switch contexts */
390
391 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n" , (A_UINT32)pDev));
392
393 do {
394
395 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
396 /* break the async processing chain right here, no need to conti nue.
397 * The DevDsrHandler() will handle things in a loop when things are driven
398 * synchronously */
399 break;
400 }
401
402 /* an optimization to bypass reading the IRQ status registers uneces sarily which can re-wake
403 * the target, if upper layers determine that we are in a low-throug hput mode, we can
404 * rely on taking another interrupt rather than re-checking the stat us registers which can
405 * re-wake the target */
406 if (pDev->RecheckIRQStatusCnt == 0) {
407 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-ac king HIF interrupts\n"));
408 /* ack interrupt */
409 HIFAckInterrupt(pDev->HIFDevice);
410 break;
411 }
412
413 /* first allocate one of our HTC packets we created for async I/O
414 * we reuse HTC packet definitions so that we can use the completion mechanism
415 * in DevRWCompletionHandler() */
416 pIOPacket = AR6KAllocIOPacket(pDev);
417
418 if (NULL == pIOPacket) {
419 /* there should be only 1 asynchronous request out at a time to read these registers
420 * so this should actually never happen */
421 status = A_NO_MEMORY;
422 A_ASSERT(FALSE);
423 break;
424 }
425
426 /* stick in our completion routine when the I/O operation completes */
427 pIOPacket->Completion = DevGetEventAsyncHandler;
428 pIOPacket->pContext = pDev;
429
430 if (pDev->GetPendingEventsFunc) {
431 /* HIF layer has it's own mechanism, pass the IO to it.. */
432 status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
433 (HIF_PENDING_EVENTS_INFO *)pIOPa cket->pBuffer,
434 pIOPacket);
435
436 } else {
437 /* standard way, read the interrupt register table asynchronousl y again */
438 status = HIFReadWrite(pDev->HIFDevice,
439 HOST_INT_STATUS_ADDRESS,
440 pIOPacket->pBuffer,
441 AR6K_IRQ_PROC_REGS_SIZE,
442 HIF_RD_ASYNC_BYTE_INC,
443 pIOPacket);
444 }
445
446 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status ...\n"));
447 } while (FALSE);
448
449 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
450
451 return status;
452 }
453
454 void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev)
455 {
456 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n"));
457 HIFAckInterrupt(pDev->HIFDevice);
458 }
459
460 /* process pending interrupts synchronously */
461 static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS yncProcessing)
462 {
463 A_STATUS status = A_OK;
464 A_UINT8 host_int_status = 0;
465 A_UINT32 lookAhead = 0;
466
467 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%X)\n", (A_UINT 32)pDev));
468
469 /*** NOTE: the HIF implementation guarantees that the context of this call a llows
470 * us to perform SYNCHRONOUS I/O, that is we can block, sleep or cal l any API that
471 * can block or switch thread/task ontexts.
472 * This is a fully schedulable context.
473 * */
474 do {
475
476 if (pDev->IrqEnableRegisters.int_status_enable == 0) {
477 /* interrupt enables have been cleared, do not try to process any pe nding interrupts that
478 * may result in more bus transactions. The target may be unrespons ive at this
479 * point. */
480 break;
481 }
482
483 if (pDev->GetPendingEventsFunc != NULL) {
484 HIF_PENDING_EVENTS_INFO events;
485
486 /* the HIF layer uses a special mechanism to get events
487 * get this synchronously */
488 status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
489 &events,
490 NULL);
491
492 if (A_FAILED(status)) {
493 break;
494 }
495
496 if (events.Events & HIF_RECV_MSG_AVAIL) {
497 lookAhead = events.LookAhead;
498 if (0 == lookAhead) {
499 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhe ad is zero! \n"));
500 }
501 }
502
503 if (!(events.Events & HIF_OTHER_EVENTS) ||
504 !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLE D)) {
505 /* no need to read the register table, no other interesting interrupts.
506 * Some interfaces (like SPI) can shadow interrupt sources w ithout
507 * requiring the host to do a full table read */
508 break;
509 }
510
511 /* otherwise fall through and read the register table */
512 }
513
514 /*
515 * Read the first 28 bytes of the HTC register table. This will yield us
516 * the value of different int status registers and the lookahead
517 * registers.
518 * length = sizeof(int_status) + sizeof(cpu_int_status) +
519 * sizeof(error_int_status) + sizeof(counter_int_status) +
520 * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) +
521 * sizeof(hole) + sizeof(rx_lookahead) +
522 * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) +
523 * sizeof(error_status_enable) +
524 * sizeof(counter_int_status_enable);
525 *
526 */
527 status = HIFReadWrite(pDev->HIFDevice,
528 HOST_INT_STATUS_ADDRESS,
529 (A_UINT8 *)&pDev->IrqProcRegisters,
530 AR6K_IRQ_PROC_REGS_SIZE,
531 HIF_RD_SYNC_BYTE_INC,
532 NULL);
533
534 if (A_FAILED(status)) {
535 break;
536 }
537
538 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
539 DevDumpRegisters(pDev,
540 &pDev->IrqProcRegisters,
541 &pDev->IrqEnableRegisters);
542 }
543
544 /* Update only those registers that are enabled */
545 host_int_status = pDev->IrqProcRegisters.host_int_status &
546 pDev->IrqEnableRegisters.int_status_enable;
547
548 if (NULL == pDev->GetPendingEventsFunc) {
549 /* only look at mailbox status if the HIF layer did not provide this function,
550 * on some HIF interfaces reading the RX lookahead is not valid to do */
551 if (host_int_status & (1 << HTC_MAILBOX)) {
552 /* mask out pending mailbox value, we use "lookAhead" as the real flag for
553 * mailbox processing below */
554 host_int_status &= ~(1 << HTC_MAILBOX);
555 if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBO X)) {
556 /* mailbox has a message and the look ahead is valid */
557 lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX] ;
558 if (0 == lookAhead) {
559 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lo okAhead is zero! \n"));
560 }
561 }
562 }
563 } else {
564 /* not valid to check if the HIF has another mechanism for readi ng mailbox pending status*/
565 host_int_status &= ~(1 << HTC_MAILBOX);
566 }
567
568 if (pDev->GMboxEnabled) {
569 /*call GMBOX layer to process any interrupts of interest */
570 status = DevCheckGMboxInterrupts(pDev);
571 }
572
573 } while (FALSE);
574
575
576 do {
577
578 /* did the interrupt status fetches succeed? */
579 if (A_FAILED(status)) {
580 break;
581 }
582
583 if ((0 == host_int_status) && (0 == lookAhead)) {
584 /* nothing to process, the caller can use this to break out of a loop */
585 *pDone = TRUE;
586 break;
587 }
588
589 if (lookAhead != 0) {
590 int fetched = 0;
591
592 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead));
593 /* Mailbox Interrupt, the HTC layer may issue async requests to empty the
594 * mailbox...
595 * When emptying the recv mailbox we use the async handler above called from the
596 * completion routine of the callers read request. This can impr ove performance
597 * by reducing context switching when we rapidly pull packets */
598 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched);
599 if (A_FAILED(status)) {
600 break;
601 }
602
603 if (!fetched) {
604 /* HTC could not pull any messages out due to lack of resour ces */
605 /* force DSR handler to ack the interrupt */
606 *pASyncProcessing = FALSE;
607 pDev->RecheckIRQStatusCnt = 0;
608 }
609 }
610
611 /* now handle the rest of them */
612 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
613 (" Valid interrupt source(s) for OTHER interrupts: 0 x%x\n",
614 host_int_status));
615
616 if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
617 /* CPU Interrupt */
618 status = DevServiceCPUInterrupt(pDev);
619 if (A_FAILED(status)){
620 break;
621 }
622 }
623
624 if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
625 /* Error Interrupt */
626 status = DevServiceErrorInterrupt(pDev);
627 if (A_FAILED(status)){
628 break;
629 }
630 }
631
632 if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
633 /* Counter Interrupt */
634 status = DevServiceCounterInterrupt(pDev);
635 if (A_FAILED(status)){
636 break;
637 }
638 }
639
640 } while (FALSE);
641
642 /* an optimization to bypass reading the IRQ status registers unecessari ly which can re-wake
643 * the target, if upper layers determine that we are in a low-throughput mode, we can
644 * rely on taking another interrupt rather than re-checking the status r egisters which can
645 * re-wake the target */
646 if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0)) {
647 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing d one \n"));
648 *pDone = TRUE;
649 }
650
651 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) sta tus=%d \n",
652 *pDone, *pASyncProcessing, status));
653
654 return status;
655 }
656
657
658 /* Synchronousinterrupt handler, this handler kicks off all interrupt processing .*/
659 A_STATUS DevDsrHandler(void *context)
660 {
661 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
662 A_STATUS status = A_OK;
663 A_BOOL done = FALSE;
664 A_BOOL asyncProc = FALSE;
665
666 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pD ev));
667
668 /* reset the recv counter that tracks when we need to yield from the DSR */
669 pDev->CurrentDSRRecvCount = 0;
670 /* reset counter used to flag a re-scan of IRQ status registers on the t arget */
671 pDev->RecheckIRQStatusCnt = 0;
672
673 while (!done) {
674 status = ProcessPendingIRQs(pDev, &done, &asyncProc);
675 if (A_FAILED(status)) {
676 break;
677 }
678
679 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
680 /* the HIF layer does not allow async IRQ processing, override the a syncProc flag */
681 asyncProc = FALSE;
682 /* this will cause us to re-enter ProcessPendingIRQ() and re-read in terrupt status registers.
683 * this has a nice side effect of blocking us until all async read r equests are completed.
684 * This behavior is required on some HIF implementations that do not allow ASYNC
685 * processing in interrupt handlers (like Windows CE) */
686
687 if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) {
688 /* ProcessPendingIRQs() pulled enough recv messages to satisfy t he yield count, stop
689 * checking for more messages and return */
690 break;
691 }
692 }
693
694 if (asyncProc) {
695 /* the function performed some async I/O for performance, we
696 need to exit the ISR immediately, the check below will preven t the interrupt from being
697 Ack'd while we handle it asynchronously */
698 break;
699 }
700
701 }
702
703 if (A_SUCCESS(status) && !asyncProc) {
704 /* Ack the interrupt only if :
705 * 1. we did not get any errors in processing interrupts
706 * 2. there are no outstanding async processing requests */
707 if (pDev->DSRCanYield) {
708 /* if the DSR can yield do not ACK the interrupt, there could be more pending messages.
709 * The HIF layer must ACK the interrupt on behalf of HTC */
710 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount));
711 } else {
712 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n"));
713 HIFAckInterrupt(pDev->HIFDevice);
714 }
715 }
716
717 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n"));
718 return status;
719 }
720
721 void DumpAR6KDevState(AR6K_DEVICE *pDev)
722 {
723 A_STATUS status;
724 AR6K_IRQ_ENABLE_REGISTERS regs;
725 AR6K_IRQ_PROC_REGISTERS procRegs;
726
727 LOCK_AR6K(pDev);
728 /* copy into our temp area */
729 A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
730 UNLOCK_AR6K(pDev);
731
732 /* load the register table from the device */
733 status = HIFReadWrite(pDev->HIFDevice,
734 HOST_INT_STATUS_ADDRESS,
735 (A_UINT8 *)&procRegs,
736 AR6K_IRQ_PROC_REGS_SIZE,
737 HIF_RD_SYNC_BYTE_INC,
738 NULL);
739
740 if (A_FAILED(status)) {
741 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
742 ("DumpAR6KDevState : Failed to read register table (%d) \n",status)) ;
743 return;
744 }
745
746 DevDumpRegisters(pDev,&procRegs,&regs);
747
748 if (pDev->GMboxInfo.pStateDumpCallback != NULL) {
749 pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext);
750 }
751
752 /* dump any bus state at the HIF layer */
753 HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0);
754
755 }
756
757
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c ('k') | chromeos/drivers/ath6kl/htc2/AR6000/ar6k_gmbox.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698