Add basic phylib support to r8169. All now unneeded old PHY handling code
will be removed in subsequent patches.

Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com>
---
 drivers/net/ethernet/realtek/Kconfig |   1 +
 drivers/net/ethernet/realtek/r8169.c | 146 +++++++++++++++++++++------
 2 files changed, 115 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/realtek/Kconfig 
b/drivers/net/ethernet/realtek/Kconfig
index 7c69f4c8..7fb1af1f 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -99,6 +99,7 @@ config R8169
        depends on PCI
        select FW_LOADER
        select CRC32
+       select PHYLIB
        select MII
        ---help---
          Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
diff --git a/drivers/net/ethernet/realtek/r8169.c 
b/drivers/net/ethernet/realtek/r8169.c
index f80ac894..7443b230 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.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>
@@ -754,6 +755,7 @@ struct rtl8169_private {
        } wk;
 
        struct mii_if_info mii;
+       struct mii_bus *mii_bus;
        dma_addr_t counters_phys_addr;
        struct rtl8169_counters *counters;
        struct rtl8169_tc_offsets tc_offset;
@@ -1444,11 +1446,6 @@ static unsigned int rtl8169_xmii_reset_pending(struct 
rtl8169_private *tp)
        return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
 }
 
-static unsigned int rtl8169_xmii_link_ok(struct rtl8169_private *tp)
-{
-       return RTL_R8(tp, PHYstatus) & LinkStatus;
-}
-
 static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
 {
        unsigned int val;
@@ -1513,25 +1510,6 @@ static void rtl_link_chg_patch(struct rtl8169_private 
*tp)
        }
 }
 
