diff options
author | imp <imp@FreeBSD.org> | 2007-02-15 07:13:38 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2007-02-15 07:13:38 +0000 |
commit | b0a1de450233d09e5dd7d67549686aff67b8ddc1 (patch) | |
tree | 22ce65edf23786281f64fae61a2e8a80eb9a9597 | |
parent | 757700b4439fdd83fc5ff5de3504d213c2082cf9 (diff) | |
download | FreeBSD-src-b0a1de450233d09e5dd7d67549686aff67b8ddc1.zip FreeBSD-src-b0a1de450233d09e5dd7d67549686aff67b8ddc1.tar.gz |
Fix three bugs:
o When detaching all children, try really hard to get all the children
list before giving up. This is based on an observation by hans petter
selasky in his usb p4 branch.
o When rescanning devices after a driver is added, abort if we can't get
the child list with a message.
o when rescanning devices, if the reprobe/attach is successful, save the
device for cardbus/pccard.
-rw-r--r-- | sys/dev/pccbb/pccbb.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index 4971e89..a7cb56b 100644 --- a/sys/dev/pccbb/pccbb.c +++ b/sys/dev/pccbb/pccbb.c @@ -281,10 +281,8 @@ int cbb_detach(device_t brdev) { struct cbb_softc *sc = device_get_softc(brdev); - int numdevs; device_t *devlist; - int tmp; - int error; + int tmp, tries, error, numdevs; /* * Before we delete the children (which we have to do because @@ -302,7 +300,19 @@ cbb_detach(device_t brdev) * for the kldload/unload case to work. If we failed to do that, then * we'd get duplicate devices when cbb.ko was reloaded. */ - device_get_children(brdev, &devlist, &numdevs); + tries = 10; + do { + error = device_get_children(brdev, &devlist, &numdevs); + if (error == 0) + break; + /* + * Try hard to cope with low memory. + */ + if (error == ENOMEM) { + tsleep(sc, PZERO, "cbbnomem", 1); + continue; + } + } while (tries-- > 0); for (tmp = 0; tmp < numdevs; tmp++) device_delete_child(brdev, devlist[tmp]); free(devlist, M_TEMP); @@ -413,12 +423,21 @@ cbb_driver_added(device_t brdev, driver_t *driver) int wake = 0; DEVICE_IDENTIFY(driver, brdev); - device_get_children(brdev, &devlist, &numdevs); + tmp = device_get_children(brdev, &devlist, &numdevs); + if (tmp != 0) { + device_printf(brdev, "Cannot get children list, no reprobe\n"); + return; + } for (tmp = 0; tmp < numdevs; tmp++) { dev = devlist[tmp]; if (device_get_state(dev) == DS_NOTPRESENT && - device_probe_and_attach(dev) == 0) + device_probe_and_attach(dev) == 0) { wake++; + if (strcmp(device_get_name(dev), "cardbus") == 0) + sc->cbdev = dev; + else if (strcmp(device_get_name(dev), "pccard") == 0) + sc->exca[0].pccarddev = dev; + } } free(devlist, M_TEMP); |