Thread (40 messages) 40 messages, 6 authors, 2022-07-19
STALE1410d
Revisions (2)
  1. rfc current
  2. v2 [diff vs current]

[RFC PATCH net-next 4/9] net: pcs: lynx: Convert to an mdio driver

From: Sean Anderson <hidden>
Date: 2022-07-11 16:06:26
Also in: lkml
Subsystem: dpaa2 ethernet driver, ethernet phy library, freescale enetc ethernet drivers, lynx pcs module, networking drivers, networking [dsa], ocelot ethernet switch driver, the rest · Maintainers: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Claudiu Manoil, Vladimir Oltean, Wei Fang, Clark Wang, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

This converts the lynx PCS driver to a proper MDIO driver. This allows
using a more conventional driver lifecycle (e.g. with a probe and
remove). For compatibility with existing device trees lacking a
compatible property, we bind the driver in lynx_pcs_create. This is
intended only as a transitional method. After compatible properties are
added to all existing device trees (and a reasonable amount of time has
passed), then lynx_pcs_create can be removed, and users can be converted
to pcs_get_fwnode.

Signed-off-by: Sean Anderson <redacted>
---

 drivers/net/dsa/ocelot/Kconfig                |  2 +
 drivers/net/dsa/ocelot/felix_vsc9959.c        |  2 +-
 drivers/net/dsa/ocelot/seville_vsc9953.c      |  2 +-
 drivers/net/ethernet/freescale/dpaa2/Kconfig  |  1 +
 .../net/ethernet/freescale/dpaa2/dpaa2-mac.c  |  4 +-
 drivers/net/ethernet/freescale/enetc/Kconfig  |  1 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  4 +-
 drivers/net/pcs/Kconfig                       | 11 +++-
 drivers/net/pcs/pcs-lynx.c                    | 65 +++++++++++++++----
 9 files changed, 72 insertions(+), 20 deletions(-)
diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 220b0b027b55..cbb0ced3f37d 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -10,6 +10,7 @@ config NET_DSA_MSCC_FELIX
 	select NET_DSA_TAG_OCELOT_8021Q
 	select NET_DSA_TAG_OCELOT
 	select FSL_ENETC_MDIO
+	select PCS
 	select PCS_LYNX
 	help
 	  This driver supports the VSC9959 (Felix) switch, which is embedded as
@@ -25,6 +26,7 @@ config NET_DSA_MSCC_SEVILLE
 	select MSCC_OCELOT_SWITCH_LIB
 	select NET_DSA_TAG_OCELOT_8021Q
 	select NET_DSA_TAG_OCELOT
+	select PCS
 	select PCS_LYNX
 	help
 	  This driver supports the VSC9953 (Seville) switch, which is embedded
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 570d0204b7be..57634e2296c0 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1094,7 +1094,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
 			continue;
 
 		phylink_pcs = lynx_pcs_create(mdio_device);
