>From 1a75f6f9065a58180de1fa3c48fd80418af6c347 Mon Sep 17 00:00:00 2001 From: Lauri Jakku Date: Mon, 13 Apr 2020 13:18:35 +0300 Subject: [PATCH] NET: r8168/r8169 identifying fix The driver installation determination made properly by checking PHY vs DRIVER id's. --- drivers/net/ethernet/realtek/r8169_main.c | 114 ++++++++++++++++++++-- drivers/net/phy/mdio_bus.c | 15 ++- 2 files changed, 119 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index bf5bf05970a2..5e992f285527 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -61,6 +61,11 @@ #define R8169_MSG_DEFAULT \ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) + +/* +#define R8169_PROBE_DEBUG +*/ + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ #define MC_FILTER_LIMIT 32 @@ -5149,6 +5154,9 @@ static int r8169_mdio_register(struct rtl8169_private *tp) { struct pci_dev *pdev = tp->pci_dev; struct mii_bus *new_bus; + u32 phydev_id = 0; + u32 phydrv_id = 0; + u32 phydrv_id_mask = 0; int ret; new_bus = devm_mdiobus_alloc(&pdev->dev); @@ -5165,20 +5173,69 @@ static int r8169_mdio_register(struct rtl8169_private *tp) new_bus->write = r8169_mdio_write_reg; ret = mdiobus_register(new_bus); + +#ifdef R8169_PROBE_DEBUG + dev_info(&pdev->dev, + "mdiobus_register: %s, %d\n", + new_bus->id, ret); +#endif if (ret) return ret; tp->phydev = mdiobus_get_phy(new_bus, 0); + if (!tp->phydev) { mdiobus_unregister(new_bus); return -ENODEV; - } else if (!tp->phydev->drv) { - /* Most chip versions fail with the genphy driver. - * Therefore ensure that the dedicated PHY driver is loaded. - */ - dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n"); - mdiobus_unregister(new_bus); - return -EUNATCH; + } else { + /* tp -> phydev ok */ + int everything_OK = 0; + + /* Check driver id versus phy */ + + if (tp->phydev->drv) { + u32 phydev_masked = 0xBEEFDEAD; + u32 drv_masked = ~0; + u32 phydev_match = ~0; + u32 drv_match = 0xDEADBEEF; + + phydev_id = tp->phydev->phy_id; + phydrv_id = tp->phydev->drv->phy_id; + phydrv_id_mask = tp->phydev->drv->phy_id_mask; + + drv_masked = phydrv_id & phydrv_id_mask; + phydev_masked = phydev_id & phydrv_id_mask; + +#ifdef R8169_PROBE_DEBUG + dev_debug(&pdev->dev, + "%s: ID Check: (%x -> %x), drv (%x -> %x)\n", + new_bus->id, phydev_id, phydev_masked, + phydrv_id, drv_masked); +#endif + + phydev_match = phydev_masked & drv_masked; + phydev_match = phydev_match == phydev_masked; + + drv_match = phydev_masked & drv_masked; + drv_match = drv_match == drv_masked; + +#ifdef R8169_PROBE_DEBUG + dev_debug(&pdev->dev, "%s: ID Check: %x == %x\n", + new_bus->id, phydev_match, drv_match); +#endif + + everything_OK = (phydev_match == drv_match); + } + + if (!everything_OK) { + /* Most chip versions fail with the genphy driver. + * Therefore ensure that the dedicated PHY driver + * is loaded. + */ + dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n"); + mdiobus_unregister(new_bus); + return -EUNATCH; + } } /* PHY will be woken up in rtl_open() */ @@ -5435,6 +5492,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u64_stats_init(&tp->rx_stats.syncp); u64_stats_init(&tp->tx_stats.syncp); +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: MAC\n"); +#endif + rtl_init_mac_address(tp); dev->ethtool_ops = &rtl8169_ethtool_ops; @@ -5483,29 +5544,64 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->hw_features |= NETIF_F_RXFCS; jumbo_max = rtl_jumbo_max(tp); + +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: jumbo max: %d\n", jumbo_max); +#endif + if (jumbo_max) dev->max_mtu = jumbo_max; +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: irq mask\n"); +#endif + rtl_set_irq_mask(tp); tp->fw_name = rtl_chip_infos[chipset].fw_name; +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: FW name: %s\n", tp->fw_name); +#endif + tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), &tp->counters_phys_addr, GFP_KERNEL); if (!tp->counters) return -ENOMEM; +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: set driver data\n"); +#endif + pci_set_drvdata(pdev, dev); +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: register mdio\n"); +#endif + rc = r8169_mdio_register(tp); + +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: mdio register: %d\n", rc); +#endif + if (rc) return rc; /* chip gets powered up in rtl_open() */ +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: pll pwr down\n"); +#endif + rtl_pll_power_down(tp); rc = register_netdev(dev); + +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: netdev register: %d\n", rc); +#endif + if (rc) goto err_mdio_unregister; @@ -5525,6 +5621,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_dev_run_wake(pdev)) pm_runtime_put_sync(&pdev->dev); +#ifdef R816X_PROBE_DEBUG + dev_dbg(&pdev->dev, "init: ALL DONE!\n"); +#endif + return 0; err_mdio_unregister: diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 522760c8bca6..41777f379a57 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -112,14 +112,22 @@ EXPORT_SYMBOL(mdiobus_unregister_device); struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) { struct mdio_device *mdiodev = bus->mdio_map[addr]; - + struct phy_device *rv = NULL; +/* + pr_debug("mii_bus %s addr %d, %p\n", bus->id, addr, mdiodev); +*/ if (!mdiodev) return NULL; if (!(mdiodev->flags & MDIO_DEVICE_FLAG_PHY)) return NULL; - return container_of(mdiodev, struct phy_device, mdio); + rv = container_of(mdiodev, struct phy_device, mdio); +/* + pr_debug("mii_bus OK? %s addr %d, %p -> %p\n", + bus->id, addr, mdiodev, rv); +*/ + return rv; } EXPORT_SYMBOL(mdiobus_get_phy); @@ -645,10 +653,11 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device); bus->state = MDIOBUS_REGISTERED; - pr_info("%s: probed\n", bus->name); + pr_info("%s: probed (mdiobus_register)\n", bus->name); return 0; error: + pr_err("%s: Error while in mdiobus_register: %d\n", bus->name, err); while (--i >= 0) { mdiodev = bus->mdio_map[i]; if (!mdiodev) -- 2.26.0