Index: sys/sys/device.h =================================================================== RCS file: /cvsroot/src/sys/sys/device.h,v retrieving revision 1.140 diff -u -p -r1.140 device.h --- sys/sys/device.h 13 Nov 2011 22:05:58 -0000 1.140 +++ sys/sys/device.h 16 Apr 2012 16:38:11 -0000 @@ -528,6 +528,9 @@ void device_active_deregister(device_t, bool device_is_a(device_t, const char *); +bool device_is_attached(device_t, cfdata_t); + + device_t device_find_by_xname(const char *); device_t device_find_by_driver_unit(const char *, int); Index: sys/kern/subr_device.c =================================================================== RCS file: /cvsroot/src/sys/kern/subr_device.c,v retrieving revision 1.2 diff -u -p -r1.2 subr_device.c --- sys/kern/subr_device.c 31 Jan 2010 15:10:12 -0000 1.2 +++ sys/kern/subr_device.c 16 Apr 2012 16:38:11 -0000 @@ -176,3 +176,32 @@ device_is_a(device_t dev, const char *dn return strcmp(dev->dv_cfdriver->cd_name, dname) == 0; } + +/* + * device_is_attached: + * + * Returns true if a driver already attached to a device. + * Useful for bus drivers to figure if driver already attached + * to prevent drivers attaching twice. + */ +bool +device_is_attached(device_t parent, cfdata_t cf) +{ + device_t dev; + deviter_t di; + bool attached = false; + + for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); dev != NULL; + dev = deviter_next(&di)) + { + if (device_parent(dev) != parent) + continue; + if (device_is_a(dev, cf->cf_name)) { + attached = true; + break; + } + } + deviter_release(&di); + + return attached; +} Index: sys/arch/x86/pci/amdnb_misc.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/pci/amdnb_misc.c,v retrieving revision 1.2 diff -u -p -r1.2 amdnb_misc.c --- sys/arch/x86/pci/amdnb_misc.c 16 Apr 2012 16:07:24 -0000 1.2 +++ sys/arch/x86/pci/amdnb_misc.c 16 Apr 2012 16:38:11 -0000 @@ -78,38 +78,13 @@ amdnb_misc_match(device_t parent, cfdata static int amdnb_misc_search(device_t parent, cfdata_t cf, const int *locs, void *aux) { - device_t dev; - deviter_t di; - bool attach; - if (!config_match(parent, cf, aux)) return 0; - attach = true; - /* Figure out if found child 'cf' is already attached. * No need to attach it twice. */ - - /* XXX: I only want to iterate over the children of *this* device. - * Can we introduce a - * deviter_first_child(&di, parent, DEVITER_F_LEAVES_ONLY) - * or even better, can we introduce a query function that returns - * if a child is already attached? - */ - for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); dev != NULL; - dev = deviter_next(&di)) - { - if (device_parent(dev) != parent) - continue; - if (device_is_a(dev, cf->cf_name)) { - attach = false; - break; - } - } - deviter_release(&di); - - if (!attach) + if (device_is_attached(parent, cf)) return 0; config_attach_loc(parent, cf, locs, aux, NULL);