All PHY's of the supported chips are MII-compatible, therefore let phylib do the work.
Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com> --- drivers/net/ethernet/realtek/Kconfig | 1 + drivers/net/ethernet/realtek/r8168.c | 152 +++++++++++++++++++++++++++-------- 2 files changed, 120 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig index 011b524c5..97b24103e 100644 --- a/drivers/net/ethernet/realtek/Kconfig +++ b/drivers/net/ethernet/realtek/Kconfig @@ -99,6 +99,7 @@ config R8168 depends on PCI select FW_LOADER select CRC32 + select PHYLIB select MII ---help--- Say Y here if you have a Realtek 8168 PCI Gigabit Ethernet adapter. diff --git a/drivers/net/ethernet/realtek/r8168.c b/drivers/net/ethernet/realtek/r8168.c index b0c4b5ea8..be6c45b11 100644 --- a/drivers/net/ethernet/realtek/r8168.c +++ b/drivers/net/ethernet/realtek/r8168.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/phy.h> #include <linux/if_vlan.h> #include <linux/crc32.h> #include <linux/in.h> @@ -818,6 +819,7 @@ struct rtl8168_private { unsigned features; struct mii_if_info mii; + struct mii_bus *mii_bus; dma_addr_t counters_phys_addr; struct rtl8168_counters *counters; struct rtl8168_tc_offsets tc_offset; @@ -1632,33 +1634,6 @@ static void rtl_link_chg_patch(struct rtl8168_private *tp) } } -static void __rtl8168_check_link_status(struct net_device *dev, - struct rtl8168_private *tp, - void __iomem *ioaddr, bool pm) -{ - if (rtl8168_xmii_link_ok(ioaddr)) { - rtl_link_chg_patch(tp); - /* This is to cancel a scheduled suspend if there's one. */ - if (pm) - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 5000); - } -} - -static void rtl8168_check_link_status(struct net_device *dev, - struct rtl8168_private *tp, - void __iomem *ioaddr) -{ - __rtl8168_check_link_status(dev, tp, ioaddr, false); -} - #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) static u32 __rtl8168_get_wol(struct rtl8168_private *tp) @@ -6694,8 +6669,8 @@ static void rtl_reset_work(struct rtl8168_private *tp) napi_enable(&tp->napi); rtl_hw_start(dev); + phy_start(dev->phydev); netif_wake_queue(dev); - rtl8168_check_link_status(dev, tp, tp->mmio_addr); } static void rtl8168_tx_timeout(struct net_device *dev) @@ -7329,7 +7304,7 @@ static void rtl_slow_event_work(struct rtl8168_private *tp) rtl8168_pcierr_interrupt(dev); if (status & LinkChg) - __rtl8168_check_link_status(dev, tp, tp->mmio_addr, true); + phy_mac_interrupt(dev->phydev, netif_carrier_ok(dev)); rtl_irq_enable_all(tp); } @@ -7405,6 +7380,8 @@ static void rtl8168_down(struct net_device *dev) { struct rtl8168_private *tp = netdev_priv(dev); + phy_stop(dev->phydev); + del_timer_sync(&tp->timer); napi_disable(&tp->napi); @@ -7466,7 +7443,6 @@ static void rtl8168_netpoll(struct net_device *dev) static int rtl_open(struct net_device *dev) { struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; int retval = -ENOMEM; @@ -7519,14 +7495,14 @@ static int rtl_open(struct net_device *dev) if (!rtl8168_init_counter_offsets(dev)) netif_warn(tp, hw, dev, "counter reset/update failed\n"); + phy_start(dev->phydev); + netif_start_queue(dev); rtl_unlock_work(tp); tp->saved_wolopts = 0; pm_runtime_put_noidle(&pdev->dev); - - rtl8168_check_link_status(dev, tp, ioaddr); out: return retval; @@ -7605,6 +7581,8 @@ static void rtl8168_net_suspend(struct net_device *dev) if (!netif_running(dev)) return; + phy_stop(dev->phydev); + netif_device_detach(dev); netif_stop_queue(dev); @@ -7796,7 +7774,10 @@ static void rtl_remove_one(struct pci_dev *pdev) netif_napi_del(&tp->napi); + phy_disconnect(dev->phydev); + unregister_netdev(dev); + mdiobus_unregister(tp->mii_bus); rtl_release_firmware(tp); @@ -7899,6 +7880,97 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond) return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; } +static int r8168_mdio_read_reg(struct mii_bus *mii_bus, int phyaddr, int phyreg) +{ + struct rtl8168_private *tp = mii_bus->priv; + + return tp->mdio_ops.read(tp, phyreg); +} + +static int r8168_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr, + int phyreg, u16 val) +{ + struct rtl8168_private *tp = mii_bus->priv; + + tp->mdio_ops.write(tp, phyreg, val); + + return 0; +} + +static int r8168_mdio_register(struct rtl8168_private *tp) +{ + struct pci_dev *pdev = tp->pci_dev; + struct mii_bus *new_bus; + int ret; + + new_bus = devm_mdiobus_alloc(&pdev->dev); + if (!new_bus) + return -ENOMEM; + + new_bus->name = "r8168"; + new_bus->priv = tp; + new_bus->phy_mask = ~1; + new_bus->parent = &pdev->dev; + new_bus->irq[0] = PHY_IGNORE_INTERRUPT; + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%02x:%02x.%x", + new_bus->name, pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + new_bus->read = r8168_mdio_read_reg; + new_bus->write = r8168_mdio_write_reg; + + ret = mdiobus_register(new_bus); + if (!ret) + tp->mii_bus = new_bus; + + return ret; +} + +static void r8168_phylink_handler(struct net_device *ndev) +{ + struct rtl8168_private *tp = netdev_priv(ndev); + + if (netif_carrier_ok(ndev)) { + rtl_link_chg_patch(tp); + pm_request_resume(&tp->pci_dev->dev); + } else { + pm_schedule_suspend(&tp->pci_dev->dev, 5000); + } + + if (net_ratelimit()) + phy_print_status(ndev->phydev); +} + +static int r8168_phy_connect(struct rtl8168_private *tp) +{ + struct phy_device *phydev; + phy_interface_t phy_mode; + int ret; + + phy_mode = tp->mii.supports_gmii ? PHY_INTERFACE_MODE_GMII : + PHY_INTERFACE_MODE_MII; + + phydev = phy_find_first(tp->mii_bus); + if (!phydev) + return -ENODEV; + + ret = phy_connect_direct(tp->dev, phydev, r8168_phylink_handler, + phy_mode); + if (ret) + return ret; + + phy_attached_info(phydev); + + if (!tp->mii.supports_gmii && (phydev->supported & + (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full))) { + netif_info(tp, probe, tp->dev, "Restrict PHY to 100Mbit because MAC doesn't support 1GBit"); + phy_set_max_speed(phydev, SPEED_100); + ret = genphy_restart_aneg(phydev); + } + + return ret; +} + static void rtl_hw_init_8168g(struct rtl8168_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -8212,10 +8284,18 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!tp->counters) return -ENOMEM; - rc = register_netdev(dev); + rc = r8168_mdio_register(tp); if (rc < 0) return rc; + rc = register_netdev(dev); + if (rc < 0) + goto err_mdio_unregister; + + rc = r8168_phy_connect(tp); + if (rc < 0) + goto err_netdev_unregister; + pci_set_drvdata(pdev, dev); netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n", @@ -8244,6 +8324,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_carrier_off(dev); return 0; + +err_netdev_unregister: + unregister_netdev(dev); +err_mdio_unregister: + mdiobus_unregister(tp->mii_bus); + return rc; } static struct pci_driver rtl8168_pci_driver = { -- 2.15.1