[PATCH net-next v10 00/15] ax88179_178a: Add support for AX88179A-based chips

Birger Koblitz posted 15 patches 3 weeks ago
There is a newer version of this series
MAINTAINERS                        |    6 +
drivers/net/phy/ax88796b.c         |  161 +++++
drivers/net/phy/phy.c              |    4 +
drivers/net/phy/phylink.c          |   16 +
drivers/net/usb/Kconfig            |   10 +-
drivers/net/usb/Makefile           |    3 +-
drivers/net/usb/ax88179_178a.c     |  664 ++------------------
drivers/net/usb/ax88179_lib.c      |  506 +++++++++++++++
drivers/net/usb/ax88179_lib.h      |  358 +++++++++++
drivers/net/usb/ax88179a_devices.c | 1212 ++++++++++++++++++++++++++++++++++++
include/linux/phy.h                |    1 +
include/linux/phylink.h            |    1 +
12 files changed, 2318 insertions(+), 624 deletions(-)
[PATCH net-next v10 00/15] ax88179_178a: Add support for AX88179A-based chips
Posted by Birger Koblitz 3 weeks ago
This adds support for the current generation of ASIX network adapter chips,
which are based on the AX88179A. This includes the AX88179A/B (1GBit-PHY),
AX88772D/E (100MBit) and AX88279 (2.5GBit).

The AX179A-based chips all provide both a CDC-NCM compatible USB interface,
and a proprietary vendor interface with more features. By default, the
proprietary vendor interface is not active and Linux will load the CDC-NCM
driver to support the devices. If the ax88179_178a module is configured by
the OS to have precedence over CDC-NCM, then this driver will switch the
device to use the vendor interface, and the device will be controlled by
the ax88179_178a driver when the device is probed again after an automatic
reset of the device bringing up the vendor interface.

The following hardware was tested:
Delock 66046 2.5GBit adapter (AX88279, FW: 1.2.0.0)
TP-Link UE306 1GBit adapter (AX88179B, FW: 1.3.0.0)
Renkforce RF-4708614 1GBit adapter (AX88179A, FW: 1.0.4.0)
UGREEN CR110 100MBit adapter (AX88722E, FW: 1.3.0.0)

The driver supports the following features
- EEE
- TCP segmentation offload
- VLAN filtering/tagging offload 
  (NETIF_F_HW_VLAN_CTAG_FILTER, NETIF_F_HW_VLAN_CTAG_RX/TX)
- RX/TX checksum offload
- FC/Pause configuration
- EEPROM read access

The code is based on the ASIX 4.1.0 out-of-tree driver published under
the GPL,, the aqc111 driver which provides support for the AX88279A,
and some tracing of USB-transfers of the Windows-driver.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
Tested-by: Jianhui Xu <neuromoments@gmail.com>
---
Changes in v10:
- Fix missing variable declaration in ax88179a_status()
- Add reviewed-bys
- Link to v9: https://lore.kernel.org/r/20260902-ax88179a-v9-0-8e6d7710a2ae@birger-koblitz.de

Changes in v9:
- Fix ax88179a_status() to not call carrier-related netif or usbnet methods
- Use genphy_read_mmd_c45() and genphy_write_mmd_c45()
- Link to v8: https://lore.kernel.org/r/20260831-ax88179a-v8-0-de905f2ee426@birger-koblitz.de

Changes in v8:
- Fix resume sequence as Suggested-by: Jianhui Xu <neuromoments@gmail.com>
- Add handling of PHYs with broken forced mode in phylib to handle AX88279 PHY
- Multple formatting fixes
- Fix transiently unused functions ax88179a_mac_disable_tx_lpi() and
  ax88179a_mac_enable_tx_lpi()
- Removed unnecessary checks for dev initialized
- Link to v7: https://lore.kernel.org/r/20260810-ax88179a-v7-0-da633191c129@birger-koblitz.de

Changes in v7:
- Add phylink_mac_interrupt() function to phylink and stop
  polling the PHY to prevent a race condition between the controller
  and phylink when configuring a new link.
