Different interrupt handling behavior on different PCs with same PCIe devices.

I’m getting different behaviors on two differnet PCs with respect to how my ISR is called. Both systems are running the same version of Windows Embedded, the same version of my driver, and are using the same version of my PCIe device, however, the PCs themselves are from different vendors with different internal hardware.

On the system I was developing on, my ISR would be called, I’d read the my device’s interrupt status register, clear out any pending interrupts, and push any further processing to various DPCs. Whenever my ISR would be called, the status register would always contain a non-zero value indicating that an interrupt was pending.

On this other system I loaded my driver and PCIe device on, the ISR would be called and the interrupt status register would sometimes contain a 0 value, indicating that there is no interrupt currently pending. Then the ISR would be called again but this time, the status register would contain a non-zero value indicating that an interrupt is pending.

While running the user application to process data on the PCIe device, I would get this behavior during the entire time it’s running; ISR called with a 0 value in the interrupt status register, then later on, the ISR would be called with a non-zero value in the interrupt status register.

On my development PC, I have yet to see in my traces a 0 value in the interrupt status register.

Why would the ISR be called when my device didn’t appear to raise an interrupt? Why would a different PC with the same version of Windows cause this behavior to occur?

After additional reading, I think I answered my own question.
I failed to mention that I have two identical PCIe devices in each PC. On my development PC, each device has different IRQ value, whereas on the other PC, they share the same IRQ value. Would this be the reason for why I sometimes see my ISR called for a device but there is no pending interrupt?

This is the definition of how things work when you have two devices that share a single interrupt.

Your driver has two devices under its control, and two devices are connected to one interrupt. When the interrupt occurs, Windows doesn’t know which device is interrupting. It’s your driver’s job to determine this!

So, when your ISR is invoked, the FIRST step you do is check to see “Is my device interrupting?” If it’s not, you return FALSE from your ISR.

If your device IS interrupting, you continue to process the interrupt (save the reason for the interrupt, acknowledge it so that the device stops interrupting, and then queue a DPC for ISR if you have more work to do).

Sharing interrupts on PCI (and on LBI emulation on PCIe) is an inherent part of the standard. Note that you can share interrupts with other devices, not just other instances of your own device. So… be sure you’re handling your interrupt correctly.

One final note: If this is a WDM driver you’re writing, make sure you check your device’s power state in your ISR before you check to see if your device is interrupting. Consider what happens if your device is powered down (in D3, let’s say) and you read your device’s Interrupt Request Register to see if your “Interrupt Request” bit is set. You know what’s going to happen, right? No? Well, I’ll tell you… when you read the register on your powered down device, chances are you’re going to read back all bits set. So it’ll LOOK like your device is interrupting, even though it’s in D3. And THAT will lead to all sorts of bad things.

Peter
OSR
@OSRDrivers

Thanks for the reply, Peter.

On Thu, Jan 5, 2017 at 2:33 PM, wrote:

>


>
> This is the definition of how things work when you have two devices that
> share a single interrupt.
>
> Your driver has two devices under its control, and two devices are
> connected to one interrupt. When the interrupt occurs, Windows doesn’t
> know which device is interrupting. It’s your driver’s job to determine
> this!
>
> So, when your ISR is invoked, the FIRST step you do is check to see “Is my
> device interrupting?” If it’s not, you return FALSE from your ISR.
>
> If your device IS interrupting, you continue to process the interrupt
> (save the reason for the interrupt, acknowledge it so that the device stops
> interrupting, and then queue a DPC for ISR if you have more work to do).
>
> Sharing interrupts on PCI (and on LBI emulation on PCIe) is an inherent
> part of the standard. Note that you can share interrupts with other
> devices, not just other instances of your own device. So… be sure you’re
> handling your interrupt correctly.
>
> One final note: If this is a WDM driver you’re writing, make sure you
> check your device’s power state in your ISR before you check to see if your
> device is interrupting. Consider what happens if your device is powered
> down (in D3, let’s say) and you read your device’s Interrupt Request
> Register to see if your “Interrupt Request” bit is set. You know what’s
> going to happen, right? No? Well, I’ll tell you… when you read the
> register on your powered down device, chances are you’re going to read back
> all bits set. So it’ll LOOK like your device is interrupting, even though
> it’s in D3. And THAT will lead to all sorts of bad things.
>
> Peter
> OSR
> @OSRDrivers
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>