📄 bus.c
字号:
device_detach_shutdown(dev); if (drv->remove) drv->remove(dev); dev->driver = NULL; }}/** * driver_detach - detach driver from all devices it controls. * @drv: driver. */static void driver_detach(struct device_driver * drv){ struct list_head * entry, * next; list_for_each_safe(entry, next, &drv->devices) { struct device * dev = container_of(entry, struct device, driver_list); device_release_driver(dev); }}static int device_add_attrs(struct bus_type * bus, struct device * dev){ int error = 0; int i; if (bus->dev_attrs) { for (i = 0; attr_name(bus->dev_attrs[i]); i++) { error = device_create_file(dev,&bus->dev_attrs[i]); if (error) goto Err; } } Done: return error; Err: while (--i >= 0) device_remove_file(dev,&bus->dev_attrs[i]); goto Done;}static void device_remove_attrs(struct bus_type * bus, struct device * dev){ int i; if (bus->dev_attrs) { for (i = 0; attr_name(bus->dev_attrs[i]); i++) device_remove_file(dev,&bus->dev_attrs[i]); }}/** * bus_add_device - add device to bus * @dev: device being added * * - Add the device to its bus's list of devices. * - Try to attach to driver. * - Create link to device's physical location. */int bus_add_device(struct device * dev){ struct bus_type * bus = get_bus(dev->bus); int error = 0; if (bus) { down_write(&dev->bus->subsys.rwsem); pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); list_add_tail(&dev->bus_list, &dev->bus->devices.list); device_attach(dev); up_write(&dev->bus->subsys.rwsem); device_add_attrs(bus, dev); sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); } return error;}/** * bus_remove_device - remove device from bus * @dev: device to be removed * * - Remove symlink from bus's directory. * - Delete device from bus's list. * - Detach from its driver. * - Drop reference taken in bus_add_device(). */void bus_remove_device(struct device * dev){ if (dev->bus) { sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); device_remove_attrs(dev->bus, dev); down_write(&dev->bus->subsys.rwsem); pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); device_release_driver(dev); list_del_init(&dev->bus_list); up_write(&dev->bus->subsys.rwsem); put_bus(dev->bus); }}static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv){ int error = 0; int i; if (bus->drv_attrs) { for (i = 0; attr_name(bus->drv_attrs[i]); i++) { error = driver_create_file(drv, &bus->drv_attrs[i]); if (error) goto Err; } } Done: return error; Err: while (--i >= 0) driver_remove_file(drv, &bus->drv_attrs[i]); goto Done;}static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv){ int i; if (bus->drv_attrs) { for (i = 0; attr_name(bus->drv_attrs[i]); i++) driver_remove_file(drv, &bus->drv_attrs[i]); }}/** * bus_add_driver - Add a driver to the bus. * @drv: driver. * */int bus_add_driver(struct device_driver * drv){ struct bus_type * bus = get_bus(drv->bus); int error = 0; if (bus) { pr_debug("bus %s: add driver %s\n", bus->name, drv->name); error = kobject_set_name(&drv->kobj, drv->name); if (error) { put_bus(bus); return error; } drv->kobj.kset = &bus->drivers; if ((error = kobject_register(&drv->kobj))) { put_bus(bus); return error; } down_write(&bus->subsys.rwsem); driver_attach(drv); up_write(&bus->subsys.rwsem); driver_add_attrs(bus, drv); } return error;}/** * bus_remove_driver - delete driver from bus's knowledge. * @drv: driver. * * Detach the driver from the devices it controls, and remove * it from its bus's list of drivers. Finally, we drop the reference * to the bus we took in bus_add_driver(). */void bus_remove_driver(struct device_driver * drv){ if (drv->bus) { driver_remove_attrs(drv->bus, drv); down_write(&drv->bus->subsys.rwsem); pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); driver_detach(drv); up_write(&drv->bus->subsys.rwsem); kobject_unregister(&drv->kobj); put_bus(drv->bus); }}/* Helper for bus_rescan_devices's iter */static int bus_rescan_devices_helper(struct device *dev, void *data){ int *count = data; if (!dev->driver && device_attach(dev)) (*count)++; return 0;}/** * bus_rescan_devices - rescan devices on the bus for possible drivers * @bus: the bus to scan. * * This function will look for devices on the bus with no driver * attached and rescan it against existing drivers to see if it * matches any. Calls device_attach(). Returns the number of devices * that were sucessfully bound to a driver. */int bus_rescan_devices(struct bus_type * bus){ int count = 0; bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); return count;}struct bus_type * get_bus(struct bus_type * bus){ return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL;}void put_bus(struct bus_type * bus){ subsys_put(&bus->subsys);}/** * find_bus - locate bus by name. * @name: name of bus. * * Call kset_find_obj() to iterate over list of buses to * find a bus by name. Return bus if found. * * Note that kset_find_obj increments bus' reference count. */struct bus_type * find_bus(char * name){ struct kobject * k = kset_find_obj(&bus_subsys.kset, name); return k ? to_bus(k) : NULL;}/** * bus_add_attrs - Add default attributes for this bus. * @bus: Bus that has just been registered. */static int bus_add_attrs(struct bus_type * bus){ int error = 0; int i; if (bus->bus_attrs) { for (i = 0; attr_name(bus->bus_attrs[i]); i++) { if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) goto Err; } } Done: return error; Err: while (--i >= 0) bus_remove_file(bus,&bus->bus_attrs[i]); goto Done;}static void bus_remove_attrs(struct bus_type * bus){ int i; if (bus->bus_attrs) { for (i = 0; attr_name(bus->bus_attrs[i]); i++) bus_remove_file(bus,&bus->bus_attrs[i]); }}/** * bus_register - register a bus with the system. * @bus: bus. * * Once we have that, we registered the bus with the kobject * infrastructure, then register the children subsystems it has: * the devices and drivers that belong to the bus. */int bus_register(struct bus_type * bus){ int retval; retval = kobject_set_name(&bus->subsys.kset.kobj, bus->name); if (retval) goto out; subsys_set_kset(bus, bus_subsys); retval = subsystem_register(&bus->subsys); if (retval) goto out; kobject_set_name(&bus->devices.kobj, "devices"); bus->devices.subsys = &bus->subsys; retval = kset_register(&bus->devices); if (retval) goto bus_devices_fail; kobject_set_name(&bus->drivers.kobj, "drivers"); bus->drivers.subsys = &bus->subsys; bus->drivers.ktype = &ktype_driver; retval = kset_register(&bus->drivers); if (retval) goto bus_drivers_fail; bus_add_attrs(bus); pr_debug("bus type '%s' registered\n", bus->name); return 0;bus_drivers_fail: kset_unregister(&bus->devices);bus_devices_fail: subsystem_unregister(&bus->subsys);out: return retval;}/** * bus_unregister - remove a bus from the system * @bus: bus. * * Unregister the child subsystems and the bus itself. * Finally, we call put_bus() to release the refcount */void bus_unregister(struct bus_type * bus){ pr_debug("bus %s: unregistering\n", bus->name); bus_remove_attrs(bus); kset_unregister(&bus->drivers); kset_unregister(&bus->devices); subsystem_unregister(&bus->subsys);}int __init buses_init(void){ return subsystem_register(&bus_subsys);}EXPORT_SYMBOL(bus_for_each_dev);EXPORT_SYMBOL(bus_for_each_drv);EXPORT_SYMBOL(device_bind_driver);EXPORT_SYMBOL(device_release_driver);EXPORT_SYMBOL(bus_add_device);EXPORT_SYMBOL(bus_remove_device);EXPORT_SYMBOL(bus_register);EXPORT_SYMBOL(bus_unregister);EXPORT_SYMBOL(bus_rescan_devices);EXPORT_SYMBOL(get_bus);EXPORT_SYMBOL(put_bus);EXPORT_SYMBOL(find_bus);EXPORT_SYMBOL(bus_create_file);EXPORT_SYMBOL(bus_remove_file);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -