diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 01:09:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-13 01:09:38 -0500 |
commit | 7dde596ef79982327d8992a579a137b4035ad599 (patch) | |
tree | d14cc58d0ea48dbece0f18b3c6823176969ecd74 /drivers/net/sfc/efx.c | |
parent | 0c53d8c84047d86169bd4147bb8f5adf2772d2bb (diff) |
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>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 8f832bf1e4d2..086629c0fe57 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -1517,18 +1517,21 @@ static const struct net_device_ops efx_netdev_ops = { | |||
1517 | #endif | 1517 | #endif |
1518 | }; | 1518 | }; |
1519 | 1519 | ||
1520 | static void efx_update_name(struct efx_nic *efx) | ||
1521 | { | ||
1522 | strcpy(efx->name, efx->net_dev->name); | ||
1523 | efx_mtd_rename(efx); | ||
1524 | efx_set_channel_names(efx); | ||
1525 | } | ||
1526 | |||
1520 | static int efx_netdev_event(struct notifier_block *this, | 1527 | static int efx_netdev_event(struct notifier_block *this, |
1521 | unsigned long event, void *ptr) | 1528 | unsigned long event, void *ptr) |
1522 | { | 1529 | { |
1523 | struct net_device *net_dev = ptr; | 1530 | struct net_device *net_dev = ptr; |
1524 | 1531 | ||
1525 | if (net_dev->netdev_ops == &efx_netdev_ops && event == NETDEV_CHANGENAME) { | 1532 | if (net_dev->netdev_ops == &efx_netdev_ops && |
1526 | struct efx_nic *efx = netdev_priv(net_dev); | 1533 | event == NETDEV_CHANGENAME) |
1527 | 1534 | efx_update_name(netdev_priv(net_dev)); | |
1528 | strcpy(efx->name, net_dev->name); | ||
1529 | efx_mtd_rename(efx); | ||
1530 | efx_set_channel_names(efx); | ||
1531 | } | ||
1532 | 1535 | ||
1533 | return NOTIFY_DONE; | 1536 | return NOTIFY_DONE; |
1534 | } | 1537 | } |
@@ -1568,8 +1571,10 @@ static int efx_register_netdev(struct efx_nic *efx) | |||
1568 | EFX_ERR(efx, "could not register net dev\n"); | 1571 | EFX_ERR(efx, "could not register net dev\n"); |
1569 | return rc; | 1572 | return rc; |
1570 | } | 1573 | } |
1571 | strcpy(efx->name, net_dev->name); | 1574 | |
1572 | efx_set_channel_names(efx); | 1575 | rtnl_lock(); |
1576 | efx_update_name(efx); | ||
1577 | rtnl_unlock(); | ||
1573 | 1578 | ||
1574 | rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); | 1579 | rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); |
1575 | if (rc) { | 1580 | if (rc) { |
@@ -1978,8 +1983,6 @@ static void efx_pci_remove(struct pci_dev *pci_dev) | |||
1978 | if (!efx) | 1983 | if (!efx) |
1979 | return; | 1984 | return; |
1980 | 1985 | ||
1981 | efx_mtd_remove(efx); | ||
1982 | |||
1983 | /* Mark the NIC as fini, then stop the interface */ | 1986 | /* Mark the NIC as fini, then stop the interface */ |
1984 | rtnl_lock(); | 1987 | rtnl_lock(); |
1985 | efx->state = STATE_FINI; | 1988 | efx->state = STATE_FINI; |
@@ -1993,6 +1996,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) | |||
1993 | 1996 | ||
1994 | efx_unregister_netdev(efx); | 1997 | efx_unregister_netdev(efx); |
1995 | 1998 | ||
1999 | efx_mtd_remove(efx); | ||
2000 | |||
1996 | /* Wait for any scheduled resets to complete. No more will be | 2001 | /* Wait for any scheduled resets to complete. No more will be |
1997 | * scheduled from this point because efx_stop_all() has been | 2002 | * scheduled from this point because efx_stop_all() has been |
1998 | * called, we are no longer registered with driverlink, and | 2003 | * called, we are no longer registered with driverlink, and |
@@ -2146,17 +2151,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2146 | /* Switch to the running state before we expose the device to | 2151 | /* Switch to the running state before we expose the device to |
2147 | * the OS. This is to ensure that the initial gathering of | 2152 | * the OS. This is to ensure that the initial gathering of |
2148 | * MAC stats succeeds. */ | 2153 | * MAC stats succeeds. */ |
2149 | rtnl_lock(); | ||
2150 | efx->state = STATE_RUNNING; | 2154 | efx->state = STATE_RUNNING; |
2151 | rtnl_unlock(); | 2155 | |
2156 | efx_mtd_probe(efx); /* allowed to fail */ | ||
2152 | 2157 | ||
2153 | rc = efx_register_netdev(efx); | 2158 | rc = efx_register_netdev(efx); |
2154 | if (rc) | 2159 | if (rc) |
2155 | goto fail5; | 2160 | goto fail5; |
2156 | 2161 | ||
2157 | EFX_LOG(efx, "initialisation successful\n"); | 2162 | EFX_LOG(efx, "initialisation successful\n"); |
2158 | |||
2159 | efx_mtd_probe(efx); /* allowed to fail */ | ||
2160 | return 0; | 2163 | return 0; |
2161 | 2164 | ||
2162 | fail5: | 2165 | fail5: |