- Fix typo in ax88179_read_cmd Reported-by: Jianhui Xu <neuromoments@gmail.com>
- Return -EOPNOTSUPP in asix_ax88279_config_aneg when autoneg is being disabled
- Link to v6: https://lore.kernel.org/r/20260806-ax88179a-v6-0-fde7414619e6@birger-koblitz.de

Changes in v6:
- Use genphy_read_status() in asix_ax88279_read_status()
- Use SGMII and 2500BaseX interfaces for PHY
- Fix speed determination of MAC/PHY link
- Fix bulk transfer configuration to use enums for bulk configuration types
- Link to v5: https://lore.kernel.org/r/20260802-ax88179a-v5-0-dcb9fea4acd4@birger-koblitz.de

Changes in v5:
- Fixed read_status() and config_aneg() in PHY driver
- Introduced netdev2data() as convenience function
- netdev_info instances and debugging relicts removed
- Several instances of badly written/formatted code that was copy and pasted from
  the original driver corrected
- select PHYLINK added to Kconfig when phylib dependency added
- PHYLINK selects PHYLIB, so not needed to specify separately
- Link to v4: https://lore.kernel.org/r/20260731-ax88179a-v4-0-2cf1f71b1dd2@birger-koblitz.de

Changes in v4:
- Split driver into library part and part2 for AX88179 and AX88179A-based
  controllers
- Driver renamed ax88179
- Improved phylink use: use phylink standard functions for speed and EEE-settings,
  correct MAC capabilities, removed ax88179_status() irq-urb callback
- Fixes in PHY driver for AX88179A integrated PHYs
- Link to v3: https://lore.kernel.org/r/20260724-ax88179a-v3-0-bdde4f905883@birger-koblitz.de

Changes in v3:
- Add PHY drivers for the PHYs of the AX88179A-based controllers
- Use phylink for the AX88179A-based chips
- Link to v2: https://lore.kernel.org/r/20260708-ax88179a-v2-0-0800fedb2e16@birger-koblitz.de

Changes in v2:
- Correctly use net-next prefix
- Fix compilation issue in HW support patch
- Split MMD support patch into patches for EEE/new chip support
- Do not use ADVERTISE_RESV but private flag definition
- Fix pause configuration to keep track of settings when autoneg disabled
- Fix issue with unitialized variable reported by kernel test robot <lkp@intel.com>
- Avoid white-space changes

- Link to v1: https://lore.kernel.org/r/20260701-ax88179a-v1-0-13685df67515@birger-koblitz.de

---
Birger Koblitz (15):
      phylink: Add phylink_mac_interrupt
      phylib: Add support for PHYs with broken forced mode
      ax88179_178a: Fix endianness of pause watermark register
      ax88179_178a: Split driver into library and device specific code
      ax88179_178a: Add netdev2data() convenience function
      ax88179_178a: Add HW support for AX179A-based chips
      ax88179_178a: Add EEE configuration support for AX88179A MACs
      ax88179_178a: Add EEE configuration support for AX88179A PHYs
      ax88179_178a: Add VLAN offload support for AX88179A
      ax88179_178a: Add AX179A/AX279 multicast configuration
      ax88179_178a: Add Suspend/resume support for AX88179A/772D/279
      ax88179_178a: Add ethtool get_drvinfo
      ax88179_178a: Update driver name and information
      ax88179_178a: Add support for AX88179A/772D/279 EEPROM access
      ax88796b: Add support for AX88772D, AX88179A and AX88279

 MAINTAINERS                        |    6 +
 drivers/net/phy/ax88796b.c         |  161 +++++
 drivers/net/phy/phy.c              |    4 +
 drivers/net/phy/phylink.c          |   16 +
 drivers/net/usb/Kconfig            |   10 +-
 drivers/net/usb/Makefile           |    3 +-
 drivers/net/usb/ax88179_178a.c     |  664 ++------------------
 drivers/net/usb/ax88179_lib.c      |  506 +++++++++++++++
 drivers/net/usb/ax88179_lib.h      |  358 +++++++++++
 drivers/net/usb/ax88179a_devices.c | 1212 ++++++++++++++++++++++++++++++++++++
 include/linux/phy.h                |    1 +
 include/linux/phylink.h            |    1 +
 12 files changed, 2318 insertions(+), 624 deletions(-)
