Commit 08338475 authored by David S. Miller's avatar David S. Miller
parents 35d9b0c9 e8f14992
...@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value"); ...@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
static void efx_remove_channels(struct efx_nic *efx); static void efx_remove_channels(struct efx_nic *efx);
static void efx_remove_port(struct efx_nic *efx); static void efx_remove_port(struct efx_nic *efx);
static void efx_init_napi(struct efx_nic *efx);
static void efx_fini_napi(struct efx_nic *efx); static void efx_fini_napi(struct efx_nic *efx);
static void efx_fini_napi_channel(struct efx_channel *channel);
static void efx_fini_struct(struct efx_nic *efx); static void efx_fini_struct(struct efx_nic *efx);
static void efx_start_all(struct efx_nic *efx); static void efx_start_all(struct efx_nic *efx);
static void efx_stop_all(struct efx_nic *efx); static void efx_stop_all(struct efx_nic *efx);
...@@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel) ...@@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel)
/* Disable interrupts and wait for ISRs to complete */ /* Disable interrupts and wait for ISRs to complete */
efx_nic_disable_interrupts(efx); efx_nic_disable_interrupts(efx);
if (efx->legacy_irq) if (efx->legacy_irq) {
synchronize_irq(efx->legacy_irq); synchronize_irq(efx->legacy_irq);
efx->legacy_irq_enabled = false;
}
if (channel->irq) if (channel->irq)
synchronize_irq(channel->irq); synchronize_irq(channel->irq);
...@@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel) ...@@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel)
efx_channel_processed(channel); efx_channel_processed(channel);
napi_enable(&channel->napi_str); napi_enable(&channel->napi_str);
if (efx->legacy_irq)
efx->legacy_irq_enabled = true;
efx_nic_enable_interrupts(efx); efx_nic_enable_interrupts(efx);
} }
...@@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel) ...@@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
*channel = *old_channel; *channel = *old_channel;
channel->napi_dev = NULL;
memset(&channel->eventq, 0, sizeof(channel->eventq)); memset(&channel->eventq, 0, sizeof(channel->eventq));
rx_queue = &channel->rx_queue; rx_queue = &channel->rx_queue;
...@@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) ...@@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
if (rc) if (rc)
goto rollback; goto rollback;
efx_init_napi(efx);
/* Destroy old channels */ /* Destroy old channels */
for (i = 0; i < efx->n_channels; i++) for (i = 0; i < efx->n_channels; i++) {
efx_fini_napi_channel(other_channel[i]);
efx_remove_channel(other_channel[i]); efx_remove_channel(other_channel[i]);
}
out: out:
/* Free unused channel structures */ /* Free unused channel structures */
for (i = 0; i < efx->n_channels; i++) for (i = 0; i < efx->n_channels; i++)
...@@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx) ...@@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx)
efx_start_channel(channel); efx_start_channel(channel);
} }
if (efx->legacy_irq)
efx->legacy_irq_enabled = true;
efx_nic_enable_interrupts(efx); efx_nic_enable_interrupts(efx);
/* Switch to event based MCDI completions after enabling interrupts. /* Switch to event based MCDI completions after enabling interrupts.
...@@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx) ...@@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx)
/* Disable interrupts and wait for ISR to complete */ /* Disable interrupts and wait for ISR to complete */
efx_nic_disable_interrupts(efx); efx_nic_disable_interrupts(efx);
if (efx->legacy_irq) if (efx->legacy_irq) {
synchronize_irq(efx->legacy_irq); synchronize_irq(efx->legacy_irq);
efx->legacy_irq_enabled = false;
}
efx_for_each_channel(channel, efx) { efx_for_each_channel(channel, efx) {
if (channel->irq) if (channel->irq)
synchronize_irq(channel->irq); synchronize_irq(channel->irq);
...@@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) ...@@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
* *
**************************************************************************/ **************************************************************************/
static int efx_init_napi(struct efx_nic *efx) static void efx_init_napi(struct efx_nic *efx)
{ {
struct efx_channel *channel; struct efx_channel *channel;
...@@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx) ...@@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx)
netif_napi_add(channel->napi_dev, &channel->napi_str, netif_napi_add(channel->napi_dev, &channel->napi_str,
efx_poll, napi_weight); efx_poll, napi_weight);
} }
return 0; }
static void efx_fini_napi_channel(struct efx_channel *channel)
{
if (channel->napi_dev)
netif_napi_del(&channel->napi_str);
channel->napi_dev = NULL;
} }
static void efx_fini_napi(struct efx_nic *efx) static void efx_fini_napi(struct efx_nic *efx)
{ {
struct efx_channel *channel; struct efx_channel *channel;
efx_for_each_channel(channel, efx) { efx_for_each_channel(channel, efx)
if (channel->napi_dev) efx_fini_napi_channel(channel);
netif_napi_del(&channel->napi_str);
channel->napi_dev = NULL;
}
} }
/************************************************************************** /**************************************************************************
...@@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx) ...@@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
if (rc) if (rc)
goto fail1; goto fail1;
rc = efx_init_napi(efx); efx_init_napi(efx);
if (rc)
goto fail2;
rc = efx->type->init(efx); rc = efx->type->init(efx);
if (rc) { if (rc) {
...@@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx) ...@@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx)
efx->type->fini(efx); efx->type->fini(efx);
fail3: fail3:
efx_fini_napi(efx); efx_fini_napi(efx);
fail2:
efx_remove_all(efx); efx_remove_all(efx);
fail1: fail1:
return rc; return rc;
......
...@@ -621,6 +621,7 @@ struct efx_filter_state; ...@@ -621,6 +621,7 @@ struct efx_filter_state;
* @pci_dev: The PCI device * @pci_dev: The PCI device
* @type: Controller type attributes * @type: Controller type attributes
* @legacy_irq: IRQ number * @legacy_irq: IRQ number
* @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)?
* @workqueue: Workqueue for port reconfigures and the HW monitor. * @workqueue: Workqueue for port reconfigures and the HW monitor.
* Work items do not hold and must not acquire RTNL. * Work items do not hold and must not acquire RTNL.
* @workqueue_name: Name of workqueue * @workqueue_name: Name of workqueue
...@@ -709,6 +710,7 @@ struct efx_nic { ...@@ -709,6 +710,7 @@ struct efx_nic {
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
const struct efx_nic_type *type; const struct efx_nic_type *type;
int legacy_irq; int legacy_irq;
bool legacy_irq_enabled;
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
char workqueue_name[16]; char workqueue_name[16];
struct work_struct reset_work; struct work_struct reset_work;
......
...@@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) ...@@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
u32 queues; u32 queues;
int syserr; int syserr;
/* Could this be ours? If interrupts are disabled then the
* channel state may not be valid.
*/
if (!efx->legacy_irq_enabled)
return result;
/* Read the ISR which also ACKs the interrupts */ /* Read the ISR which also ACKs the interrupts */
efx_readd(efx, &reg, FR_BZ_INT_ISR0); efx_readd(efx, &reg, FR_BZ_INT_ISR0);
queues = EFX_EXTRACT_DWORD(reg, 0, 31); queues = EFX_EXTRACT_DWORD(reg, 0, 31);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment