Rearrange interrupt handler a bit and remove forever loop.

Previously dc(4) always checked whether there is pending interrupts
and this consumed a lot of CPU cycles in interrupt handler. Limit
the number of processing for TX/RX frames to 16. Also allow sending
frames in the loop not to starve TX under high RX load.
Reading DC_ISR register should be protected with driver lock,
otherwise interrupt handler could be run(e.g. link state change)
before the completion of dc_init_locked().

While I'm here remove unneeded code.
This commit is contained in:
Pyun YongHyeon 2011-02-19 01:37:28 +00:00
parent 76d40c8593
commit a84b4e80ca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=218831

View File

@ -3135,16 +3135,19 @@ dc_intr(void *arg)
struct dc_softc *sc;
struct ifnet *ifp;
u_int32_t status;
int curpkts, n;
sc = arg;
if (sc->suspended)
return;
if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
return;
DC_LOCK(sc);
status = CSR_READ_4(sc, DC_ISR);
if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) {
DC_UNLOCK(sc);
return;
}
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
@ -3152,26 +3155,16 @@ dc_intr(void *arg)
return;
}
#endif
/* Suppress unwanted interrupts */
if (!(ifp->if_flags & IFF_UP)) {
if (CSR_READ_4(sc, DC_ISR) & DC_INTRS)
dc_stop(sc);
DC_UNLOCK(sc);
return;
}
/* Disable interrupts. */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) &&
status != 0xFFFFFFFF &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
for (n = 16; n > 0; n--) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
/* Ack interrupts. */
CSR_WRITE_4(sc, DC_ISR, status);
if (status & DC_ISR_RX_OK) {
int curpkts;
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
@ -3196,7 +3189,6 @@ dc_intr(void *arg)
if ((status & DC_ISR_RX_WATDOGTIMEO)
|| (status & DC_ISR_RX_NOBUF)) {
int curpkts;
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
@ -3205,17 +3197,23 @@ dc_intr(void *arg)
}
}
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start_locked(ifp);
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
dc_init_locked(sc);
DC_UNLOCK(sc);
return;
}
status = CSR_READ_4(sc, DC_ISR);
if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0)
break;
}
/* Re-enable interrupts. */
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start_locked(ifp);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
DC_UNLOCK(sc);
}