-		if (!phylink_pcs) {
+		if (IS_ERR(phylink_pcs)) {
 			mdio_device_free(mdio_device);
 			continue;
 		}
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index ea0649211356..8c52de5d0b02 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1049,7 +1049,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 			continue;
 
 		phylink_pcs = lynx_pcs_create(mdio_device);
-		if (!phylink_pcs) {
+		if (IS_ERR(phylink_pcs)) {
 			mdio_device_free(mdio_device);
 			continue;
 		}
diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig
index d029b69c3f18..2648e9fb6e13 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
@@ -3,6 +3,7 @@ config FSL_DPAA2_ETH
 	tristate "Freescale DPAA2 Ethernet"
 	depends on FSL_MC_BUS && FSL_MC_DPIO
 	select PHYLINK
+	select PCS
 	select PCS_LYNX
 	select FSL_XGMAC_MDIO
 	select NET_DEVLINK
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index c9bee9a0c9b2..e82c0d23eeb5 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -268,10 +268,10 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
 		return -EPROBE_DEFER;
 
 	mac->pcs = lynx_pcs_create(mdiodev);
-	if (!mac->pcs) {
+	if (IS_ERR(mac->pcs)) {
 		netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
 		put_device(&mdiodev->dev);
-		return -ENOMEM;
+		return PTR_ERR(mac->pcs);
 	}
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index cdc0ff89388a..c7dcdeb9a333 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -5,6 +5,7 @@ config FSL_ENETC
 	select FSL_ENETC_IERB
 	select FSL_ENETC_MDIO
 	select PHYLINK
+	select PCS
 	select PCS_LYNX
 	select DIMLIB
 	help
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c4a0e836d4f0..8c923a93da88 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -859,9 +859,9 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 	}
 
 	phylink_pcs = lynx_pcs_create(mdio_device);
-	if (!phylink_pcs) {
+	if (IS_ERR(phylink_pcs)) {
 		mdio_device_free(mdio_device);
-		err = -ENOMEM;
+		err = PTR_ERR(phylink_pcs);
 		dev_err(dev, "cannot create lynx pcs (%d)\n", err);
 		goto unregister_mdiobus;
 	}
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index fed6264fdf33..a225176f92e8 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -25,9 +25,14 @@ config PCS_XPCS
 	  controllers.
 
 config PCS_LYNX
-	tristate
+	tristate "NXP Lynx PCS driver"
+	depends on PCS && MDIO_DEVICE
 	help
-	  This module provides helpers to phylink for managing the Lynx PCS
-	  which is part of the Layerscape and QorIQ Ethernet SERDES.
+	  This module provides driver support for the PCSs in Lynx 10g and 28g
+	  SerDes devices. These devices are present in NXP QorIQ SoCs,
+	  including the Layerscape series.
+
+	  If you want to use Ethernet on a QorIQ SoC, say "Y". If compiled as a
+	  module, it will be called "pcs-lynx".
 
 endmenu
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index fd3445374955..8272072698e4 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -1,11 +1,14 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2020 NXP
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
+ * Copyright 2020 NXP
  * Lynx PCS MDIO helpers
  */
 
 #include <linux/mdio.h>
-#include <linux/phylink.h>
+#include <linux/of.h>
+#include <linux/pcs.h>
 #include <linux/pcs-lynx.h>
+#include <linux/phylink.h>
 
 #define SGMII_CLOCK_PERIOD_NS		8 /* PCS is clocked at 125 MHz */
 #define LINK_TIMER_VAL(ns)		((u32)((ns) / SGMII_CLOCK_PERIOD_NS))
@@ -337,34 +340,74 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
 }
 
 static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
+	.owner = THIS_MODULE,
 	.pcs_get_state = lynx_pcs_get_state,
 	.pcs_config = lynx_pcs_config,
 	.pcs_an_restart = lynx_pcs_an_restart,
 	.pcs_link_up = lynx_pcs_link_up,
 };
 
-struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+static int lynx_pcs_probe(struct mdio_device *mdio)
 {
+	struct device *dev = &mdio->dev;
 	struct lynx_pcs *lynx;
+	int ret;
 
-	lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
+	lynx = devm_kzalloc(dev, sizeof(*lynx), GFP_KERNEL);
 	if (!lynx)
-		return NULL;
+		return -ENOMEM;
 
 	lynx->mdio = mdio;
+	lynx->pcs.dev = dev;
 	lynx->pcs.ops = &lynx_pcs_phylink_ops;
 	lynx->pcs.poll = true;
 
-	return lynx_to_phylink_pcs(lynx);
+	ret = devm_pcs_register(dev, &lynx->pcs);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register PCS\n");
+	dev_info(dev, "probed\n");
+	return 0;
+}
+
+static const struct of_device_id lynx_pcs_of_match[] = {
+	{ .compatible = "fsl,lynx-pcs" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, lynx_pcs_of_match);
+
+static struct mdio_driver lynx_pcs_driver = {
+	.probe = lynx_pcs_probe,
+	.mdiodrv.driver = {
+		.name = "lynx-pcs",
+		.of_match_table = of_match_ptr(lynx_pcs_of_match),
+	},
+};
+mdio_module_driver(lynx_pcs_driver);
+
+struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+{
+	struct device *dev = &mdio->dev;
+	int err;
+
+	/* For compatibility with device trees lacking compatible strings, we
+	 * bind the device manually here.
+	 */
+	err = device_driver_attach(&lynx_pcs_driver.mdiodrv.driver, dev);
+	if (err && err != -EBUSY) {
+		if (err == -EAGAIN)
+			err = -EPROBE_DEFER;
+		return ERR_PTR(err);
+	}
+
+	return pcs_get_by_provider(&mdio->dev);
 }
 EXPORT_SYMBOL(lynx_pcs_create);
 
 void lynx_pcs_destroy(struct phylink_pcs *pcs)
 {
-	struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
-
-	kfree(lynx);
+	pcs_put(pcs);
 }
 EXPORT_SYMBOL(lynx_pcs_destroy);
 
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("NXP Lynx 10G/28G PCS driver");
+MODULE_LICENSE("GPL");
-- 
2.35.1.1320.gc452695387.dirty
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help