sfc: Fix synchronisation of efx_mtd_{probe,rename,remove}
Currently efx_mtd_rename() can race with the probe() and remove() functions. Move probe() before device registration and remove() after unregistration. Move initialisation/update of all names based on the netdev name into a new function and call it under the RTNL immediately after registration. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
0c53d8c840
commit
7dde596ef7
@@ -1517,18 +1517,21 @@ static const struct net_device_ops efx_netdev_ops = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void efx_update_name(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
strcpy(efx->name, efx->net_dev->name);
|
||||||
|
efx_mtd_rename(efx);
|
||||||
|
efx_set_channel_names(efx);
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_netdev_event(struct notifier_block *this,
|
static int efx_netdev_event(struct notifier_block *this,
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
{
|
{
|
||||||
struct net_device *net_dev = ptr;
|
struct net_device *net_dev = ptr;
|
||||||
|
|
||||||
if (net_dev->netdev_ops == &efx_netdev_ops && event == NETDEV_CHANGENAME) {
|
if (net_dev->netdev_ops == &efx_netdev_ops &&
|
||||||
struct efx_nic *efx = netdev_priv(net_dev);
|
event == NETDEV_CHANGENAME)
|
||||||
|
efx_update_name(netdev_priv(net_dev));
|
||||||
strcpy(efx->name, net_dev->name);
|
|
||||||
efx_mtd_rename(efx);
|
|
||||||
efx_set_channel_names(efx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
@@ -1568,8 +1571,10 @@ static int efx_register_netdev(struct efx_nic *efx)
|
|||||||
EFX_ERR(efx, "could not register net dev\n");
|
EFX_ERR(efx, "could not register net dev\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
strcpy(efx->name, net_dev->name);
|
|
||||||
efx_set_channel_names(efx);
|
rtnl_lock();
|
||||||
|
efx_update_name(efx);
|
||||||
|
rtnl_unlock();
|
||||||
|
|
||||||
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
|
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -1978,8 +1983,6 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
|
|||||||
if (!efx)
|
if (!efx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
efx_mtd_remove(efx);
|
|
||||||
|
|
||||||
/* Mark the NIC as fini, then stop the interface */
|
/* Mark the NIC as fini, then stop the interface */
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
efx->state = STATE_FINI;
|
efx->state = STATE_FINI;
|
||||||
@@ -1993,6 +1996,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
|
|||||||
|
|
||||||
efx_unregister_netdev(efx);
|
efx_unregister_netdev(efx);
|
||||||
|
|
||||||
|
efx_mtd_remove(efx);
|
||||||
|
|
||||||
/* Wait for any scheduled resets to complete. No more will be
|
/* Wait for any scheduled resets to complete. No more will be
|
||||||
* scheduled from this point because efx_stop_all() has been
|
* scheduled from this point because efx_stop_all() has been
|
||||||
* called, we are no longer registered with driverlink, and
|
* called, we are no longer registered with driverlink, and
|
||||||
@@ -2146,17 +2151,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
|
|||||||
/* Switch to the running state before we expose the device to
|
/* Switch to the running state before we expose the device to
|
||||||
* the OS. This is to ensure that the initial gathering of
|
* the OS. This is to ensure that the initial gathering of
|
||||||
* MAC stats succeeds. */
|
* MAC stats succeeds. */
|
||||||
rtnl_lock();
|
|
||||||
efx->state = STATE_RUNNING;
|
efx->state = STATE_RUNNING;
|
||||||
rtnl_unlock();
|
|
||||||
|
efx_mtd_probe(efx); /* allowed to fail */
|
||||||
|
|
||||||
rc = efx_register_netdev(efx);
|
rc = efx_register_netdev(efx);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fail5;
|
goto fail5;
|
||||||
|
|
||||||
EFX_LOG(efx, "initialisation successful\n");
|
EFX_LOG(efx, "initialisation successful\n");
|
||||||
|
|
||||||
efx_mtd_probe(efx); /* allowed to fail */
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail5:
|
fail5:
|
||||||
|
Reference in New Issue
Block a user