summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/bge/if_bge.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 5bd13cb..3363584 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -2978,13 +2978,32 @@ bge_intr(void *xsc)
#endif
/*
+ * Ack the interrupt by writing something to BGE_MBX_IRQ0_LO. Don't
+ * disable interrupts by writing nonzero like we used to, since with
+ * our current organization this just gives complications and
+ * pessimizations for re-enabling interrupts. We used to have races
+ * instead of the necessary complications. Disabling interrupts
+ * would just reduce the chance of a status update while we are
+ * running (by switching to the interrupt-mode coalescence
+ * parameters), but this chance is already very low so it is more
+ * efficient to get another interrupt than prevent it.
+ *
+ * We do the ack first to ensure another interrupt if there is a
+ * status update after the ack. We don't check for the status
+ * changing later because it is more efficient to get another
+ * interrupt than prevent it, not quite as above (not checking is
+ * a smaller optimization than not toggling the interrupt enable,
+ * since checking doesn't involve PCI accesses and toggling require
+ * the status check). So toggling would probably be a pessimization
+ * even with MSI. It would only be needed for using a task queue.
+ */
+ CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+
+ /*
* Do the mandatory PCI flush as well as get the link status.
*/
statusword = CSR_READ_4(sc, BGE_MAC_STS) & BGE_MACSTAT_LINK_CHANGED;
- /* Ack interrupt and stop others from occuring. */
- CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
-
/* Make sure the descriptor ring indexes are coherent. */
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
sc->bge_cdata.bge_status_map, BUS_DMASYNC_POSTREAD);
@@ -3004,9 +3023,6 @@ bge_intr(void *xsc)
bge_txeof(sc);
}
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
-
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bge_start_locked(ifp);
OpenPOWER on IntegriCloud