From 9713c15d2e62d51b154f43c70632e9f5f7ef1ff8 Mon Sep 17 00:00:00 2001 From: Khoa Hoang Date: Thu, 7 Nov 2024 21:51:35 -0800 Subject: [PATCH 1/2] eth: asix88179: Fix ASIX AX88179A PHY hang The ASIX AX88179A locks up when the ADVERTISE_NPAGE bit is set in the MII_ADVERTISE register, suggesting that this feature may be broken or unsupported on this chip. In the Linux kernel, this bit is not set, and enabling it also causes the PHY to lock up and stay in a link-down state. Additionally, the AX88179 and AX88179A variants do not appear to support the ADVERTISE_LPACK bit, as setting it consistently reads back as 0. This patch removes the ADVERTISE_NPAGE and ADVERTISE_LPACK bits from the MII_ADVERTISE register configuration. It also resets the PHY before modifying the MII_ADVERTISE register, then restarts auto-negotiation, following the same flow used in the U-Boot asix.c driver. Signed-off-by: Khoa Hoang Reviewed-by: Marek Vasut --- drivers/usb/eth/asix88179.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c index 4bd3b9d10dc..4bd353b93af 100644 --- a/drivers/usb/eth/asix88179.c +++ b/drivers/usb/eth/asix88179.c @@ -176,6 +176,7 @@ #define AX_RX_URB_SIZE 1024 * 0x12 #define BLK_FRAME_SIZE 0x200 #define PHY_CONNECT_TIMEOUT 5000 +#define PHY_RESET_TIMEOUT 500 #define TIMEOUT_RESOLUTION 50 /* ms */ @@ -285,6 +286,26 @@ static int asix_write_mac(struct ueth_data *dev, uint8_t *enetaddr) return ret; } +static int asix_reset_phy(struct ueth_data *dev) +{ + u16 bmcr; + u32 t; + + /* Reset the PHY */ + bmcr = BMCR_RESET; + asix_write_cmd(dev, AX_ACCESS_PHY, 0x03, MII_BMCR, 2, &bmcr); + + for (t = 0; t < PHY_RESET_TIMEOUT; t += TIMEOUT_RESOLUTION) { + asix_read_cmd(dev, AX_ACCESS_PHY, 0x03, MII_BMCR, 2, &bmcr); + if (!(bmcr & BMCR_RESET)) + return 0; + mdelay(TIMEOUT_RESOLUTION); + } + + debug("Reset PHY timeout\n"); + return -ETIMEDOUT; +} + static int asix_basic_reset(struct ueth_data *dev, struct asix_private *dev_priv) { @@ -344,14 +365,22 @@ static int asix_basic_reset(struct ueth_data *dev, AX_MEDIUM_GIGAMODE | AX_MEDIUM_JUMBO_EN; asix_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, tmp16); + asix_reset_phy(dev); + u16 adv = 0; - adv = ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_LPACK | - ADVERTISE_NPAGE | ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP; + adv = ADVERTISE_ALL | ADVERTISE_CSMA | + ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP; asix_write_cmd(dev, AX_ACCESS_PHY, 0x03, MII_ADVERTISE, 2, &adv); adv = ADVERTISE_1000FULL; asix_write_cmd(dev, AX_ACCESS_PHY, 0x03, MII_CTRL1000, 2, &adv); + /* Restart auto-negotiation */ + u16 bmcr = 0; + asix_read_cmd(dev, AX_ACCESS_PHY, 0x03, MII_BMCR, 2, &bmcr); + bmcr |= BMCR_ANENABLE | BMCR_ANRESTART; + asix_write_cmd(dev, AX_ACCESS_PHY, 0x03, MII_BMCR, 2, &bmcr); + return 0; } From 05278af8b3df1c0c02e345ccf4c8c59bd0111f68 Mon Sep 17 00:00:00 2001 From: Khoa Hoang Date: Thu, 7 Nov 2024 21:51:36 -0800 Subject: [PATCH 2/2] eth: asix88179: packet drop when receiving large fragmented packets The ASIX 88179A drops packets when receiving fragmented packets larger than the MTU size due to an insufficient URB buffer size. This change synchronizes the URB buffer size with the configuration used in the Linux kernel, resolving the packet drop issue. To reproduce the issue, set the following configuration: CONFIG_IP_DEFRAG=y CONFIG_TFTP_BLOCKSIZE=16352 Then, run the `tftp` command. It will fail with a timeout error: U-Boot> tftp zero.bin Using ax88179_eth device TFTP from server 10.0.0.196; our IP address is 10.0.0.18 Filename 'zero.bin' Load address: 0x10000000 Loading: T T T T T T T T T T T Retry count exceeded; starting again Signed-off-by: Khoa Hoang Reviewed-by: Marek Vasut --- drivers/usb/eth/asix88179.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c index 4bd353b93af..69d3073b669 100644 --- a/drivers/usb/eth/asix88179.c +++ b/drivers/usb/eth/asix88179.c @@ -173,7 +173,7 @@ #define USB_BULK_SEND_TIMEOUT 5000 #define USB_BULK_RECV_TIMEOUT 5000 -#define AX_RX_URB_SIZE 1024 * 0x12 +#define AX_RX_URB_SIZE 1024 * 0x1a #define BLK_FRAME_SIZE 0x200 #define PHY_CONNECT_TIMEOUT 5000 #define PHY_RESET_TIMEOUT 500 @@ -193,10 +193,10 @@ static const struct { unsigned char ctrl, timer_l, timer_h, size, ifg; } AX88179_BULKIN_SIZE[] = { - {7, 0x4f, 0, 0x02, 0xff}, - {7, 0x20, 3, 0x03, 0xff}, - {7, 0xae, 7, 0x04, 0xff}, - {7, 0xcc, 0x4c, 0x04, 8}, + {7, 0x4f, 0, 0x12, 0xff}, + {7, 0x20, 3, 0x16, 0xff}, + {7, 0xae, 7, 0x18, 0xff}, + {7, 0xcc, 0x4c, 0x18, 8}, }; /* driver private */ @@ -332,7 +332,7 @@ static int asix_basic_reset(struct ueth_data *dev, memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); asix_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - dev_priv->rx_urb_size = 128 * 20; + dev_priv->rx_urb_size = 1024 * 20; /* Water Level configuration */ *tmp = 0x34;