napi_schedule(&channel->napi_str);
 }
 
+static inline void efx_schedule_channel_irq(struct efx_channel *channel)
+{
+       channel->last_irq_cpu = raw_smp_processor_id();
+       efx_schedule_channel(channel);
+}
+
 extern void efx_link_status_changed(struct efx_nic *efx);
 extern void efx_link_set_advertising(struct efx_nic *efx, u32);
 extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
 
        falcon_irq_ack_a1(efx);
 
        if (queues & 1)
-               efx_schedule_channel(efx_get_channel(efx, 0));
+               efx_schedule_channel_irq(efx_get_channel(efx, 0));
        if (queues & 2)
-               efx_schedule_channel(efx_get_channel(efx, 1));
+               efx_schedule_channel_irq(efx_get_channel(efx, 1));
        return IRQ_HANDLED;
 }
 /**************************************************************************
 
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
+ * @last_irq_cpu: Last CPU to handle interrupt for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
        unsigned int eventq_read_ptr;
        unsigned int last_eventq_read_ptr;
 
+       int last_irq_cpu;
        unsigned int irq_count;
        unsigned int irq_mod_score;
 #ifdef CONFIG_RFS_ACCEL
  * @int_error_expire: Time at which error count will be expired
  * @irq_status: Interrupt status buffer
  * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
- * @fatal_irq_level: IRQ level (bit number) used for serious errors
+ * @irq_level: IRQ level/index for IRQs not triggered by an event queue
  * @mtd_list: List of MTDs attached to the NIC
  * @nic_data: Hardware dependent state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
  * @loopback_selftest: Offline self-test private state
  * @monitor_work: Hardware monitor workitem
  * @biu_lock: BIU (bus interface unit) lock
- * @last_irq_cpu: Last CPU to handle interrupt.
- *     This register is written with the SMP processor ID whenever an
- *     interrupt is handled.  It is used by efx_nic_test_interrupt()
- *     to verify that an interrupt has occurred.
+ * @last_irq_cpu: Last CPU to handle a possible test interrupt.  This
+ *     field is used by efx_test_interrupts() to verify that an
+ *     interrupt has occurred.
  * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
  * @mac_stats: MAC statistics. These include all statistics the MACs
  *     can provide.  Generic code converts these into a standard
 
        struct efx_buffer irq_status;
        unsigned irq_zero_count;
-       unsigned fatal_irq_level;
+       unsigned irq_level;
 
 #ifdef CONFIG_SFC_MTD
        struct list_head mtd_list;
 
        struct delayed_work monitor_work ____cacheline_aligned_in_smp;
        spinlock_t biu_lock;
-       volatile signed int last_irq_cpu;
+       int last_irq_cpu;
        unsigned n_rx_nodesc_drop_cnt;
        struct efx_mac_stats mac_stats;
        spinlock_t stats_lock;
 
        efx_oword_t int_en_reg_ker;
 
        EFX_POPULATE_OWORD_3(int_en_reg_ker,
-                            FRF_AZ_KER_INT_LEVE_SEL, efx->fatal_irq_level,
+                            FRF_AZ_KER_INT_LEVE_SEL, efx->irq_level,
                             FRF_AZ_KER_INT_KER, force,
                             FRF_AZ_DRV_INT_EN_KER, enabled);
        efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
        efx_readd(efx, ®, FR_BZ_INT_ISR0);
        queues = EFX_EXTRACT_DWORD(reg, 0, 31);
 
-       /* Check to see if we have a serious error condition */
-       if (queues & (1U << efx->fatal_irq_level)) {
+       /* Handle non-event-queue sources */
+       if (queues & (1U << efx->irq_level)) {
                syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
                if (unlikely(syserr))
                        return efx_nic_fatal_interrupt(efx);
+               efx->last_irq_cpu = raw_smp_processor_id();
        }
 
        if (queues != 0) {
                /* Schedule processing of any interrupting queues */
                efx_for_each_channel(channel, efx) {
                        if (queues & 1)
-                               efx_schedule_channel(channel);
+                               efx_schedule_channel_irq(channel);
                        queues >>= 1;
                }
                result = IRQ_HANDLED;
                efx_for_each_channel(channel, efx) {
                        event = efx_event(channel, channel->eventq_read_ptr);
                        if (efx_event_present(event))
-                               efx_schedule_channel(channel);
+                               efx_schedule_channel_irq(channel);
                        else
                                efx_nic_eventq_read_ack(channel);
                }
        }
 
-       if (result == IRQ_HANDLED) {
-               efx->last_irq_cpu = raw_smp_processor_id();
+       if (result == IRQ_HANDLED)
                netif_vdbg(efx, intr, efx->net_dev,
                           "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
                           irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
-       }
 
        return result;
 }
        efx_oword_t *int_ker = efx->irq_status.addr;
        int syserr;
 
-       efx->last_irq_cpu = raw_smp_processor_id();
        netif_vdbg(efx, intr, efx->net_dev,
                   "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
                   irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
 
-       /* Check to see if we have a serious error condition */
-       if (channel->channel == efx->fatal_irq_level) {
+       /* Handle non-event-queue sources */
+       if (channel->channel == efx->irq_level) {
                syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
                if (unlikely(syserr))
                        return efx_nic_fatal_interrupt(efx);
+               efx->last_irq_cpu = raw_smp_processor_id();
        }
 
        /* Schedule processing of the channel */
-       efx_schedule_channel(channel);
+       efx_schedule_channel_irq(channel);
 
        return IRQ_HANDLED;
 }
 
        if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
                /* Use an interrupt level unused by event queues */
-               efx->fatal_irq_level = 0x1f;
+               efx->irq_level = 0x1f;
        else
                /* Use a valid MSI-X vector */
-               efx->fatal_irq_level = 0;
+               efx->irq_level = 0;
 
        /* Enable all the genuinely fatal interrupts.  (They are still
         * masked by the overall interrupt mask, controlled by
 
 static int efx_test_interrupts(struct efx_nic *efx,
                               struct efx_self_tests *tests)
 {
+       int cpu;
+
        netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
        tests->interrupt = -1;
 
        /* Wait for arrival of test interrupt. */
        netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
        schedule_timeout_uninterruptible(HZ / 10);
-       if (efx->last_irq_cpu >= 0)
+       cpu = ACCESS_ONCE(efx->last_irq_cpu);
+       if (cpu >= 0)
                goto success;
 
        netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n");
 
  success:
        netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n",
-                 INT_MODE(efx),
-               efx->last_irq_cpu);
+                 INT_MODE(efx), cpu);
        tests->interrupt = 1;
        return 0;
 }
        bool napi_ran, dma_seen, int_seen;
 
        read_ptr = channel->eventq_read_ptr;
-       channel->efx->last_irq_cpu = -1;
+       channel->last_irq_cpu = -1;
        smp_wmb();
 
        efx_nic_generate_test_event(channel);
        } else {
                napi_ran = false;
                dma_seen = efx_nic_event_present(channel);
-               int_seen = efx->last_irq_cpu >= 0;
+               int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0;
        }
        napi_enable(&channel->napi_str);
        efx_nic_eventq_read_ack(channel);