Rearrange the lifetime functions (probe, remove, etc.) in preparation
for the next commit. No functional change intended.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
(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/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, ðres);
- 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, ðres);
+ 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 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 <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);
@@ -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
On Tue, Aug 05, 2025 at 11:34:55AM -0400, Sean Anderson wrote: > Rearrange the lifetime functions (probe, remove, etc.) in preparation > for the next commit. No functional change intended. > > Signed-off-by: Sean Anderson <sean.anderson@linux.dev> ... > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h ... > /** > * 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; nit: Please add cp to, and remove axi_clk and regs_start from the Kernel doc for this structure. Flagged by ./scripts/kernel-doc -none > > 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; > ...
On Tue, Aug 05, 2025 at 11:34:55AM -0400, Sean Anderson wrote: > Rearrange the lifetime functions (probe, remove, etc.) in preparation > for the next commit. No functional change intended. There is a lot going on in this patch. Can it be broken up a bit more? The phase "No functional change intended" generally means, its the same code, just in a different place in the files. This is not true of this patch. > +struct axienet_common { > + struct platform_device *pdev; > + > + struct clk *axi_clk; > + > + struct mutex reset_lock; > 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); This lock is different to the bus lock. This is definitely not a "no functional change". Please make this lock change a patch of its own, with a good commit message which considers the consequences of this change of lock. > 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; That looks like a whitespace change. This is a "No functional change intended" sort of patch. You can collect all such whitespace changes into one patch. > } > lp->pcs_phy = of_mdio_find_device(np); > - np1 = of_find_node_by_name(NULL, "lpu"); > + np1 = of_find_node_by_name(NULL, "cpu"); Interesting. Maybe you should review your own patches. Andrew --- pw-bot: cr
On 8/5/25 17:32, Andrew Lunn wrote: > On Tue, Aug 05, 2025 at 11:34:55AM -0400, Sean Anderson wrote: >> Rearrange the lifetime functions (probe, remove, etc.) in preparation >> for the next commit. No functional change intended. > > There is a lot going on in this patch. Can it be broken up a bit more? > > The phase "No functional change intended" generally means, its the > same code, just in a different place in the files. This is not true of > this patch. Sorry, at one point that was true and then I made a some edits. I will update the commit message. >> +struct axienet_common { >> + struct platform_device *pdev; >> + >> + struct clk *axi_clk; >> + >> + struct mutex reset_lock; > >> 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); > > This lock is different to the bus lock. This is definitely not a "no > functional change". > > Please make this lock change a patch of its own, with a good commit > message which considers the consequences of this change of lock. OK >> 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; > > That looks like a whitespace change. This is a "No functional change > intended" sort of patch. You can collect all such whitespace changes > into one patch. The main purpose of that hunk is to remove the `goto cleanup_mdio`. The dev_err change is just because I was "in the area". >> } >> lp->pcs_phy = of_mdio_find_device(np); >> - np1 = of_find_node_by_name(NULL, "lpu"); >> + np1 = of_find_node_by_name(NULL, "cpu"); > > Interesting. Maybe you should review your own patches. Will do. --Sean
© 2016 - 2025 Red Hat, Inc.