···133133decl_subsys(bus, &ktype_bus, NULL);134134135135136136+/* Manually detach a device from it's associated driver. */137137+static int driver_helper(struct device *dev, void *data)138138+{139139+ const char *name = data;140140+141141+ if (strcmp(name, dev->bus_id) == 0)142142+ return 1;143143+ return 0;144144+}145145+146146+static ssize_t driver_unbind(struct device_driver *drv,147147+ const char *buf, size_t count)148148+{149149+ struct bus_type *bus = get_bus(drv->bus);150150+ struct device *dev;151151+ int err = -ENODEV;152152+153153+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);154154+ if ((dev) &&155155+ (dev->driver == drv)) {156156+ device_release_driver(dev);157157+ err = count;158158+ }159159+ return err;160160+}161161+static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);162162+163163+/*164164+ * Manually attach a device to a driver.165165+ * Note: the driver must want to bind to the device,166166+ * it is not possible to override the driver's id table.167167+ */168168+static ssize_t driver_bind(struct device_driver *drv,169169+ const char *buf, size_t count)170170+{171171+ struct bus_type *bus = get_bus(drv->bus);172172+ struct device *dev;173173+ int err = -ENODEV;174174+175175+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);176176+ if ((dev) &&177177+ (dev->driver == NULL)) {178178+ down(&dev->sem);179179+ err = driver_probe_device(drv, dev);180180+ up(&dev->sem);181181+ put_device(dev);182182+ }183183+ return err;184184+}185185+static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);186186+187187+136188static struct device * next_device(struct klist_iter * i)137189{138190 struct klist_node * n = klist_next(i);···229177 return error;230178}231179180180+/**181181+ * bus_find_device - device iterator for locating a particular device.182182+ * @bus: bus type183183+ * @start: Device to begin with184184+ * @data: Data to pass to match function185185+ * @match: Callback function to check device186186+ *187187+ * This is similar to the bus_for_each_dev() function above, but it188188+ * returns a reference to a device that is 'found' for later use, as189189+ * determined by the @match callback.190190+ *191191+ * The callback should return 0 if the device doesn't match and non-zero192192+ * if it does. If the callback returns non-zero, this function will193193+ * return to the caller and not iterate over any more devices.194194+ */195195+struct device * bus_find_device(struct bus_type *bus,196196+ struct device *start, void *data,197197+ int (*match)(struct device *, void *))198198+{199199+ struct klist_iter i;200200+ struct device *dev;201201+202202+ if (!bus)203203+ return NULL;204204+205205+ klist_iter_init_node(&bus->klist_devices, &i,206206+ (start ? &start->knode_bus : NULL));207207+ while ((dev = next_device(&i)))208208+ if (match(dev, data) && get_device(dev))209209+ break;210210+ klist_iter_exit(&i);211211+ return dev;212212+}232213233214234215static struct device_driver * next_driver(struct klist_iter * i)···448363 module_add_driver(drv->owner, drv);449364450365 driver_add_attrs(bus, drv);366366+ driver_create_file(drv, &driver_attr_unbind);367367+ driver_create_file(drv, &driver_attr_bind);451368 }452369 return error;453370}···467380void bus_remove_driver(struct device_driver * drv)468381{469382 if (drv->bus) {383383+ driver_remove_file(drv, &driver_attr_bind);384384+ driver_remove_file(drv, &driver_attr_unbind);470385 driver_remove_attrs(drv->bus, drv);471386 klist_remove(&drv->knode_bus);472387 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);···483394/* Helper for bus_rescan_devices's iter */484395static int bus_rescan_devices_helper(struct device *dev, void *data)485396{486486- int *count = data;487487-488488- if (!dev->driver && (device_attach(dev) > 0))489489- (*count)++;490490-397397+ if (!dev->driver)398398+ device_attach(dev);491399 return 0;492400}493401494494-495402/**496496- * bus_rescan_devices - rescan devices on the bus for possible drivers497497- * @bus: the bus to scan.403403+ * bus_rescan_devices - rescan devices on the bus for possible drivers404404+ * @bus: the bus to scan.498405 *499499- * This function will look for devices on the bus with no driver500500- * attached and rescan it against existing drivers to see if it501501- * matches any. Calls device_attach(). Returns the number of devices502502- * that were sucessfully bound to a driver.406406+ * This function will look for devices on the bus with no driver407407+ * attached and rescan it against existing drivers to see if it matches408408+ * any by calling device_attach() for the unbound devices.503409 */504504-int bus_rescan_devices(struct bus_type * bus)410410+void bus_rescan_devices(struct bus_type * bus)505411{506506- int count = 0;507507-508508- bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);509509-510510- return count;412412+ bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);511413}512414513415···637557638558639559EXPORT_SYMBOL_GPL(bus_for_each_dev);560560+EXPORT_SYMBOL_GPL(bus_find_device);640561EXPORT_SYMBOL_GPL(bus_for_each_drv);641562642563EXPORT_SYMBOL_GPL(bus_add_device);
+1-1
drivers/base/core.c
···333333 struct device * parent = dev->parent;334334335335 if (parent)336336- klist_remove(&dev->knode_parent);336336+ klist_del(&dev->knode_parent);337337338338 /* Notify the platform of the removal, in case they339339 * need to do anything...
+1-1
drivers/base/dd.c
···6565 *6666 * This function must be called with @dev->sem held.6767 */6868-static int driver_probe_device(struct device_driver * drv, struct device * dev)6868+int driver_probe_device(struct device_driver * drv, struct device * dev)6969{7070 int ret = 0;7171
+35
drivers/base/driver.c
···565657575858/**5959+ * driver_find_device - device iterator for locating a particular device.6060+ * @driver: The device's driver6161+ * @start: Device to begin with6262+ * @data: Data to pass to match function6363+ * @match: Callback function to check device6464+ *6565+ * This is similar to the driver_for_each_device() function above, but6666+ * it returns a reference to a device that is 'found' for later use, as6767+ * determined by the @match callback.6868+ *6969+ * The callback should return 0 if the device doesn't match and non-zero7070+ * if it does. If the callback returns non-zero, this function will7171+ * return to the caller and not iterate over any more devices.7272+ */7373+struct device * driver_find_device(struct device_driver *drv,7474+ struct device * start, void * data,7575+ int (*match)(struct device *, void *))7676+{7777+ struct klist_iter i;7878+ struct device *dev;7979+8080+ if (!drv)8181+ return NULL;8282+8383+ klist_iter_init_node(&drv->klist_devices, &i,8484+ (start ? &start->knode_driver : NULL));8585+ while ((dev = next_device(&i)))8686+ if (match(dev, data) && get_device(dev))8787+ break;8888+ klist_iter_exit(&i);8989+ return dev;9090+}9191+EXPORT_SYMBOL_GPL(driver_find_device);9292+9393+/**5994 * driver_create_file - create sysfs file for driver.6095 * @drv: driver.6196 * @attr: driver attribute descriptor.