···133decl_subsys(bus, &ktype_bus, NULL);1341350000000000000000000000000000000000000000000000000000136static struct device * next_device(struct klist_iter * i)137{138 struct klist_node * n = klist_next(i);···229 return error;230}231000000000000000000000000000000000232233234static struct device_driver * next_driver(struct klist_iter * i)···448 module_add_driver(drv->owner, drv);449450 driver_add_attrs(bus, drv);00451 }452 return error;453}···467void bus_remove_driver(struct device_driver * drv)468{469 if (drv->bus) {00470 driver_remove_attrs(drv->bus, drv);471 klist_remove(&drv->knode_bus);472 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);···483/* Helper for bus_rescan_devices's iter */484static int bus_rescan_devices_helper(struct device *dev, void *data)485{486- int *count = data;487-488- if (!dev->driver && (device_attach(dev) > 0))489- (*count)++;490-491 return 0;492}493494-495/**496- * bus_rescan_devices - rescan devices on the bus for possible drivers497- * @bus: the bus to scan.498 *499- * This function will look for devices on the bus with no driver500- * attached and rescan it against existing drivers to see if it501- * matches any. Calls device_attach(). Returns the number of devices502- * that were sucessfully bound to a driver.503 */504-int bus_rescan_devices(struct bus_type * bus)505{506- int count = 0;507-508- bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);509-510- return count;511}512513···637638639EXPORT_SYMBOL_GPL(bus_for_each_dev);0640EXPORT_SYMBOL_GPL(bus_for_each_drv);641642EXPORT_SYMBOL_GPL(bus_add_device);
···133decl_subsys(bus, &ktype_bus, NULL);134135136+/* Manually detach a device from it's associated driver. */137+static int driver_helper(struct device *dev, void *data)138+{139+ const char *name = data;140+141+ if (strcmp(name, dev->bus_id) == 0)142+ return 1;143+ return 0;144+}145+146+static ssize_t driver_unbind(struct device_driver *drv,147+ const char *buf, size_t count)148+{149+ struct bus_type *bus = get_bus(drv->bus);150+ struct device *dev;151+ int err = -ENODEV;152+153+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);154+ if ((dev) &&155+ (dev->driver == drv)) {156+ device_release_driver(dev);157+ err = count;158+ }159+ return err;160+}161+static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);162+163+/*164+ * Manually attach a device to a driver.165+ * Note: the driver must want to bind to the device,166+ * it is not possible to override the driver's id table.167+ */168+static ssize_t driver_bind(struct device_driver *drv,169+ const char *buf, size_t count)170+{171+ struct bus_type *bus = get_bus(drv->bus);172+ struct device *dev;173+ int err = -ENODEV;174+175+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);176+ if ((dev) &&177+ (dev->driver == NULL)) {178+ down(&dev->sem);179+ err = driver_probe_device(drv, dev);180+ up(&dev->sem);181+ put_device(dev);182+ }183+ return err;184+}185+static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);186+187+188static struct device * next_device(struct klist_iter * i)189{190 struct klist_node * n = klist_next(i);···177 return error;178}179180+/**181+ * bus_find_device - device iterator for locating a particular device.182+ * @bus: bus type183+ * @start: Device to begin with184+ * @data: Data to pass to match function185+ * @match: Callback function to check device186+ *187+ * This is similar to the bus_for_each_dev() function above, but it188+ * returns a reference to a device that is 'found' for later use, as189+ * determined by the @match callback.190+ *191+ * The callback should return 0 if the device doesn't match and non-zero192+ * if it does. If the callback returns non-zero, this function will193+ * return to the caller and not iterate over any more devices.194+ */195+struct device * bus_find_device(struct bus_type *bus,196+ struct device *start, void *data,197+ int (*match)(struct device *, void *))198+{199+ struct klist_iter i;200+ struct device *dev;201+202+ if (!bus)203+ return NULL;204+205+ klist_iter_init_node(&bus->klist_devices, &i,206+ (start ? &start->knode_bus : NULL));207+ while ((dev = next_device(&i)))208+ if (match(dev, data) && get_device(dev))209+ break;210+ klist_iter_exit(&i);211+ return dev;212+}213214215static struct device_driver * next_driver(struct klist_iter * i)···363 module_add_driver(drv->owner, drv);364365 driver_add_attrs(bus, drv);366+ driver_create_file(drv, &driver_attr_unbind);367+ driver_create_file(drv, &driver_attr_bind);368 }369 return error;370}···380void bus_remove_driver(struct device_driver * drv)381{382 if (drv->bus) {383+ driver_remove_file(drv, &driver_attr_bind);384+ driver_remove_file(drv, &driver_attr_unbind);385 driver_remove_attrs(drv->bus, drv);386 klist_remove(&drv->knode_bus);387 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);···394/* Helper for bus_rescan_devices's iter */395static int bus_rescan_devices_helper(struct device *dev, void *data)396{397+ if (!dev->driver)398+ device_attach(dev);000399 return 0;400}4010402/**403+ * bus_rescan_devices - rescan devices on the bus for possible drivers404+ * @bus: the bus to scan.405 *406+ * This function will look for devices on the bus with no driver407+ * attached and rescan it against existing drivers to see if it matches408+ * any by calling device_attach() for the unbound devices.0409 */410+void bus_rescan_devices(struct bus_type * bus)411{412+ bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);0000413}414415···557558559EXPORT_SYMBOL_GPL(bus_for_each_dev);560+EXPORT_SYMBOL_GPL(bus_find_device);561EXPORT_SYMBOL_GPL(bus_for_each_drv);562563EXPORT_SYMBOL_GPL(bus_add_device);
+1-1
drivers/base/core.c
···333 struct device * parent = dev->parent;334335 if (parent)336- klist_remove(&dev->knode_parent);337338 /* Notify the platform of the removal, in case they339 * need to do anything...
···333 struct device * parent = dev->parent;334335 if (parent)336+ klist_del(&dev->knode_parent);337338 /* Notify the platform of the removal, in case they339 * need to do anything...
+1-1
drivers/base/dd.c
···65 *66 * This function must be called with @dev->sem held.67 */68-static int driver_probe_device(struct device_driver * drv, struct device * dev)69{70 int ret = 0;71
···65 *66 * This function must be called with @dev->sem held.67 */68+int driver_probe_device(struct device_driver * drv, struct device * dev)69{70 int ret = 0;71
···565758/**59+ * driver_find_device - device iterator for locating a particular device.60+ * @driver: The device's driver61+ * @start: Device to begin with62+ * @data: Data to pass to match function63+ * @match: Callback function to check device64+ *65+ * This is similar to the driver_for_each_device() function above, but66+ * it returns a reference to a device that is 'found' for later use, as67+ * determined by the @match callback.68+ *69+ * The callback should return 0 if the device doesn't match and non-zero70+ * if it does. If the callback returns non-zero, this function will71+ * return to the caller and not iterate over any more devices.72+ */73+struct device * driver_find_device(struct device_driver *drv,74+ struct device * start, void * data,75+ int (*match)(struct device *, void *))76+{77+ struct klist_iter i;78+ struct device *dev;79+80+ if (!drv)81+ return NULL;82+83+ klist_iter_init_node(&drv->klist_devices, &i,84+ (start ? &start->knode_driver : NULL));85+ while ((dev = next_device(&i)))86+ if (match(dev, data) && get_device(dev))87+ break;88+ klist_iter_exit(&i);89+ return dev;90+}91+EXPORT_SYMBOL_GPL(driver_find_device);92+93+/**94 * driver_create_file - create sysfs file for driver.95 * @drv: driver.96 * @attr: driver attribute descriptor.