Ok, tested it (eh8811h firmware 24011202) and now indeed 2500M LPA gets set if the link partner advertises 2500M. However, it doesn’t get cleared if the link partner no longer advertises it or even the cable is unplugged and a different link-partner is plugged in, then we see
[ 56.198597] Airoha EN8811H mdio-bus:0f: Downshift occurred from negotiated speed 2.5Gbps to actual speed 1Gbps, check cabling!
[ 56.209986] mtk_soc_eth 15100000.ethernet eth1: Link is Up - 1Gbps/Full - flow control rx/tx
I’ve tried that and added some debugging code to actually validate the content of the register.
The full output including my debugging printout which I added to the (pbus_value & EN8811H_2P5G_LPA_2P5G) condition:
[ 56.191775] Airoha EN8811H mdio-bus:0f: EN8811H_2P5G_LPA_2P5G bit was set
[ 56.198597] Airoha EN8811H mdio-bus:0f: Downshift occurred from negotiated speed 2.5Gbps to actual speed 1Gbps, check cabling!
[ 56.209986] mtk_soc_eth 15100000.ethernet eth1: Link is Up - 1Gbps/Full - flow control rx/tx
(link partner is NetXtreme BCM5762 Gigabit Ethernet PCIe which doesn’t use 2.5G/5G/10G advertisement bits at all. But before another link partner with RTL8221BV PHY which does support and did advertise 2.5G was plugged.)
One comment is that we can simplify things a bit by storing the firmware version as u32 instead of bool firmware_loaded. All memory in the priv struct gets zerod on allocation anyway, and we should only set firmware_version once we read it and it was non-zero. Then we can use the firmware_version member just like the firmware_loaded member before (ie. decide whether to call en8811h_load_firmware or en8811h_restart_host) and we could even use work-arounds for known firmware bugs (such as missing 2.5G LPA…) if the version u32 (which luckily can be compared as in unsigned int in a meaningful way as in 0x24011202 > 0x23112102).
Maybe diff is better than English to explain what I mean
The original code only setting the bit had genphy_c45_read_lpa() but this was changed. There the bit was always cleared. So this is why my old code was only setting the bit.
I was also thinking about using the firmware version… before firmware load it always reads a different number, but always 0x8bxxxxxx. Always negative then it would always be smaller than loaded firmware version.
I will look into your suggestions this weekend.
Edit:
@dangowrt
I was thinking to drop the dirty bug fix lpa2500 totally If by any chance someone is still using old firmware, there is no big deal, only missing the lpa2500 bit…
Actually, my first thought of using the firmware version register, to use it to check if firmware is loaded or not. But I am not sure if the register value reliably can be used before any firmware is loaded (to determine it is not loaded). It is then always 0x8bxxxxxx, but I am but sure this will always in the future be the case …
I’m testing with your latest driver now and it does not work for me when switching cables from 2500M-capable link partner to Gigabit Ethernet link partner without any 802.3bz capabilities. See email for details and pull-request for a working work-around.
It doesn’t hurt to include it at this point, also because linux-next and linux-firmware are asynchronous trees side-by-side and linux-firmware is updated in distros (and OpenWrt) independenly of the Linux kernel.
Hence, as I want to also merge this in OpenWrt asap it will have to still support the old firmware until the new one got merged to linux-firmware and a new linux-firmware release came out (because that’s what we are packaging in OpenWrt – doing a git checkout of linux-firmware is quite insane as you might now, so we rely on the released tarballs).
So please keep it, so we can have the identical driver to have users of OpenWrt and vanilla kernel with your driver test the same thing (and eventually submit bug reports for the same code).
I just added hwmon temperature readout, in a new a patch in net-next-airoha branch.
I do not have any info on the units read from the register (only register address number, I do not have datasheet), so I think only thing to check is if this is the correct units.
If this is ok, I can just squash it to the first patch version (then I do not need a new patch for it).