netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Heiner Kallweit <hkallweit1@gmail.com>
To: Andrew Lunn <andrew@lunn.ch>,
	Realtek linux nic maintainers <nic_swsd@realtek.com>,
	Chun-Hao Lin <hau@realtek.com>
Cc: David Miller <davem@davemloft.net>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>
Subject: [PATCH RFC 08/18] r8168: add basic phylib support
Date: Thu, 21 Dec 2017 21:50:25 +0100	[thread overview]
Message-ID: <8d117cab-2221-2cc4-ff0a-891f4a60dc92@gmail.com> (raw)
In-Reply-To: <83321b2e-8402-26c5-9703-3fe795cc893d@gmail.com>

All PHY's of the supported chips are MII-compatible, therefore let
phylib do the work.

Signed-off-by: Heiner Kallweit <hkallweit1@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

  parent reply	other threads:[~2017-12-21 20:51 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-21 20:38 [PATCH RFC 00/18] r8169: separate r8168 driver and add experimental phylib support Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 01/18] r8169: split driver to one for the non-PCIE cards (r8169) and one for the PCIE cards (r8168) Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 02/18] r8168: remove code specific to MAC version 01 - 06 Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 03/18] r8168: remove magic register handling used on MAC version 05 and 06 only Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 04/18] r8168: remove TBI mode support needed for MAC version 01 only Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 05/18] r8168: remove unneeded callbacks from struct rtl8169_private Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 06/18] r8168: remove function rtl8169_rx_missed() being specific to MAC version 01 - 06 Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 07/18] r8168: replace 8169 with 8168 in all relevant symbols Heiner Kallweit
2017-12-21 20:50 ` Heiner Kallweit [this message]
2017-12-22  9:44   ` [PATCH RFC 08/18] r8168: add basic phylib support Andrew Lunn
2017-12-21 20:50 ` [PATCH RFC 09/18] r8168: use genphy_soft_reset instead of open coding the soft reset Heiner Kallweit
2017-12-22  9:57   ` Andrew Lunn
2017-12-22 22:19     ` Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 10/18] r8168: switch to phy_ethtool_get/set_link_ksettings Heiner Kallweit
2017-12-22  9:57   ` Andrew Lunn
2017-12-21 20:50 ` [PATCH RFC 11/18] r8168: switch to phy_ethtool_nway_reset Heiner Kallweit
2017-12-22  9:58   ` Andrew Lunn
2017-12-21 20:50 ` [PATCH RFC 12/18] r8168: switch to phy_mii_ioctl Heiner Kallweit
2017-12-22 10:00   ` Andrew Lunn
2017-12-22 23:01     ` Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 13/18] r8168: replace speed_down with genphy_restart_aneg Heiner Kallweit
2017-12-22 10:14   ` Andrew Lunn
2017-12-22 23:36     ` Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 14/18] r8168: remove rtl8168_set_speed Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 15/18] r8168: remove rtl_phy_work and rtl8168_phy_timer Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 16/18] r8168: use phy_read/write in rtl_readphy/writephy helpers Heiner Kallweit
2017-12-21 20:50 ` [PATCH RFC 17/18] r8168: remove use of struct mii_if_info Heiner Kallweit
2017-12-22 10:21   ` Andrew Lunn
2017-12-21 20:50 ` [PATCH RFC 18/18] r8168: use link speed information as maintained by phylib Heiner Kallweit
2017-12-22 10:22   ` Andrew Lunn
2017-12-21 21:16 ` [PATCH RFC 00/18] r8169: separate r8168 driver and add experimental phylib support David Miller
2017-12-21 21:27   ` Heiner Kallweit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8d117cab-2221-2cc4-ff0a-891f4a60dc92@gmail.com \
    --to=hkallweit1@gmail.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=hau@realtek.com \
    --cc=netdev@vger.kernel.org \
    --cc=nic_swsd@realtek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).