summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/kern_conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/kern/kern_conf.c')
-rw-r--r--freebsd/sys/kern/kern_conf.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/freebsd/sys/kern/kern_conf.c b/freebsd/sys/kern/kern_conf.c
index 8605cc43..e1553915 100644
--- a/freebsd/sys/kern/kern_conf.c
+++ b/freebsd/sys/kern/kern_conf.c
@@ -174,12 +174,6 @@ dev_rel(struct cdev *dev)
dev->si_refcount--;
KASSERT(dev->si_refcount >= 0,
("dev_rel(%s) gave negative count", devtoname(dev)));
-#if 0
- if (dev->si_usecount == 0 &&
- (dev->si_flags & SI_CHEAPCLONE) && (dev->si_flags & SI_NAMED))
- ;
- else
-#endif
if (dev->si_devsw == NULL && dev->si_refcount == 0) {
LIST_REMOVE(dev, si_list);
flag = 1;
@@ -601,20 +595,41 @@ newdev(struct make_dev_args *args, struct cdev *si)
mtx_assert(&devmtx, MA_OWNED);
csw = args->mda_devsw;
+ si2 = NULL;
if (csw->d_flags & D_NEEDMINOR) {
/* We may want to return an existing device */
LIST_FOREACH(si2, &csw->d_devs, si_list) {
if (dev2unit(si2) == args->mda_unit) {
dev_free_devlocked(si);
- return (si2);
+ si = si2;
+ break;
}
}
+
+ /*
+ * If we're returning an existing device, we should make sure
+ * it isn't already initialized. This would have been caught
+ * in consumers anyways, but it's good to catch such a case
+ * early. We still need to complete initialization of the
+ * device, and we'll use whatever make_dev_args were passed in
+ * to do so.
+ */
+ KASSERT(si2 == NULL || (si2->si_flags & SI_NAMED) == 0,
+ ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
+ args->mda_devsw->d_name, dev2unit(si2), devtoname(si2)));
}
si->si_drv0 = args->mda_unit;
- si->si_devsw = csw;
si->si_drv1 = args->mda_si_drv1;
si->si_drv2 = args->mda_si_drv2;
- LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
+ /* Only push to csw->d_devs if it's not a cloned device. */
+ if (si2 == NULL) {
+ si->si_devsw = csw;
+ LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
+ } else {
+ KASSERT(si->si_devsw == csw,
+ ("%s: inconsistent devsw between clone_create() and make_dev()",
+ __func__));
+ }
return (si);
}
@@ -832,17 +847,6 @@ make_dev_sv(struct make_dev_args *args1, struct cdev **dres,
dev_refl(dev);
if ((args.mda_flags & MAKEDEV_ETERNAL) != 0)
dev->si_flags |= SI_ETERNAL;
- if (dev->si_flags & SI_CHEAPCLONE &&
- dev->si_flags & SI_NAMED) {
- /*
- * This is allowed as it removes races and generally
- * simplifies cloning devices.
- * XXX: still ??
- */
- dev_unlock_and_free();
- *dres = dev;
- return (0);
- }
KASSERT(!(dev->si_flags & SI_NAMED),
("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
args.mda_devsw->d_name, dev2unit(dev), devtoname(dev)));
@@ -1592,7 +1596,6 @@ DB_SHOW_COMMAND(cdev, db_show_cdev)
SI_FLAG(SI_ETERNAL);
SI_FLAG(SI_ALIAS);
SI_FLAG(SI_NAMED);
- SI_FLAG(SI_CHEAPCLONE);
SI_FLAG(SI_CHILD);
SI_FLAG(SI_DUMPDEV);
SI_FLAG(SI_CLONELIST);