diff options
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/fxp/if_fxp.c | 54 | ||||
| -rw-r--r-- | sys/dev/fxp/if_fxpvar.h | 1 |
2 files changed, 24 insertions, 31 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 63b2b9ec9d7e..9befadbf41bd 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -1239,6 +1239,13 @@ fxp_intr_body(struct fxp_softc *sc, u_int8_t statack, int count) if (rnr) fxp_rnr++; +#ifdef DEVICE_POLLING + /* Pick up a deferred RNR condition if `count' ran out last time. */ + if (sc->flags & FXP_FLAG_DEFERRED_RNR) { + sc->flags &= ~FXP_FLAG_DEFERRED_RNR; + rnr = 1; + } +#endif /* * Free any finished transmit mbuf chains. @@ -1281,47 +1288,40 @@ fxp_intr_body(struct fxp_softc *sc, u_int8_t statack, int count) /* * Just return if nothing happened on the receive side. */ - if ( (statack & (FXP_SCB_STATACK_FR | FXP_SCB_STATACK_RNR)) == 0) + if (!rnr && (statack & FXP_SCB_STATACK_FR) == 0) return; /* * Process receiver interrupts. If a no-resource (RNR) * condition exists, get whatever packets we can and * re-start the receiver. - */ - -#ifdef DEVICE_POLLING - /* + * * When using polling, we do not process the list to completion, * so when we get an RNR interrupt we must defer the restart * until we hit the last buffer with the C bit set. * If we run out of cycles and rfa_headm has the C bit set, - * record the pending RNR in an unused status bit, so that the - * info will be used in the subsequent polling cycle. - * - * XXX there is absolutely no guarantee that this reserved bit - * will be ignored by the hardware! + * record the pending RNR in the FXP_FLAG_DEFERRED_RNR flag so + * that the info will be used in the subsequent polling cycle. */ -#define FXP_RFA_RNRMARK 0x4000 /* used to mark a pending RNR intr */ -#endif - for (;;) { m = sc->rfa_headm; rfa = (struct fxp_rfa *)(m->m_ext.ext_buf + RFA_ALIGNMENT_FUDGE); #ifdef DEVICE_POLLING /* loop at most count times if count >=0 */ - if (count >= 0 && count-- == 0) + if (count >= 0 && count-- == 0) { + if (rnr) { + /* Defer RNR processing until the next time. */ + sc->flags |= FXP_FLAG_DEFERRED_RNR; + rnr = 0; + } break; + } #endif /* DEVICE_POLLING */ if ( (rfa->rfa_status & FXP_RFA_STATUS_C) == 0) break; -#ifdef DEVICE_POLLING - if (rfa->rfa_status & FXP_RFA_RNRMARK) - rnr = 1; -#endif /* * Remove first packet from the chain. */ @@ -1356,19 +1356,11 @@ fxp_intr_body(struct fxp_softc *sc, u_int8_t statack, int count) } } if (rnr) { -#ifdef DEVICE_POLLING - if (rfa->rfa_status & FXP_RFA_STATUS_C) - rfa->rfa_status |= FXP_RFA_RNRMARK; - else { -#endif - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, - vtophys(sc->rfa_headm->m_ext.ext_buf) + - RFA_ALIGNMENT_FUDGE); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START); -#ifdef DEVICE_POLLING - } -#endif + fxp_scb_wait(sc); + CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, + vtophys(sc->rfa_headm->m_ext.ext_buf) + + RFA_ALIGNMENT_FUDGE); + fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START); } } diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h index d18ca393b0e8..1042f1f2f0f3 100644 --- a/sys/dev/fxp/if_fxpvar.h +++ b/sys/dev/fxp/if_fxpvar.h @@ -157,6 +157,7 @@ struct fxp_softc { #define FXP_FLAG_ALL_MCAST 0x0040 /* accept all multicast frames */ #define FXP_FLAG_CU_RESUME_BUG 0x0080 /* requires workaround for CU_RESUME */ #define FXP_FLAG_UCODE 0x0100 /* ucode is loaded */ +#define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */ /* Macros to ease CSR access. */ #define CSR_READ_1(sc, reg) \ |
