rtwn(4) extension rtl8188ee receiving constantly interrupts

Farhan Khan khanzf at gmail.com
Wed Dec 27 04:05:49 UTC 2017


Hi Adrian,

> So, what do the bits in R88EE_HIMR mean? What about HIRME? Let's
> figure out which it is.

Unfortunately, I do not know what these values are regarding. My
speculation is that R88EE_HIMR and HIMRE are how you notify the device to
clear the interrupt. On the Linux source, they are both in a function
called rtl88ee_disable_interrupt. The Linux documentation puts them in a
struct called rtl_var_map and labels this section as"reg map". It is not
clear to me what that means.

It could be the C2H, but I commented out the FW loading code entirely, but
this issue remains. I am going to re-review the initialization code.
Perhaps the issue lays there. Its a challenge, because the Linux and
FreeBSD structure of the code is not 1-to-1.



--
Farhan Khan
PGP Fingerprint: B28D 2726 E2BC A97E 3854 5ABE 9A9F 00BC D525 16EE

On Sun, Dec 24, 2017 at 9:55 PM, Adrian Chadd <adrian at freebsd.org> wrote:

> Hi,
>
> So it looks like the thing that's generating the interrupt isn't being
> cleared.
>
> So, what do the bits in R88EE_HIMR mean? What about HIRME? Let's
> figure out which it is.
>
> Also, is it something in C2H (the target to host event channel) that's
> not being handled?
>
>
>
> -adrian
>
>
>
> On 21 December 2017 at 14:43, Farhan Khan <khanzf at gmail.com> wrote:
> > Hi,
> >
> > As I wrote a few weeks back, I am working on the extension to rtwn(4) to
> add
> > RTL8188EE support. At the moment, I am working on the Rx code, which
> handles
> > interrupts. After the interrupt is triggered, the code goes into the Rx
> routine
> > and delivers "junk data" in a continuous loop. It seems that the
> interrupt code
> > is **constantly** called - enough that the load average is frequently
> above 1.0.
> >
> > I suspect the issue is giving the WiFi driver an acknowledgement of some
> sort,
> > but I am not certain. I attempted to copy Linux's interrupt code as best
> as
> > possible, but cannot determine if the error is within my code.
> >
> > Here is a verbose explanation of what I believe Linux is doing and what
> I am
> > doing on FreeBSD.
> >
> > -----Linux code works as follows-----
> >
> > 1. The IRQ trigger calls the function _rtl_pci_interrupt
> >    (drivers/net/wireless/realtek/rtlwifi/pci.c)
> > 2. This calls disable_interrupt, which for rtl8188ee is
> >    rtl88ee_disable_interrupt. This function writes IMR_DISABLED (0x0) to
> >    REG_HIMR (0xb0) and REG_HIMRE (0xb8).
> > 3. Next _rtl_pci_interrupt calls interrupt_recognized(), a function
> pointer to
> >    rtl88ee_interrupt_recognized(), which:
> >    * Reads from REG_HISR (0xb4), stores the value in 'inta', ANDs that
> value by
> >      0x200084ff, then writes that value back to the same register.
> >    * Reads from REG_HISRE (0xbc), stores the value in 'intb', ANDs that
> value by
> >      0x100, then writes that value back to the same register.
> >    Then the function returns returns.
> >
> > 4. Back in _rtl_pci_interrupt if 'inta' is 0 and 'intb' is 0xffff, the
> code will
> >    skip step 5, goto to "done" and execute enable_interrupt code
> >    (rtl88ee_enable_interrupt)
> >
> > 5. If bit(0) is set to 1, this is an Rx interrupt and will run
> >    _rtl_pci_rx_interrupt(). From my review of the code, from here the
> Linux
> >    driver will read from the DMA memory and send the frame to the
> ieee80211
> >    layer. I only found 1 additional read instruction related to the
> power value,
> >    but nothing else is changed.
> >
> > 6. Here is the "done" portion, that happens no matter what, but is
> jumped to
> >    immediately as referenced above. It will call enable_interrupt(), a
> function
> >    pointer to rtl88ee_enable_Interrupt(), which will:
> >    a. Write 0x200084ff to REG_HIMR (0xb0)
> >    b. Write 0x100 to REG_HIMRE (0xb8)
> >    c. Write 0 to to REG_C2HEVT_CLEAR (0x01AF, A register having to do
> with C2H
> >       firmware)
> >    d. Write 0xc0 to REG_HSIMR (0x58 , I know this value from printf'ing
> it)
> >
> > This is what I identified from reviewing from the Linux code.
> >
> > -----My FreeBSD Code-----
> >
> > My code is located here:
> > https://github.com/khanzf/freebsd/tree/rx_not_working/sys/dev/rtwn/.
> >
> > 1. The IRQ trigger calls the function rtwn_pci_intr()
> >    (sys/dev/rtwn/pci/rtwn_pci_rx.c)
> > 2. The equivalent of Linux's line 2 and 3 is in rtwn_classify_intr,
> which is a
> >    pointer to r88ee_enable_intr located in sys/dev/rtwn/rtl8188e/pci/r88e
> e_rx.
> >    This write's 0x0 to REG_HIMR (0xb0) and REG_HIMRE (0xb8)
> > 3. Continuing, the same function:
> >    * Reads from ISR_MINE (same as REG_HISR, 0xb4), ANDs the value by
> 0x200084ff,
> >      store it in 'status'. Then I write the value back to the same
> register.
> >    * Read from REG_HISRE (0xbc), AND the value by 0x100, store it in
> 'statusb'.
> >      Write this value back to the same register.
> >    * Since this is an Rx register, the 'ret' value is AND'd by
> RTWN_PCI_INTR_RX.
> >
> > 4. In the Linux code, if 'status' is 0x0 and 'statusb' is 0xFFFF, it
> will goto
> >    to "done". On FreeBSD, it simply does not set any bits on the 'ret'
> value and
> >    the function returns 0, going back to rtwn_pci_intr.
> >
> > 5. Returning to rtwn_pci_intr(), if the 'ret' (now 'status') has
> >    RTWN_PCI_INTR_RX flag on, it executes rtwn_pci_tx_done(), which will
> read the
> >    DMA memory and send the frame to the ieee80211 layer. The execution
> will skip
> >    step 5 if 'ret' was 0 (the RTWN_PCI_INTR_RX flag was never set). This
> returns
> >    execution back to rtwn_pci_intr().
> >
> > 6. rtwn_pci_intr() concludes by running rtwn_pci_enable_intr(). This is
> similar
> >    to Linux's enable_interrupt(), it does the following:
> >    a. Write 0x200084f to R88EE_HIMR (0xb0)
> >    b. Write 0x100 to R88EE_HIMRE (0xb8)
> >    c. Write 0x0 to REG_C2HEVT_CLEAR (0x01AF)
> >    d. Write 0xc0 to REG_HSIMR
> >
> > ---------
> >
> > To me, it appears that I did a complete 1-to-1 copy of the Linux code.
> However,
> > in my case the driver is receiving constant interrupts without stopping.
> I am
> > not certain what I am missing or what is different. Could it be that
> something
> > outside of this particular code path was not properly set. If so, what
> might
> > that be?
> >
> > Please advise.
> > Thank you,
> >
> > --
> > Farhan Khan
> > PGP Fingerprint: B28D 2726 E2BC A97E 3854 5ABE 9A9F 00BC D525 16EE
> > _______________________________________________
> > freebsd-wireless at freebsd.org mailing list
> > https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
> > To unsubscribe, send any mail to "freebsd-wireless-unsubscribe@
> freebsd.org"
>


More information about the freebsd-wireless mailing list