Date: Sun, 8 Jul 2007 14:35:39 GMT From: Maxim Zhuravlev <thioretic@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123130 for review Message-ID: <200707081435.l68EZddO007639@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123130 Change 123130 by thioretic@thioretic on 2007/07/08 14:34:58 Some rethinking of api (eg. no initto in make_device); Some logic stuff. Affected files ... .. //depot/projects/soc2007/thioretic_gidl/TODO#10 edit .. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#8 edit Differences ... ==== //depot/projects/soc2007/thioretic_gidl/TODO#10 (text+ko) ==== @@ -105,4 +105,22 @@ # driver without any probing. Also a device may have multiple parents # and children. At this point it becomes obvious, that we should let # a driver not just process, but also produce and destroy an io request. - + # Inportant note: from above-said one can see, that since now newbus + # won't be a tree, it will be a graph! + # New logic: + # probe/attach: the dev->driver is set to drv_compat(driver) to be + # probed and attached. + # detach: will detach DRV_LOWEST driver and all filters consequently. + # As for functional devices (let's call like this all drivers with + # DR_REQDEV flag set), the following scenario looks reasonable: + # + # driver_handler: make_dev() & attach_all_parents() & DEVICE_PROBE + # DEVICE_PROBE: driver_probe + # driver_probe: parents = get_all_parents() + # FOR_EACH (parent, parents){ + # if (DEVICE_INFO (parent) == bad) + # detach_parent(parent) + # } + # + # here driver_handler & DEVICE_PROBE reside in subr_bus + # driver_probe resides in driver ==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#8 (text+ko) ==== @@ -93,6 +93,7 @@ typedef TAILQ_HEAD(pdevclass_list, pdevclass) pdevclass_list_t; typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; typedef TAILQ_HEAD(device_list, device) device_list_t; +typedef TAILQ_HEAD(pdevice_list, pdevice) pdevice_list_t; typedef TAILQ_HEAD(drv_compat_list, drv_compat) drv_compat_list_t; typedef TAILQ_HEAD(pdrv_compat_list, pdrv_compat) pdrv_compat_list_t; @@ -133,8 +134,8 @@ TAILQ_ENTRY(device) link; /**< list of devices in parent */ TAILQ_ENTRY(device) devlink; /**< global device list membership */ //device_t parent; /**< parent of this device */ - device_list_t parents; - device_list_t children; /**< list of child devices */ + /*device_list_t*/ pdevice_list_t parents; + /*device_list_t*/ pdevice_list_t children; /**< list of child devices */ /* * Details of this device. @@ -163,11 +164,18 @@ u_char pad; void *ivars; /**< instance variables */ void *softc; /**< current driver's variables */ + u_long refs; struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */ struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */ }; +struct pdevice { + device_t device_ptr; + TAILQ(pdevice) link; +}; + + static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); @@ -1335,7 +1343,7 @@ dev = dc->devices[i]; if (/*dev->driver == driver*/ is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) && - (TAILQ_FIRST(&(dev->parent->devclass))) == busclass) { + (TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) { if ((error = device_detach(dev)) != 0) return (error); device_set_driver(dev, NULL); @@ -1411,7 +1419,7 @@ dev = dc->devices[i]; if (/*dev->driver == driver*/ is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents) && - (TAILQ_FIRST(&(dev->parent)))->devclass == busclass) { + (TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) { if ((error = device_quiesce(dev)) != 0) return (error); } @@ -1832,12 +1840,13 @@ * @returns the new device */ static device_t -make_device(device_t parent, const char *name, int unit, driver_t *initto) /*TODO*/ +make_device(device_t parent, const char *name, int unit/*, driver_t *initto*/) /*TODO*/ { device_t dev; devclass_t dc; int level; drv_compat_t drvc; + pdevice *pd; PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); @@ -1856,26 +1865,30 @@ if (!dev) return (NULL); TAILQ_INIT(&(dev->parents)); - TAILQ_INSERT_TAIL(&(dev->parents), *parent, link) + pd = malloc(sizeof(struct pdevice), M_BUS, M_NOWAIT|M_ZERO); + pd->device_ptr = parent; + TAILQ_INSERT_TAIL(&(dev->parents), pd, link); TAILQ_INIT(&(dev->children)); //kobj_init((kobj_t) dev, &null_class); kobj_init((kobj_t) dev, &drv_compat_ctrl_driver) //dev->driver = NULL; for (level=DRV_LOWEST; level<=DRV_TOPMOST; level++) TAILQ_INIT(&((dev->drivers)[level])); - if (initto){ + /*if (initto){ drvc = drv_compat_find_driver (initto); if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO))) /*todo what??*/; - dev->devclass = devclass_find (DRIVERNAME(driver)); + /* dev->devclass = devclass_find (DRIVERNAME(driver)); level = drv_compat_flags2idx(drvc->flags); TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link); dev->state = DS_ALIVE; } - else{ + else{*/ dev->devclass = NULL; dev->state = DS_NOTPRESENT; - } + /*}*/ + + dev->refs = 0; dev->unit = unit; dev->nameunit = NULL; dev->desc = NULL; @@ -1965,19 +1978,22 @@ device_t device_add_child_ordered(device_t dev, int order, const char *name, int unit) { - device_t child; - device_t place; + /*device_t*/ pdevice *child; + /*device_t*/ pdevice *place; PDEBUG(("%s at %s with order %d as unit %d", name, DEVICENAME(dev), order, unit)); - child = make_device(dev, name, unit, NULL); - if (child == NULL) - return (child); + child = malloc (sizeof(pdevice), M_BUS, M_NOWAIT|M_ZERO); + child->device_ptr = make_device(dev, name, unit/*, NULL*/); + if (child->device_ptr == NULL){ + free (child); + return (NULL); + } child->order = order; TAILQ_FOREACH(place, &dev->children, link) { - if (place->order > order) + if (place->device_ptr->order > order) break; } @@ -1994,6 +2010,7 @@ */ TAILQ_INSERT_TAIL(&dev->children, child, link); } + child->device_ptr->refs++; bus_data_generation_update(); return (child); @@ -2013,39 +2030,54 @@ * @retval non-zero a unit error code describing the error */ int -device_delete_child(device_t dev, device_t child) +device_delete_child(device_t dev, device_t child) /*TODO*/ { int error; - device_t grandchild; + /*device_t*/ pdevice *grandchild; + pdevice *pd; PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); - + + child->refs--; + if (child->refs) goto deletefromparent; /* remove children first */ while ( (grandchild = TAILQ_FIRST(&child->children)) ) { - error = device_delete_child(child, grandchild); + error = device_delete_child(child, grandchild->device_ptr); if (error) return (error); + free (grandchild); } if ((error = device_detach(child)) != 0) return (error); if (child->devclass) devclass_delete_device(child->devclass, child); - TAILQ_REMOVE(&dev->children, child, link); +deletefromparent: + TAILQ_FOREACH_SAFE(pd, &dev->children, link){ + if (pd->device_ptr == child){ + TAILQ_REMOVE(&dev->children, child, link); + free (pd); + break; + } + } + + if (child->refs) + return (0); + TAILQ_REMOVE(&bus_data_devices, child, devlink); kobj_delete((kobj_t) child, M_BUS); - + bus_data_generation_update(); return (0); } static int is_device_parent (device_t dev, device_t child){ - device_t dc; + pdevice *dc; TAILQ_FOREACH (dc, &(child->parents), link){ - if (dc == dev) return (1); + if (dc->device_ptr == dev) return (TRUE); } - return (0); + return (FALSE); } /** @@ -2263,8 +2295,11 @@ device_t device_get_parent(device_t dev) /*TODO*/ { - if (!TAILQ_EMPTY(&(dev->parents))) - return (TAILQ_FIRST(&(dev->parents))); + pdevice *pd; + if (!TAILQ_EMPTY(&(dev->parents))){ + pd = TAILQ_FIRST(&(dev->parents)); + return (pd->device_ptr); + } return (NULL); } @@ -2288,7 +2323,7 @@ device_get_children(device_t dev, device_t **devlistp, int *devcountp) { int count; - device_t child; + /*device_t*/ pdevice *child; device_t *list; count = 0; @@ -2302,7 +2337,7 @@ count = 0; TAILQ_FOREACH(child, &dev->children, link) { - list[count] = child; + list[count] = child->device_ptr; count++; } @@ -2584,12 +2619,12 @@ void device_busy(device_t dev) { - device_t parent; + pdevice *parent; if (dev->state < DS_ATTACHED) panic("device_busy: called for unattached device"); if (dev->busy == 0 && !TAILQ_EMPTY(&(dev->parents))){ TAILQ_FOREACH (parent, &(dev->parents), link){ - device_busy(parent); + device_busy(parent->device_ptr); } } dev->busy++; @@ -2602,6 +2637,7 @@ void device_unbusy(device_t dev) { + pdevice *parent; if (dev->state != DS_BUSY) panic("device_unbusy: called for non-busy device %s", device_get_nameunit(dev)); @@ -2609,7 +2645,7 @@ if (dev->busy == 0) { if (/*dev->parent*/!TAILQ_EMPTY(&(dev->parents))){ TAILQ_FOREACH (parent, &(dev->parents), link){ - device_unbusy(parent); + device_unbusy(parent->device_ptr); } } //device_unbusy(dev->parent); @@ -2713,6 +2749,8 @@ int device_set_driver(device_t dev, driver_t *driver) { + drv_compat_t drvc; + if (dev->state >= DS_ATTACHED) return (EBUSY); @@ -2723,23 +2761,26 @@ free(dev->softc, M_BUS_SC); dev->softc = NULL; } - kobj_delete((kobj_t) dev, 0); - dev->driver = driver; + //kobj_delete((kobj_t) dev, 0); + dev->driver = drvc = drv_compat_find_driver (driver); if (driver) { - kobj_init((kobj_t) dev, (kobj_class_t) driver); + if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO))) + /*todo what??*/; + dev->driver = drvc; + //kobj_init((kobj_t) dev, (kobj_class_t) driver); if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) { dev->softc = malloc(driver->size, M_BUS_SC, M_NOWAIT | M_ZERO); if (!dev->softc) { - kobj_delete((kobj_t) dev, 0); - kobj_init((kobj_t) dev, &null_class); + //kobj_delete((kobj_t) dev, 0); + //kobj_init((kobj_t) dev, &null_class); dev->driver = NULL; return (ENOMEM); } } - } else { + } /*else { kobj_init((kobj_t) dev, &null_class); - } + }*/ bus_data_generation_update(); return (0); @@ -2824,12 +2865,13 @@ device_attach(device_t dev) { int error; - device_t parent; + pdevice *pd; + drv_compat_t drvc; device_sysctl_init(dev); if (!device_is_quiet(dev)){ - TAILQ_FOREACH (parent, &(dev->parents), link){ - device_print_child(parent, dev); + TAILQ_FOREACH (pd, &(dev->parents), link){ + device_print_child(pd->device_ptr, dev); } } if ((error = DEVICE_ATTACH(dev)) != 0) { @@ -2842,6 +2884,12 @@ device_sysctl_fini(dev); dev->state = DS_NOTPRESENT; return (error); + } else { + drvc = dev->driver; + dev->devclass = devclass_find (DRIVERNAME(drvc->driver)); + level = drv_compat_flags2idx(drvc->flags); + TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link); + driver = NULL; } dev->state = DS_ATTACHED; devadded(dev); @@ -2868,7 +2916,7 @@ device_detach(device_t dev) { int error; - device_t parent; + pdevice *pd; GIANT_REQUIRED; @@ -2882,9 +2930,9 @@ return (error); devremoved(dev); device_printf(dev, "detached\n"); - if (!TAILQ_EMPTY(&(dev->parent))){ - TAILQ_FOREACH (parent, &(dev->parents), link){ - BUS_CHILD_DETACHED(parent, dev); + if (!TAILQ_EMPTY(&(dev->parents))){ + TAILQ_FOREACH (pd, &(dev->parents), link){ + BUS_CHILD_DETACHED(pd->device_ptr, dev); } } @@ -3338,10 +3386,10 @@ int bus_generic_attach(device_t dev) { - device_t child; + /*device_t*/ pdevice *child; TAILQ_FOREACH(child, &dev->children, link) { - device_probe_and_attach(child); + device_probe_and_attach(child->device_ptr); } return (0); @@ -4112,7 +4160,7 @@ case MOD_LOAD: TAILQ_INIT(&bus_data_devices); kobj_class_compile((kobj_class_t) &root_driver); - root_bus = make_device(NULL, "root", 0, NULL); + root_bus = make_device(NULL, "root", 0/*, NULL*/); root_bus->desc = "System root bus"; kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); root_bus->driver = &root_driver; @@ -4221,6 +4269,7 @@ kobj_class_t driver; char* parents[]; int count=0, isfilter; + device_t dev; dmd = (struct driver_module_data *)arg; drv_intnl = dmd->dmd_driver; @@ -4278,7 +4327,17 @@ } if(drv_intnl->flags & DR_REQDEV){ /*restrict to DR_LOWEST? */ - make_device (root_bus, DRIVERNAME(driver), -1, driver); + dev = make_device (root_bus, DRIVERNAME(driver), -1/*, driver*/); + device_set_driver(dev, driver); + /*if (!hasclass)*/ + device_set_devclass(child, dl->driver->name); + + /* Fetch any flags for the device before probing. + resource_int_value(dl->driver->name, child->unit, + "flags", &child->devflags); + */ + + result = DEVICE_PROBE(dev); /* todo: set all parents for device * parents are all devices (alive) in parent * devclasses
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707081435.l68EZddO007639>