Hi everyone,
I'm trying to write a driver for Realtek RTL81xx-style network cards (all are similar to RTL8169 basically). I have a physical RTL8168H, which I pass through to qemu using vfio-pci.
I perform a set up sequence somewhat similar to what's described on the wiki page for 8169, except I also needed to explicitly reset and power on the PHY, because otherwise it would stay in link-down state. Might want to add this note to the wiki page as well.
After I set up a Rx descriptor ring and configure all Rx-related regitsers (RDSAR, RCR, RMS), start Rx in the CR, unmask all valid IRQs, I never get any Rx-related IRQs. I do use MSI's instead of legacy IRQs, because both my OS and the device support those. I am quite sure the MSI works, because I get an IRQ ~1sec after resetting the PHY and starting link autonegotiation, saying that the link state changed to up, 1000Mbps full-duplex.
Maybe there's some extra step required specifically for 8168H to make Rx work which I missed?
[SOLVED] RTL8168H Rx issues
-
- Posts: 17
- Joined: Fri Dec 13, 2024 7:08 pm
- Location: Kyiv, Ukraine
- GitHub: https://git.alnyan.me/
- Contact:
[SOLVED] RTL8168H Rx issues
Last edited by alnyannn on Wed Jan 29, 2025 3:50 am, edited 1 time in total.
https://git.alnyan.me/alnyan/yggdrasil — yet another UNIX-like OS for aarch64/i686/x86_64/riscv64, this time in Rust
-
- Posts: 17
- Joined: Fri Dec 13, 2024 7:08 pm
- Location: Kyiv, Ukraine
- GitHub: https://git.alnyan.me/
- Contact:
Re: RTL8168H Rx issues
UPD: For some clarity, here're some suspicions I've ruled out:
* PCI power management: RTL81xx cards advertise PCI power management capability, but forcing a transition to D0 state didn't change anything.
* Double-checked the Rx descriptor format
* Placed a dummy Tx descriptor ring just in case the card gets stuck trying to get Tx descriptors from a null address
* Poll the PHY state after reset until the link is established before proceeding to initialize the card.
* C+ mode enable for Rx/Tx (bits 0/1 of C+CR) before doing any configuration. I couldn't find any documentation regarding those in all of the register manuals I've found, but the OpenBSD's re driver seems to do this, and the manuals mention this step is mandatory before doing any further Rx/Tx init
* OpenBSD's driver also unmasks the 1 << 19 bit in the MISC register, for which I couldn't find the docs as well. This unmasking is done for RTL8186H and named "rxdv masked".
* Resetting the missed packet counter (also no docs), OpenBSD's re driver does that as well after enabling the RE/TE bits in the CR.
* PCI power management: RTL81xx cards advertise PCI power management capability, but forcing a transition to D0 state didn't change anything.
* Double-checked the Rx descriptor format
* Placed a dummy Tx descriptor ring just in case the card gets stuck trying to get Tx descriptors from a null address
* Poll the PHY state after reset until the link is established before proceeding to initialize the card.
* C+ mode enable for Rx/Tx (bits 0/1 of C+CR) before doing any configuration. I couldn't find any documentation regarding those in all of the register manuals I've found, but the OpenBSD's re driver seems to do this, and the manuals mention this step is mandatory before doing any further Rx/Tx init
* OpenBSD's driver also unmasks the 1 << 19 bit in the MISC register, for which I couldn't find the docs as well. This unmasking is done for RTL8186H and named "rxdv masked".
* Resetting the missed packet counter (also no docs), OpenBSD's re driver does that as well after enabling the RE/TE bits in the CR.
https://git.alnyan.me/alnyan/yggdrasil — yet another UNIX-like OS for aarch64/i686/x86_64/riscv64, this time in Rust
-
- Posts: 17
- Joined: Fri Dec 13, 2024 7:08 pm
- Location: Kyiv, Ukraine
- GitHub: https://git.alnyan.me/
- Contact:
Re: RTL8168H Rx issues
Today, I managed to fix the problem. I'm really not sure which of these steps fixed the issue, but here's what I did:
1. After sending a reset to the PHY, I also perform two writes of 0x00 to registers 0x1F and 0x0E (as OpenBSD's re does). I'm not sure what those are, as they're shown as "reserved" in my datasheets.
2. Reordered the driver init sequence a bunch of times, until it ended up looking like this:
* Read chip revision from TCR
* Perform soft reset
* Enable C+ Tx mode, and additional flags in C+CR based on chip rev
* Perform PHY reset (with step 1 included)
* Setup RDSAR/TNPDS for Tx/Rx rings
* Unmask that undocumented bit in the undocumented MISC register
* Setup TCR/RCR, also enabling the undocumented EARLYOFFV2 bit in the RCR
* Enable Tx/Rx in the CR
* Unmask IMR interrupts, write all ones to ISR to avoid immediately getting an interrupt about some outdated event
* Reset the missed packet counter, though it is not strictly necessary
* Set MTPS/RMS for max Tx/Rx frame sizes
* Set "driver loaded" bit in the CONFIG1 register
The wiki also mentions you need to "unlock" the registers by writing an EEPROM setup mode to the 9346CR, but I think this is misleading, because you only need to do this if you're going to write to any of the CONFIGi registers.
Hope that might be helpful to someone, marking the thread as resolved.
1. After sending a reset to the PHY, I also perform two writes of 0x00 to registers 0x1F and 0x0E (as OpenBSD's re does). I'm not sure what those are, as they're shown as "reserved" in my datasheets.
2. Reordered the driver init sequence a bunch of times, until it ended up looking like this:
* Read chip revision from TCR
* Perform soft reset
* Enable C+ Tx mode, and additional flags in C+CR based on chip rev
* Perform PHY reset (with step 1 included)
* Setup RDSAR/TNPDS for Tx/Rx rings
* Unmask that undocumented bit in the undocumented MISC register
* Setup TCR/RCR, also enabling the undocumented EARLYOFFV2 bit in the RCR
* Enable Tx/Rx in the CR
* Unmask IMR interrupts, write all ones to ISR to avoid immediately getting an interrupt about some outdated event
* Reset the missed packet counter, though it is not strictly necessary
* Set MTPS/RMS for max Tx/Rx frame sizes
* Set "driver loaded" bit in the CONFIG1 register
The wiki also mentions you need to "unlock" the registers by writing an EEPROM setup mode to the 9346CR, but I think this is misleading, because you only need to do this if you're going to write to any of the CONFIGi registers.
Hope that might be helpful to someone, marking the thread as resolved.
https://git.alnyan.me/alnyan/yggdrasil — yet another UNIX-like OS for aarch64/i686/x86_64/riscv64, this time in Rust
Re: [SOLVED] RTL8168H Rx issues
I have some problems with the H2 variant (device type 46). It works when the network cable is connected on boot, but if it is not, or if it's unplugged and reinserted, then the link fails to establish. For other types, this appears to work. Apparently, this device needs some special settings of undocumented variables on link state change.
I try to avoid RTL nowadays, and get computers with Intels i2xx instead, as it doesn't require custom patches per chip version.
I try to avoid RTL nowadays, and get computers with Intels i2xx instead, as it doesn't require custom patches per chip version.
Re: [SOLVED] RTL8168H Rx issues
Funny thing, I buy devices with intel networking in the listing and more often than not, the seller has pulled a "keep the model number, swap for a realtek chip." The broader public seems to only want intel, like what is preferred here.
-
- Posts: 17
- Joined: Fri Dec 13, 2024 7:08 pm
- Location: Kyiv, Ukraine
- GitHub: https://git.alnyan.me/
- Contact:
Re: [SOLVED] RTL8168H Rx issues
Yeah, Intel docs are usually pretty good and their hardware usually behaves almost exactly (if not 100%) as documented. I'm writing a rtl81xx driver set because I want to get more hardware working on the test devices I already have, which is a couple of Lenovo ThinkPad laptops + my desktop PC. At least the Lenovo laptops do have an Intel WiFi chip, so I think it'll be more pleasant to develop drivers for once I reach WiFi support in my plans
https://git.alnyan.me/alnyan/yggdrasil — yet another UNIX-like OS for aarch64/i686/x86_64/riscv64, this time in Rust
Re: [SOLVED] RTL8168H Rx issues
I'm not sure about Intel WiFi. I still have no WiFi chip that I have been able to get documentation about so I could write a driver.alnyannn wrote: ↑Mon Feb 03, 2025 7:14 am Yeah, Intel docs are usually pretty good and their hardware usually behaves almost exactly (if not 100%) as documented. I'm writing a rtl81xx driver set because I want to get more hardware working on the test devices I already have, which is a couple of Lenovo ThinkPad laptops + my desktop PC. At least the Lenovo laptops do have an Intel WiFi chip, so I think it'll be more pleasant to develop drivers for once I reach WiFi support in my plans