Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Dec 2017 15:22:24 -0500
From:      Farhan Khan <khanzf@gmail.com>
To:        Andriy Voskoboinyk <s3erios@gmail.com>
Cc:        freebsd-wireless@freebsd.org
Subject:   Re: rtwn(4) extension rtl8188ee receiving constantly interrupts
Message-ID:  <CAFd4kYAPE%2BZxbVZfjxGHZWYSBdCyATS5=bF5LtPXrLjoRYUCQQ@mail.gmail.com>
In-Reply-To: <op.zbx9x9ktiew4ia@localhost>
References:  <CAFd4kYD_McuQC3=vwo9RxJfXkVn=NmLWKCj5r%2BhQaEUmWMRv2w@mail.gmail.com> <CA%2BRfiRFA8YBTB0tfJSxb9UUqUKGeUWb720EqKX-GFHTqeWT1Pg@mail.gmail.com> <op.zbx9x9ktiew4ia@localhost>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi Andriy,

I attempted to re-write all bits back, but the result is the same. Strange.

Perhaps the initialization code is wrong somewhere? I will give it another
review.

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

On Thu, Dec 28, 2017 at 4:28 AM, Andriy Voskoboinyk <s3erios@gmail.com>
wrote:

> Hi,
>
> there are some issues that may cause wrong interrupt handling:
>
> 1) IMR register bits - they were taken from 92c
> (and they are not compatible - for example, RXFOVW seems to be moved
> to the ext register)
>
> 2) Try to ACK (write back) all bits,
> not masked ones (like it is done for 92c)
>
>
>
> 2017-12-22 0:43 GMT+02:00, Farhan Khan <khanzf@gmail.com>:
>
>> 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/r88ee_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@freebsd.org mailing list
>>> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
>>> To unsubscribe, send any mail to "freebsd-wireless-unsubscribe@
>>> freebsd.org"
>>>
>>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFd4kYAPE%2BZxbVZfjxGHZWYSBdCyATS5=bF5LtPXrLjoRYUCQQ>