Get rid of the redundant 'gone' field, and overload suspend instead.

Check for suspend before the device polling, rather than after it.
Check to see if the current thread owns the lock in ioctl and return
EBUSY if it does.

This advances the locking to the point that I can eject my fxp card 10
times in a row, but I agree with Jeff Hsu that we need to get the
network layer locking finished before chasing more of the races here
(actually, he doesn't think this set is worth it even).  There's a
number of races between FXP_LOCK in detach and all other users of
FXP_LOCK, and this gets back to the 'device with sleepers being
forcibly detached' problem as well...
This commit is contained in:
Warner Losh 2003-04-30 01:54:38 +00:00
parent 5c29a450ae
commit 704d196541
2 changed files with 13 additions and 14 deletions

View File

@ -881,7 +881,7 @@ fxp_detach(device_t dev)
FXP_LOCK(sc);
s = splimp();
sc->gone = 1;
sc->suspend = 1; /* Do same thing as we do for suspend */
/*
* Close down routes etc.
*/
@ -1499,10 +1499,12 @@ fxp_intr(void *xsc)
struct ifnet *ifp = &sc->sc_if;
u_int8_t statack;
if (sc->gone)
return;
FXP_LOCK(sc);
if (sc->suspended) {
FXP_UNLOCK(sc);
return;
}
#ifdef DEVICE_POLLING
if (ifp->if_flags & IFF_POLLING) {
FXP_UNLOCK(sc);
@ -1516,12 +1518,6 @@ fxp_intr(void *xsc)
return;
}
#endif
if (sc->suspended) {
FXP_UNLOCK(sc);
return;
}
while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) {
/*
* It should not be possible to have all bits set; the
@ -2362,8 +2358,12 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int s, error = 0;
if (sc->gone)
return (ENODEV);
/*
* Detaching causes us to call ioctl with the mutex owned. Preclude
* that by saying we're busy if the lock is already held.
*/
if (mtx_owned(&sc->sc_mtx))
return (EBUSY);
FXP_LOCK(sc);
s = splimp();

View File

@ -185,11 +185,10 @@ struct fxp_softc {
int tunable_int_delay; /* interrupt delay value for ucode */
int tunable_bundle_max; /* max # frames per interrupt (ucode) */
int eeprom_size; /* size of serial EEPROM */
int suspended; /* 0 = normal 1 = suspended (APM) */
int suspended; /* 0 = normal 1 = suspended or dead */
int cu_resume_bug;
int revision;
int flags;
int gone;
u_int32_t saved_maps[5]; /* pci data */
u_int32_t saved_biosaddr;
u_int8_t saved_intline;