lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250728221823.11968-7-sean.anderson@linux.dev>
Date: Mon, 28 Jul 2025 18:18:22 -0400
From: Sean Anderson <sean.anderson@...ux.dev>
To: Radhey Shyam Pandey <radhey.shyam.pandey@....com>,
	Andrew Lunn <andrew+netdev@...n.ch>,
	"David S . Miller" <davem@...emloft.net>,
	Eric Dumazet <edumazet@...gle.com>,
	Jakub Kicinski <kuba@...nel.org>,
	Paolo Abeni <pabeni@...hat.com>,
	netdev@...r.kernel.org
Cc: linux-kernel@...r.kernel.org,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Michal Simek <michal.simek@....com>,
	linux-arm-kernel@...ts.infradead.org,
	Leon Romanovsky <leon@...nel.org>,
	Sean Anderson <sean.anderson@...ux.dev>
Subject: [PATCH net-next v3 6/7] net: axienet: Rearrange lifetime functions

Rearrange the lifetime functions (probe, remove, etc.) in preparation
for the next commit. No functional change intended.

Signed-off-by: Sean Anderson <sean.anderson@...ux.dev>
---

Changes in v3:
- Rework to use a separate axienet_common structure

 drivers/net/ethernet/xilinx/xilinx_axienet.h  |  41 ++++--
 .../net/ethernet/xilinx/xilinx_axienet_main.c | 135 ++++++++++--------
 .../net/ethernet/xilinx/xilinx_axienet_mdio.c |  45 +++---
 3 files changed, 127 insertions(+), 94 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 5ff742103beb..d7215dd92ce9 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -467,6 +467,29 @@ struct skbuf_dma_descriptor {
 	int sg_len;
 };
 
+/**
+ * struct axienet_common - axienet private common data
+ * @pdev: Pointer to common platform device structure
+ * @axi_clk: AXI4-Lite bus clock
+ * @reset_lock: Lock held while resetting the device to prevent register access
+ * @mii_bus: Pointer to MII bus structure
+ * @mii_clk_div: MII bus clock divider value
+ * @regs_start: Resource start for axienet device addresses
+ * @regs: Base address for the axienet_local device address space
+ */
+struct axienet_common {
+	struct platform_device *pdev;
+
+	struct clk *axi_clk;
+
+	struct mutex reset_lock;
+	struct mii_bus *mii_bus;
+	u8 mii_clk_div;
+
+	void __iomem *regs;
+	resource_size_t regs_start;
+};
+
 /**
  * struct axienet_local - axienet private per device data
  * @ndev:	Pointer for net_device to which it will be attached.
@@ -549,6 +572,7 @@ struct skbuf_dma_descriptor {
 struct axienet_local {
 	struct net_device *ndev;
 	struct device *dev;
+	struct axienet_common *cp;
 
 	struct phylink *phylink;
 	struct phylink_config phylink_config;
@@ -558,13 +582,11 @@ struct axienet_local {
 
 	bool switch_x_sgmii;
 
-	struct clk *axi_clk;
 	struct clk_bulk_data misc_clks[XAE_NUM_MISC_CLOCKS];
 
 	struct mii_bus *mii_bus;
 	u8 mii_clk_div;
 
-	resource_size_t regs_start;
 	void __iomem *regs;
 	void __iomem *dma_regs;
 
@@ -654,21 +676,14 @@ static inline u32 axienet_ior(struct axienet_local *lp, off_t offset)
 	return ioread32(lp->regs + offset);
 }
 
-static inline u32 axinet_ior_read_mcr(struct axienet_local *lp)
-{
-	return axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
-}
-
 static inline void axienet_lock_mii(struct axienet_local *lp)
 {
-	if (lp->mii_bus)
-		mutex_lock(&lp->mii_bus->mdio_lock);
+	mutex_lock(&lp->cp->reset_lock);
 }
 
 static inline void axienet_unlock_mii(struct axienet_local *lp)
 {
-	if (lp->mii_bus)
-		mutex_unlock(&lp->mii_bus->mdio_lock);
+	mutex_unlock(&lp->cp->reset_lock);
 }
 
 /**
@@ -738,7 +753,7 @@ static inline void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
 #endif /* CONFIG_64BIT */
 
 /* Function prototypes visible in xilinx_axienet_mdio.c for other files */
