Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: usb: asix: ax88772: move embedded PHY detection as early as possible

Some HW revisions need additional MAC configuration before the embedded PHY
can be enabled. If this is not done, we won't be able to get response
from the internal PHY.

This issue was detected on chipcode == AX_AX88772_CHIPCODE variant,
where ax88772_hw_reset() was executed with missing embd_phy flag.

Fixes: e532a096be0e ("net: usb: asix: ax88772: add phylib support")
Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleksij Rempel and committed by
David S. Miller
7a141e64 359f4cdd

+21 -21
+1
drivers/net/usb/asix.h
··· 184 184 struct phy_device *phydev; 185 185 u16 phy_addr; 186 186 char phy_name[20]; 187 + bool embd_phy; 187 188 }; 188 189 189 190 extern const struct driver_info ax88172a_info;
+20 -21
drivers/net/usb/asix_devices.c
··· 354 354 static int ax88772_hw_reset(struct usbnet *dev, int in_pm) 355 355 { 356 356 struct asix_data *data = (struct asix_data *)&dev->data; 357 - int ret, embd_phy; 357 + struct asix_common_private *priv = dev->driver_priv; 358 358 u16 rx_ctl; 359 + int ret; 359 360 360 361 ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | 361 362 AX_GPIO_GPO2EN, 5, in_pm); 362 363 if (ret < 0) 363 364 goto out; 364 365 365 - embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); 366 - 367 - ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 366 + ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy, 368 367 0, 0, NULL, in_pm); 369 368 if (ret < 0) { 370 369 netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); 371 370 goto out; 372 371 } 373 372 374 - if (embd_phy) { 373 + if (priv->embd_phy) { 375 374 ret = asix_sw_reset(dev, AX_SWRESET_IPPD, in_pm); 376 375 if (ret < 0) 377 376 goto out; ··· 448 449 static int ax88772a_hw_reset(struct usbnet *dev, int in_pm) 449 450 { 450 451 struct asix_data *data = (struct asix_data *)&dev->data; 451 - int ret, embd_phy; 452 + struct asix_common_private *priv = dev->driver_priv; 452 453 u16 rx_ctl, phy14h, phy15h, phy16h; 453 454 u8 chipcode = 0; 455 + int ret; 454 456 455 457 ret = asix_write_gpio(dev, AX_GPIO_RSE, 5, in_pm); 456 458 if (ret < 0) 457 459 goto out; 458 460 459 - embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); 460 - 461 - ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy | 461 + ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy | 462 462 AX_PHYSEL_SSEN, 0, 0, NULL, in_pm); 463 463 if (ret < 0) { 464 464 netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); ··· 681 683 struct asix_common_private *priv = dev->driver_priv; 682 684 int ret; 683 685 684 - ret = asix_read_phy_addr(dev, true); 685 - if (ret < 0) 686 - return ret; 687 - 688 - priv->phy_addr = ret; 689 - 690 686 snprintf(priv->phy_name, sizeof(priv->phy_name), PHY_ID_FMT, 691 687 priv->mdio->id, priv->phy_addr); 692 688 ··· 707 715 struct asix_common_private *priv; 708 716 int ret, i; 709 717 u32 phyid; 718 + 719 + priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL); 720 + if (!priv) 721 + return -ENOMEM; 722 + 723 + dev->driver_priv = priv; 710 724 711 725 usbnet_get_endpoints(dev, intf); 712 726 ··· 749 751 dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */ 750 752 dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */ 751 753 754 + ret = asix_read_phy_addr(dev, true); 755 + if (ret < 0) 756 + return ret; 757 + 758 + priv->phy_addr = ret; 759 + priv->embd_phy = ((priv->phy_addr & 0x1f) == 0x10 ? true : false); 760 + 752 761 asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0); 753 762 chipcode &= AX_CHIPCODE_MASK; 754 763 ··· 777 772 jumbo eth frames */ 778 773 dev->rx_urb_size = 2048; 779 774 } 780 - 781 - priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL); 782 - if (!priv) 783 - return -ENOMEM; 784 - 785 - dev->driver_priv = priv; 786 775 787 776 priv->presvd_phy_bmcr = 0; 788 777 priv->presvd_phy_advertise = 0;