summaryrefslogtreecommitdiffstats
path: root/sys/dev/pccbb
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2007-02-15 07:13:38 +0000
committerimp <imp@FreeBSD.org>2007-02-15 07:13:38 +0000
commitb0a1de450233d09e5dd7d67549686aff67b8ddc1 (patch)
tree22ce65edf23786281f64fae61a2e8a80eb9a9597 /sys/dev/pccbb
parent757700b4439fdd83fc5ff5de3504d213c2082cf9 (diff)
downloadFreeBSD-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.
Diffstat (limited to 'sys/dev/pccbb')
-rw-r--r--sys/dev/pccbb/pccbb.c31
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);
OpenPOWER on IntegriCloud