-int axienet_mdio_setup(struct axienet_local *lp);
-void axienet_mdio_teardown(struct axienet_local *lp);
+int axienet_mdio_setup(struct axienet_common *lp);
+void axienet_mdio_teardown(struct axienet_common *lp);
 
 #endif /* XILINX_AXI_ENET_H */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 28927c7c6c41..f235ef15187c 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -225,8 +225,8 @@ static void axienet_dma_bd_release(struct net_device *ndev)
 
 static u64 axienet_dma_rate(struct axienet_local *lp)
 {
-	if (lp->axi_clk)
-		return clk_get_rate(lp->axi_clk);
+	if (lp->cp->axi_clk)
+		return clk_get_rate(lp->cp->axi_clk);
 	return 125000000; /* arbitrary guess if no clock rate set */
 }
 
@@ -2749,29 +2749,17 @@ static void axienet_disable_misc(void *clocks)
 	clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, clocks);
 }
 
-/**
- * axienet_probe - Axi Ethernet probe function.
- * @pdev:	Pointer to platform device structure.
- *
- * Return: 0, on success
- *	    Non-zero error value on failure.
- *
- * This is the probe routine for Axi Ethernet driver. This is called before
- * any other driver routines are invoked. It allocates and sets up the Ethernet
- * device. Parses through device tree and populates fields of
- * axienet_local. It registers the Ethernet device.
- */
-static int axienet_probe(struct platform_device *pdev)
+static int axienet_mac_probe(struct axienet_common *cp)
 {
-	int ret;
+	struct platform_device *pdev = cp->pdev;
 	struct device *dev = &pdev->dev;
-	struct device_node *np;
 	struct axienet_local *lp;
 	struct net_device *ndev;
-	struct resource *ethres;
+	struct device_node *np;
 	u8 mac_addr[ETH_ALEN];
 	int addr_width = 32;
 	u32 value;
+	int ret;
 
 	ndev = devm_alloc_etherdev(dev, sizeof(*lp));
 	if (!ndev)
@@ -2790,6 +2778,8 @@ static int axienet_probe(struct platform_device *pdev)
 	lp = netdev_priv(ndev);
 	lp->ndev = ndev;
 	lp->dev = dev;
+	lp->cp = cp;
+	lp->regs = cp->regs;
 	lp->options = XAE_OPTION_DEFAULTS;
 	lp->rx_bd_num = RX_BD_NUM_DEFAULT;
 	lp->tx_bd_num = TX_BD_NUM_DEFAULT;
@@ -2801,17 +2791,6 @@ static int axienet_probe(struct platform_device *pdev)
 	seqcount_mutex_init(&lp->hw_stats_seqcount, &lp->stats_lock);
 	INIT_DEFERRABLE_WORK(&lp->stats_work, axienet_refresh_stats);
 
-	lp->axi_clk = devm_clk_get_optional_enabled(dev, "s_axi_lite_clk");
-	if (!lp->axi_clk) {
-		/* For backward compatibility, if named AXI clock is not present,
-		 * treat the first clock specified as the AXI clock.
-		 */
-		lp->axi_clk = devm_clk_get_optional_enabled(dev, NULL);
-	}
-	if (IS_ERR(lp->axi_clk))
-		return dev_err_probe(dev, PTR_ERR(lp->axi_clk),
-				     "could not get AXI clock\n");
-
 	lp->misc_clks[0].id = "axis_clk";
 	lp->misc_clks[1].id = "ref_clk";
 	lp->misc_clks[2].id = "mgt_clk";
@@ -2831,12 +2810,6 @@ static int axienet_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	/* Map device registers */
-	lp->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &ethres);
-	if (IS_ERR(lp->regs))
-		return PTR_ERR(lp->regs);
-	lp->regs_start = ethres->start;
-
 	/* Setup checksum offload, but default to off if not specified */
 	lp->features = 0;
 