---
base-commit: 1bb784eb6e38fd73143f021608e4ef3095d0c0d7
change-id: 20260630-ax88179a-a1d89fe21730

Best regards,
-- 
Birger Koblitz <mail@birger-koblitz.de>
Re: [PATCH net-next v10 00/15] ax88179_178a: Add support for AX88179A-based chips
Posted by Jianhui Xu 2 weeks, 5 days ago
Hi Birger,

I tested v9 on the same ASIX AX88179B adapter. By the time you read this,
v10 has already been posted. Given the relatively small differences between
v9 and v10, I expect the issue I found in v9 to apply to v10 as well.

First, as you already noticed, `data` is undeclared.

For QEMU runtime testing I also had to apply Chen-Yu Tsai's unrelated
`usb: xhci: Fix HCS_ERST_MAX conversion` patch. Without it, this base kernel
fails to initialize QEMU's xHCI controller before the network driver is
reached.

All three fresh functional starts completed cold DHCP at 1000baseT/Full
without reloading the driver and passed the normal 1000/100/10/1000 Mbit/s
matrix, EEE disable/restore, pause enable/restore, and EEPROM read.

During repeated speed transitions, I observed one intermittent carrier-loss
failure. Of 19 normally initiated restores from 100/full to the default
1000/full advertisement, 18 passed and one failed to regain carrier. After
that failure, ethtool reported unknown speed and no link, and further
advertisement changes did not recover it. Dmesg showed the preceding
100-Mbit Link Up followed by Link Down, with no subsequent Link Up before
the device was reattached.

I could not reproduce the failure in two later fresh starts or in a further
90 unmodified-v9 stress cycles. Counting the normal matrix and stress
points, all 22 tested 100/full points passed, so I also did not reproduce
the earlier 100-Mbit carrier-without-RX failure.

I repeated the QEMU deep-S3 tests as well. One fresh `wol d` cycle and five
fresh `wol g` cycles all passed. After `system_wakeup`, management SSH
returned, the adapter regained carrier at 1000baseT/Full, and gateway and
test-host traffic increased RX. These tests use QEMU-emulated xHCI and
monitor-triggered wake, not a physical xHCI controller or an actual magic
packet.

I then investigated the intermittent carrier loss with function tracing.
Each advertisement change generates hardware link-down and link-up status
notifications. V9 forwards both to phylib even though the ethtool-triggered
PHY state-machine run has already taken the link down before the hardware
down notification is handled. This results in three PHY state/read-status
runs per advertisement change, including a redundant read while
autonegotiation and controller link setup are still in progress.

In light of your previous observation [1]:

> There is a race condition between the controller of the AX88179A
> trying to set up and optimize the link and phylink trying to
> configure the link on the mac-side.
>
> At this point, the PHY may report that the link is up before the
> controller is actually finished configuring it.

I suspected that the redundant PHY read during autonegotiation might
interact badly with the controller's own link-setup sequence.

As a focused experiment, I changed ax88179a_status() to inspect
AX_INT_PPLS_LINK and track whether phylink currently considers the MAC link
active. A down notification is ignored if phylink has already taken the MAC
down, while up notifications are always forwarded. mac_link_up() marks the
state active before configuring the MAC, so a genuine down event during
configuration is still forwarded.

The experimental kernel built successfully, including focused W=1 checks,
and strict checkpatch reported no findings. I then ran:

- 100 rapid 100/full -> 1000/full cycles;
- 30 paced cycles, holding each endpoint for 8 seconds;
- a 2-cycle trace smoke test.

All 264 requested-speed endpoints reached carrier at the correct speed. The
fixed traces consistently showed four raw status callbacks but only two
phylink interrupts and four PHY reads per complete cycle.

