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 | |
| 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>
| -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 d06cb742164..fb83cdd9464 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; |
