From nobody Sun Oct 5 10:51:31 2025 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C15F812F5A5 for ; Tue, 5 Aug 2025 15:35:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408118; cv=none; b=gW/wM+JAMOqe04i64H0SyZqzxHONVFHCnZi50O2JpHWPwJ+SgNe5o/GRJQD6klTWx8Dq3EnCOOvE54nNHmcfzPqZL/0dP56MJkfU/p8vhgdXlhnhwD3J0jBrorQU5lwZHFwcdF4A7hZjT4cHfJp2ED8hiH84e4m4zYsdMZSq65w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408118; c=relaxed/simple; bh=ajgHpML/BnyZkQ98KfbunMJrDhKSPNmDjFzxbRlbStU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JrOsKSH0e7jD+C8SXi+kBAeDBRMIHIFNdwpTN22S5tovkhj5j0kJoxj+JLxKvG0aLjp0e6fSPDbc5MuXH7BCBUArMH17fkjRWO9vas/xX7ArLCUej1R4OMlyhDquygQ3AXIjTwuzsor3rilfRjLUaTep7hUEqukV0UC+udfPPGU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=L8XqVjC0; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="L8XqVjC0" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408113; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=80XuwmV2GDU/jOjydwT587YtNDMxz2Lo5jVH+ix/bS0=; b=L8XqVjC07oHYulX2y8WINlaJOncm3ENK3GW/MNXsdNX7ujLviujsv1SZvyuEiNI3wjfK3I iCgHU0Kp0NVQmmGTd2dEh9F3FLCLCQAZAAtdBe3XXSd14wGqDBfUn3itt+0C4cW1Vy3o1l 5xU8teNtC4piZ7nsFLkzy3eB6uUnosU= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson , Suraj Gupta Subject: [PATCH net-next v4 1/7] net: axienet: Fix resource release ordering Date: Tue, 5 Aug 2025 11:34:50 -0400 Message-Id: <20250805153456.1313661-2-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Device-managed resources are released after manually-managed resources. Therefore, once any manually-managed resource is acquired, all further resources must be manually-managed too. Convert all resources before the MDIO bus is created into device-managed resources. In all cases but one there are already devm variants available. Fixes: 46aa27df8853 ("net: axienet: Use devm_* calls") Signed-off-by: Sean Anderson Reviewed-by: Suraj Gupta --- (no changes since v1) .../net/ethernet/xilinx/xilinx_axienet_main.c | 89 ++++++++----------- 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_main.c index 6011d7eae0c7..1f277e5e4a62 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -2744,6 +2744,11 @@ static void axienet_dma_err_handler(struct work_stru= ct *work) axienet_setoptions(ndev, lp->options); } =20 +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. @@ -2767,7 +2772,7 @@ static int axienet_probe(struct platform_device *pdev) int addr_width =3D 32; u32 value; =20 - ndev =3D alloc_etherdev(sizeof(*lp)); + ndev =3D devm_alloc_etherdev(&pdev->dev, sizeof(*lp)); if (!ndev) return -ENOMEM; =20 @@ -2795,22 +2800,17 @@ static int axienet_probe(struct platform_device *pd= ev) seqcount_mutex_init(&lp->hw_stats_seqcount, &lp->stats_lock); INIT_DEFERRABLE_WORK(&lp->stats_work, axienet_refresh_stats); =20 - lp->axi_clk =3D devm_clk_get_optional(&pdev->dev, "s_axi_lite_clk"); + lp->axi_clk =3D devm_clk_get_optional_enabled(&pdev->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 =3D devm_clk_get_optional(&pdev->dev, NULL); - } - if (IS_ERR(lp->axi_clk)) { - ret =3D PTR_ERR(lp->axi_clk); - goto free_netdev; - } - ret =3D clk_prepare_enable(lp->axi_clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable AXI clock: %d\n", ret); - goto free_netdev; + lp->axi_clk =3D devm_clk_get_optional_enabled(&pdev->dev, NULL); } + if (IS_ERR(lp->axi_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(lp->axi_clk), + "could not get AXI clock\n"); =20 lp->misc_clks[0].id =3D "axis_clk"; lp->misc_clks[1].id =3D "ref_clk"; @@ -2818,18 +2818,23 @@ static int axienet_probe(struct platform_device *pd= ev) =20 ret =3D devm_clk_bulk_get_optional(&pdev->dev, XAE_NUM_MISC_CLOCKS, lp->m= isc_clks); if (ret) - goto cleanup_clk; + return dev_err_probe(&pdev->dev, ret, + "could not get misc. clocks\n"); =20 ret =3D clk_bulk_prepare_enable(XAE_NUM_MISC_CLOCKS, lp->misc_clks); if (ret) - goto cleanup_clk; + return dev_err_probe(&pdev->dev, ret, + "could not enable misc. clocks\n"); + + ret =3D devm_add_action_or_reset(&pdev->dev, axienet_disable_misc, + lp->misc_clks); + if (ret) + return ret; =20 /* Map device registers */ lp->regs =3D devm_platform_get_and_ioremap_resource(pdev, 0, ðres); - if (IS_ERR(lp->regs)) { - ret =3D PTR_ERR(lp->regs); - goto cleanup_clk; - } + if (IS_ERR(lp->regs)) + return PTR_ERR(lp->regs); lp->regs_start =3D ethres->start; =20 /* Setup checksum offload, but default to off if not specified */ @@ -2898,19 +2903,17 @@ static int axienet_probe(struct platform_device *pd= ev) lp->phy_mode =3D PHY_INTERFACE_MODE_1000BASEX; break; default: - ret =3D -EINVAL; - goto cleanup_clk; + return -EINVAL; } } else { ret =3D of_get_phy_mode(pdev->dev.of_node, &lp->phy_mode); if (ret) - goto cleanup_clk; + return ret; } if (lp->switch_x_sgmii && lp->phy_mode !=3D PHY_INTERFACE_MODE_SGMII && lp->phy_mode !=3D PHY_INTERFACE_MODE_1000BASEX) { dev_err(&pdev->dev, "xlnx,switch-x-sgmii only supported with SGMII or 10= 00BaseX\n"); - ret =3D -EINVAL; - goto cleanup_clk; + return -EINVAL; } =20 if (!of_property_present(pdev->dev.of_node, "dmas")) { @@ -2925,7 +2928,7 @@ static int axienet_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to get DMA resource\n"); of_node_put(np); - goto cleanup_clk; + return ret; } lp->dma_regs =3D devm_ioremap_resource(&pdev->dev, &dmares); @@ -2942,19 +2945,17 @@ static int axienet_probe(struct platform_device *pd= ev) } if (IS_ERR(lp->dma_regs)) { dev_err(&pdev->dev, "could not map DMA regs\n"); - ret =3D PTR_ERR(lp->dma_regs); - goto cleanup_clk; + return PTR_ERR(lp->dma_regs); } if (lp->rx_irq <=3D 0 || lp->tx_irq <=3D 0) { dev_err(&pdev->dev, "could not determine irqs\n"); - ret =3D -ENOMEM; - goto cleanup_clk; + return -ENOMEM; } =20 /* Reset core now that clocks are enabled, prior to accessing MDIO */ ret =3D __axienet_device_reset(lp); if (ret) - goto cleanup_clk; + return ret; =20 /* Autodetect the need for 64-bit DMA pointers. * When the IP is configured for a bus width bigger than 32 bits, @@ -2981,14 +2982,13 @@ static int axienet_probe(struct platform_device *pd= ev) } if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) { dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-b= it architecture\n"); - ret =3D -EINVAL; - goto cleanup_clk; + return -EINVAL; } =20 ret =3D dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width)); if (ret) { dev_err(&pdev->dev, "No suitable DMA available\n"); - goto cleanup_clk; + return ret; } netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll); netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll); @@ -2998,15 +2998,12 @@ static int axienet_probe(struct platform_device *pd= ev) =20 lp->eth_irq =3D platform_get_irq_optional(pdev, 0); if (lp->eth_irq < 0 && lp->eth_irq !=3D -ENXIO) { - ret =3D lp->eth_irq; - goto cleanup_clk; + return lp->eth_irq; } tx_chan =3D dma_request_chan(lp->dev, "tx_chan0"); - if (IS_ERR(tx_chan)) { - ret =3D PTR_ERR(tx_chan); - dev_err_probe(lp->dev, ret, "No Ethernet DMA (TX) channel found\n"); - goto cleanup_clk; - } + if (IS_ERR(tx_chan)) + return dev_err_probe(lp->dev, PTR_ERR(tx_chan), + "No Ethernet DMA (TX) channel found\n"); =20 cfg.reset =3D 1; /* As name says VDMA but it has support for DMA channel reset */ @@ -3014,7 +3011,7 @@ static int axienet_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Reset channel failed\n"); dma_release_channel(tx_chan); - goto cleanup_clk; + return ret; } =20 dma_release_channel(tx_chan); @@ -3119,13 +3116,6 @@ static int axienet_probe(struct platform_device *pde= v) put_device(&lp->pcs_phy->dev); if (lp->mii_bus) axienet_mdio_teardown(lp); -cleanup_clk: - clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, lp->misc_clks); - clk_disable_unprepare(lp->axi_clk); - -free_netdev: - free_netdev(ndev); - return ret; } =20 @@ -3143,11 +3133,6 @@ static void axienet_remove(struct platform_device *p= dev) put_device(&lp->pcs_phy->dev); =20 axienet_mdio_teardown(lp); - - clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, lp->misc_clks); - clk_disable_unprepare(lp->axi_clk); - - free_netdev(ndev); } =20 static void axienet_shutdown(struct platform_device *pdev) --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-171.mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 523CC274FFC for ; Tue, 5 Aug 2025 15:35:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408119; cv=none; b=ebl/E5VE/1R6ZuUDcqnKV2cx8deG5W01d1o2k3p3sWfE5mNAHcfG45vY0l/8uClTfQHUCkLCfj/7AVXkoIRn8CbKFOdRkreQtfU5l7lAvURRIYrxW6NYv79N/NYhcPBweJVAtz9o4U4XAinDx/baVIM0V6byFHjVa/zbYuYsk8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408119; c=relaxed/simple; bh=NREG7/jRvkNZrpdOCBLKO3g8W24+uCDycZzojHqEAGI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XTK8HBeo6jbzaucoQztzcqYAg8NIB8/Iyj9L8Ce/zw/uCdk967Djjv4mIF4vExDac0brxR2k4RLmoRhAXk4LQ1SFSXwJJ4knYL56qu1ahe8hJXqOyXpzus1jJfwuRHc+QN86dx0fEqKG1C6eItO3SDcWzTNEAmLvmf8HkSvfUSc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=XKiL6+sy; arc=none smtp.client-ip=91.218.175.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="XKiL6+sy" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408115; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nNBYWAsuzIbCLC3bKrAXDMPpx02Wco1ifzGZfSbmA94=; b=XKiL6+syGx8brdUMIVg+2pEOlXfLRLuYqP+45kzSWStGBd27ngIv1EWIZZ53FSaAV1sMIJ uN+yAiNwHtCklX5arBtJIslEuhqqW3JLPJcaSHAOIj6qVPtwE3p7jf7s9+bdY3pBGp2MTJ /TfMxiVBTb0NUb/GDgA4e+CCR0BygwE= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 2/7] net: axienet: Use ioread32/iowrite32 directly Date: Tue, 5 Aug 2025 11:34:51 -0400 Message-Id: <20250805153456.1313661-3-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for splitting the MDIO bus into a separate driver, convert all register reads/writes to use ioread32/iowrite32 directly instead of using the axienet_ior/iow helpers. While we're at it, clean up the register calculations a bit. Signed-off-by: Sean Anderson --- (no changes since v3) Changes in v3: - New .../net/ethernet/xilinx/xilinx_axienet_mdio.c | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_mdio.c index 9ca2643c921e..16f3581390dd 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -32,7 +32,7 @@ static int axienet_mdio_wait_until_ready(struct axienet_l= ocal *lp) { u32 val; =20 - return readx_poll_timeout(axinet_ior_read_mcr, lp, + return readx_poll_timeout(ioread32, lp->regs + XAE_MDIO_MCR_OFFSET, val, val & XAE_MDIO_MCR_READY_MASK, 1, 20000); } @@ -45,8 +45,8 @@ static int axienet_mdio_wait_until_ready(struct axienet_l= ocal *lp) */ static void axienet_mdio_mdc_enable(struct axienet_local *lp) { - axienet_iow(lp, XAE_MDIO_MC_OFFSET, - ((u32)lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK)); + iowrite32((u32)lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK, + lp->regs + XAE_MDIO_MC_OFFSET); } =20 /** @@ -59,9 +59,9 @@ static void axienet_mdio_mdc_disable(struct axienet_local= *lp) { u32 mc_reg; =20 - mc_reg =3D axienet_ior(lp, XAE_MDIO_MC_OFFSET); - axienet_iow(lp, XAE_MDIO_MC_OFFSET, - (mc_reg & ~XAE_MDIO_MC_MDIOEN_MASK)); + mc_reg =3D ioread32(lp->regs + XAE_MDIO_MC_OFFSET); + iowrite32(mc_reg & ~XAE_MDIO_MC_MDIOEN_MASK, + lp->regs + XAE_MDIO_MC_OFFSET); } =20 /** @@ -90,13 +90,11 @@ static int axienet_mdio_read(struct mii_bus *bus, int p= hy_id, int reg) return ret; } =20 - axienet_iow(lp, XAE_MDIO_MCR_OFFSET, - (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) & - XAE_MDIO_MCR_PHYAD_MASK) | - ((reg << XAE_MDIO_MCR_REGAD_SHIFT) & - XAE_MDIO_MCR_REGAD_MASK) | - XAE_MDIO_MCR_INITIATE_MASK | - XAE_MDIO_MCR_OP_READ_MASK)); + rc =3D FIELD_PREP(XAE_MDIO_MCR_PHYAD_MASK, phy_id) | + FIELD_PREP(XAE_MDIO_MCR_REGAD_MASK, reg) | + XAE_MDIO_MCR_INITIATE_MASK | + XAE_MDIO_MCR_OP_READ_MASK; + iowrite32(rc, lp->regs + XAE_MDIO_MCR_OFFSET); =20 ret =3D axienet_mdio_wait_until_ready(lp); if (ret < 0) { @@ -104,7 +102,7 @@ static int axienet_mdio_read(struct mii_bus *bus, int p= hy_id, int reg) return ret; } =20 - rc =3D axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF; + rc =3D ioread32(lp->regs + XAE_MDIO_MRD_OFFSET) & 0x0000FFFF; =20 dev_dbg(lp->dev, "axienet_mdio_read(phy_id=3D%i, reg=3D%x) =3D=3D %x\n", phy_id, reg, rc); @@ -129,8 +127,9 @@ static int axienet_mdio_read(struct mii_bus *bus, int p= hy_id, int reg) static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) { - int ret; struct axienet_local *lp =3D bus->priv; + int ret; + u32 mcr; =20 dev_dbg(lp->dev, "axienet_mdio_write(phy_id=3D%i, reg=3D%x, val=3D%x)\n", phy_id, reg, val); @@ -143,14 +142,12 @@ static int axienet_mdio_write(struct mii_bus *bus, in= t phy_id, int reg, return ret; } =20 - axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32)val); - axienet_iow(lp, XAE_MDIO_MCR_OFFSET, - (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) & - XAE_MDIO_MCR_PHYAD_MASK) | - ((reg << XAE_MDIO_MCR_REGAD_SHIFT) & - XAE_MDIO_MCR_REGAD_MASK) | - XAE_MDIO_MCR_INITIATE_MASK | - XAE_MDIO_MCR_OP_WRITE_MASK)); + iowrite32(val, lp->regs + XAE_MDIO_MWD_OFFSET); + mcr =3D FIELD_PREP(XAE_MDIO_MCR_PHYAD_MASK, phy_id) | + FIELD_PREP(XAE_MDIO_MCR_REGAD_MASK, reg) | + XAE_MDIO_MCR_INITIATE_MASK | + XAE_MDIO_MCR_OP_WRITE_MASK; + iowrite32(mcr, lp->regs + XAE_MDIO_MCR_OFFSET); =20 ret =3D axienet_mdio_wait_until_ready(lp); if (ret < 0) { --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-189.mta0.migadu.com (out-189.mta0.migadu.com [91.218.175.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30ABF279DCD for ; Tue, 5 Aug 2025 15:35:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.189 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408121; cv=none; b=rrOrzJZbhqeBdx9RxWC/Am/KkscCQ1FuHVUZeM3X9zbBzNqVHcOuN78q0+VAS7TeT/1UDxtWSf6QgqVPRcZ5TwhB5xYPU4tvY8eQB4b2lPcx8Fy5phzjeU2yH7mOiEJ+kgxdfrfBswcIJUZWOYMTte8cWdIZwYvJH0oQT/3DTII= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408121; c=relaxed/simple; bh=FVteCX5nFxedLEyY4hDIrw5cfazi5xYujvhmEo2iJl4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XIlRLPRLFR/zBMD1iS1GkfTDJnwjBCo1RlIHo+juyYmGui4wO/Js1TjCud74VuJ/O2U0uvT5GewedemN5TU/HSKO7TFd+JU+IL9c1f1T/mnDg5ATo0lvlSitT3ShHTt3rYfI+cchN3ExWv+FgD9NvU3UgSFLhuLuuBeZhE1yZ6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=lL+1wBuk; arc=none smtp.client-ip=91.218.175.189 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="lL+1wBuk" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408117; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HxGmLz1Ya+65fQyO+OBLk3+/0Yu+grwyrGLrIKSUdNI=; b=lL+1wBukjB18xJ/83De9sKF6yCO5nNDD6stJGI67OLitbyVv7ZJr6tqED5WnsBq9xnQde0 /gmwmwItwIB5/CwZxOnPd5hB+WXv0ZwQX9bxUTsSYWspG+158ClunVrN8YojhqzZqH1HuS VhL8617F1l4mPEPw84uAI+p3lYVu+K0= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 3/7] net: axienet: Use MDIO bus device in prints Date: Tue, 5 Aug 2025 11:34:52 -0400 Message-Id: <20250805153456.1313661-4-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" For clarity and to remove the dependency on the parent netdev, use the MDIO bus device in print statements. Signed-off-by: Sean Anderson --- Changes in v4: - Fix documentation for axienet_mdio_enable Changes in v3: - New .../net/ethernet/xilinx/xilinx_axienet_mdio.c | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_mdio.c index 16f3581390dd..dd5f961801dc 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -104,7 +104,7 @@ static int axienet_mdio_read(struct mii_bus *bus, int p= hy_id, int reg) =20 rc =3D ioread32(lp->regs + XAE_MDIO_MRD_OFFSET) & 0x0000FFFF; =20 - dev_dbg(lp->dev, "axienet_mdio_read(phy_id=3D%i, reg=3D%x) =3D=3D %x\n", + dev_dbg(&bus->dev, "%s(phy_id=3D%i, reg=3D%x) =3D=3D %x\n", __func__, phy_id, reg, rc); =20 axienet_mdio_mdc_disable(lp); @@ -131,7 +131,7 @@ static int axienet_mdio_write(struct mii_bus *bus, int = phy_id, int reg, int ret; u32 mcr; =20 - dev_dbg(lp->dev, "axienet_mdio_write(phy_id=3D%i, reg=3D%x, val=3D%x)\n", + dev_dbg(&bus->dev, "%s(phy_id=3D%i, reg=3D%x, val=3D%x)\n", __func__, phy_id, reg, val); =20 axienet_mdio_mdc_enable(lp); @@ -160,7 +160,7 @@ static int axienet_mdio_write(struct mii_bus *bus, int = phy_id, int reg, =20 /** * axienet_mdio_enable - MDIO hardware setup function - * @lp: Pointer to axienet local data structure. + * @bus: MDIO bus * @np: Pointer to mdio device tree node. * * Return: 0 on success, -ETIMEDOUT on a timeout, -EOVERFLOW on a clock @@ -169,8 +169,9 @@ static int axienet_mdio_write(struct mii_bus *bus, int = phy_id, int reg, * Sets up the MDIO interface by initializing the MDIO clock and enabling = the * MDIO interface in hardware. **/ -static int axienet_mdio_enable(struct axienet_local *lp, struct device_nod= e *np) +static int axienet_mdio_enable(struct mii_bus *bus, struct device_node *np) { + struct axienet_local *lp =3D bus->priv; u32 mdio_freq =3D DEFAULT_MDIO_FREQ; u32 host_clock; u32 clk_div; @@ -186,28 +187,31 @@ static int axienet_mdio_enable(struct axienet_local *= lp, struct device_node *np) /* Legacy fallback: detect CPU clock frequency and use as AXI * bus clock frequency. This only works on certain platforms. */ - np1 =3D of_find_node_by_name(NULL, "cpu"); + np1 =3D of_find_node_by_name(NULL, "lpu"); if (!np1) { - netdev_warn(lp->ndev, "Could not find CPU device node.\n"); + dev_warn(&bus->dev, + "Could not find CPU device node.\n"); host_clock =3D DEFAULT_HOST_CLOCK; } else { int ret =3D of_property_read_u32(np1, "clock-frequency", &host_clock); if (ret) { - netdev_warn(lp->ndev, "CPU clock-frequency property not found.\n"); + dev_warn(&bus->dev, + "CPU clock-frequency property not found.\n"); host_clock =3D DEFAULT_HOST_CLOCK; } of_node_put(np1); } - netdev_info(lp->ndev, "Setting assumed host clock to %u\n", - host_clock); + dev_info(&bus->dev, + "Setting assumed host clock to %u\n", host_clock); } =20 if (np) of_property_read_u32(np, "clock-frequency", &mdio_freq); if (mdio_freq !=3D DEFAULT_MDIO_FREQ) - netdev_info(lp->ndev, "Setting non-standard mdio bus frequency to %u Hz\= n", - mdio_freq); + dev_info(&bus->dev, + "Setting non-standard mdio bus frequency to %u Hz\n", + mdio_freq); =20 /* clk_div can be calculated by deriving it from the equation: * fMDIO =3D fHOST / ((1 + clk_div) * 2) @@ -245,14 +249,14 @@ static int axienet_mdio_enable(struct axienet_local *= lp, struct device_node *np) =20 /* Check for overflow of mii_clk_div */ if (clk_div & ~XAE_MDIO_MC_CLOCK_DIVIDE_MAX) { - netdev_warn(lp->ndev, "MDIO clock divisor overflow\n"); + dev_warn(&bus->dev, "MDIO clock divisor overflow\n"); return -EOVERFLOW; } lp->mii_clk_div =3D (u8)clk_div; =20 - netdev_dbg(lp->ndev, - "Setting MDIO clock divisor to %u/%u Hz host clock.\n", - lp->mii_clk_div, host_clock); + dev_dbg(&bus->dev, + "Setting MDIO clock divisor to %u/%u Hz host clock.\n", + lp->mii_clk_div, host_clock); =20 axienet_mdio_mdc_enable(lp); =20 @@ -295,7 +299,7 @@ int axienet_mdio_setup(struct axienet_local *lp) lp->mii_bus =3D bus; =20 mdio_node =3D of_get_child_by_name(lp->dev->of_node, "mdio"); - ret =3D axienet_mdio_enable(lp, mdio_node); + ret =3D axienet_mdio_enable(bus, mdio_node); if (ret < 0) goto unregister; ret =3D of_mdiobus_register(bus, mdio_node); --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91F0327A46A for ; Tue, 5 Aug 2025 15:35:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408122; cv=none; b=dPJpKzSV3RTTKSi0d8iAu1Fl5py4kSVwZ48L0z6mh/2+7SvowZZZO2xqGkhdyO57tJZ3hfHDQOXNqxbY0lRs+rhyieLx23OEaz0GZ5ve37QjcPQYPHIHFzwnIb1BFPS8jbtWuCgUdwp1zihwr6c6GAnZQ8y+xZ2xeOkMRAIGrOQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408122; c=relaxed/simple; bh=JINeEfUReHlNfN4Ns88LU3c1dRlUKvpggMNQDivnrWU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OMRHnZQ+hla86mzpyN8/ukOnOmdRMlv1WdCmtOJZz9DXu/CaccqsDsICRCs8mNjpEcAstYWxOtLa584b8IhsWu2bdP5jOBhSx1fEKklxfjQAOBlV/AYDkmO6rSx2A8ICJn4P8E39bYCTuWOdmuxOYs4f8WCv7ZRenTnrg2JGOAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Kv7ki/X0; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Kv7ki/X0" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408118; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=e10nwhxIlKlTQ6jthVLQK0vr7NmPf1h0C4lBIa7W+ls=; b=Kv7ki/X0PsflZN88cFaLMLhtxUkWt33JZfCUJy2KKmgkrUzome7qbHV+B0GVsLHaEA5OT/ aeIplRfGiARRhVYpjErSdPpFn1oajrNuN2Z4dvYiQ1aTtjz4+QsTycLeW8ZzPj+JOO9F8T SRNadM2VR3ZT0ExfqMqPD5agQPvkq4E= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 4/7] net: axienet: Simplify axienet_mdio_setup Date: Tue, 5 Aug 2025 11:34:53 -0400 Message-Id: <20250805153456.1313661-5-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" We always put the mdio_node and disable the bus after probing, so perform these steps unconditionally. Signed-off-by: Sean Anderson --- (no changes since v1) drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_mdio.c index dd5f961801dc..1903a1d50b05 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -302,19 +302,14 @@ int axienet_mdio_setup(struct axienet_local *lp) ret =3D axienet_mdio_enable(bus, mdio_node); if (ret < 0) goto unregister; + ret =3D of_mdiobus_register(bus, mdio_node); - if (ret) - goto unregister_mdio_enabled; of_node_put(mdio_node); axienet_mdio_mdc_disable(lp); - return 0; - -unregister_mdio_enabled: - axienet_mdio_mdc_disable(lp); -unregister: - of_node_put(mdio_node); - mdiobus_free(bus); - lp->mii_bus =3D NULL; + if (ret) { + mdiobus_free(bus); + lp->mii_bus =3D NULL; + } return ret; } =20 --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 091D927AC45 for ; Tue, 5 Aug 2025 15:35:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408124; cv=none; b=OUXZS8UITMk3NcXtYl4eDXuJQXXWCJdZ14h5f5vHuA7spxnYbDGWac0irpsLffkkw5kdpHv7jDwssRrDTFYlIGGReImajy8Oq+rEP+pU5NFjtjCCyE5mUAbkIQAmhY7xbk5kKIzKdL1ZELCDt5TDSafXo9BECpqpSC33ctqd7sM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408124; c=relaxed/simple; bh=j89Mk7CLXpGWMIuDYA/C4WFABh735Lw+vrLWVJ0giZA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CBcbjaosJhB9+dmSeIwc7Uv2RqyaANOWlnre3D/R3UahLAKWKCM3aIe+Pb3cDzMBYidYttGCdiYfFFkU0HU9LcKxqUarNAP1etca74yUZ1bA7HJ4WiB7K2kEyjGcN73QxQQbgd7wJj/SJpD9e0Jgk0aWYrQw5eIFgQQQDMw9bns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=qzZ2u1s+; arc=none smtp.client-ip=91.218.175.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="qzZ2u1s+" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4F/VhVHf5F041lHROkv/5STe3v2JEXbKH06Lbt6s5EQ=; b=qzZ2u1s+IV+1Wo3NUZsvhUqhL3h42+WH4TcA0GIg38JMIcvjVHPDN9RNUSvpqGZXRyEx2t 5MbHo4FON1LEoRQCoWvOiCW6m8vdyNI72Trj/gEIRrBMbVkI9DADVAGF/awqLiuHUp7d+w dLI5u3STCvwsckclF/gzb8WSwqTgmtU= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 5/7] net: axienet: Use device variable in probe Date: Tue, 5 Aug 2025 11:34:54 -0400 Message-Id: <20250805153456.1313661-6-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" There are a lot of references to pdev->dev that we can shorten by using a dev variable. Signed-off-by: Sean Anderson Reviewed-by: Andrew Lunn --- (no changes since v3) Changes in v3: - New .../net/ethernet/xilinx/xilinx_axienet_main.c | 83 +++++++++---------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_main.c index 1f277e5e4a62..28927c7c6c41 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -2764,6 +2764,7 @@ static void axienet_disable_misc(void *clocks) static int axienet_probe(struct platform_device *pdev) { int ret; + struct device *dev =3D &pdev->dev; struct device_node *np; struct axienet_local *lp; struct net_device *ndev; @@ -2772,13 +2773,13 @@ static int axienet_probe(struct platform_device *pd= ev) int addr_width =3D 32; u32 value; =20 - ndev =3D devm_alloc_etherdev(&pdev->dev, sizeof(*lp)); + ndev =3D devm_alloc_etherdev(dev, sizeof(*lp)); if (!ndev) return -ENOMEM; =20 platform_set_drvdata(pdev, ndev); =20 - SET_NETDEV_DEV(ndev, &pdev->dev); + SET_NETDEV_DEV(ndev, dev); ndev->features =3D NETIF_F_SG; ndev->ethtool_ops =3D &axienet_ethtool_ops; =20 @@ -2788,7 +2789,7 @@ static int axienet_probe(struct platform_device *pdev) =20 lp =3D netdev_priv(ndev); lp->ndev =3D ndev; - lp->dev =3D &pdev->dev; + lp->dev =3D dev; lp->options =3D XAE_OPTION_DEFAULTS; lp->rx_bd_num =3D RX_BD_NUM_DEFAULT; lp->tx_bd_num =3D TX_BD_NUM_DEFAULT; @@ -2800,33 +2801,32 @@ static int axienet_probe(struct platform_device *pd= ev) seqcount_mutex_init(&lp->hw_stats_seqcount, &lp->stats_lock); INIT_DEFERRABLE_WORK(&lp->stats_work, axienet_refresh_stats); =20 - lp->axi_clk =3D devm_clk_get_optional_enabled(&pdev->dev, - "s_axi_lite_clk"); + lp->axi_clk =3D 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 =3D devm_clk_get_optional_enabled(&pdev->dev, NULL); + lp->axi_clk =3D devm_clk_get_optional_enabled(dev, NULL); } if (IS_ERR(lp->axi_clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(lp->axi_clk), + return dev_err_probe(dev, PTR_ERR(lp->axi_clk), "could not get AXI clock\n"); =20 lp->misc_clks[0].id =3D "axis_clk"; lp->misc_clks[1].id =3D "ref_clk"; lp->misc_clks[2].id =3D "mgt_clk"; =20 - ret =3D devm_clk_bulk_get_optional(&pdev->dev, XAE_NUM_MISC_CLOCKS, lp->m= isc_clks); + ret =3D devm_clk_bulk_get_optional(dev, XAE_NUM_MISC_CLOCKS, lp->misc_clk= s); if (ret) - return dev_err_probe(&pdev->dev, ret, + return dev_err_probe(dev, ret, "could not get misc. clocks\n"); =20 ret =3D clk_bulk_prepare_enable(XAE_NUM_MISC_CLOCKS, lp->misc_clks); if (ret) - return dev_err_probe(&pdev->dev, ret, + return dev_err_probe(dev, ret, "could not enable misc. clocks\n"); =20 - ret =3D devm_add_action_or_reset(&pdev->dev, axienet_disable_misc, + ret =3D devm_add_action_or_reset(dev, axienet_disable_misc, lp->misc_clks); if (ret) return ret; @@ -2843,7 +2843,7 @@ static int axienet_probe(struct platform_device *pdev) if (axienet_ior(lp, XAE_ABILITY_OFFSET) & XAE_ABILITY_STATS) lp->features |=3D XAE_FEATURE_STATS; =20 - ret =3D of_property_read_u32(pdev->dev.of_node, "xlnx,txcsum", &value); + ret =3D of_property_read_u32(dev->of_node, "xlnx,txcsum", &value); if (!ret) { switch (value) { case 1: @@ -2858,7 +2858,7 @@ static int axienet_probe(struct platform_device *pdev) break; } } - ret =3D of_property_read_u32(pdev->dev.of_node, "xlnx,rxcsum", &value); + ret =3D of_property_read_u32(dev->of_node, "xlnx,rxcsum", &value); if (!ret) { switch (value) { case 1: @@ -2877,13 +2877,13 @@ static int axienet_probe(struct platform_device *pd= ev) * Here we check for memory allocated for Rx/Tx in the hardware from * the device-tree and accordingly set flags. */ - of_property_read_u32(pdev->dev.of_node, "xlnx,rxmem", &lp->rxmem); + of_property_read_u32(dev->of_node, "xlnx,rxmem", &lp->rxmem); =20 - lp->switch_x_sgmii =3D of_property_read_bool(pdev->dev.of_node, + lp->switch_x_sgmii =3D of_property_read_bool(dev->of_node, "xlnx,switch-x-sgmii"); =20 /* Start with the proprietary, and broken phy_type */ - ret =3D of_property_read_u32(pdev->dev.of_node, "xlnx,phy-type", &value); + ret =3D of_property_read_u32(dev->of_node, "xlnx,phy-type", &value); if (!ret) { netdev_warn(ndev, "Please upgrade your device tree binary blob to use ph= y-mode"); switch (value) { @@ -2906,32 +2906,31 @@ static int axienet_probe(struct platform_device *pd= ev) return -EINVAL; } } else { - ret =3D of_get_phy_mode(pdev->dev.of_node, &lp->phy_mode); + ret =3D of_get_phy_mode(dev->of_node, &lp->phy_mode); if (ret) return ret; } if (lp->switch_x_sgmii && lp->phy_mode !=3D PHY_INTERFACE_MODE_SGMII && lp->phy_mode !=3D PHY_INTERFACE_MODE_1000BASEX) { - dev_err(&pdev->dev, "xlnx,switch-x-sgmii only supported with SGMII or 10= 00BaseX\n"); + dev_err(dev, "xlnx,switch-x-sgmii only supported with SGMII or 1000BaseX= \n"); return -EINVAL; } =20 - if (!of_property_present(pdev->dev.of_node, "dmas")) { + if (!of_property_present(dev->of_node, "dmas")) { /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ - np =3D of_parse_phandle(pdev->dev.of_node, "axistream-connected", 0); + np =3D of_parse_phandle(dev->of_node, "axistream-connected", 0); =20 if (np) { struct resource dmares; =20 ret =3D of_address_to_resource(np, 0, &dmares); if (ret) { - dev_err(&pdev->dev, + dev_err(dev, "unable to get DMA resource\n"); of_node_put(np); return ret; } - lp->dma_regs =3D devm_ioremap_resource(&pdev->dev, - &dmares); + lp->dma_regs =3D devm_ioremap_resource(dev, &dmares); lp->rx_irq =3D irq_of_parse_and_map(np, 1); lp->tx_irq =3D irq_of_parse_and_map(np, 0); of_node_put(np); @@ -2944,11 +2943,11 @@ static int axienet_probe(struct platform_device *pd= ev) lp->eth_irq =3D platform_get_irq_optional(pdev, 2); } if (IS_ERR(lp->dma_regs)) { - dev_err(&pdev->dev, "could not map DMA regs\n"); + dev_err(dev, "could not map DMA regs\n"); return PTR_ERR(lp->dma_regs); } if (lp->rx_irq <=3D 0 || lp->tx_irq <=3D 0) { - dev_err(&pdev->dev, "could not determine irqs\n"); + dev_err(dev, "could not determine irqs\n"); return -ENOMEM; } =20 @@ -2974,20 +2973,20 @@ static int axienet_probe(struct platform_device *pd= ev) if (ioread32(desc) > 0) { lp->features |=3D XAE_FEATURE_DMA_64BIT; addr_width =3D 64; - dev_info(&pdev->dev, + dev_info(dev, "autodetected 64-bit DMA range\n"); } iowrite32(0x0, desc); } } if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) { - dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-b= it architecture\n"); + dev_err(dev, "64-bit addressable DMA is not compatible with 32-bit arch= itecture\n"); return -EINVAL; } =20 - ret =3D dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width)); + ret =3D dma_set_mask_and_coherent(dev, DMA_BIT_MASK(addr_width)); if (ret) { - dev_err(&pdev->dev, "No suitable DMA available\n"); + dev_err(dev, "No suitable DMA available\n"); return ret; } netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll); @@ -3000,16 +2999,16 @@ static int axienet_probe(struct platform_device *pd= ev) if (lp->eth_irq < 0 && lp->eth_irq !=3D -ENXIO) { return lp->eth_irq; } - tx_chan =3D dma_request_chan(lp->dev, "tx_chan0"); + tx_chan =3D dma_request_chan(dev, "tx_chan0"); if (IS_ERR(tx_chan)) - return dev_err_probe(lp->dev, PTR_ERR(tx_chan), + return dev_err_probe(dev, PTR_ERR(tx_chan), "No Ethernet DMA (TX) channel found\n"); =20 cfg.reset =3D 1; /* As name says VDMA but it has support for DMA channel reset */ ret =3D xilinx_vdma_channel_set_config(tx_chan, &cfg); if (ret < 0) { - dev_err(&pdev->dev, "Reset channel failed\n"); + dev_err(dev, "Reset channel failed\n"); dma_release_channel(tx_chan); return ret; } @@ -3024,14 +3023,14 @@ static int axienet_probe(struct platform_device *pd= ev) ndev->netdev_ops =3D &axienet_netdev_ops; /* Check for Ethernet core IRQ (optional) */ if (lp->eth_irq <=3D 0) - dev_info(&pdev->dev, "Ethernet core IRQ not defined\n"); + dev_info(dev, "Ethernet core IRQ not defined\n"); =20 /* Retrieve the MAC address */ - ret =3D of_get_mac_address(pdev->dev.of_node, mac_addr); + ret =3D of_get_mac_address(dev->of_node, mac_addr); if (!ret) { axienet_set_mac_address(ndev, mac_addr); } else { - dev_warn(&pdev->dev, "could not find MAC address property: %d\n", + dev_warn(dev, "could not find MAC address property: %d\n", ret); axienet_set_mac_address(ndev, NULL); } @@ -3048,21 +3047,21 @@ static int axienet_probe(struct platform_device *pd= ev) =20 ret =3D axienet_mdio_setup(lp); if (ret) - dev_warn(&pdev->dev, + dev_warn(dev, "error registering MDIO bus: %d\n", ret); =20 if (lp->phy_mode =3D=3D PHY_INTERFACE_MODE_SGMII || lp->phy_mode =3D=3D PHY_INTERFACE_MODE_1000BASEX) { - np =3D of_parse_phandle(pdev->dev.of_node, "pcs-handle", 0); + np =3D of_parse_phandle(dev->of_node, "pcs-handle", 0); if (!np) { /* Deprecated: Always use "pcs-handle" for pcs_phy. * Falling back to "phy-handle" here is only for * backward compatibility with old device trees. */ - np =3D of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); + np =3D of_parse_phandle(dev->of_node, "phy-handle", 0); } if (!np) { - dev_err(&pdev->dev, "pcs-handle (preferred) or phy-handle required for = 1000BaseX/SGMII\n"); + dev_err(dev, "pcs-handle (preferred) or phy-handle required for 1000Bas= eX/SGMII\n"); ret =3D -EINVAL; goto cleanup_mdio; } @@ -3091,18 +3090,18 @@ static int axienet_probe(struct platform_device *pd= ev) lp->phylink_config.supported_interfaces); } =20 - lp->phylink =3D phylink_create(&lp->phylink_config, pdev->dev.fwnode, + lp->phylink =3D phylink_create(&lp->phylink_config, dev->fwnode, lp->phy_mode, &axienet_phylink_ops); if (IS_ERR(lp->phylink)) { ret =3D PTR_ERR(lp->phylink); - dev_err(&pdev->dev, "phylink_create error (%i)\n", ret); + dev_err(dev, "phylink_create error (%i)\n", ret); goto cleanup_mdio; } =20 ret =3D register_netdev(lp->ndev); if (ret) { - dev_err(lp->dev, "register_netdev() error (%i)\n", ret); + dev_err(dev, "register_netdev() error (%i)\n", ret); goto cleanup_phylink; } =20 --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83BB627CCCD for ; Tue, 5 Aug 2025 15:35:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408125; cv=none; b=Kens4GYOY5gOHFJmFGnXo9tEXsQeNFJU8S/WYq0KVq2ijRTLc3/8MlnO4zK4qnRHGFpv/pJc1mp8ArtqqV+Tvf8LswVLn+EHGycE2Ta2OTizWwDWgQhLk9z+tgbT2DZwTVCS6fLejYEqu8mF6cEvifzq8dN7uUmTFOnJCqS/9eU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408125; c=relaxed/simple; bh=rHKpjajgpDGTgG+3OF/YtVmm8fzh8QZi+8NsTsdD4GM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KDuNIzJ2ubD39Bs2oTES2PB042TrEvVMAuuYhi3JxppI7SvkbLumi6hyFF4kUhoI1msypWYhWdwF4pgJnxQ2iFVI/oHSGOiXvW1zhPgpj/unlrI2zj0V5f/23UdrWvZxbCueT1iZpkDYCKto6ZcvcP2kt4R3OTEgOkrhodVHP/U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=J18TIwth; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="J18TIwth" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=M7RpDsALexoT6DD56ZX3x5H76tqdICKHDob8Z0ppPBA=; b=J18TIwthw0muA5Tm7KlBMymbpiq4+G9ZepfTg6MtVQoWIN4ClFDjF35LljZ2jbzN2crIhw n08MfYc/PzEowphhH7wveYsICOCseiyNTLGn8JGTmrRgxc1xVRjDJFQa2tL8XuMqgNE1R9 gF1uAeNHqS4O3NYgH7KqlHblWDnUdvU= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 6/7] net: axienet: Rearrange lifetime functions Date: Tue, 5 Aug 2025 11:34:55 -0400 Message-Id: <20250805153456.1313661-7-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Rearrange the lifetime functions (probe, remove, etc.) in preparation for the next commit. No functional change intended. Signed-off-by: Sean Anderson --- (no changes since v3) 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 | 43 +++--- 3 files changed, 126 insertions(+), 93 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/eth= ernet/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; }; =20 +/** + * 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 a= ccess + * @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; =20 struct phylink *phylink; struct phylink_config phylink_config; @@ -558,13 +582,11 @@ struct axienet_local { =20 bool switch_x_sgmii; =20 - struct clk *axi_clk; struct clk_bulk_data misc_clks[XAE_NUM_MISC_CLOCKS]; =20 struct mii_bus *mii_bus; u8 mii_clk_div; =20 - resource_size_t regs_start; void __iomem *regs; void __iomem *dma_regs; =20 @@ -654,21 +676,14 @@ static inline u32 axienet_ior(struct axienet_local *l= p, off_t offset) return ioread32(lp->regs + offset); } =20 -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); } =20 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); } =20 /** @@ -738,7 +753,7 @@ static inline void axienet_dma_out_addr(struct axienet_= local *lp, off_t reg, #endif /* CONFIG_64BIT */ =20 /* 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); =20 #endif /* XILINX_AXI_ENET_H */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/ne= t/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 *n= dev) =20 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 */ } =20 @@ -2749,29 +2749,17 @@ static void axienet_disable_misc(void *clocks) clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, clocks); } =20 -/** - * 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 Eth= ernet - * 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 =3D cp->pdev; struct device *dev =3D &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 =3D 32; u32 value; + int ret; =20 ndev =3D devm_alloc_etherdev(dev, sizeof(*lp)); if (!ndev) @@ -2790,6 +2778,8 @@ static int axienet_probe(struct platform_device *pdev) lp =3D netdev_priv(ndev); lp->ndev =3D ndev; lp->dev =3D dev; + lp->cp =3D cp; + lp->regs =3D cp->regs; lp->options =3D XAE_OPTION_DEFAULTS; lp->rx_bd_num =3D RX_BD_NUM_DEFAULT; lp->tx_bd_num =3D TX_BD_NUM_DEFAULT; @@ -2801,17 +2791,6 @@ static int axienet_probe(struct platform_device *pde= v) seqcount_mutex_init(&lp->hw_stats_seqcount, &lp->stats_lock); INIT_DEFERRABLE_WORK(&lp->stats_work, axienet_refresh_stats); =20 - lp->axi_clk =3D 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 =3D 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 =3D "axis_clk"; lp->misc_clks[1].id =3D "ref_clk"; lp->misc_clks[2].id =3D "mgt_clk"; @@ -2831,12 +2810,6 @@ static int axienet_probe(struct platform_device *pde= v) if (ret) return ret; =20 - /* Map device registers */ - lp->regs =3D devm_platform_get_and_ioremap_resource(pdev, 0, ðres); - if (IS_ERR(lp->regs)) - return PTR_ERR(lp->regs); - lp->regs_start =3D ethres->start; - /* Setup checksum offload, but default to off if not specified */ lp->features =3D 0; =20 @@ -3045,11 +3018,6 @@ static int axienet_probe(struct platform_device *pde= v) lp->tx_dma_cr =3D axienet_calc_cr(lp, XAXIDMA_DFT_TX_THRESHOLD, XAXIDMA_DFT_TX_USEC); =20 - ret =3D axienet_mdio_setup(lp); - if (ret) - dev_warn(dev, - "error registering MDIO bus: %d\n", ret); - if (lp->phy_mode =3D=3D PHY_INTERFACE_MODE_SGMII || lp->phy_mode =3D=3D PHY_INTERFACE_MODE_1000BASEX) { np =3D of_parse_phandle(dev->of_node, "pcs-handle", 0); @@ -3061,17 +3029,14 @@ static int axienet_probe(struct platform_device *pd= ev) np =3D of_parse_phandle(dev->of_node, "phy-handle", 0); } if (!np) { - dev_err(dev, "pcs-handle (preferred) or phy-handle required for 1000Bas= eX/SGMII\n"); - ret =3D -EINVAL; - goto cleanup_mdio; + dev_err(dev, + "pcs-handle (preferred) or phy-handle required for 1000BaseX/SGMII\n"); + return -EINVAL; } lp->pcs_phy =3D of_mdio_find_device(np); - if (!lp->pcs_phy) { - ret =3D -EPROBE_DEFER; - of_node_put(np); - goto cleanup_mdio; - } of_node_put(np); + if (!lp->pcs_phy) + return -EPROBE_DEFER; lp->pcs.ops =3D &axienet_pcs_ops; lp->pcs.poll =3D true; } @@ -3096,7 +3061,7 @@ static int axienet_probe(struct platform_device *pdev) if (IS_ERR(lp->phylink)) { ret =3D PTR_ERR(lp->phylink); dev_err(dev, "phylink_create error (%i)\n", ret); - goto cleanup_mdio; + goto cleanup_pcs; } =20 ret =3D register_netdev(lp->ndev); @@ -3109,32 +3074,24 @@ static int axienet_probe(struct platform_device *pd= ev) =20 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; } =20 -static void axienet_remove(struct platform_device *pdev) +static void axienet_mac_remove(struct platform_device *pdev) { struct net_device *ndev =3D platform_get_drvdata(pdev); struct axienet_local *lp =3D netdev_priv(ndev); =20 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); } =20 -static void axienet_shutdown(struct platform_device *pdev) +static void axienet_mac_shutdown(struct platform_device *pdev) { struct net_device *ndev =3D platform_get_drvdata(pdev); =20 @@ -3182,10 +3139,64 @@ static int axienet_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(axienet_pm_ops, axienet_suspend, axienet_resume); =20 +static int axienet_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct axienet_common *cp; + struct resource *ethres; + int ret; + + cp =3D devm_kzalloc(dev, sizeof(*cp), GFP_KERNEL); + if (!cp) + return -ENOMEM; + + cp->pdev =3D pdev; + mutex_init(&cp->reset_lock); + + cp->axi_clk =3D 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 =3D 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 =3D devm_platform_get_and_ioremap_resource(pdev, 0, ðres); + if (IS_ERR(cp->regs)) + return PTR_ERR(cp->regs); + cp->regs_start =3D ethres->start; + + ret =3D axienet_mdio_setup(cp); + if (ret) + dev_warn(dev, "error registering MDIO bus: %d\n", ret); + + ret =3D 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 =3D platform_get_drvdata(pdev); + struct axienet_local *lp =3D netdev_priv(ndev); + + axienet_mac_remove(pdev); + if (lp->mii_bus) + axienet_mdio_teardown(lp->cp); +} + static struct platform_driver axienet_driver =3D { .probe =3D axienet_probe, .remove =3D axienet_remove, - .shutdown =3D axienet_shutdown, + .shutdown =3D axienet_mac_shutdown, .driver =3D { .name =3D "xilinx_axienet", .pm =3D &axienet_pm_ops, diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_mdio.c index 1903a1d50b05..4d50b3d0f7ee 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include =20 @@ -22,13 +23,13 @@ =20 /** * 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; =20 @@ -39,11 +40,11 @@ static int axienet_mdio_wait_until_ready(struct axienet= _local *lp) =20 /** * 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_loca= l *lp) =20 /** * 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; =20 @@ -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 =3D bus->priv; + struct axienet_common *lp =3D bus->priv; =20 + guard(mutex)(&lp->reset_lock); axienet_mdio_mdc_enable(lp); =20 ret =3D 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 =3D bus->priv; + struct axienet_common *lp =3D bus->priv; int ret; u32 mcr; =20 dev_dbg(&bus->dev, "%s(phy_id=3D%i, reg=3D%x, val=3D%x)\n", __func__, phy_id, reg, val); =20 + guard(mutex)(&lp->reset_lock); axienet_mdio_mdc_enable(lp); =20 ret =3D axienet_mdio_wait_until_ready(lp); @@ -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 =3D bus->priv; + struct axienet_common *lp =3D bus->priv; u32 mdio_freq =3D DEFAULT_MDIO_FREQ; u32 host_clock; u32 clk_div; @@ -187,7 +190,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, str= uct device_node *np) /* Legacy fallback: detect CPU clock frequency and use as AXI * bus clock frequency. This only works on certain platforms. */ - np1 =3D of_find_node_by_name(NULL, "lpu"); + np1 =3D 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, str= uct device_node *np) "Setting MDIO clock divisor to %u/%u Hz host clock.\n", lp->mii_clk_div, host_clock); =20 + guard(mutex)(&lp->reset_lock); axienet_mdio_mdc_enable(lp); =20 ret =3D axienet_mdio_wait_until_ready(lp); @@ -269,7 +273,7 @@ static int axienet_mdio_enable(struct mii_bus *bus, str= uct device_node *np) =20 /** * 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, str= uct 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 =3D "Xilinx Axi Ethernet MDIO"; bus->read =3D axienet_mdio_read; bus->write =3D axienet_mdio_write; - bus->parent =3D lp->dev; + bus->parent =3D &lp->pdev->dev; lp->mii_bus =3D bus; =20 - mdio_node =3D of_get_child_by_name(lp->dev->of_node, "mdio"); - ret =3D axienet_mdio_enable(bus, mdio_node); + mdio_node =3D of_get_child_by_name(lp->pdev->dev.of_node, "mdio"); + scoped_guard(mutex, &lp->reset_lock) + ret =3D axienet_mdio_enable(bus, mdio_node); if (ret < 0) goto unregister; =20 ret =3D 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 =3D NULL; } @@ -315,11 +322,11 @@ int axienet_mdio_setup(struct axienet_local *lp) =20 /** * 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); --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Oct 5 10:51:31 2025 Received: from out-181.mta0.migadu.com (out-181.mta0.migadu.com [91.218.175.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32B9227E1B1 for ; Tue, 5 Aug 2025 15:35:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408127; cv=none; b=JXi3Oe2gVW9l7QbVwJ4BMXA1Z7Z1eXhdfWsMmOwLtzlpCRdszIHSAFzidjqBsLmkjPMLp1REU5FM3II4OlVfHO10mv0JCqh6fY07lUrxBB3XLnqiPKBwHNwTY3ap0uSPXiQSYAXkttt5qGgjZGm80RiJD7rYDfIdgD4SLi6Dfd8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754408127; c=relaxed/simple; bh=F/8m0O3VviudAVc3E7rZ4tXF4LTmstmfN0/YM31+WEQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QttCC0M9/hC8LY8DCVMBg3s0gethVxdjkhGrNzTZhHvd3Ke9470e1gEUMGaz4nZ2Y8HZ9fD+t6DYtj6HO58/r29enNFupTP/ZS/ZACt7DpO3QGwKZypvXcuPtYi7vQvrvmnbrRsDVSmCq65LOgOKpOAR2tTD2rrOw8gYDbMkcnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=EgqUDthf; arc=none smtp.client-ip=91.218.175.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="EgqUDthf" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1754408123; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IkavQd3hgx1pQSnll1yq/i6k0i16E+opJNVxmuRLHYQ=; b=EgqUDthf2hRoexd05e88HeyQsb585C8lIu6huqaETHvoZaIBS1D4LHzrOs02dwhVfygIgd DxOGngN0b7X3yYEjBUWPt9wI9u0LxFRXI7635H5z5BiEcUNPHSwyErv3otNuqQ7fO7X/8J VhVdDIUWKFE7n0ia8u1jsF1riq/n4ZA= From: Sean Anderson To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Michal Simek , Leon Romanovsky , Sean Anderson Subject: [PATCH net-next v4 7/7] net: axienet: Split into MAC and MDIO drivers Date: Tue, 5 Aug 2025 11:34:56 -0400 Message-Id: <20250805153456.1313661-8-sean.anderson@linux.dev> In-Reply-To: <20250805153456.1313661-1-sean.anderson@linux.dev> References: <20250805153456.1313661-1-sean.anderson@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Returning EPROBE_DEFER after probing a bus may result in an infinite probe loop if the EPROBE_DEFER error is never resolved. There are two mutually-exclusive scenarios (that can both occur in the same system). First, the PCS can be attached to our own MDIO bus: MAC | +->MDIO | +->PCS +->PHY (etc) In this scenario, we have to probe the MDIO bus before we can look up the PCS, since otherwise the PCS will always be missing when we look for it. But if we do things in the right order then we can't get EPROBE_DEFER, and so there's no risk of a probe loop. Second, the PCS can be attached to some other MDIO bus: MAC MDIO | | +->MDIO +->PCS | +->PHY (etc) In this scenario, the MDIO bus might not be present for whatever reason (module not loaded, error in probe, etc.) and we have the possibility of an EPROBE_DEFER error. If that happens, we will end up in a probe loop because the PHY on our own MDIO bus incremented deferred_trigger_count when it probed successfully: deferred_probe_work_func() driver_probe_device(MAC) axienet_probe(MAC) mdiobus_register(MDIO) device_add(PHY) (probe successful) driver_bound(PHY) driver_deferred_probe_trigger() return -EPROBE_DEFER driver_deferred_probe_add(MAC) // deferred_trigger_count changed, so... driver_deferred_probe_trigger() As I see it, this problem could be solved in the following four ways: - Modify the driver core to detect and mitigate this sort of scenario (NACKed by Greg). - Split the driver into MAC and MDIO parts (this commit). - Modify phylink to allow connecting a PCS after phylink_create but before phylink_start. This is tricky because the PCS can affect the supported phy interfaces, and phy interfaces are validated in phylink_create. - Defer phylink_create to ndo_open. This means that all the netdev/ethtool ops that use phylink now need to check ip the netdev is open and fall back to some other implementation. I don't think we can just return -EINVAL or whatever because using ethtool on a down device has historically worked. I am wary of breaking userspace because some tool assumes it can get_ksettings while the netdev is down. Aside from the first option, the second one (this commit) has the best UX. With the latter two, you could have a netdev that never comes up and the user may not have very good insight as to why. For example, it may not be obvious that the user should try to bring the netdev up again after the PCS is probed. By waiting to create the netdev until after we successfully probe the PCS we show up in devices_deferred and the netdev can be brought up as usual. Per the second bullet point above, split the MAC and MDIO functionality into separate auxiliary devices. If the MAC fails with EPROBE_DEFER, then the MDIO bus will remain bound, preventing a probe loop. Fixes: 1a02556086fc ("net: axienet: Properly handle PCS/PMA PHY for 1000Bas= eX mode") Signed-off-by: Sean Anderson --- Changes in v4: - Fix platform_driver_register in exit Changes in v3: - Rework to use a separate axienet_common structure, as netdevs cannot be reused once registered. - Use ida_alloc for aux id Changes in v2: - Fix building as a module - Expand commit message with much more info on the problem and possible solutions drivers/net/ethernet/xilinx/Kconfig | 1 + drivers/net/ethernet/xilinx/xilinx_axienet.h | 10 +- .../net/ethernet/xilinx/xilinx_axienet_main.c | 168 ++++++++++++++---- .../net/ethernet/xilinx/xilinx_axienet_mdio.c | 59 +++--- 4 files changed, 169 insertions(+), 69 deletions(-) diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xil= inx/Kconfig index 7502214cc7d5..3b940d2d3115 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -27,6 +27,7 @@ config XILINX_AXI_EMAC tristate "Xilinx 10/100/1000 AXI Ethernet support" depends on HAS_IOMEM depends on XILINX_DMA + select AUXILIARY_BUS select PHYLINK select DIMLIB help diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/eth= ernet/xilinx/xilinx_axienet.h index d7215dd92ce9..69665c7f264a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -470,6 +470,7 @@ struct skbuf_dma_descriptor { /** * struct axienet_common - axienet private common data * @pdev: Pointer to common platform device structure + * @mac: Pointer to MAC (netdev parent) device structure * @axi_clk: AXI4-Lite bus clock * @reset_lock: Lock held while resetting the device to prevent register a= ccess * @mii_bus: Pointer to MII bus structure @@ -479,11 +480,12 @@ struct skbuf_dma_descriptor { */ struct axienet_common { struct platform_device *pdev; + struct auxiliary_device mac; =20 struct clk *axi_clk; =20 struct mutex reset_lock; - struct mii_bus *mii_bus; + struct auxiliary_device mii_bus; u8 mii_clk_div; =20 void __iomem *regs; @@ -493,7 +495,7 @@ struct axienet_common { /** * struct axienet_local - axienet private per device data * @ndev: Pointer for net_device to which it will be attached. - * @dev: Pointer to device structure + * @dev: Pointer to parent device structure for DMA access * @phylink: Pointer to phylink instance * @phylink_config: phylink configuration settings * @pcs_phy: Reference to PCS/PMA PHY if used @@ -752,8 +754,6 @@ static inline void axienet_dma_out_addr(struct axienet_= local *lp, off_t reg, =20 #endif /* CONFIG_64BIT */ =20 -/* Function prototypes visible in xilinx_axienet_mdio.c for other files */ -int axienet_mdio_setup(struct axienet_common *lp); -void axienet_mdio_teardown(struct axienet_common *lp); +extern struct auxiliary_driver xilinx_axienet_mdio; =20 #endif /* XILINX_AXI_ENET_H */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_main.c index f235ef15187c..97b3956a831c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -22,6 +22,7 @@ * - Add support for extended VLAN support. */ =20 +#include #include #include #include @@ -1907,8 +1908,11 @@ static const struct net_device_ops axienet_netdev_dm= aengine_ops =3D { static void axienet_ethtools_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *ed) { + struct axienet_local *lp =3D netdev_priv(ndev); + strscpy(ed->driver, DRIVER_NAME, sizeof(ed->driver)); strscpy(ed->version, DRIVER_VERSION, sizeof(ed->version)); + strscpy(ed->bus_info, dev_name(lp->dev), sizeof(ed->bus_info)); } =20 /** @@ -2749,10 +2753,12 @@ static void axienet_disable_misc(void *clocks) clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, clocks); } =20 -static int axienet_mac_probe(struct axienet_common *cp) +static int axienet_mac_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) { + struct axienet_common *cp =3D auxdev->dev.platform_data; struct platform_device *pdev =3D cp->pdev; - struct device *dev =3D &pdev->dev; + struct device *dev =3D &auxdev->dev; struct axienet_local *lp; struct net_device *ndev; struct device_node *np; @@ -2765,7 +2771,7 @@ static int axienet_mac_probe(struct axienet_common *c= p) if (!ndev) return -ENOMEM; =20 - platform_set_drvdata(pdev, ndev); + auxiliary_set_drvdata(auxdev, ndev); =20 SET_NETDEV_DEV(ndev, dev); ndev->features =3D NETIF_F_SG; @@ -2777,7 +2783,7 @@ static int axienet_mac_probe(struct axienet_common *c= p) =20 lp =3D netdev_priv(ndev); lp->ndev =3D ndev; - lp->dev =3D dev; + lp->dev =3D &pdev->dev; lp->cp =3D cp; lp->regs =3D cp->regs; lp->options =3D XAE_OPTION_DEFAULTS; @@ -2909,8 +2915,11 @@ static int axienet_mac_probe(struct axienet_common *= cp) of_node_put(np); lp->eth_irq =3D platform_get_irq_optional(pdev, 0); } else { + struct resource *dmares; + /* Check for these resources directly on the Ethernet node. */ - lp->dma_regs =3D devm_platform_get_and_ioremap_resource(pdev, 1, NULL); + dmares =3D platform_get_resource(pdev, IORESOURCE_MEM, 1); + lp->dma_regs =3D devm_ioremap_resource(dev, dmares); lp->rx_irq =3D platform_get_irq(pdev, 1); lp->tx_irq =3D platform_get_irq(pdev, 0); lp->eth_irq =3D platform_get_irq_optional(pdev, 2); @@ -2925,7 +2934,9 @@ static int axienet_mac_probe(struct axienet_common *c= p) } =20 /* Reset core now that clocks are enabled, prior to accessing MDIO */ + axienet_lock_mii(lp); ret =3D __axienet_device_reset(lp); + axienet_unlock_mii(lp); if (ret) return ret; =20 @@ -2957,7 +2968,8 @@ static int axienet_mac_probe(struct axienet_common *c= p) return -EINVAL; } =20 - ret =3D dma_set_mask_and_coherent(dev, DMA_BIT_MASK(addr_width)); + ret =3D dma_set_mask_and_coherent(lp->dev, + DMA_BIT_MASK(addr_width)); if (ret) { dev_err(dev, "No suitable DMA available\n"); return ret; @@ -3055,7 +3067,7 @@ static int axienet_mac_probe(struct axienet_common *c= p) lp->phylink_config.supported_interfaces); } =20 - lp->phylink =3D phylink_create(&lp->phylink_config, dev->fwnode, + lp->phylink =3D phylink_create(&lp->phylink_config, dev_fwnode(dev), lp->phy_mode, &axienet_phylink_ops); if (IS_ERR(lp->phylink)) { @@ -3080,9 +3092,9 @@ static int axienet_mac_probe(struct axienet_common *c= p) return ret; } =20 -static void axienet_mac_remove(struct platform_device *pdev) +static void axienet_mac_remove(struct auxiliary_device *auxdev) { - struct net_device *ndev =3D platform_get_drvdata(pdev); + struct net_device *ndev =3D auxiliary_get_drvdata(auxdev); struct axienet_local *lp =3D netdev_priv(ndev); =20 unregister_netdev(ndev); @@ -3091,9 +3103,9 @@ static void axienet_mac_remove(struct platform_device= *pdev) put_device(&lp->pcs_phy->dev); } =20 -static void axienet_mac_shutdown(struct platform_device *pdev) +static void axienet_mac_shutdown(struct auxiliary_device *auxdev) { - struct net_device *ndev =3D platform_get_drvdata(pdev); + struct net_device *ndev =3D auxiliary_get_drvdata(auxdev); =20 rtnl_lock(); netif_device_detach(ndev); @@ -3139,12 +3151,78 @@ static int axienet_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(axienet_pm_ops, axienet_suspend, axienet_resume); =20 +static const struct auxiliary_device_id xilinx_axienet_mac_id_table[] =3D { + { .name =3D KBUILD_MODNAME ".mac", }, + { }, +}; +MODULE_DEVICE_TABLE(auxiliary, xilinx_axienet_mac_id_table); + +static struct auxiliary_driver xilinx_axienet_mac =3D { + .name =3D "mac", + .id_table =3D xilinx_axienet_mac_id_table, + .probe =3D axienet_mac_probe, + .remove =3D axienet_mac_remove, + .shutdown =3D axienet_mac_shutdown, + .driver =3D { + .pm =3D &axienet_pm_ops, + }, +}; + +static DEFINE_IDA(axienet_id); + +static void axienet_id_free(void *data) +{ + int id =3D (intptr_t)data; + + ida_free(&axienet_id, id); +} + +static void auxenet_aux_release(struct device *dev) { } + +static void axienet_aux_destroy(void *data) +{ + struct auxiliary_device *auxdev =3D data; + + auxiliary_device_delete(auxdev); + auxiliary_device_uninit(auxdev); + fwnode_handle_put(auxdev->dev.fwnode); +} + +static int axienet_aux_create(struct axienet_common *cp, + struct auxiliary_device *auxdev, const char *name, + int id, struct fwnode_handle *fwnode) +{ + struct device *dev =3D &cp->pdev->dev; + int ret; + + auxdev->name =3D name; + auxdev->id =3D id; + auxdev->dev.parent =3D dev; + auxdev->dev.platform_data =3D cp; + auxdev->dev.release =3D auxenet_aux_release; + device_set_node(&auxdev->dev, fwnode); + ret =3D auxiliary_device_init(auxdev); + if (ret) { + fwnode_handle_put(fwnode); + return ret; + } + + ret =3D auxiliary_device_add(auxdev); + if (ret) { + fwnode_handle_put(fwnode); + auxiliary_device_uninit(auxdev); + return ret; + } + + return devm_add_action_or_reset(dev, axienet_aux_destroy, auxdev); +} + static int axienet_probe(struct platform_device *pdev) { struct device *dev =3D &pdev->dev; struct axienet_common *cp; struct resource *ethres; - int ret; + int ret, id; =20 cp =3D devm_kzalloc(dev, sizeof(*cp), GFP_KERNEL); if (!cp) @@ -3170,33 +3248,31 @@ static int axienet_probe(struct platform_device *pd= ev) return PTR_ERR(cp->regs); cp->regs_start =3D ethres->start; =20 - ret =3D axienet_mdio_setup(cp); - if (ret) - dev_warn(dev, "error registering MDIO bus: %d\n", ret); + id =3D ida_alloc(&axienet_id, GFP_KERNEL); + if (id < 0) + return dev_err_probe(dev, id, "could not allocate id\n"); =20 - ret =3D axienet_mac_probe(cp); - if (!ret) - return 0; + ret =3D devm_add_action_or_reset(dev, axienet_id_free, + (void *)(intptr_t)id); + if (ret) + return dev_err_probe(dev, ret, + "could not register id free action\n"); =20 - if (cp->mii_bus) - axienet_mdio_teardown(cp); - return ret; -} + ret =3D axienet_aux_create(cp, &cp->mii_bus, "mdio", id, + device_get_named_child_node(dev, "mdio")); + if (ret) + return dev_err_probe(dev, ret, "could not create mdio bus\n"); =20 -static void axienet_remove(struct platform_device *pdev) -{ - struct net_device *ndev =3D platform_get_drvdata(pdev); - struct axienet_local *lp =3D netdev_priv(ndev); + ret =3D axienet_aux_create(cp, &cp->mac, "mac", id, + fwnode_handle_get(dev_fwnode(dev))); + if (ret) + return dev_err_probe(dev, ret, "could not create MAC\n"); =20 - axienet_mac_remove(pdev); - if (lp->mii_bus) - axienet_mdio_teardown(lp->cp); + return 0; } =20 static struct platform_driver axienet_driver =3D { .probe =3D axienet_probe, - .remove =3D axienet_remove, - .shutdown =3D axienet_mac_shutdown, .driver =3D { .name =3D "xilinx_axienet", .pm =3D &axienet_pm_ops, @@ -3204,7 +3280,35 @@ static struct platform_driver axienet_driver =3D { }, }; =20 -module_platform_driver(axienet_driver); +static int __init axienet_init(void) +{ + int ret; + + ret =3D auxiliary_driver_register(&xilinx_axienet_mdio); + if (ret) + return ret; + + ret =3D auxiliary_driver_register(&xilinx_axienet_mac); + if (ret) + goto unregister_mdio; + + ret =3D platform_driver_register(&axienet_driver); + if (ret) { + auxiliary_driver_unregister(&xilinx_axienet_mac); +unregister_mdio: + auxiliary_driver_unregister(&xilinx_axienet_mdio); + } + return ret; +} +module_init(axienet_init); + +static void __exit axienet_exit(void) +{ + platform_driver_unregister(&axienet_driver); + auxiliary_driver_unregister(&xilinx_axienet_mac); + auxiliary_driver_unregister(&xilinx_axienet_mdio); +} +module_exit(axienet_exit); =20 MODULE_DESCRIPTION("Xilinx Axi Ethernet driver"); MODULE_AUTHOR("Xilinx"); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/ne= t/ethernet/xilinx/xilinx_axienet_mdio.c index 4d50b3d0f7ee..58f7245e6a69 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -9,10 +9,10 @@ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved. */ =20 +#include #include #include #include -#include #include #include =20 @@ -271,19 +271,10 @@ static int axienet_mdio_enable(struct mii_bus *bus, s= truct device_node *np) return ret; } =20 -/** - * axienet_mdio_setup - MDIO setup function - * @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 - * memory for mii bus structure) fails. - * - * Sets up the MDIO interface by initializing the MDIO clock. - * Register the MDIO interface. - **/ -int axienet_mdio_setup(struct axienet_common *lp) +static int axienet_mdio_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) { + struct axienet_common *lp =3D auxdev->dev.platform_data; struct device_node *mdio_node; struct mii_bus *bus; int ret; @@ -299,36 +290,40 @@ int axienet_mdio_setup(struct axienet_common *lp) bus->name =3D "Xilinx Axi Ethernet MDIO"; bus->read =3D axienet_mdio_read; bus->write =3D axienet_mdio_write; - bus->parent =3D &lp->pdev->dev; - lp->mii_bus =3D bus; + bus->parent =3D &auxdev->dev; + auxiliary_set_drvdata(auxdev, bus); =20 - mdio_node =3D of_get_child_by_name(lp->pdev->dev.of_node, "mdio"); - scoped_guard(mutex, &lp->reset_lock) - ret =3D axienet_mdio_enable(bus, mdio_node); + mdio_node =3D dev_of_node(&auxdev->dev); + ret =3D axienet_mdio_enable(bus, mdio_node); if (ret < 0) goto unregister; =20 ret =3D of_mdiobus_register(bus, mdio_node); - of_node_put(mdio_node); scoped_guard(mutex, &lp->reset_lock) axienet_mdio_mdc_disable(lp); - if (ret) { + if (ret) unregister: mdiobus_free(bus); - lp->mii_bus =3D NULL; - } return ret; } =20 -/** - * axienet_mdio_teardown - MDIO remove function - * @lp: Pointer to axienet common data structure. - * - * Unregisters the MDIO and frees any associate memory for mii bus. - */ -void axienet_mdio_teardown(struct axienet_common *lp) +static void axienet_mdio_remove(struct auxiliary_device *auxdev) { - mdiobus_unregister(lp->mii_bus); - mdiobus_free(lp->mii_bus); - lp->mii_bus =3D NULL; + struct mii_bus *mii_bus =3D auxiliary_get_drvdata(auxdev); + + mdiobus_unregister(mii_bus); + mdiobus_free(mii_bus); } + +static const struct auxiliary_device_id xilinx_axienet_mdio_id_table[] =3D= { + { .name =3D KBUILD_MODNAME ".mdio", }, + { }, +}; +MODULE_DEVICE_TABLE(auxiliary, xilinx_axienet_mdio_id_table); + +struct auxiliary_driver xilinx_axienet_mdio =3D { + .name =3D "mdio", + .id_table =3D xilinx_axienet_mdio_id_table, + .probe =3D axienet_mdio_probe, + .remove =3D axienet_mdio_remove, +}; --=20 2.35.1.1320.gc452695387.dirty