| OLD | NEW |
| 1 //------------------------------------------------------------------------------ | 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="ar6k_events.c" company="Atheros"> | 2 // <copyright file="ar6k_events.c" company="Atheros"> |
| 3 // Copyright (c) 2007-2008 Atheros Corporation. All rights reserved. | 3 // Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. |
| 4 // | 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 // | 5 // |
| 9 // Software distributed under the License is distributed on an "AS | 6 // Permission to use, copy, modify, and/or distribute this software for any |
| 10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | 7 // purpose with or without fee is hereby granted, provided that the above |
| 11 // implied. See the License for the specific language governing | 8 // copyright notice and this permission notice appear in all copies. |
| 12 // rights and limitations under the License. | 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. |
| 13 // | 17 // |
| 14 // | 18 // |
| 15 //------------------------------------------------------------------------------ | 19 //------------------------------------------------------------------------------ |
| 16 //============================================================================== | 20 //============================================================================== |
| 17 // AR6K Driver layer event handling (i.e. interrupts, message polling) | 21 // AR6K Driver layer event handling (i.e. interrupts, message polling) |
| 18 // | 22 // |
| 19 // Author(s): ="Atheros" | 23 // Author(s): ="Atheros" |
| 20 //============================================================================== | 24 //============================================================================== |
| 21 | 25 |
| 22 #include "a_config.h" | 26 #include "a_config.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 35 static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev); | 39 static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev); |
| 36 | 40 |
| 37 #define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */ | 41 #define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */ |
| 38 | 42 |
| 39 /* completion routine for ALL HIF layer async I/O */ | 43 /* completion routine for ALL HIF layer async I/O */ |
| 40 A_STATUS DevRWCompletionHandler(void *context, A_STATUS status) | 44 A_STATUS DevRWCompletionHandler(void *context, A_STATUS status) |
| 41 { | 45 { |
| 42 HTC_PACKET *pPacket = (HTC_PACKET *)context; | 46 HTC_PACKET *pPacket = (HTC_PACKET *)context; |
| 43 | 47 |
| 44 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, | 48 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, |
| 45 ("+DevRWCompletionHandler (Pkt:0x%X) , Status: %d \n", | 49 ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n", |
| 46 (A_UINT32)pPacket, | 50 (unsigned long)pPacket, |
| 47 status)); | 51 status)); |
| 48 | 52 |
| 49 COMPLETE_HTC_PACKET(pPacket,status); | 53 COMPLETE_HTC_PACKET(pPacket,status); |
| 50 | 54 |
| 51 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, | 55 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, |
| 52 ("-DevRWCompletionHandler\n")); | 56 ("-DevRWCompletionHandler\n")); |
| 53 | 57 |
| 54 return A_OK; | 58 return A_OK; |
| 55 } | 59 } |
| 56 | 60 |
| 57 /* mailbox recv message polling */ | 61 /* mailbox recv message polling */ |
| 58 A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, | 62 A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, |
| 59 A_UINT32 *pLookAhead, | 63 A_UINT32 *pLookAhead, |
| 60 int TimeoutMS) | 64 int TimeoutMS) |
| 61 { | 65 { |
| 62 A_STATUS status = A_OK; | 66 A_STATUS status = A_OK; |
| 63 int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS; | 67 int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS; |
| 64 | 68 |
| 65 A_ASSERT(timeout > 0); | 69 A_ASSERT(timeout > 0); |
| 66 | 70 |
| 67 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n")); | 71 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n")); |
| 68 | 72 |
| 69 while (TRUE) { | 73 while (TRUE) { |
| 70 | 74 |
| 71 if (pDev->GetPendingEventsFunc != NULL) { | 75 if (pDev->GetPendingEventsFunc != NULL) { |
| 72 | 76 |
| 73 HIF_PENDING_EVENTS_INFO events; | 77 HIF_PENDING_EVENTS_INFO events; |
| 74 | 78 |
| 79 #ifdef THREAD_X |
| 80 events.Polling =1; |
| 81 #endif |
| 82 |
| 75 /* the HIF layer uses a special mechanism to get events, do this | 83 /* the HIF layer uses a special mechanism to get events, do this |
| 76 * synchronously */ | 84 * synchronously */ |
| 77 status = pDev->GetPendingEventsFunc(pDev->HIFDevice, | 85 status = pDev->GetPendingEventsFunc(pDev->HIFDevice, |
| 78 &events, | 86 &events, |
| 79 NULL); | 87 NULL); |
| 80 if (A_FAILED(status)) | 88 if (A_FAILED(status)) |
| 81 { | 89 { |
| 82 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"
)); | 90 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"
)); |
| 83 break; | 91 break; |
| 84 } | 92 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 { | 249 { |
| 242 A_UINT32 dummy; | 250 A_UINT32 dummy; |
| 243 A_STATUS status; | 251 A_STATUS status; |
| 244 | 252 |
| 245 /* Send a target failure event to the application */ | 253 /* Send a target failure event to the application */ |
| 246 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); | 254 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); |
| 247 | 255 |
| 248 if (pDev->TargetFailureCallback != NULL) { | 256 if (pDev->TargetFailureCallback != NULL) { |
| 249 pDev->TargetFailureCallback(pDev->HTCContext); | 257 pDev->TargetFailureCallback(pDev->HTCContext); |
| 250 } | 258 } |
| 251 | 259 |
| 252 if (pDev->GMboxEnabled) { | 260 if (pDev->GMboxEnabled) { |
| 253 DevNotifyGMboxTargetFailure(pDev); | 261 DevNotifyGMboxTargetFailure(pDev); |
| 254 } | 262 } |
| 255 | 263 |
| 256 /* clear the interrupt , the debug error interrupt is | 264 /* clear the interrupt , the debug error interrupt is |
| 257 * counter 0 */ | 265 * counter 0 */ |
| 258 /* read counter to clear interrupt */ | 266 /* read counter to clear interrupt */ |
| 259 status = HIFReadWrite(pDev->HIFDevice, | 267 status = HIFReadWrite(pDev->HIFDevice, |
| 260 COUNT_DEC_ADDRESS, | 268 COUNT_DEC_ADDRESS, |
| 261 (A_UINT8 *)&dummy, | 269 (A_UINT8 *)&dummy, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 275 | 283 |
| 276 counter_int_status = pDev->IrqProcRegisters.counter_int_status & | 284 counter_int_status = pDev->IrqProcRegisters.counter_int_status & |
| 277 pDev->IrqEnableRegisters.counter_int_status_enable; | 285 pDev->IrqEnableRegisters.counter_int_status_enable; |
| 278 | 286 |
| 279 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, | 287 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, |
| 280 ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", | 288 ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", |
| 281 counter_int_status)); | 289 counter_int_status)); |
| 282 | 290 |
| 283 /* Check if the debug interrupt is pending | 291 /* Check if the debug interrupt is pending |
| 284 * NOTE: other modules like GMBOX may use the counter interrupt for | 292 * NOTE: other modules like GMBOX may use the counter interrupt for |
| 285 * credit flow control on other counters, we only need to check for the
debug assertion | 293 * credit flow control on other counters, we only need to check for the
debug assertion |
| 286 * counter interrupt */ | 294 * counter interrupt */ |
| 287 if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { | 295 if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { |
| 288 return DevServiceDebugInterrupt(pDev); | 296 return DevServiceDebugInterrupt(pDev); |
| 289 } | 297 } |
| 290 | 298 |
| 291 return A_OK; | 299 return A_OK; |
| 292 } | 300 } |
| 293 | 301 |
| 294 /* callback when our fetch to get interrupt status registers completes */ | 302 /* callback when our fetch to get interrupt status registers completes */ |
| 295 static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket) | 303 static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket) |
| 296 { | 304 { |
| 297 AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; | 305 AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; |
| 298 A_UINT32 lookAhead = 0; | 306 A_UINT32 lookAhead = 0; |
| 299 A_BOOL otherInts = FALSE; | 307 A_BOOL otherInts = FALSE; |
| 300 | 308 |
| 301 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%X)\n", (A
_UINT32)pDev)); | 309 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (
unsigned long)pDev)); |
| 302 | 310 |
| 303 do { | 311 do { |
| 304 | 312 |
| 305 if (A_FAILED(pPacket->Status)) { | 313 if (A_FAILED(pPacket->Status)) { |
| 306 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | 314 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, |
| 307 (" GetEvents I/O request failed, status:%d \n", pPacket->Sta
tus)); | 315 (" GetEvents I/O request failed, status:%d \n", pPacket->Sta
tus)); |
| 308 /* bail out, don't unmask HIF interrupt */ | 316 /* bail out, don't unmask HIF interrupt */ |
| 309 break; | 317 break; |
| 310 } | 318 } |
| 311 | 319 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 /* if there are other interrupts to process, we cannot do this in th
e async handler so | 357 /* if there are other interrupts to process, we cannot do this in th
e async handler so |
| 350 * ack the interrupt which will cause our sync handler to run again | 358 * ack the interrupt which will cause our sync handler to run again |
| 351 * if however there are no more messages, we can now ack the interru
pt */ | 359 * if however there are no more messages, we can now ack the interru
pt */ |
| 352 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, | 360 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, |
| 353 (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d,
lookahead:0x%X)\n", | 361 (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d,
lookahead:0x%X)\n", |
| 354 otherInts, lookAhead)); | 362 otherInts, lookAhead)); |
| 355 HIFAckInterrupt(pDev->HIFDevice); | 363 HIFAckInterrupt(pDev->HIFDevice); |
| 356 } else { | 364 } else { |
| 357 int fetched = 0; | 365 int fetched = 0; |
| 358 A_STATUS status; | 366 A_STATUS status; |
| 359 | 367 |
| 360 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, | 368 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, |
| 361 (" DevGetEventAsyncHandler : detected another message, looka
head :0x%X \n", | 369 (" DevGetEventAsyncHandler : detected another message, looka
head :0x%X \n", |
| 362 lookAhead)); | 370 lookAhead)); |
| 363 /* lookahead is non-zero and there are no other interrupts to se
rvice, | 371 /* lookahead is non-zero and there are no other interrupts to se
rvice, |
| 364 * go get the next message */ | 372 * go get the next message */ |
| 365 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead,
1, NULL, &fetched); | 373 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead,
1, NULL, &fetched); |
| 366 | 374 |
| 367 if (A_SUCCESS(status) && !fetched) { | 375 if (A_SUCCESS(status) && !fetched) { |
| 368 /* HTC layer could not pull out messages due to lack of reso
urces, stop IRQ processing */ | 376 /* HTC layer could not pull out messages due to lack of reso
urces, stop IRQ processing */ |
| 369 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not p
ull any messages, force-ack \n")); | 377 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not p
ull any messages, force-ack \n")); |
| 370 DevAsyncIrqProcessComplete(pDev); | 378 DevAsyncIrqProcessComplete(pDev); |
| 371 } | 379 } |
| 372 } | 380 } |
| 373 | 381 |
| 374 } while (FALSE); | 382 } while (FALSE); |
| 375 | 383 |
| 376 /* free this IO packet */ | 384 /* free this IO packet */ |
| 377 AR6KFreeIOPacket(pDev,pPacket); | 385 AR6KFreeIOPacket(pDev,pPacket); |
| 378 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); | 386 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); |
| 379 } | 387 } |
| 380 | 388 |
| 381 /* called by the HTC layer when it wants us to check if the device has any more
pending | 389 /* called by the HTC layer when it wants us to check if the device has any more
pending |
| 382 * recv messages, this starts off a series of async requests to read interrupt r
egisters */ | 390 * recv messages, this starts off a series of async requests to read interrupt r
egisters */ |
| 383 A_STATUS DevCheckPendingRecvMsgsAsync(void *context) | 391 A_STATUS DevCheckPendingRecvMsgsAsync(void *context) |
| 384 { | 392 { |
| 385 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; | 393 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; |
| 386 A_STATUS status = A_OK; | 394 A_STATUS status = A_OK; |
| 387 HTC_PACKET *pIOPacket; | 395 HTC_PACKET *pIOPacket; |
| 388 | 396 |
| 389 /* this is called in an ASYNC only context, we may NOT block, sleep or call
any apis that can | 397 /* this is called in an ASYNC only context, we may NOT block, sleep or call
any apis that can |
| 390 * cause us to switch contexts */ | 398 * cause us to switch contexts */ |
| 391 | 399 |
| 392 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n"
, (A_UINT32)pDev)); | 400 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%lX)\n
", (unsigned long)pDev)); |
| 393 | 401 |
| 394 do { | 402 do { |
| 395 | 403 |
| 396 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { | 404 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { |
| 397 /* break the async processing chain right here, no need to conti
nue. | 405 /* break the async processing chain right here, no need to conti
nue. |
| 398 * The DevDsrHandler() will handle things in a loop when things
are driven | 406 * The DevDsrHandler() will handle things in a loop when things
are driven |
| 399 * synchronously */ | 407 * synchronously */ |
| 400 break; | 408 break; |
| 401 } | 409 } |
| 402 | 410 |
| 403 /* an optimization to bypass reading the IRQ status registers uneces
sarily which can re-wake | 411 /* an optimization to bypass reading the IRQ status registers uneces
sarily which can re-wake |
| 404 * the target, if upper layers determine that we are in a low-throug
hput mode, we can | 412 * the target, if upper layers determine that we are in a low-throug
hput mode, we can |
| 405 * rely on taking another interrupt rather than re-checking the stat
us registers which can | 413 * rely on taking another interrupt rather than re-checking the stat
us registers which can |
| 406 * re-wake the target */ | 414 * re-wake the target */ |
| 407 if (pDev->RecheckIRQStatusCnt == 0) { | 415 if (pDev->RecheckIRQStatusCnt == 0) { |
| 408 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-ac
king HIF interrupts\n")); | 416 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-ac
king HIF interrupts\n")); |
| 409 /* ack interrupt */ | 417 /* ack interrupt */ |
| 410 HIFAckInterrupt(pDev->HIFDevice); | 418 HIFAckInterrupt(pDev->HIFDevice); |
| 411 break; | 419 break; |
| 412 } | 420 } |
| 413 | 421 |
| 414 /* first allocate one of our HTC packets we created for async I/O | 422 /* first allocate one of our HTC packets we created for async I/O |
| 415 * we reuse HTC packet definitions so that we can use the completion
mechanism | 423 * we reuse HTC packet definitions so that we can use the completion
mechanism |
| 416 * in DevRWCompletionHandler() */ | 424 * in DevRWCompletionHandler() */ |
| 417 pIOPacket = AR6KAllocIOPacket(pDev); | 425 pIOPacket = AR6KAllocIOPacket(pDev); |
| 418 | 426 |
| 419 if (NULL == pIOPacket) { | 427 if (NULL == pIOPacket) { |
| 420 /* there should be only 1 asynchronous request out at a time to
read these registers | 428 /* there should be only 1 asynchronous request out at a time to
read these registers |
| 421 * so this should actually never happen */ | 429 * so this should actually never happen */ |
| 422 status = A_NO_MEMORY; | 430 status = A_NO_MEMORY; |
| 423 A_ASSERT(FALSE); | 431 A_ASSERT(FALSE); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 446 | 454 |
| 447 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status
...\n")); | 455 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status
...\n")); |
| 448 } while (FALSE); | 456 } while (FALSE); |
| 449 | 457 |
| 450 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); | 458 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); |
| 451 | 459 |
| 452 return status; | 460 return status; |
| 453 } | 461 } |
| 454 | 462 |
| 455 void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev) | 463 void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev) |
| 456 { | 464 { |
| 457 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ
ACK \n")); | 465 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ
ACK \n")); |
| 458 HIFAckInterrupt(pDev->HIFDevice); | 466 HIFAckInterrupt(pDev->HIFDevice); |
| 459 } | 467 } |
| 460 | 468 |
| 461 /* process pending interrupts synchronously */ | 469 /* process pending interrupts synchronously */ |
| 462 static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
yncProcessing) | 470 static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
yncProcessing) |
| 463 { | 471 { |
| 464 A_STATUS status = A_OK; | 472 A_STATUS status = A_OK; |
| 465 A_UINT8 host_int_status = 0; | 473 A_UINT8 host_int_status = 0; |
| 466 A_UINT32 lookAhead = 0; | 474 A_UINT32 lookAhead = 0; |
| 467 | 475 |
| 468 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%X)\n", (A_UINT
32)pDev)); | 476 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsig
ned long)pDev)); |
| 469 | 477 |
| 470 /*** NOTE: the HIF implementation guarantees that the context of this call a
llows | 478 /*** NOTE: the HIF implementation guarantees that the context of this call a
llows |
| 471 * us to perform SYNCHRONOUS I/O, that is we can block, sleep or cal
l any API that | 479 * us to perform SYNCHRONOUS I/O, that is we can block, sleep or cal
l any API that |
| 472 * can block or switch thread/task ontexts. | 480 * can block or switch thread/task ontexts. |
| 473 * This is a fully schedulable context. | 481 * This is a fully schedulable context. |
| 474 * */ | 482 * */ |
| 475 do { | 483 do { |
| 476 | 484 |
| 477 if (pDev->IrqEnableRegisters.int_status_enable == 0) { | 485 if (pDev->IrqEnableRegisters.int_status_enable == 0) { |
| 478 /* interrupt enables have been cleared, do not try to process any pe
nding interrupts that | 486 /* interrupt enables have been cleared, do not try to process an
y pending interrupts that |
| 479 * may result in more bus transactions. The target may be unrespons
ive at this | 487 * may result in more bus transactions. The target may be unres
ponsive at this |
| 480 * point. */ | 488 * point. */ |
| 481 break; | 489 break; |
| 482 } | 490 } |
| 483 | |
| 484 if (pDev->GetPendingEventsFunc != NULL) { | |
| 485 HIF_PENDING_EVENTS_INFO events; | |
| 486 | 491 |
| 492 if (pDev->GetPendingEventsFunc != NULL) { |
| 493 HIF_PENDING_EVENTS_INFO events; |
| 494 |
| 495 #ifdef THREAD_X |
| 496 events.Polling= 0; |
| 497 #endif |
| 487 /* the HIF layer uses a special mechanism to get events | 498 /* the HIF layer uses a special mechanism to get events |
| 488 * get this synchronously */ | 499 * get this synchronously */ |
| 489 status = pDev->GetPendingEventsFunc(pDev->HIFDevice, | 500 status = pDev->GetPendingEventsFunc(pDev->HIFDevice, |
| 490 &events, | 501 &events, |
| 491 NULL); | 502 NULL); |
| 492 | 503 |
| 493 if (A_FAILED(status)) { | 504 if (A_FAILED(status)) { |
| 494 break; | 505 break; |
| 495 } | 506 } |
| 496 | 507 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 HOST_INT_STATUS_ADDRESS, | 547 HOST_INT_STATUS_ADDRESS, |
| 537 (A_UINT8 *)&pDev->IrqProcRegisters, | 548 (A_UINT8 *)&pDev->IrqProcRegisters, |
| 538 AR6K_IRQ_PROC_REGS_SIZE, | 549 AR6K_IRQ_PROC_REGS_SIZE, |
| 539 HIF_RD_SYNC_BYTE_INC, | 550 HIF_RD_SYNC_BYTE_INC, |
| 540 NULL); | 551 NULL); |
| 541 | 552 |
| 542 if (A_FAILED(status)) { | 553 if (A_FAILED(status)) { |
| 543 break; | 554 break; |
| 544 } | 555 } |
| 545 | 556 |
| 557 #ifdef ATH_DEBUG_MODULE |
| 546 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { | 558 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { |
| 547 DevDumpRegisters(pDev, | 559 DevDumpRegisters(pDev, |
| 548 &pDev->IrqProcRegisters, | 560 &pDev->IrqProcRegisters, |
| 549 &pDev->IrqEnableRegisters); | 561 &pDev->IrqEnableRegisters); |
| 550 } | 562 } |
| 563 #endif |
| 551 | 564 |
| 552 /* Update only those registers that are enabled */ | 565 /* Update only those registers that are enabled */ |
| 553 host_int_status = pDev->IrqProcRegisters.host_int_status & | 566 host_int_status = pDev->IrqProcRegisters.host_int_status & |
| 554 pDev->IrqEnableRegisters.int_status_enable; | 567 pDev->IrqEnableRegisters.int_status_enable; |
| 555 | 568 |
| 556 if (NULL == pDev->GetPendingEventsFunc) { | 569 if (NULL == pDev->GetPendingEventsFunc) { |
| 557 /* only look at mailbox status if the HIF layer did not provide
this function, | 570 /* only look at mailbox status if the HIF layer did not provide
this function, |
| 558 * on some HIF interfaces reading the RX lookahead is not valid
to do */ | 571 * on some HIF interfaces reading the RX lookahead is not valid
to do */ |
| 559 if (host_int_status & (1 << HTC_MAILBOX)) { | 572 if (host_int_status & (1 << HTC_MAILBOX)) { |
| 560 /* mask out pending mailbox value, we use "lookAhead" as the
real flag for | 573 /* mask out pending mailbox value, we use "lookAhead" as the
real flag for |
| 561 * mailbox processing below */ | 574 * mailbox processing below */ |
| 562 host_int_status &= ~(1 << HTC_MAILBOX); | 575 host_int_status &= ~(1 << HTC_MAILBOX); |
| 563 if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBO
X)) { | 576 if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBO
X)) { |
| 564 /* mailbox has a message and the look ahead is valid */ | 577 /* mailbox has a message and the look ahead is valid */ |
| 565 lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]
; | 578 lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]
; |
| 566 if (0 == lookAhead) { | 579 if (0 == lookAhead) { |
| 567 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lo
okAhead is zero! \n")); | 580 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lo
okAhead is zero! \n")); |
| 568 } | 581 } |
| 569 } | 582 } |
| 570 } | 583 } |
| 571 } else { | 584 } else { |
| 572 /* not valid to check if the HIF has another mechanism for readi
ng mailbox pending status*/ | 585 /* not valid to check if the HIF has another mechanism for readi
ng mailbox pending status*/ |
| 573 host_int_status &= ~(1 << HTC_MAILBOX); | 586 host_int_status &= ~(1 << HTC_MAILBOX); |
| 574 } | 587 } |
| 575 | 588 |
| 576 if (pDev->GMboxEnabled) { | 589 if (pDev->GMboxEnabled) { |
| 577 /*call GMBOX layer to process any interrupts of interest */ | 590 /*call GMBOX layer to process any interrupts of interest */ |
| 578 status = DevCheckGMboxInterrupts(pDev); | 591 status = DevCheckGMboxInterrupts(pDev); |
| 579 } | 592 } |
| 580 | 593 |
| 581 } while (FALSE); | 594 } while (FALSE); |
| 582 | 595 |
| 583 | 596 |
| 584 do { | 597 do { |
| 585 | 598 |
| 586 /* did the interrupt status fetches succeed? */ | 599 /* did the interrupt status fetches succeed? */ |
| 587 if (A_FAILED(status)) { | 600 if (A_FAILED(status)) { |
| 588 break; | 601 break; |
| 589 } | 602 } |
| 590 | 603 |
| 591 if ((0 == host_int_status) && (0 == lookAhead)) { | 604 if ((0 == host_int_status) && (0 == lookAhead)) { |
| 592 /* nothing to process, the caller can use this to break out of a
loop */ | 605 /* nothing to process, the caller can use this to break out of a
loop */ |
| 593 *pDone = TRUE; | 606 *pDone = TRUE; |
| 594 break; | 607 break; |
| 595 } | 608 } |
| 596 | 609 |
| 597 if (lookAhead != 0) { | 610 if (lookAhead != 0) { |
| 598 int fetched = 0; | 611 int fetched = 0; |
| 599 | 612 |
| 600 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead:
0x%X\n",lookAhead)); | 613 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead:
0x%X\n",lookAhead)); |
| 601 /* Mailbox Interrupt, the HTC layer may issue async requests to
empty the | 614 /* Mailbox Interrupt, the HTC layer may issue async requests to
empty the |
| 602 * mailbox... | 615 * mailbox... |
| 603 * When emptying the recv mailbox we use the async handler above
called from the | 616 * When emptying the recv mailbox we use the async handler above
called from the |
| 604 * completion routine of the callers read request. This can impr
ove performance | 617 * completion routine of the callers read request. This can impr
ove performance |
| 605 * by reducing context switching when we rapidly pull packets */ | 618 * by reducing context switching when we rapidly pull packets */ |
| 606 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead,
1, pASyncProcessing, &fetched); | 619 status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead,
1, pASyncProcessing, &fetched); |
| 607 if (A_FAILED(status)) { | 620 if (A_FAILED(status)) { |
| 608 break; | 621 break; |
| 609 } | 622 } |
| 610 | 623 |
| 611 if (!fetched) { | 624 if (!fetched) { |
| 612 /* HTC could not pull any messages out due to lack of resour
ces */ | 625 /* HTC could not pull any messages out due to lack of resour
ces */ |
| 613 /* force DSR handler to ack the interrupt */ | 626 /* force DSR handler to ack the interrupt */ |
| 614 *pASyncProcessing = FALSE; | 627 *pASyncProcessing = FALSE; |
| 615 pDev->RecheckIRQStatusCnt = 0; | 628 pDev->RecheckIRQStatusCnt = 0; |
| 616 } | 629 } |
| 617 } | 630 } |
| 618 | 631 |
| 619 /* now handle the rest of them */ | 632 /* now handle the rest of them */ |
| 620 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, | 633 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, |
| 621 (" Valid interrupt source(s) for OTHER interrupts: 0
x%x\n", | 634 (" Valid interrupt source(s) for OTHER interrupts: 0
x%x\n", |
| 622 host_int_status)); | 635 host_int_status)); |
| 623 | 636 |
| 624 if (HOST_INT_STATUS_CPU_GET(host_int_status)) { | 637 if (HOST_INT_STATUS_CPU_GET(host_int_status)) { |
| 625 /* CPU Interrupt */ | 638 /* CPU Interrupt */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 644 break; | 657 break; |
| 645 } | 658 } |
| 646 } | 659 } |
| 647 | 660 |
| 648 } while (FALSE); | 661 } while (FALSE); |
| 649 | 662 |
| 650 /* an optimization to bypass reading the IRQ status registers unecessari
ly which can re-wake | 663 /* an optimization to bypass reading the IRQ status registers unecessari
ly which can re-wake |
| 651 * the target, if upper layers determine that we are in a low-throughput
mode, we can | 664 * the target, if upper layers determine that we are in a low-throughput
mode, we can |
| 652 * rely on taking another interrupt rather than re-checking the status r
egisters which can | 665 * rely on taking another interrupt rather than re-checking the status r
egisters which can |
| 653 * re-wake the target. | 666 * re-wake the target. |
| 654 * | 667 * |
| 655 * NOTE : for host interfaces that use the special GetPendingEventsFunc,
this optimization cannot | 668 * NOTE : for host interfaces that use the special GetPendingEventsFunc,
this optimization cannot |
| 656 * be used due to possible side-effects. For example, SPI requires the
host to drain all | 669 * be used due to possible side-effects. For example, SPI requires the
host to drain all |
| 657 * messages from the mailbox before exiting the ISR routine. */ | 670 * messages from the mailbox before exiting the ISR routine. */ |
| 658 if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPe
ndingEventsFunc == NULL)) { | 671 if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPe
ndingEventsFunc == NULL)) { |
| 659 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing d
one \n")); | 672 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing d
one \n")); |
| 660 *pDone = TRUE; | 673 *pDone = TRUE; |
| 661 } | 674 } |
| 662 | 675 |
| 663 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) sta
tus=%d \n", | 676 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) sta
tus=%d \n", |
| 664 *pDone, *pASyncProcessing, status)); | 677 *pDone, *pASyncProcessing, status)); |
| 665 | 678 |
| 666 return status; | 679 return status; |
| 667 } | 680 } |
| 668 | 681 |
| 669 | 682 |
| 670 /* Synchronousinterrupt handler, this handler kicks off all interrupt processing
.*/ | 683 /* Synchronousinterrupt handler, this handler kicks off all interrupt processing
.*/ |
| 671 A_STATUS DevDsrHandler(void *context) | 684 A_STATUS DevDsrHandler(void *context) |
| 672 { | 685 { |
| 673 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; | 686 AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; |
| 674 A_STATUS status = A_OK; | 687 A_STATUS status = A_OK; |
| 675 A_BOOL done = FALSE; | 688 A_BOOL done = FALSE; |
| 676 A_BOOL asyncProc = FALSE; | 689 A_BOOL asyncProc = FALSE; |
| 677 | 690 |
| 678 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pD
ev)); | 691 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned l
ong)pDev)); |
| 679 | 692 |
| 680 /* reset the recv counter that tracks when we need to yield from the DSR
*/ | 693 /* reset the recv counter that tracks when we need to yield from the DSR
*/ |
| 681 pDev->CurrentDSRRecvCount = 0; | 694 pDev->CurrentDSRRecvCount = 0; |
| 682 /* reset counter used to flag a re-scan of IRQ status registers on the t
arget */ | 695 /* reset counter used to flag a re-scan of IRQ status registers on the t
arget */ |
| 683 pDev->RecheckIRQStatusCnt = 0; | 696 pDev->RecheckIRQStatusCnt = 0; |
| 684 | 697 |
| 685 while (!done) { | 698 while (!done) { |
| 686 status = ProcessPendingIRQs(pDev, &done, &asyncProc); | 699 status = ProcessPendingIRQs(pDev, &done, &asyncProc); |
| 687 if (A_FAILED(status)) { | 700 if (A_FAILED(status)) { |
| 688 break; | 701 break; |
| 689 } | 702 } |
| 690 | 703 |
| 691 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { | 704 if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { |
| 692 /* the HIF layer does not allow async IRQ processing, override the a
syncProc flag */ | 705 /* the HIF layer does not allow async IRQ processing, override the a
syncProc flag */ |
| 693 asyncProc = FALSE; | 706 asyncProc = FALSE; |
| 694 /* this will cause us to re-enter ProcessPendingIRQ() and re-read in
terrupt status registers. | 707 /* this will cause us to re-enter ProcessPendingIRQ() and re-read in
terrupt status registers. |
| 695 * this has a nice side effect of blocking us until all async read r
equests are completed. | 708 * this has a nice side effect of blocking us until all async read r
equests are completed. |
| 696 * This behavior is required on some HIF implementations that do not
allow ASYNC | 709 * This behavior is required on some HIF implementations that do not
allow ASYNC |
| 697 * processing in interrupt handlers (like Windows CE) */ | 710 * processing in interrupt handlers (like Windows CE) */ |
| 698 | 711 |
| 699 if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { | 712 if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { |
| 700 /* ProcessPendingIRQs() pulled enough recv messages to satisfy t
he yield count, stop | 713 /* ProcessPendingIRQs() pulled enough recv messages to satisfy t
he yield count, stop |
| 701 * checking for more messages and return */ | 714 * checking for more messages and return */ |
| 702 break; | 715 break; |
| 703 } | 716 } |
| 704 } | 717 } |
| 705 | 718 |
| 706 if (asyncProc) { | 719 if (asyncProc) { |
| 707 /* the function performed some async I/O for performance, we | 720 /* the function performed some async I/O for performance, we |
| 708 need to exit the ISR immediately, the check below will preven
t the interrupt from being | 721 need to exit the ISR immediately, the check below will preven
t the interrupt from being |
| 709 Ack'd while we handle it asynchronously */ | 722 Ack'd while we handle it asynchronously */ |
| 710 break; | 723 break; |
| 711 } | 724 } |
| 712 | 725 |
| 713 } | 726 } |
| 714 | 727 |
| 715 if (A_SUCCESS(status) && !asyncProc) { | 728 if (A_SUCCESS(status) && !asyncProc) { |
| 716 /* Ack the interrupt only if : | 729 /* Ack the interrupt only if : |
| 717 * 1. we did not get any errors in processing interrupts | 730 * 1. we did not get any errors in processing interrupts |
| 718 * 2. there are no outstanding async processing requests */ | 731 * 2. there are no outstanding async processing requests */ |
| 719 if (pDev->DSRCanYield) { | 732 if (pDev->DSRCanYield) { |
| 720 /* if the DSR can yield do not ACK the interrupt, there could be
more pending messages. | 733 /* if the DSR can yield do not ACK the interrupt, there could be
more pending messages. |
| 721 * The HIF layer must ACK the interrupt on behalf of HTC */ | 734 * The HIF layer must ACK the interrupt on behalf of HTC */ |
| 722 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d)
\n", pDev->CurrentDSRRecvCount)); | 735 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d)
\n", pDev->CurrentDSRRecvCount)); |
| 723 } else { | 736 } else { |
| 724 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler
\n")); | 737 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler
\n")); |
| 725 HIFAckInterrupt(pDev->HIFDevice); | 738 HIFAckInterrupt(pDev->HIFDevice); |
| 726 } | 739 } |
| 727 } | 740 } |
| 728 | 741 |
| 729 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); | 742 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); |
| 730 return status; | 743 return status; |
| 731 } | 744 } |
| 732 | 745 |
| 746 #ifdef ATH_DEBUG_MODULE |
| 733 void DumpAR6KDevState(AR6K_DEVICE *pDev) | 747 void DumpAR6KDevState(AR6K_DEVICE *pDev) |
| 734 { | 748 { |
| 735 A_STATUS status; | 749 A_STATUS status; |
| 736 AR6K_IRQ_ENABLE_REGISTERS regs; | 750 AR6K_IRQ_ENABLE_REGISTERS regs; |
| 737 AR6K_IRQ_PROC_REGISTERS procRegs; | 751 AR6K_IRQ_PROC_REGISTERS procRegs; |
| 738 | 752 |
| 739 LOCK_AR6K(pDev); | 753 LOCK_AR6K(pDev); |
| 740 /* copy into our temp area */ | 754 /* copy into our temp area */ |
| 741 A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); | 755 A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); |
| 742 UNLOCK_AR6K(pDev); | 756 UNLOCK_AR6K(pDev); |
| 743 | 757 |
| 744 /* load the register table from the device */ | 758 /* load the register table from the device */ |
| 745 status = HIFReadWrite(pDev->HIFDevice, | 759 status = HIFReadWrite(pDev->HIFDevice, |
| 746 HOST_INT_STATUS_ADDRESS, | 760 HOST_INT_STATUS_ADDRESS, |
| 747 (A_UINT8 *)&procRegs, | 761 (A_UINT8 *)&procRegs, |
| 748 AR6K_IRQ_PROC_REGS_SIZE, | 762 AR6K_IRQ_PROC_REGS_SIZE, |
| 749 HIF_RD_SYNC_BYTE_INC, | 763 HIF_RD_SYNC_BYTE_INC, |
| 750 NULL); | 764 NULL); |
| 751 | 765 |
| 752 if (A_FAILED(status)) { | 766 if (A_FAILED(status)) { |
| 753 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | 767 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, |
| 754 ("DumpAR6KDevState : Failed to read register table (%d) \n",status))
; | 768 ("DumpAR6KDevState : Failed to read register table (%d) \n",status))
; |
| 755 return; | 769 return; |
| 756 } | 770 } |
| 757 | 771 |
| 758 DevDumpRegisters(pDev,&procRegs,®s); | 772 DevDumpRegisters(pDev,&procRegs,®s); |
| 759 | 773 |
| 760 if (pDev->GMboxInfo.pStateDumpCallback != NULL) { | 774 if (pDev->GMboxInfo.pStateDumpCallback != NULL) { |
| 761 pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext);
| 775 pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext); |
| 762 } | 776 } |
| 763 | 777 |
| 764 /* dump any bus state at the HIF layer */ | 778 /* dump any bus state at the HIF layer */ |
| 765 HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0); | 779 HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0); |
| 766 | 780 |
| 767 } | 781 } |
| 782 #endif |
| 768 | 783 |
| 769 | 784 |
| OLD | NEW |