none
Not getting all interrupts in KMDF driver RRS feed

  • Question

  • Hello,

    I'm trying to port an existing linux device driver to windows. It's mostly working, but there's a weird issue - sometimes device won't interrupt or the interrupt is lost.
    Interrupts are only lost when I'm not actively debugging.

    My ISR looks like this:
      pDE  = xGetDeviceContext(WdfInterruptGetDevice(Interrupt));
      intrv = READ_REG_32(pDE, OFFSET_INTERRUPT_REG);
      pDE->interruptMask = READ_REG_32(pDE, OFFSET_INTERRUPT_MASK_REG);
     
      intrv &= pDE->interruptMask;
      if(intrv == 0){
          return FALSE;
      }
      pDE->interruptStatus |= intrv; //trying to save values in case different interrupts come too fast for dpc
      WdfInterruptQueueDpcForIsr( pDE->m_Interrupt);

    DPC:
     pDE  = xGetDeviceContext(WdfInterruptGetDevice(Interrupt));
     WdfInterruptAcquireLock(Interrupt);
     nMainIntStatus = pDE->interruptStatus;
     pDE->interruptStatus = 0;
     WdfInterruptReleaseLock(Interrupt);
     
     if(nManIntStatus & interrupt_mask_event_1){
       KeSetEvent(&pDE->interrupt_event_1, IO_SOUND_INCREMENT, FALSE);
     }
     //and so on...
     
    In my code I'm waiting on pDE->interrupt_event_1:
     status = KeWaitForSingleObject(&pDE->interrupt_event_1, Executive, KernelMode, TRUE, &timeout);
     
    I also tried enabling automatic serialization in interrupt config, but this did not resolve my issue.
     
    I'm currently out of options, I suspect either improper synchronization or that I should be using a different wait method.
    Please give me any advice you could think of.

    Kind regards.
    Thursday, July 4, 2019 3:34 PM

Answers

  • What are the characteristics of the "loss of interrupts"?   If you get two of the same interrupt type, i.e. the INTERRUPT_REG has the same bit set you will see this with this approach, since DPC's can take a while to fire.

    A few things you might want to do:

    1.  Use InterlockedOr in the ISR to set interruptStatus and InterlockedExchange in the DPC to copy interruptStatus to nMainIntStatus and set the interruptStatus to zero.  You have a potential race condition if the DPC is running and an ISR fires.

    2.  Consider using circular list or a queue to record the value you calculate for intrv then process that in the DPC.  You may even want to use a semaphore instead of an event to signal things.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Thursday, July 4, 2019 4:25 PM
  • > pDE->interruptStatus |= intrv; //trying to save values in case different interrupts come too fast for dpc
    > WdfInterruptQueueDpcForIsr( pDE->m_Interrupt);

    Why do you allow the device to cause more interrupts after scheduling the DPC? It usually (not always but typically) makes no sense. When the DPC starts running it can learn the device state itself and handle as much as it can. Getting more interrupts won't make the DPC react faster and is not helpful. Same in Linux too.

    -- pa

    Friday, July 5, 2019 9:29 PM

All replies

  • What are the characteristics of the "loss of interrupts"?   If you get two of the same interrupt type, i.e. the INTERRUPT_REG has the same bit set you will see this with this approach, since DPC's can take a while to fire.

    A few things you might want to do:

    1.  Use InterlockedOr in the ISR to set interruptStatus and InterlockedExchange in the DPC to copy interruptStatus to nMainIntStatus and set the interruptStatus to zero.  You have a potential race condition if the DPC is running and an ISR fires.

    2.  Consider using circular list or a queue to record the value you calculate for intrv then process that in the DPC.  You may even want to use a semaphore instead of an event to signal things.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Thursday, July 4, 2019 4:25 PM
  • > pDE->interruptStatus |= intrv; //trying to save values in case different interrupts come too fast for dpc
    > WdfInterruptQueueDpcForIsr( pDE->m_Interrupt);

    Why do you allow the device to cause more interrupts after scheduling the DPC? It usually (not always but typically) makes no sense. When the DPC starts running it can learn the device state itself and handle as much as it can. Getting more interrupts won't make the DPC react faster and is not helpful. Same in Linux too.

    -- pa

    Friday, July 5, 2019 9:29 PM