@@ -3045,11 +3018,6 @@ static int axienet_probe(struct platform_device *pdev)
 	lp->tx_dma_cr = axienet_calc_cr(lp, XAXIDMA_DFT_TX_THRESHOLD,
 					XAXIDMA_DFT_TX_USEC);
 
-	ret = axienet_mdio_setup(lp);
-	if (ret)
-		dev_warn(dev,
-			 "error registering MDIO bus: %d\n", ret);
-
 	if (lp->phy_mode == PHY_INTERFACE_MODE_SGMII ||
 	    lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) {
 		np = of_parse_phandle(dev->of_node, "pcs-handle", 0);
@@ -3061,17 +3029,14 @@ static int axienet_probe(struct platform_device *pdev)
 			np = of_parse_phandle(dev->of_node, "phy-handle", 0);
 		}
 		if (!np) {
-			dev_err(dev, "pcs-handle (preferred) or phy-handle required for 1000BaseX/SGMII\n");
-			ret = -EINVAL;
-			goto cleanup_mdio;
+			dev_err(dev,
+				"pcs-handle (preferred) or phy-handle required for 1000BaseX/SGMII\n");
+			return -EINVAL;
 		}
 		lp->pcs_phy = of_mdio_find_device(np);
-		if (!lp->pcs_phy) {
-			ret = -EPROBE_DEFER;
-			of_node_put(np);
-			goto cleanup_mdio;
-		}
 		of_node_put(np);
+		if (!lp->pcs_phy)
+			return -EPROBE_DEFER;
 		lp->pcs.ops = &axienet_pcs_ops;
 		lp->pcs.poll = true;
 	}
@@ -3096,7 +3061,7 @@ static int axienet_probe(struct platform_device *pdev)
 	if (IS_ERR(lp->phylink)) {
 		ret = PTR_ERR(lp->phylink);
 		dev_err(dev, "phylink_create error (%i)\n", ret);
-		goto cleanup_mdio;
+		goto cleanup_pcs;
 	}
 
 	ret = register_netdev(lp->ndev);
@@ -3109,32 +3074,24 @@ static int axienet_probe(struct platform_device *pdev)
 
 cleanup_phylink:
 	phylink_destroy(lp->phylink);
-
-cleanup_mdio:
+cleanup_pcs:
 	if (lp->pcs_phy)
 		put_device(&lp->pcs_phy->dev);
-	if (lp->mii_bus)
-		axienet_mdio_teardown(lp);
 	return ret;
 }
 
-static void axienet_remove(struct platform_device *pdev)
+static void axienet_mac_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct axienet_local *lp = netdev_priv(ndev);
 
 	unregister_netdev(ndev);
-
-	if (lp->phylink)
-		phylink_destroy(lp->phylink);
-
+	phylink_destroy(lp->phylink);
 	if (lp->pcs_phy)
 		put_device(&lp->pcs_phy->dev);
-
-	axienet_mdio_teardown(lp);
 }
 
