Commit efbaa828 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller

amd-xgbe: Add support to handle device renaming

Many of the names used by the driver are based upon the name of the device
found during device probe.  Move the formatting of the names into the
device open function so that any renaming that occurs before the device is
brought up will be accounted for.  This also means moving the creation of
some named workqueues into the device open path.

Add support to register for net events so that if a device is renamed
the corresponding debugfs directory can be renamed.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1b631424
...@@ -527,3 +527,28 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) ...@@ -527,3 +527,28 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
debugfs_remove_recursive(pdata->xgbe_debugfs); debugfs_remove_recursive(pdata->xgbe_debugfs);
pdata->xgbe_debugfs = NULL; pdata->xgbe_debugfs = NULL;
} }
void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
{
struct dentry *pfile;
char *buf;
if (!pdata->xgbe_debugfs)
return;
buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
if (!buf)
return;
if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
goto out;
pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent,
pdata->xgbe_debugfs,
pdata->xgbe_debugfs->d_parent, buf);
if (!pfile)
netdev_err(pdata->netdev, "debugfs_rename failed\n");
out:
kfree(buf);
}
...@@ -887,7 +887,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) ...@@ -887,7 +887,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
(unsigned long)pdata); (unsigned long)pdata);
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
netdev->name, pdata); netdev_name(netdev), pdata);
if (ret) { if (ret) {
netdev_alert(netdev, "error requesting irq %d\n", netdev_alert(netdev, "error requesting irq %d\n",
pdata->dev_irq); pdata->dev_irq);
...@@ -1589,16 +1589,42 @@ static int xgbe_open(struct net_device *netdev) ...@@ -1589,16 +1589,42 @@ static int xgbe_open(struct net_device *netdev)
DBGPR("-->xgbe_open\n"); DBGPR("-->xgbe_open\n");
/* Create the various names based on netdev name */
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
netdev_name(netdev));
snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
netdev_name(netdev));
snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
netdev_name(netdev));
/* Create workqueues */
pdata->dev_workqueue =
create_singlethread_workqueue(netdev_name(netdev));
if (!pdata->dev_workqueue) {
netdev_err(netdev, "device workqueue creation failed\n");
return -ENOMEM;
}
pdata->an_workqueue =
create_singlethread_workqueue(pdata->an_name);
if (!pdata->an_workqueue) {
netdev_err(netdev, "phy workqueue creation failed\n");
ret = -ENOMEM;
goto err_dev_wq;
}
/* Reset the phy settings */ /* Reset the phy settings */
ret = xgbe_phy_reset(pdata); ret = xgbe_phy_reset(pdata);
if (ret) if (ret)
return ret; goto err_an_wq;
/* Enable the clocks */ /* Enable the clocks */
ret = clk_prepare_enable(pdata->sysclk); ret = clk_prepare_enable(pdata->sysclk);
if (ret) { if (ret) {
netdev_alert(netdev, "dma clk_prepare_enable failed\n"); netdev_alert(netdev, "dma clk_prepare_enable failed\n");
return ret; goto err_an_wq;
} }
ret = clk_prepare_enable(pdata->ptpclk); ret = clk_prepare_enable(pdata->ptpclk);
...@@ -1651,6 +1677,12 @@ static int xgbe_open(struct net_device *netdev) ...@@ -1651,6 +1677,12 @@ static int xgbe_open(struct net_device *netdev)
err_sysclk: err_sysclk:
clk_disable_unprepare(pdata->sysclk); clk_disable_unprepare(pdata->sysclk);
err_an_wq:
destroy_workqueue(pdata->an_workqueue);
err_dev_wq:
destroy_workqueue(pdata->dev_workqueue);
return ret; return ret;
} }
...@@ -1674,6 +1706,12 @@ static int xgbe_close(struct net_device *netdev) ...@@ -1674,6 +1706,12 @@ static int xgbe_close(struct net_device *netdev)
clk_disable_unprepare(pdata->ptpclk); clk_disable_unprepare(pdata->ptpclk);
clk_disable_unprepare(pdata->sysclk); clk_disable_unprepare(pdata->sysclk);
flush_workqueue(pdata->an_workqueue);
destroy_workqueue(pdata->an_workqueue);
flush_workqueue(pdata->dev_workqueue);
destroy_workqueue(pdata->dev_workqueue);
set_bit(XGBE_DOWN, &pdata->dev_state); set_bit(XGBE_DOWN, &pdata->dev_state);
DBGPR("<--xgbe_close\n"); DBGPR("<--xgbe_close\n");
......
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/notifier.h>
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
...@@ -399,35 +400,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) ...@@ -399,35 +400,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
return ret; return ret;
} }
/* Create the PHY/ANEG name based on netdev name */
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
netdev_name(netdev));
/* Create the ECC name based on netdev name */
snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
netdev_name(netdev));
/* Create the I2C name based on netdev name */
snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
netdev_name(netdev));
/* Create workqueues */
pdata->dev_workqueue =
create_singlethread_workqueue(netdev_name(netdev));
if (!pdata->dev_workqueue) {
netdev_err(netdev, "device workqueue creation failed\n");
ret = -ENOMEM;
goto err_netdev;
}
pdata->an_workqueue =
create_singlethread_workqueue(pdata->an_name);
if (!pdata->an_workqueue) {
netdev_err(netdev, "phy workqueue creation failed\n");
ret = -ENOMEM;
goto err_wq;
}
if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK)) if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
xgbe_ptp_register(pdata); xgbe_ptp_register(pdata);
...@@ -439,14 +411,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) ...@@ -439,14 +411,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
pdata->rx_ring_count); pdata->rx_ring_count);
return 0; return 0;
err_wq:
destroy_workqueue(pdata->dev_workqueue);
err_netdev:
unregister_netdev(netdev);
return ret;
} }
void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
...@@ -461,18 +425,42 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) ...@@ -461,18 +425,42 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
unregister_netdev(netdev); unregister_netdev(netdev);
pdata->phy_if.phy_exit(pdata); pdata->phy_if.phy_exit(pdata);
}
flush_workqueue(pdata->an_workqueue); static int xgbe_netdev_event(struct notifier_block *nb, unsigned long event,
destroy_workqueue(pdata->an_workqueue); void *data)
{
struct net_device *netdev = netdev_notifier_info_to_dev(data);
struct xgbe_prv_data *pdata = netdev_priv(netdev);
if (netdev->netdev_ops != xgbe_get_netdev_ops())
goto out;
switch (event) {
case NETDEV_CHANGENAME:
xgbe_debugfs_rename(pdata);
break;
default:
break;
}
flush_workqueue(pdata->dev_workqueue); out:
destroy_workqueue(pdata->dev_workqueue); return NOTIFY_DONE;
} }
static struct notifier_block xgbe_netdev_notifier = {
.notifier_call = xgbe_netdev_event,
};
static int __init xgbe_mod_init(void) static int __init xgbe_mod_init(void)
{ {
int ret; int ret;
ret = register_netdevice_notifier(&xgbe_netdev_notifier);
if (ret)
return ret;
ret = xgbe_platform_init(); ret = xgbe_platform_init();
if (ret) if (ret)
return ret; return ret;
...@@ -489,6 +477,8 @@ static void __exit xgbe_mod_exit(void) ...@@ -489,6 +477,8 @@ static void __exit xgbe_mod_exit(void)
xgbe_pci_exit(); xgbe_pci_exit();
xgbe_platform_exit(); xgbe_platform_exit();
unregister_netdevice_notifier(&xgbe_netdev_notifier);
} }
module_init(xgbe_mod_init); module_init(xgbe_mod_init);
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dcache.h>
#define XGBE_DRV_NAME "amd-xgbe" #define XGBE_DRV_NAME "amd-xgbe"
#define XGBE_DRV_VERSION "1.0.3" #define XGBE_DRV_VERSION "1.0.3"
...@@ -1172,7 +1173,6 @@ struct xgbe_prv_data { ...@@ -1172,7 +1173,6 @@ struct xgbe_prv_data {
struct tasklet_struct tasklet_i2c; struct tasklet_struct tasklet_i2c;
struct tasklet_struct tasklet_an; struct tasklet_struct tasklet_an;
#ifdef CONFIG_DEBUG_FS
struct dentry *xgbe_debugfs; struct dentry *xgbe_debugfs;
unsigned int debugfs_xgmac_reg; unsigned int debugfs_xgmac_reg;
...@@ -1183,7 +1183,6 @@ struct xgbe_prv_data { ...@@ -1183,7 +1183,6 @@ struct xgbe_prv_data {
unsigned int debugfs_xprop_reg; unsigned int debugfs_xprop_reg;
unsigned int debugfs_xi2c_reg; unsigned int debugfs_xi2c_reg;
#endif
}; };
/* Function prototypes*/ /* Function prototypes*/
...@@ -1232,9 +1231,11 @@ void xgbe_init_tx_coalesce(struct xgbe_prv_data *); ...@@ -1232,9 +1231,11 @@ void xgbe_init_tx_coalesce(struct xgbe_prv_data *);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void xgbe_debugfs_init(struct xgbe_prv_data *); void xgbe_debugfs_init(struct xgbe_prv_data *);
void xgbe_debugfs_exit(struct xgbe_prv_data *); void xgbe_debugfs_exit(struct xgbe_prv_data *);
void xgbe_debugfs_rename(struct xgbe_prv_data *pdata);
#else #else
static inline void xgbe_debugfs_init(struct xgbe_prv_data *pdata) {} static inline void xgbe_debugfs_init(struct xgbe_prv_data *pdata) {}
static inline void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) {} static inline void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) {}
static inline void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) {}
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
/* NOTE: Uncomment for function trace log messages in KERNEL LOG */ /* NOTE: Uncomment for function trace log messages in KERNEL LOG */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment