irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) { struct efx_nic *efx = dev_id; efx_oword_t *int_ker = efx->irq_status.addr; int syserr; int queues; if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) { netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d not for me\n", irq, raw_smp_processor_id()); return IRQ_NONE; } 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)); syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); EFX_ZERO_OWORD(*int_ker); wmb(); falcon_irq_ack_a1(efx); if (queues & 1) efx_schedule_channel_irq(efx_get_channel(efx, 0)); if (queues & 2) efx_schedule_channel_irq(efx_get_channel(efx, 1)); return IRQ_HANDLED; }
irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) { struct efx_nic *efx = dev_id; efx_oword_t *int_ker = efx->irq_status.addr; struct efx_channel *channel; int syserr; int queues; /* Check to see if this is our interrupt. If it isn't, we * exit without having touched the hardware. */ if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) { EFX_TRACE(efx, "IRQ %d on CPU %d not for me\n", irq, raw_smp_processor_id()); return IRQ_NONE; } efx->last_irq_cpu = raw_smp_processor_id(); EFX_TRACE(efx, "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 */ syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); /* Determine interrupting queues, clear interrupt status * register and acknowledge the device interrupt. */ BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); EFX_ZERO_OWORD(*int_ker); wmb(); /* Ensure the vector is cleared before interrupt ack */ falcon_irq_ack_a1(efx); /* Schedule processing of any interrupting queues */ channel = &efx->channel[0]; while (queues) { if (queues & 0x01) efx_schedule_channel(channel); channel++; queues >>= 1; } return IRQ_HANDLED; }
/* Wait for GMII access to complete */ static int falcon_gmii_wait(struct efx_nic *efx) { efx_oword_t md_stat; int count; /* wait upto 50ms - taken max from datasheet */ for (count = 0; count < 5000; count++) { efx_reado(efx, &md_stat, FR_AB_MD_STAT); if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) { if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 || EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) { EFX_ERR(efx, "error from GMII access " EFX_OWORD_FMT"\n", EFX_OWORD_VAL(md_stat)); return -EIO; } return 0; } udelay(10); } EFX_ERR(efx, "timed out waiting for GMII\n"); return -ETIMEDOUT; }
static int falcon_gmii_wait(struct efx_nic *efx) { efx_oword_t md_stat; int count; for (count = 0; count < 5000; count++) { efx_reado(efx, &md_stat, FR_AB_MD_STAT); if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) { if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 || EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) { netif_err(efx, hw, efx->net_dev, "error from GMII access " EFX_OWORD_FMT"\n", EFX_OWORD_VAL(md_stat)); return -EIO; } return 0; } udelay(10); } netif_err(efx, hw, efx->net_dev, "timed out waiting for GMII\n"); return -ETIMEDOUT; }