-static void axienet_shutdown(struct platform_device *pdev)
+static void axienet_mac_shutdown(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 
@@ -3182,10 +3139,64 @@ static int axienet_resume(struct device *dev)
 static DEFINE_SIMPLE_DEV_PM_OPS(axienet_pm_ops,
 				axienet_suspend, axienet_resume);
 
+static int axienet_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct axienet_common *cp;
+	struct resource *ethres;
+	int ret;
+
+	cp = devm_kzalloc(dev, sizeof(*cp), GFP_KERNEL);
+	if (!cp)
+		return -ENOMEM;
+
+	cp->pdev = pdev;
+	mutex_init(&cp->reset_lock);
+
+	cp->axi_clk = devm_clk_get_optional_enabled(dev, "s_axi_lite_clk");
+	if (!cp->axi_clk) {
+		/* For backward compatibility, if named AXI clock is not present,
+		 * treat the first clock specified as the AXI clock.
+		 */
+		cp->axi_clk = devm_clk_get_optional_enabled(dev, NULL);
+	}
+	if (IS_ERR(cp->axi_clk))
+		return dev_err_probe(dev, PTR_ERR(cp->axi_clk),
+				     "could not get AXI clock\n");
+
+	/* Map device registers */
+	cp->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &ethres);
+	if (IS_ERR(cp->regs))
+		return PTR_ERR(cp->regs);
+	cp->regs_start = ethres->start;
+
+	ret = axienet_mdio_setup(cp);
+	if (ret)
+		dev_warn(dev, "error registering MDIO bus: %d\n", ret);
+
+	ret = axienet_mac_probe(cp);
+	if (!ret)
+		return 0;
+
+	if (cp->mii_bus)
+		axienet_mdio_teardown(cp);
+	return ret;
+}
+
+static void axienet_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	axienet_mac_remove(pdev);
+	if (lp->mii_bus)
+		axienet_mdio_teardown(lp->cp);
+}
+
 static struct platform_driver axienet_driver = {
 	.probe = axienet_probe,
 	.remove = axienet_remove,
-	.shutdown = axienet_shutdown,
+	.shutdown = axienet_mac_shutdown,
 	.driver = {
 		 .name = "xilinx_axienet",
 		 .pm = &axienet_pm_ops,
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index 2799d168ed9d..d428ce6da639 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/of_address.h>
 #include <linux/of_mdio.h>
+#include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <linux/iopoll.h>
 
@@ -22,13 +23,13 @@
 
 /**
  * axienet_mdio_wait_until_ready - MDIO wait function
- * @lp:	Pointer to axienet local data structure.
+ * @lp:	Pointer to axienet common data structure.
  *
  * Return :	0 on success, Negative value on errors
  *
  * Wait till MDIO interface is ready to accept a new transaction.
  */
-static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
+static int axienet_mdio_wait_until_ready(struct axienet_common *lp)
 {
 	u32 val;
 
@@ -39,11 +40,11 @@ static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
 
 /**
  * axienet_mdio_mdc_enable - MDIO MDC enable function
- * @lp:	Pointer to axienet local data structure.
+ * @lp:	Pointer to axienet common data structure.
  *
  * Enable the MDIO MDC. Called prior to a read/write operation
  */
-static void axienet_mdio_mdc_enable(struct axienet_local *lp)
+static void axienet_mdio_mdc_enable(struct axienet_common *lp)
 {
 	iowrite32((u32)lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK,
 		  lp->regs + XAE_MDIO_MC_OFFSET);
@@ -51,11 +52,11 @@ static void axienet_mdio_mdc_enable(struct axienet_local *lp)
 
 /**
  * axienet_mdio_mdc_disable - MDIO MDC disable function
- * @lp:	Pointer to axienet local data structure.
+ * @lp:	Pointer to axienet common data structure.
  *
  * Disable the MDIO MDC. Called after a read/write operation
  */
-static void axienet_mdio_mdc_disable(struct axienet_local *lp)
+static void axienet_mdio_mdc_disable(struct axienet_common *lp)
 {
 	u32 mc_reg;
 
@@ -80,8 +81,9 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
 {
 	u32 rc;
 	int ret;
-	struct axienet_local *lp = bus->priv;
+	struct axienet_common *lp = bus->priv;
 
+	guard(mutex)(&lp->reset_lock);
 	axienet_mdio_mdc_enable(lp);
 
 	ret = axienet_mdio_wait_until_ready(lp);
@@ -127,13 +129,14 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
 static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
 			      u16 val)
 {
-	struct axienet_local *lp = bus->priv;
+	struct axienet_common *lp = bus->priv;
 	int ret;
 	u32 mcr;
 
 	dev_dbg(&bus->dev, "%s(phy_id=%i, reg=%x, val=%x)\n", __func__,
 		phy_id, reg, val);
 
+	guard(mutex)(&lp->reset_lock);
 	axienet_mdio_mdc_enable(lp);
 
 	ret = axienet_mdio_wait_until_ready(lp);
@@ -160,7 +163,7 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
 
 /**
  * axienet_mdio_enable - MDIO hardware setup function
- * @lp:		Pointer to axienet local data structure.
+ * @lp:		Pointer to axienet common data structure.
  * @np:		Pointer to mdio device tree node.
  *
  * Return:	0 on success, -ETIMEDOUT on a timeout, -EOVERFLOW on a clock
@@ -171,7 +174,7 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
  **/
 static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np)
 {
-	struct axienet_local *lp = bus->priv;
+	struct axienet_common *lp = bus->priv;
 	u32 mdio_freq = DEFAULT_MDIO_FREQ;
 	u32 host_clock;
 	u32 clk_div;
@@ -187,7 +190,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np)
 		/* Legacy fallback: detect CPU clock frequency and use as AXI
 		 * bus clock frequency. This only works on certain platforms.
 		 */
-		np1 = of_find_node_by_name(NULL, "lpu");
+		np1 = of_find_node_by_name(NULL, "cpu");
 		if (!np1) {
 			dev_warn(&bus->dev,
 				 "Could not find CPU device node.\n");
@@ -258,6 +261,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np)
 		"Setting MDIO clock divisor to %u/%u Hz host clock.\n",
 		lp->mii_clk_div, host_clock);
 
+	guard(mutex)(&lp->reset_lock);
 	axienet_mdio_mdc_enable(lp);
 
 	ret = axienet_mdio_wait_until_ready(lp);
@@ -269,7 +273,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np)
 
 /**
  * axienet_mdio_setup - MDIO setup function
- * @lp:		Pointer to axienet local data structure.
+ * @lp:		Pointer to axienet common data structure.
  *
  * Return:	0 on success, -ETIMEDOUT on a timeout, -EOVERFLOW on a clock
  *		divisor overflow, -ENOMEM when mdiobus_alloc (to allocate
@@ -278,7 +282,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np)
  * Sets up the MDIO interface by initializing the MDIO clock.
  * Register the MDIO interface.
  **/
-int axienet_mdio_setup(struct axienet_local *lp)
+int axienet_mdio_setup(struct axienet_common *lp)
 {
 	struct device_node *mdio_node;
 	struct mii_bus *bus;
@@ -295,18 +299,21 @@ int axienet_mdio_setup(struct axienet_local *lp)
 	bus->name = "Xilinx Axi Ethernet MDIO";
 	bus->read = axienet_mdio_read;
 	bus->write = axienet_mdio_write;
-	bus->parent = lp->dev;
+	bus->parent = &lp->pdev->dev;
 	lp->mii_bus = bus;
 
-	mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
-	ret = axienet_mdio_enable(bus, mdio_node);
+	mdio_node = of_get_child_by_name(lp->pdev->dev.of_node, "mdio");
+	scoped_guard(mutex, &lp->reset_lock)
+		ret = axienet_mdio_enable(bus, mdio_node);
 	if (ret < 0)
 		goto unregister;
 
 	ret = of_mdiobus_register(bus, mdio_node);
 	of_node_put(mdio_node);
-	axienet_mdio_mdc_disable(lp);
+	scoped_guard(mutex, &lp->reset_lock)
+		axienet_mdio_mdc_disable(lp);
 	if (ret) {
+unregister:
 		mdiobus_free(bus);
 		lp->mii_bus = NULL;
 	}
@@ -315,11 +322,11 @@ int axienet_mdio_setup(struct axienet_local *lp)
 
 /**
  * axienet_mdio_teardown - MDIO remove function
- * @lp:		Pointer to axienet local data structure.
+ * @lp:		Pointer to axienet common data structure.
  *
  * Unregisters the MDIO and frees any associate memory for mii bus.
  */
-void axienet_mdio_teardown(struct axienet_local *lp)
+void axienet_mdio_teardown(struct axienet_common *lp)
 {
 	mdiobus_unregister(lp->mii_bus);
 	mdiobus_free(lp->mii_bus);
-- 
2.35.1.1320.gc452695387.dirty


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