But this does not necessarily prove that the change fixes the original rare
failure: that failure occurred only once in 19 normally initiated restores
and could not be reproduced in another 90 unmodified-v9 stress cycles.

The experimental patch follows for review.

Thanks,
Jianhui

[1] https://lore.kernel.org/netdev/5b2c4498-2e3c-4ae6-b078-deeccf8b7a5c@birger-koblitz.de/

---
 drivers/net/usb/ax88179_lib.h      |  1 +
 drivers/net/usb/ax88179a_devices.c | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/ax88179_lib.h b/drivers/net/usb/ax88179_lib.h
--- a/drivers/net/usb/ax88179_lib.h
+++ b/drivers/net/usb/ax88179_lib.h
@@ -306,6 +306,7 @@ struct ax88179_data {
 	u8 is_ax88772d;
 	u8 ip_align;
 	u8 link;
+	bool mac_link_active;
 	u8 speed;
 	u8 full_duplex;
 	u8 rx_checksum;
diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_devices.c
--- a/drivers/net/usb/ax88179a_devices.c
+++ b/drivers/net/usb/ax88179a_devices.c
@@ -118,11 +118,22 @@ static int ax88179_mdiobus_write_c45(struct mii_bus *bus, int addr, int devnum,
 static void ax88179a_status(struct usbnet *dev, struct urb *urb)
 {
 	struct ax88179_data *data = dev->driver_priv;
+	struct ax88179_int_data *event;
+	bool link;
 
 	if (urb->actual_length < 8)
 		return;
 
-	phylink_mac_interrupt(data->phylink);
+	event = urb->transfer_buffer;
+	link = le32_to_cpu(event->intdata1) & AX_INT_PPLS_LINK;
+
+	/* Changing the advertisement has already told phylib that the link is
+	 * down. Avoid another PHY read while the controller is still setting up
+	 * the new link, but always process link-up notifications so that speed
+	 * changes cannot be missed.
+	 */
+	if (link || READ_ONCE(data->mac_link_active))
+		phylink_mac_interrupt(data->phylink);
 }
 
 static int ax88179a_suspend(struct usb_interface *intf, pm_message_t message)
@@ -437,7 +448,9 @@ static void ax88179a_mac_config(struct phylink_config *config, unsigned int mode,
 static void ax88179a_mac_link_down(struct phylink_config *config,
 				   unsigned int mode, phy_interface_t interface)
 {
-	/* Nothing to do */
+	struct ax88179_data *data = netdev2data(to_net_dev(config->dev));
+
+	WRITE_ONCE(data->mac_link_active, false);
 }
 
 static void ax88179a_mac_link_up(struct phylink_config *config,
@@ -448,9 +461,11 @@ static void ax88179a_mac_link_up(struct phylink_config *config,
 {
 	struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
 	struct ax88179_data *ax179_data = dev->driver_priv;
 	u8 tmp8, link_sts, reg8[3];
 	u8 bulk_config_speed = 0;
 	u16 tmp16, mode;
 
+	WRITE_ONCE(ax179_data->mac_link_active, true);
+
 	/* Stop RX/TX for link configuration */
 	tmp16 = AX_RX_CTL_STOP;
Re: [PATCH net-next v10 00/15] ax88179_178a: Add support for AX88179A-based chips
Posted by Birger Koblitz 2 weeks, 5 days ago
Hi Jianhui,

On 06/09/2026 12:40 pm, Jianhui Xu wrote:
> Hi Birger,
> 
> I tested v9 on the same ASIX AX88179B adapter. By the time you read this,
> v10 has already been posted. Given the relatively small differences between
> v9 and v10, I expect the issue I found in v9 to apply to v10 as well.
> 
> First, as you already noticed, `data` is undeclared.
> 
> For QEMU runtime testing I also had to apply Chen-Yu Tsai's unrelated
> `usb: xhci: Fix HCS_ERST_MAX conversion` patch. Without it, this base kernel
> fails to initialize QEMU's xHCI controller before the network driver is
> reached.
> 
> All three fresh functional starts completed cold DHCP at 1000baseT/Full
> without reloading the driver and passed the normal 1000/100/10/1000 Mbit/s
> matrix, EEE disable/restore, pause enable/restore, and EEPROM read.
> 
> During repeated speed transitions, I observed one intermittent carrier-loss
> failure. Of 19 normally initiated restores from 100/full to the default
> 1000/full advertisement, 18 passed and one failed to regain carrier. After
> that failure, ethtool reported unknown speed and no link, and further
> advertisement changes did not recover it. Dmesg showed the preceding
> 100-Mbit Link Up followed by Link Down, with no subsequent Link Up before
> the device was reattached.
> 
> I could not reproduce the failure in two later fresh starts or in a further
> 90 unmodified-v9 stress cycles. Counting the normal matrix and stress
> points, all 22 tested 100/full points passed, so I also did not reproduce
> the earlier 100-Mbit carrier-without-RX failure.
> 
I tried to reproduce the issue myself. I am running the v10 USB and PHY 
driver modules directly on a PC with otherwise Kernel
Linux version 7.1.8+deb13-amd64

I am using the following script to change between 100MBit and 1GBit
1000 times with an AX88179A 1GBit dongle, each time testing a ping and 
printing out the negotiated speed:
!/bin/bash
i=0
speed=100
while [ $i -lt 1000 ]
do
         ((i++))
         echo "Run $i"
         success="BAD"
         success=$(ping -c 1 -q 192.168.10.247 >1 2>&1 && echo "OK")
         echo "Success: $success"

         if [ "$success" != "OK" ]; then
                 echo "Failed: $success $i"
         fi

         ethtool -s enx9c69d380ffff autoneg on speed $speed
         if [ "$speed" != "100" ]; then
                 speed=100
         else
                 speed=1000
         fi
         sleep 6
         echo `ethtool enx9c69d380ffff | grep Speed:`
done

This runs through without issues 1000 times:
[...]
Success: OK
Speed: 1000Mb/s
Run 999
Success: OK
Speed: 100Mb/s
Run 1000
Success: OK
Speed: 1000Mb/s

ethtool changes the speed, then reliably reads the correct speed while 
ping works and the device continues to respond normally through the 
entire test. All of this 1000 times.

So, either what you observed is extremely rare, or it could also be 
influenced by the different test setup, including the fact my test is on 
bare metal, but also by the link partner (an RTL8372-switch in my case).

The other point is that in principle what we are testing is not 
something users do regularly: you plug the dongle in, it autonegotiates, 
and that's it. And if you change the speed, there is a 50% chance you 
will do it from the other side of the link, which seems to be much less 
problematic as I noticed previously when we had the race condition due 
to PHY polling, because the dongle does not try to optimize the link: it 
accepts what is being offered.

I did not test your code, but I am wondering whether it is not simply 
enough to do:
+	if (link)
+		phylink_mac_interrupt(data->phylink);
without reading the bit whether the MAC link is up. Speed changes come
with a link-down, so I would think this is enough to do it like that. Or 
maybe I am missing something?

Given that we do not really know whether there is actually an issue, 
what it is and whether it is really relevant, otherwise your tests all 
succeed, and also because I have a feeling that Andrew may not like it 
if we try to be smarter than phylink, I would suggest we leave it like 
this for the moment. I would really like to see this being finally 
reviewed to the point where it can be merged.

Birger
Re: [PATCH net-next v10 00/15] ax88179_178a: Add support for AX88179A-based chips
Posted by Jianhui Xu 2 weeks, 4 days ago
Hi Birger,

Thanks for your testing.

Using only

  if (link)
          phylink_mac_interrupt(data->phylink);

would be simpler, but it would also discard every hardware link-down
notification. I agree that we should leave the driver unchanged for now,
since I could not reproduce that event in a further 90 unmodified-v9
cycles, and your 1,000 v10 cycles also passed.

Please disregard my experimental patch. I will report again if I find a
reliable reproducer or evidence that identifies a specific driver problem.

Thanks,
Jianhui