|
@@ -191,8 +191,8 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
|
|
|
*
|
|
|
*************************************************************************/
|
|
|
|
|
|
-static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq);
|
|
|
-static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq);
|
|
|
+static void efx_soft_enable_interrupts(struct efx_nic *efx);
|
|
|
+static void efx_soft_disable_interrupts(struct efx_nic *efx);
|
|
|
static void efx_remove_channel(struct efx_channel *channel);
|
|
|
static void efx_remove_channels(struct efx_nic *efx);
|
|
|
static const struct efx_channel_type efx_default_channel_type;
|
|
@@ -520,8 +520,8 @@ static void efx_set_channel_names(struct efx_nic *efx)
|
|
|
|
|
|
efx_for_each_channel(channel, efx)
|
|
|
channel->type->get_name(channel,
|
|
|
- efx->channel_name[channel->channel],
|
|
|
- sizeof(efx->channel_name[0]));
|
|
|
+ efx->msi_context[channel->channel].name,
|
|
|
+ sizeof(efx->msi_context[0].name));
|
|
|
}
|
|
|
|
|
|
static int efx_probe_channels(struct efx_nic *efx)
|
|
@@ -746,7 +746,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
|
|
|
|
|
|
efx_device_detach_sync(efx);
|
|
|
efx_stop_all(efx);
|
|
|
- efx_stop_interrupts(efx, true);
|
|
|
+ efx_soft_disable_interrupts(efx);
|
|
|
|
|
|
/* Clone channels (where possible) */
|
|
|
memset(other_channel, 0, sizeof(other_channel));
|
|
@@ -796,7 +796,7 @@ out:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- efx_start_interrupts(efx, true);
|
|
|
+ efx_soft_enable_interrupts(efx);
|
|
|
efx_start_all(efx);
|
|
|
netif_device_attach(efx->net_dev);
|
|
|
return rc;
|
|
@@ -1329,23 +1329,17 @@ static int efx_probe_interrupts(struct efx_nic *efx)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Enable interrupts, then probe and start the event queues */
|
|
|
-static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
|
|
|
+static void efx_soft_enable_interrupts(struct efx_nic *efx)
|
|
|
{
|
|
|
struct efx_channel *channel;
|
|
|
|
|
|
BUG_ON(efx->state == STATE_DISABLED);
|
|
|
|
|
|
- if (efx->eeh_disabled_legacy_irq) {
|
|
|
- enable_irq(efx->legacy_irq);
|
|
|
- efx->eeh_disabled_legacy_irq = false;
|
|
|
- }
|
|
|
- if (efx->legacy_irq)
|
|
|
- efx->legacy_irq_enabled = true;
|
|
|
- efx_nic_enable_interrupts(efx);
|
|
|
+ efx->irq_soft_enabled = true;
|
|
|
+ smp_wmb();
|
|
|
|
|
|
efx_for_each_channel(channel, efx) {
|
|
|
- if (!channel->type->keep_eventq || !may_keep_eventq)
|
|
|
+ if (!channel->type->keep_eventq)
|
|
|
efx_init_eventq(channel);
|
|
|
efx_start_eventq(channel);
|
|
|
}
|
|
@@ -1353,7 +1347,7 @@ static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
|
|
|
efx_mcdi_mode_event(efx);
|
|
|
}
|
|
|
|
|
|
-static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
|
|
|
+static void efx_soft_disable_interrupts(struct efx_nic *efx)
|
|
|
{
|
|
|
struct efx_channel *channel;
|
|
|
|
|
@@ -1362,22 +1356,57 @@ static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
|
|
|
|
|
|
efx_mcdi_mode_poll(efx);
|
|
|
|
|
|
- efx_nic_disable_interrupts(efx);
|
|
|
- if (efx->legacy_irq) {
|
|
|
+ efx->irq_soft_enabled = false;
|
|
|
+ smp_wmb();
|
|
|
+
|
|
|
+ if (efx->legacy_irq)
|
|
|
synchronize_irq(efx->legacy_irq);
|
|
|
- efx->legacy_irq_enabled = false;
|
|
|
- }
|
|
|
|
|
|
efx_for_each_channel(channel, efx) {
|
|
|
if (channel->irq)
|
|
|
synchronize_irq(channel->irq);
|
|
|
|
|
|
efx_stop_eventq(channel);
|
|
|
- if (!channel->type->keep_eventq || !may_keep_eventq)
|
|
|
+ if (!channel->type->keep_eventq)
|
|
|
efx_fini_eventq(channel);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void efx_enable_interrupts(struct efx_nic *efx)
|
|
|
+{
|
|
|
+ struct efx_channel *channel;
|
|
|
+
|
|
|
+ BUG_ON(efx->state == STATE_DISABLED);
|
|
|
+
|
|
|
+ if (efx->eeh_disabled_legacy_irq) {
|
|
|
+ enable_irq(efx->legacy_irq);
|
|
|
+ efx->eeh_disabled_legacy_irq = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ efx_nic_enable_interrupts(efx);
|
|
|
+
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (channel->type->keep_eventq)
|
|
|
+ efx_init_eventq(channel);
|
|
|
+ }
|
|
|
+
|
|
|
+ efx_soft_enable_interrupts(efx);
|
|
|
+}
|
|
|
+
|
|
|
+static void efx_disable_interrupts(struct efx_nic *efx)
|
|
|
+{
|
|
|
+ struct efx_channel *channel;
|
|
|
+
|
|
|
+ efx_soft_disable_interrupts(efx);
|
|
|
+
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (channel->type->keep_eventq)
|
|
|
+ efx_fini_eventq(channel);
|
|
|
+ }
|
|
|
+
|
|
|
+ efx_nic_disable_interrupts(efx);
|
|
|
+}
|
|
|
+
|
|
|
static void efx_remove_interrupts(struct efx_nic *efx)
|
|
|
{
|
|
|
struct efx_channel *channel;
|
|
@@ -2160,7 +2189,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
|
|
|
EFX_ASSERT_RESET_SERIALISED(efx);
|
|
|
|
|
|
efx_stop_all(efx);
|
|
|
- efx_stop_interrupts(efx, false);
|
|
|
+ efx_disable_interrupts(efx);
|
|
|
|
|
|
mutex_lock(&efx->mac_lock);
|
|
|
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
|
|
@@ -2199,7 +2228,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
|
|
|
|
|
|
efx->type->reconfigure_mac(efx);
|
|
|
|
|
|
- efx_start_interrupts(efx, false);
|
|
|
+ efx_enable_interrupts(efx);
|
|
|
efx_restore_filters(efx);
|
|
|
efx_sriov_reset(efx);
|
|
|
|
|
@@ -2464,6 +2493,8 @@ static int efx_init_struct(struct efx_nic *efx,
|
|
|
efx->channel[i] = efx_alloc_channel(efx, i, NULL);
|
|
|
if (!efx->channel[i])
|
|
|
goto fail;
|
|
|
+ efx->msi_context[i].efx = efx;
|
|
|
+ efx->msi_context[i].index = i;
|
|
|
}
|
|
|
|
|
|
EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
|
|
@@ -2516,7 +2547,7 @@ static void efx_pci_remove_main(struct efx_nic *efx)
|
|
|
BUG_ON(efx->state == STATE_READY);
|
|
|
cancel_work_sync(&efx->reset_work);
|
|
|
|
|
|
- efx_stop_interrupts(efx, false);
|
|
|
+ efx_disable_interrupts(efx);
|
|
|
efx_nic_fini_interrupt(efx);
|
|
|
efx_fini_port(efx);
|
|
|
efx->type->fini(efx);
|
|
@@ -2538,7 +2569,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
|
|
|
/* Mark the NIC as fini, then stop the interface */
|
|
|
rtnl_lock();
|
|
|
dev_close(efx->net_dev);
|
|
|
- efx_stop_interrupts(efx, false);
|
|
|
+ efx_disable_interrupts(efx);
|
|
|
rtnl_unlock();
|
|
|
|
|
|
efx_sriov_fini(efx);
|
|
@@ -2640,7 +2671,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
|
|
|
rc = efx_nic_init_interrupt(efx);
|
|
|
if (rc)
|
|
|
goto fail5;
|
|
|
- efx_start_interrupts(efx, false);
|
|
|
+ efx_enable_interrupts(efx);
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -2761,7 +2792,7 @@ static int efx_pm_freeze(struct device *dev)
|
|
|
efx_device_detach_sync(efx);
|
|
|
|
|
|
efx_stop_all(efx);
|
|
|
- efx_stop_interrupts(efx, false);
|
|
|
+ efx_disable_interrupts(efx);
|
|
|
}
|
|
|
|
|
|
rtnl_unlock();
|
|
@@ -2776,7 +2807,7 @@ static int efx_pm_thaw(struct device *dev)
|
|
|
rtnl_lock();
|
|
|
|
|
|
if (efx->state != STATE_DISABLED) {
|
|
|
- efx_start_interrupts(efx, false);
|
|
|
+ efx_enable_interrupts(efx);
|
|
|
|
|
|
mutex_lock(&efx->mac_lock);
|
|
|
efx->phy_op->reconfigure(efx);
|
|
@@ -2879,7 +2910,7 @@ static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev,
|
|
|
efx_device_detach_sync(efx);
|
|
|
|
|
|
efx_stop_all(efx);
|
|
|
- efx_stop_interrupts(efx, false);
|
|
|
+ efx_disable_interrupts(efx);
|
|
|
|
|
|
status = PCI_ERS_RESULT_NEED_RESET;
|
|
|
} else {
|