-static void rtl8169_check_link_status(struct net_device *dev,
-                                     struct rtl8169_private *tp)
-{
-       struct device *d = tp_to_dev(tp);
-
-       if (rtl8169_xmii_link_ok(tp)) {
-               rtl_link_chg_patch(tp);
-               /* This is to cancel a scheduled suspend if there's one. */
-               pm_request_resume(d);
-               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");
-               pm_runtime_idle(d);
-       }
-}
-
 #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
 
 /* Currently we only enable WoL if explicitly told by userspace to circumvent
@@ -6228,7 +6206,6 @@ static void rtl_reset_work(struct rtl8169_private *tp)
        napi_enable(&tp->napi);
        rtl_hw_start(tp);
        netif_wake_queue(dev);
-       rtl8169_check_link_status(dev, tp);
 }
 
 static void rtl8169_tx_timeout(struct net_device *dev)
@@ -6845,7 +6822,7 @@ static void rtl_slow_event_work(struct rtl8169_private 
*tp)
                rtl8169_pcierr_interrupt(dev);
 
        if (status & LinkChg)
-               rtl8169_check_link_status(dev, tp);
+               phy_mac_interrupt(dev->phydev);
 
        rtl_irq_enable_all(tp);
 }
@@ -6927,10 +6904,53 @@ static void rtl8169_rx_missed(struct net_device *dev)
        RTL_W32(tp, RxMissed, 0);
 }
 
+static void r8169_phylink_handler(struct net_device *ndev)
+{
+       struct rtl8169_private *tp = netdev_priv(ndev);
+
+       if (netif_carrier_ok(ndev)) {
+               rtl_link_chg_patch(tp);
+               pm_request_resume(&tp->pci_dev->dev);
+       } else {
+               pm_runtime_idle(&tp->pci_dev->dev);
+       }
+
+       if (net_ratelimit())
+               phy_print_status(ndev->phydev);
+}
+
+static int r8169_phy_connect(struct rtl8169_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 = mdiobus_get_phy(tp->mii_bus, 0);
+       if (!phydev)
+               return -ENODEV;
+
+       if (!tp->mii.supports_gmii && phydev->supported & PHY_1000BT_FEATURES) {
+               netif_info(tp, probe, tp->dev, "Restrict PHY to 100Mbit because 
MAC doesn't support 1GBit\n");
+               phy_set_max_speed(phydev, SPEED_100);
+       }
+
+       ret = phy_connect_direct(tp->dev, phydev, r8169_phylink_handler,
+                                phy_mode);
+       if (!ret)
+               phy_attached_info(phydev);
+
+       return ret;
+}
+
 static void rtl8169_down(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
 
+       phy_stop(dev->phydev);
+
        napi_disable(&tp->napi);
        netif_stop_queue(dev);
 
@@ -6970,6 +6990,8 @@ static int rtl8169_close(struct net_device *dev)
 
        cancel_work_sync(&tp->wk.work);
 
+       phy_disconnect(dev->phydev);
+
        pci_free_irq(pdev, 0, tp);
 
        dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
@@ -7030,6 +7052,10 @@ static int rtl_open(struct net_device *dev)
        if (retval < 0)
                goto err_release_fw_2;
 
+       retval = r8169_phy_connect(tp);
+       if (retval)
+               goto err_free_irq;
+
        rtl_lock_work(tp);
 
        set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
@@ -7045,16 +7071,17 @@ static int rtl_open(struct net_device *dev)
        if (!rtl8169_init_counter_offsets(tp))
                netif_warn(tp, hw, dev, "counter reset/update failed\n");
 
+       phy_start(dev->phydev);
        netif_start_queue(dev);
 
        rtl_unlock_work(tp);
 
        pm_runtime_put_sync(&pdev->dev);
-
-       rtl8169_check_link_status(dev, tp);
 out:
        return retval;
 
+err_free_irq:
+       pci_free_irq(pdev, 0, tp);
 err_release_fw_2:
        rtl_release_firmware(tp);
        rtl8169_rx_clear(tp);
@@ -7133,6 +7160,7 @@ static void rtl8169_net_suspend(struct net_device *dev)
        if (!netif_running(dev))
                return;
 
+       phy_stop(dev->phydev);
        netif_device_detach(dev);
        netif_stop_queue(dev);
 
@@ -7165,6 +7193,8 @@ static void __rtl8169_resume(struct net_device *dev)
        rtl_pll_power_up(tp);
        rtl8169_init_phy(dev, tp);
 
+       phy_start(tp->dev->phydev);
+
        rtl_lock_work(tp);
        napi_enable(&tp->napi);
        set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
@@ -7310,6 +7340,7 @@ static void rtl_remove_one(struct pci_dev *pdev)
        netif_napi_del(&tp->napi);
 
        unregister_netdev(dev);
+       mdiobus_unregister(tp->mii_bus);
 
        rtl_release_firmware(tp);
 
@@ -7395,6 +7426,51 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond)
        return (RTL_R8(tp, MCU) & RXTX_EMPTY) == RXTX_EMPTY;
 }
 
+static int r8169_mdio_read_reg(struct mii_bus *mii_bus, int phyaddr, int 
phyreg)
+{
+       struct rtl8169_private *tp = mii_bus->priv;
+
+       return rtl_readphy(tp, phyreg);
+}
+
+static int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr,
+                               int phyreg, u16 val)
+{
+       struct rtl8169_private *tp = mii_bus->priv;
+
+       rtl_writephy(tp, phyreg, val);
+
+       return 0;
+}
+
+static int r8169_mdio_register(struct rtl8169_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 = "r8169";
+       new_bus->phy_mask = ~1;
+       new_bus->priv = tp;
+       new_bus->parent = &pdev->dev;
+       new_bus->irq[0] = PHY_IGNORE_INTERRUPT;
+       snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x",
+                PCI_DEVID(pdev->bus->number, pdev->devfn));
+
+       new_bus->read = r8169_mdio_read_reg;
+       new_bus->write = r8169_mdio_write_reg;
+
+       ret = mdiobus_register(new_bus);
+       if (!ret)
+               tp->mii_bus = new_bus;
+
+       return ret;
+}
+
 static void rtl_hw_init_8168g(struct rtl8169_private *tp)
 {
        u32 data;
@@ -7651,10 +7727,14 @@ static int rtl_init_one(struct pci_dev *pdev, const 
struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, dev);
 
-       rc = register_netdev(dev);
-       if (rc < 0)
+       rc = r8169_mdio_register(tp);
+       if (rc)
                return rc;
 
+       rc = register_netdev(dev);
+       if (rc)
+               goto err_mdio_unregister;
+
        netif_info(tp, probe, dev, "%s, %pM, XID %08x, IRQ %d\n",
                   rtl_chip_infos[chipset].name, dev->dev_addr,
                   (u32)(RTL_R32(tp, TxConfig) & 0xfcf0f8ff),
@@ -7669,12 +7749,14 @@ static int rtl_init_one(struct pci_dev *pdev, const 
struct pci_device_id *ent)
        if (r8168_check_dash(tp))
                rtl8168_driver_start(tp);
 
-       netif_carrier_off(dev);
-
        if (pci_dev_run_wake(pdev))
                pm_runtime_put_sync(&pdev->dev);
 
        return 0;
+
+err_mdio_unregister:
+       mdiobus_unregister(tp->mii_bus);
+       return rc;
 }
 
 static struct pci_driver rtl8169_pci_driver = {
-- 
2.18.0


Reply via email to