1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

More cleanup when detaching. Clone device entries will now be

destroyed properly (otherwise bad things would happen after a clone
dev had been created, and the module was kldunloaded).  Allocated
children that have not successfully probed are being deleted again
(otherwise fd0 and fd1 have always been allocated, even if only
fd0 was acutally present, and fd1 even survived kldunloading the
module).

Still, kldunloading leaves remnants of the previously existing devices
intact.  Why doesn't it destroy all the devices?  As a consequence,
since dev->descr now points into no longer allocated memory, the
system panics deep inside printf(9) when running devinfo(1) after
kldunloading the module.  Ideas sought...

Also, when kldloading the module on a hints-populated isab0, this bus
somehow has already created an fdc0 entry (a dummy) so the load
attempt fails and will register fdc1 instead.  What are those dummy
entries for?  Loading the module from the bootloader works, and it
can be unloaded an re-loaded then later.
This commit is contained in:
Joerg Wunsch 2001-07-04 22:10:33 +00:00
parent 616203938d
commit 6044485346
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=79254
2 changed files with 82 additions and 34 deletions

View File

@ -181,6 +181,8 @@ struct fd_data {
struct devstat device_stats;
eventhandler_tag clonetag;
dev_t masterdev;
#define NCLONEDEVS 10 /* must match the table below */
dev_t clonedevs[NCLONEDEVS];
device_t dev;
fdu_t fdu;
};
@ -832,8 +834,9 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error, dunit;
const char *name, *dname;
device_t *children;
int i, error, dunit, nchildren;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -875,7 +878,17 @@ fdc_attach(device_t dev)
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
if ((error = bus_generic_attach(dev)) != 0)
return (error);
/* Now remove all children not successfully probed (if any). */
if ((error = device_get_children(dev, &children, &nchildren)) != 0)
return (error);
for (i = 0; i < nchildren; i++)
if (!device_is_alive(children[i]))
device_delete_child(dev, children[i]);
return (0);
}
static int
@ -949,14 +962,10 @@ static struct {
int minor;
int link;
} fd_suffix[] = {
{ "a", 0, 1 },
{ "b", 0, 1 },
{ "c", 0, 1 },
{ "d", 0, 1 },
{ "e", 0, 1 },
{ "f", 0, 1 },
{ "g", 0, 1 },
{ "h", 0, 1 },
/*
* Genuine clone devices must come first, and their number must
* match NCLONEDEVS above.
*/
{ ".1720", 1, 0 },
{ ".1480", 2, 0 },
{ ".1440", 3, 0 },
@ -967,15 +976,24 @@ static struct {
{ ".360", 8, 0 },
{ ".640", 9, 0 },
{ ".1232", 10, 0 },
{ "a", 0, 1 },
{ "b", 0, 1 },
{ "c", 0, 1 },
{ "d", 0, 1 },
{ "e", 0, 1 },
{ "f", 0, 1 },
{ "g", 0, 1 },
{ "h", 0, 1 },
{ 0, 0 }
};
static void
fd_clone (void *arg, char *name, int namelen, dev_t *dev)
fd_clone(void *arg, char *name, int namelen, dev_t *dev)
{
struct fd_data *fd;
int u, d, i;
char *n;
dev_t pdev;
fd = (struct fd_data *)arg;
if (*dev != NODEV)
return;
if (dev_stdclone(name, &n, "fd", &u) != 2)
@ -991,9 +1009,9 @@ fd_clone (void *arg, char *name, int namelen, dev_t *dev)
if (fd_suffix[i].link == 0) {
*dev = make_dev(&fd_cdevsw, (u << 6) + d,
UID_ROOT, GID_OPERATOR, 0640, name);
fd->clonedevs[i] = *dev;
} else {
pdev = makedev(fd_cdevsw.d_maj, (u << 6) + d);
*dev = make_dev_alias(pdev, name);
*dev = make_dev_alias(fd->masterdev, name);
}
}
@ -1148,15 +1166,18 @@ fd_attach(device_t dev)
{
struct fd_data *fd;
static int cdevsw_add_done;
int i;
if (!cdevsw_add_done) {
cdevsw_add(&fd_cdevsw); /* XXX */
cdevsw_add_done = 1;
}
fd = device_get_softc(dev);
fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, 0, 1000);
fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, fd, 1000);
fd->masterdev = make_dev(&fd_cdevsw, fd->fdu << 6,
UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
for (i = 0; i < NCLONEDEVS; i++)
fd->clonedevs[i] = NODEV;
devstat_add_entry(&fd->device_stats, device_get_name(dev),
device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
@ -1168,14 +1189,17 @@ static int
fd_detach(device_t dev)
{
struct fd_data *fd;
int i;
fd = device_get_softc(dev);
untimeout(fd_turnoff, fd, fd->toffhandle);
devstat_remove_entry(&fd->device_stats);
destroy_dev(fd->masterdev);
for (i = 0; i < NCLONEDEVS; i++)
if (fd->clonedevs[i] != NODEV)
destroy_dev(fd->clonedevs[i]);
cdevsw_remove(&fd_cdevsw);
/* XXX need to destroy cloned devs as well */
EVENTHANDLER_DEREGISTER(dev_clone, fd->clonetag);
untimeout(fd_turnoff, fd, fd->toffhandle);
return (0);
}

View File

@ -181,6 +181,8 @@ struct fd_data {
struct devstat device_stats;
eventhandler_tag clonetag;
dev_t masterdev;
#define NCLONEDEVS 10 /* must match the table below */
dev_t clonedevs[NCLONEDEVS];
device_t dev;
fdu_t fdu;
};
@ -832,8 +834,9 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error, dunit;
const char *name, *dname;
device_t *children;
int i, error, dunit, nchildren;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -875,7 +878,17 @@ fdc_attach(device_t dev)
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
if ((error = bus_generic_attach(dev)) != 0)
return (error);
/* Now remove all children not successfully probed (if any). */
if ((error = device_get_children(dev, &children, &nchildren)) != 0)
return (error);
for (i = 0; i < nchildren; i++)
if (!device_is_alive(children[i]))
device_delete_child(dev, children[i]);
return (0);
}
static int
@ -949,14 +962,10 @@ static struct {
int minor;
int link;
} fd_suffix[] = {
{ "a", 0, 1 },
{ "b", 0, 1 },
{ "c", 0, 1 },
{ "d", 0, 1 },
{ "e", 0, 1 },
{ "f", 0, 1 },
{ "g", 0, 1 },
{ "h", 0, 1 },
/*
* Genuine clone devices must come first, and their number must
* match NCLONEDEVS above.
*/
{ ".1720", 1, 0 },
{ ".1480", 2, 0 },
{ ".1440", 3, 0 },
@ -967,15 +976,24 @@ static struct {
{ ".360", 8, 0 },
{ ".640", 9, 0 },
{ ".1232", 10, 0 },
{ "a", 0, 1 },
{ "b", 0, 1 },
{ "c", 0, 1 },
{ "d", 0, 1 },
{ "e", 0, 1 },
{ "f", 0, 1 },
{ "g", 0, 1 },
{ "h", 0, 1 },
{ 0, 0 }
};
static void
fd_clone (void *arg, char *name, int namelen, dev_t *dev)
fd_clone(void *arg, char *name, int namelen, dev_t *dev)
{
struct fd_data *fd;
int u, d, i;
char *n;
dev_t pdev;
fd = (struct fd_data *)arg;
if (*dev != NODEV)
return;
if (dev_stdclone(name, &n, "fd", &u) != 2)
@ -991,9 +1009,9 @@ fd_clone (void *arg, char *name, int namelen, dev_t *dev)
if (fd_suffix[i].link == 0) {
*dev = make_dev(&fd_cdevsw, (u << 6) + d,
UID_ROOT, GID_OPERATOR, 0640, name);
fd->clonedevs[i] = *dev;
} else {
pdev = makedev(fd_cdevsw.d_maj, (u << 6) + d);
*dev = make_dev_alias(pdev, name);
*dev = make_dev_alias(fd->masterdev, name);
}
}
@ -1148,15 +1166,18 @@ fd_attach(device_t dev)
{
struct fd_data *fd;
static int cdevsw_add_done;
int i;
if (!cdevsw_add_done) {
cdevsw_add(&fd_cdevsw); /* XXX */
cdevsw_add_done = 1;
}
fd = device_get_softc(dev);
fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, 0, 1000);
fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, fd, 1000);
fd->masterdev = make_dev(&fd_cdevsw, fd->fdu << 6,
UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
for (i = 0; i < NCLONEDEVS; i++)
fd->clonedevs[i] = NODEV;
devstat_add_entry(&fd->device_stats, device_get_name(dev),
device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
@ -1168,14 +1189,17 @@ static int
fd_detach(device_t dev)
{
struct fd_data *fd;
int i;
fd = device_get_softc(dev);
untimeout(fd_turnoff, fd, fd->toffhandle);
devstat_remove_entry(&fd->device_stats);
destroy_dev(fd->masterdev);
for (i = 0; i < NCLONEDEVS; i++)
if (fd->clonedevs[i] != NODEV)
destroy_dev(fd->clonedevs[i]);
cdevsw_remove(&fd_cdevsw);
/* XXX need to destroy cloned devs as well */
EVENTHANDLER_DEREGISTER(dev_clone, fd->clonetag);
untimeout(fd_turnoff, fd, fd->toffhandle);
return (0);
}