Search Linux Wireless

Re: [PATCH v2] rtw88: pci: enable MSI interrupt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 27, 2019 at 8:11 PM Tony Chuang <yhchuang@xxxxxxxxxxx> wrote:
> Because there's a race condition between SW/HW when clearing the ISR.
> If interrupt comes after reading ISR and before write-1-clear, the interrupt
> controller would have interrupt status raised, and never issue interrupt
> signal to host when other new interrupts status are raised.
>
> To avoid this, driver requires to protect the ISR write-1-clear process by
> disabling the IMR.

Just to be clear with an example of two interrupts in quick
succession, first ROK then MGNTDOK. I would expect the hardware to
behave as follows:

1. Interrupts are enabled in HIMR reg. MSI is in use.
--- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
then raises a MSI interrupt.
--- Interrupt controller receives this and begins handling it:
2. rtw88 interrupt handler begins execution
3. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
--- Hardware needs to flag MGNTDOK condition, so it sets the MGNTDOK
bit in HISR and raises another interrupt.
--- Interrupt controller queues this interrupt since it's in the
middle of handling the original ROK interrupt.
4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
written back to clear them. In this case just the ROK bit is written
back to unset the interrupt. MGNTDOK interrupt is left pending (not
yet noticed by the driver)
5. Interrupt handler continues & finishes handling the RX event.
6. With the first interrupt done, interrupt controller handles the
queued interrupt and causes rtw88 interrupt handler to execute again
7. rtw88 interrupt handler handles and MGNTDOK interrupt.


But are you saying it does not do this, and the behaviour (without
your change) is instead:

1. Interrupts are enabled in HIMR reg. MSI is in use.
--- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
then raises a MSI interrupt.
--- Interrupt controller receives this and begins handling it:
2. rtw88 interrupt handler begins execution
3. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
--- Hardware needs to flag MGNTDOK condition, so it sets the MGNTDOK
bit in HISR. However it does NOT raise an interrupt since other bits
in HISR were still set at this time.
4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
written back. In this case just the ROK bit is written back to unset
the interrupt. MGNTDOK interrupt is left pending (not yet noticed by
the driver)
5. Interrupt handler continues & finishes handling the RX event.
6. MGNTDOK interrupt is left pending, and no more interrupts will be
generated by the hardware because even if it sets more HISR bits, the
MGNTDOK bit was already set so it doesn't raise more interrupts.

i.e. you're effectively saying that the hardware will *only* generate
an interrupt when *all* HISR bits were zero immediately before the new
interrupt HISR bit is set?


And then with your change applied it would look like this:

1. Interrupts are enabled in HIMR reg. MSI is in use.
--- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
then raises a MSI interrupt.
--- Interrupt controller receives this and begins handling it:
2. rtw88 interrupt handler begins execution
3. Interrupts are disabled in HIMR reg.
4. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
--- Hardware needs to flag MGNTDOK condition, however because
interrupts are disabled in HIMR, it simply queues this condition
internally, without affecting HISR values, without generating another
interrupt.
4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
written back. In this case just the ROK bit is written back to unset
the interrupt. HISR is now value 0.
5. Interrupt handler handles the RX event.
6. Interrupt handler re-enables interrupts in HIMR just before finishing.
--- In response, hardware checks its internal queue and realises that
a MGNTDOK condition is pending. It sets the MGNTDOK bit in HISR and
raises a new interrupt.

Is that right? It seems like strange behaviour on the hardware side.

> Do you mean I should remove this?
> But I cannot find another proper way to enable the MSI.
> Maybe pci_alloc_irq_vectors() could work but I am not sure if
> It is recommended.

Yes, I think you should switch to pci_alloc_irq_vectors() which is the
recommended, documented way.

Thanks,
Daniel



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux