diff options
| author | David S. Miller <davem@davemloft.net> | 2010-12-08 15:13:23 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-12-08 15:13:23 -0500 |
| commit | 083384755252cde25af187acf1807a0f5edb901f (patch) | |
| tree | 27beb76ed915641d07f5dbdfbcf67c0715061f5a /drivers | |
| parent | 35d9b0c906ad92d32a0b8db5daa6fabfcc2f068d (diff) | |
| parent | e8f149924a3111015d16dfbbb4816cfc75ba53cd (diff) | |
Merge branch 'sfc-2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-2.6
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/sfc/efx.c | 43 | ||||
| -rw-r--r-- | drivers/net/sfc/net_driver.h | 2 | ||||
| -rw-r--r-- | drivers/net/sfc/nic.c | 6 |
3 files changed, 37 insertions, 14 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 05df20e4797..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); |
| @@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel) | |||
| 335 | 337 | ||
| 336 | /* Disable interrupts and wait for ISRs to complete */ | 338 | /* Disable interrupts and wait for ISRs to complete */ |
| 337 | efx_nic_disable_interrupts(efx); | 339 | efx_nic_disable_interrupts(efx); |
| 338 | if (efx->legacy_irq) | 340 | if (efx->legacy_irq) { |
| 339 | synchronize_irq(efx->legacy_irq); | 341 | synchronize_irq(efx->legacy_irq); |
| 342 | efx->legacy_irq_enabled = false; | ||
| 343 | } | ||
| 340 | if (channel->irq) | 344 | if (channel->irq) |
| 341 | synchronize_irq(channel->irq); | 345 | synchronize_irq(channel->irq); |
| 342 | 346 | ||
| @@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel) | |||
| 351 | efx_channel_processed(channel); | 355 | efx_channel_processed(channel); |
| 352 | 356 | ||
| 353 | napi_enable(&channel->napi_str); | 357 | napi_enable(&channel->napi_str); |
| 358 | if (efx->legacy_irq) | ||
| 359 | efx->legacy_irq_enabled = true; | ||
| 354 | efx_nic_enable_interrupts(efx); | 360 | efx_nic_enable_interrupts(efx); |
| 355 | } | 361 | } |
| 356 | 362 | ||
| @@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel) | |||
| 426 | 432 | ||
| 427 | *channel = *old_channel; | 433 | *channel = *old_channel; |
| 428 | 434 | ||
| 435 | channel->napi_dev = NULL; | ||
| 429 | memset(&channel->eventq, 0, sizeof(channel->eventq)); | 436 | memset(&channel->eventq, 0, sizeof(channel->eventq)); |
| 430 | 437 | ||
| 431 | rx_queue = &channel->rx_queue; | 438 | rx_queue = &channel->rx_queue; |
| @@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) | |||
| 736 | if (rc) | 743 | if (rc) |
| 737 | goto rollback; | 744 | goto rollback; |
| 738 | 745 | ||
| 746 | efx_init_napi(efx); | ||
| 747 | |||
| 739 | /* Destroy old channels */ | 748 | /* Destroy old channels */ |
| 740 | 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]); | ||
| 741 | efx_remove_channel(other_channel[i]); | 751 | efx_remove_channel(other_channel[i]); |
| 752 | } | ||
| 742 | out: | 753 | out: |
| 743 | /* Free unused channel structures */ | 754 | /* Free unused channel structures */ |
| 744 | for (i = 0; i < efx->n_channels; i++) | 755 | for (i = 0; i < efx->n_channels; i++) |
| @@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx) | |||
| 1400 | efx_start_channel(channel); | 1411 | efx_start_channel(channel); |
| 1401 | } | 1412 | } |
| 1402 | 1413 | ||
| 1414 | if (efx->legacy_irq) | ||
| 1415 | efx->legacy_irq_enabled = true; | ||
| 1403 | efx_nic_enable_interrupts(efx); | 1416 | efx_nic_enable_interrupts(efx); |
| 1404 | 1417 | ||
| 1405 | /* Switch to event based MCDI completions after enabling interrupts. | 1418 | /* Switch to event based MCDI completions after enabling interrupts. |
| @@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx) | |||
| 1460 | 1473 | ||
| 1461 | /* Disable interrupts and wait for ISR to complete */ | 1474 | /* Disable interrupts and wait for ISR to complete */ |
| 1462 | efx_nic_disable_interrupts(efx); | 1475 | efx_nic_disable_interrupts(efx); |
| 1463 | if (efx->legacy_irq) | 1476 | if (efx->legacy_irq) { |
| 1464 | synchronize_irq(efx->legacy_irq); | 1477 | synchronize_irq(efx->legacy_irq); |
| 1478 | efx->legacy_irq_enabled = false; | ||
| 1479 | } | ||
| 1465 | efx_for_each_channel(channel, efx) { | 1480 | efx_for_each_channel(channel, efx) { |
| 1466 | if (channel->irq) | 1481 | if (channel->irq) |
| 1467 | synchronize_irq(channel->irq); | 1482 | synchronize_irq(channel->irq); |
| @@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) | |||
| 1593 | * | 1608 | * |
| 1594 | **************************************************************************/ | 1609 | **************************************************************************/ |
| 1595 | 1610 | ||
| 1596 | static int efx_init_napi(struct efx_nic *efx) | 1611 | static void efx_init_napi(struct efx_nic *efx) |
| 1597 | { | 1612 | { |
| 1598 | struct efx_channel *channel; | 1613 | struct efx_channel *channel; |
| 1599 | 1614 | ||
| @@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx) | |||
| 1602 | netif_napi_add(channel->napi_dev, &channel->napi_str, | 1617 | netif_napi_add(channel->napi_dev, &channel->napi_str, |
| 1603 | efx_poll, napi_weight); | 1618 | efx_poll, napi_weight); |
| 1604 | } | 1619 | } |
| 1605 | 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; | ||
| 1606 | } | 1627 | } |
| 1607 | 1628 | ||
| 1608 | static void efx_fini_napi(struct efx_nic *efx) | 1629 | static void efx_fini_napi(struct efx_nic *efx) |
| 1609 | { | 1630 | { |
| 1610 | struct efx_channel *channel; | 1631 | struct efx_channel *channel; |
| 1611 | 1632 | ||
| 1612 | efx_for_each_channel(channel, efx) { | 1633 | efx_for_each_channel(channel, efx) |
| 1613 | if (channel->napi_dev) | 1634 | efx_fini_napi_channel(channel); |
| 1614 | netif_napi_del(&channel->napi_str); | ||
| 1615 | channel->napi_dev = NULL; | ||
| 1616 | } | ||
| 1617 | } | 1635 | } |
| 1618 | 1636 | ||
| 1619 | /************************************************************************** | 1637 | /************************************************************************** |
| @@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx) | |||
| 2335 | if (rc) | 2353 | if (rc) |
| 2336 | goto fail1; | 2354 | goto fail1; |
| 2337 | 2355 | ||
| 2338 | rc = efx_init_napi(efx); | 2356 | efx_init_napi(efx); |
| 2339 | if (rc) | ||
| 2340 | goto fail2; | ||
| 2341 | 2357 | ||
| 2342 | rc = efx->type->init(efx); | 2358 | rc = efx->type->init(efx); |
| 2343 | if (rc) { | 2359 | if (rc) { |
| @@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx) | |||
| 2368 | efx->type->fini(efx); | 2384 | efx->type->fini(efx); |
| 2369 | fail3: | 2385 | fail3: |
| 2370 | efx_fini_napi(efx); | 2386 | efx_fini_napi(efx); |
| 2371 | fail2: | ||
| 2372 | efx_remove_all(efx); | 2387 | efx_remove_all(efx); |
| 2373 | fail1: | 2388 | fail1: |
| 2374 | return rc; | 2389 | return rc; |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 0a7e26d73b5..b137c889152 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
| @@ -621,6 +621,7 @@ struct efx_filter_state; | |||
| 621 | * @pci_dev: The PCI device | 621 | * @pci_dev: The PCI device |
| 622 | * @type: Controller type attributes | 622 | * @type: Controller type attributes |
| 623 | * @legacy_irq: IRQ number | 623 | * @legacy_irq: IRQ number |
| 624 | * @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)? | ||
| 624 | * @workqueue: Workqueue for port reconfigures and the HW monitor. | 625 | * @workqueue: Workqueue for port reconfigures and the HW monitor. |
| 625 | * Work items do not hold and must not acquire RTNL. | 626 | * Work items do not hold and must not acquire RTNL. |
| 626 | * @workqueue_name: Name of workqueue | 627 | * @workqueue_name: Name of workqueue |
| @@ -709,6 +710,7 @@ struct efx_nic { | |||
| 709 | struct pci_dev *pci_dev; | 710 | struct pci_dev *pci_dev; |
| 710 | const struct efx_nic_type *type; | 711 | const struct efx_nic_type *type; |
| 711 | int legacy_irq; | 712 | int legacy_irq; |
| 713 | bool legacy_irq_enabled; | ||
| 712 | struct workqueue_struct *workqueue; | 714 | struct workqueue_struct *workqueue; |
| 713 | char workqueue_name[16]; | 715 | char workqueue_name[16]; |
| 714 | struct work_struct reset_work; | 716 | struct work_struct reset_work; |
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 41c36b9a424..67cb0c96838 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c | |||
| @@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) | |||
| 1418 | u32 queues; | 1418 | u32 queues; |
| 1419 | int syserr; | 1419 | int syserr; |
| 1420 | 1420 | ||
| 1421 | /* Could this be ours? If interrupts are disabled then the | ||
| 1422 | * channel state may not be valid. | ||
| 1423 | */ | ||
| 1424 | if (!efx->legacy_irq_enabled) | ||
| 1425 | return result; | ||
| 1426 | |||
| 1421 | /* Read the ISR which also ACKs the interrupts */ | 1427 | /* Read the ISR which also ACKs the interrupts */ |
| 1422 | efx_readd(efx, ®, FR_BZ_INT_ISR0); | 1428 | efx_readd(efx, ®, FR_BZ_INT_ISR0); |
| 1423 | queues = EFX_EXTRACT_DWORD(reg, 0, 31); | 1429 | queues = EFX_EXTRACT_DWORD(reg, 0, 31); |
