diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-12-07 14:47:34 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2010-12-07 15:04:22 -0500 |
commit | e8f149924a3111015d16dfbbb4816cfc75ba53cd (patch) | |
tree | 69bbe1b466ba31ecaa105f6c330bf80f633b93ff /drivers/net/sfc | |
parent | 94dec6a2d20a26a779b63bb584e48db5fb0ddb53 (diff) |
sfc: Fix NAPI list corruption during ring reallocation
Call netif_napi_{add,del}() on the NAPI contexts in the new and
old channels, respectively.
Since efx_init_napi() cannot fail, make its return type void.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index d06cb742164b..fb83cdd94643 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value"); | |||
197 | 197 | ||
198 | static void efx_remove_channels(struct efx_nic *efx); | 198 | static void efx_remove_channels(struct efx_nic *efx); |
199 | static void efx_remove_port(struct efx_nic *efx); | 199 | static void efx_remove_port(struct efx_nic *efx); |
200 | static void efx_init_napi(struct efx_nic *efx); | ||
200 | static void efx_fini_napi(struct efx_nic *efx); | 201 | static void efx_fini_napi(struct efx_nic *efx); |
202 | static void efx_fini_napi_channel(struct efx_channel *channel); | ||
201 | static void efx_fini_struct(struct efx_nic *efx); | 203 | static void efx_fini_struct(struct efx_nic *efx); |
202 | static void efx_start_all(struct efx_nic *efx); | 204 | static void efx_start_all(struct efx_nic *efx); |
203 | static void efx_stop_all(struct efx_nic *efx); | 205 | static void efx_stop_all(struct efx_nic *efx); |
@@ -430,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel) | |||
430 | 432 | ||
431 | *channel = *old_channel; | 433 | *channel = *old_channel; |
432 | 434 | ||
435 | channel->napi_dev = NULL; | ||
433 | memset(&channel->eventq, 0, sizeof(channel->eventq)); | 436 | memset(&channel->eventq, 0, sizeof(channel->eventq)); |
434 | 437 | ||
435 | rx_queue = &channel->rx_queue; | 438 | rx_queue = &channel->rx_queue; |
@@ -740,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) | |||
740 | if (rc) | 743 | if (rc) |
741 | goto rollback; | 744 | goto rollback; |
742 | 745 | ||
746 | efx_init_napi(efx); | ||
747 | |||
743 | /* Destroy old channels */ | 748 | /* Destroy old channels */ |
744 | for (i = 0; i < efx->n_channels; i++) | 749 | for (i = 0; i < efx->n_channels; i++) { |
750 | efx_fini_napi_channel(other_channel[i]); | ||
745 | efx_remove_channel(other_channel[i]); | 751 | efx_remove_channel(other_channel[i]); |
752 | } | ||
746 | out: | 753 | out: |
747 | /* Free unused channel structures */ | 754 | /* Free unused channel structures */ |
748 | for (i = 0; i < efx->n_channels; i++) | 755 | for (i = 0; i < efx->n_channels; i++) |
@@ -1601,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) | |||
1601 | * | 1608 | * |
1602 | **************************************************************************/ | 1609 | **************************************************************************/ |
1603 | 1610 | ||
1604 | static int efx_init_napi(struct efx_nic *efx) | 1611 | static void efx_init_napi(struct efx_nic *efx) |
1605 | { | 1612 | { |
1606 | struct efx_channel *channel; | 1613 | struct efx_channel *channel; |
1607 | 1614 | ||
@@ -1610,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx) | |||
1610 | netif_napi_add(channel->napi_dev, &channel->napi_str, | 1617 | netif_napi_add(channel->napi_dev, &channel->napi_str, |
1611 | efx_poll, napi_weight); | 1618 | efx_poll, napi_weight); |
1612 | } | 1619 | } |
1613 | return 0; | 1620 | } |
1621 | |||
1622 | static void efx_fini_napi_channel(struct efx_channel *channel) | ||
1623 | { | ||
1624 | if (channel->napi_dev) | ||
1625 | netif_napi_del(&channel->napi_str); | ||
1626 | channel->napi_dev = NULL; | ||
1614 | } | 1627 | } |
1615 | 1628 | ||
1616 | static void efx_fini_napi(struct efx_nic *efx) | 1629 | static void efx_fini_napi(struct efx_nic *efx) |
1617 | { | 1630 | { |
1618 | struct efx_channel *channel; | 1631 | struct efx_channel *channel; |
1619 | 1632 | ||
1620 | efx_for_each_channel(channel, efx) { | 1633 | efx_for_each_channel(channel, efx) |
1621 | if (channel->napi_dev) | 1634 | efx_fini_napi_channel(channel); |
1622 | netif_napi_del(&channel->napi_str); | ||
1623 | channel->napi_dev = NULL; | ||
1624 | } | ||
1625 | } | 1635 | } |
1626 | 1636 | ||
1627 | /************************************************************************** | 1637 | /************************************************************************** |
@@ -2343,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx) | |||
2343 | if (rc) | 2353 | if (rc) |
2344 | goto fail1; | 2354 | goto fail1; |
2345 | 2355 | ||
2346 | rc = efx_init_napi(efx); | 2356 | efx_init_napi(efx); |
2347 | if (rc) | ||
2348 | goto fail2; | ||
2349 | 2357 | ||
2350 | rc = efx->type->init(efx); | 2358 | rc = efx->type->init(efx); |
2351 | if (rc) { | 2359 | if (rc) { |
@@ -2376,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx) | |||
2376 | efx->type->fini(efx); | 2384 | efx->type->fini(efx); |
2377 | fail3: | 2385 | fail3: |
2378 | efx_fini_napi(efx); | 2386 | efx_fini_napi(efx); |
2379 | fail2: | ||
2380 | efx_remove_all(efx); | 2387 | efx_remove_all(efx); |
2381 | fail1: | 2388 | fail1: |
2382 | return rc; | 2389 | return rc; |