1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * driver.c - centralized device driver management 4 * 5 * Copyright (c) 2002-3 Patrick Mochel 6 * Copyright (c) 2002-3 Open Source Development Labs 7 * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> 8 * Copyright (c) 2007 Novell Inc. 9 */ 10 11 #include <linux/device.h> 12 #include <linux/module.h> 13 #include <linux/errno.h> 14 #include <linux/slab.h> 15 #include <linux/string.h> 16 #include <linux/sysfs.h> 17 #include "base.h" 18 19 static struct device *next_device(struct klist_iter *i) 20 { 21 struct klist_node *n = klist_next(i); 22 struct device *dev = NULL; 23 struct device_private *dev_prv; 24 25 if (n) { 26 dev_prv = to_device_private_driver(n); 27 dev = dev_prv->device; 28 } 29 return dev; 30 } 31 32 /** 33 * driver_for_each_device - Iterator for devices bound to a driver. 34 * @drv: Driver we're iterating. 35 * @start: Device to begin with 36 * @data: Data to pass to the callback. 37 * @fn: Function to call for each device. 38 * 39 * Iterate over the @drv's list of devices calling @fn for each one. 40 */ 41 int driver_for_each_device(struct device_driver *drv, struct device *start, 42 void *data, int (*fn)(struct device *, void *)) 43 { 44 struct klist_iter i; 45 struct device *dev; 46 int error = 0; 47 48 if (!drv) 49 return -EINVAL; 50 51 klist_iter_init_node(&drv->p->klist_devices, &i, 52 start ? &start->p->knode_driver : NULL); 53 while (!error && (dev = next_device(&i))) 54 error = fn(dev, data); 55 klist_iter_exit(&i); 56 return error; 57 } 58 EXPORT_SYMBOL_GPL(driver_for_each_device); 59 60 /** 61 * driver_find_device - device iterator for locating a particular device. 62 * @drv: The device's driver 63 * @start: Device to begin with 64 * @data: Data to pass to match function 65 * @match: Callback function to check device 66 * 67 * This is similar to the driver_for_each_device() function above, but 68 * it returns a reference to a device that is 'found' for later use, as 69 * determined by the @match callback. 70 * 71 * The callback should return 0 if the device doesn't match and non-zero 72 * if it does. If the callback returns non-zero, this function will 73 * return to the caller and not iterate over any more devices. 74 */ 75 struct device *driver_find_device(struct device_driver *drv, 76 struct device *start, void *data, 77 int (*match)(struct device *dev, void *data)) 78 { 79 struct klist_iter i; 80 struct device *dev; 81 82 if (!drv || !drv->p) 83 return NULL; 84 85 klist_iter_init_node(&drv->p->klist_devices, &i, 86 (start ? &start->p->knode_driver : NULL)); 87 while ((dev = next_device(&i))) 88 if (match(dev, data) && get_device(dev)) 89 break; 90 klist_iter_exit(&i); 91 return dev; 92 } 93 EXPORT_SYMBOL_GPL(driver_find_device); 94 95 /** 96 * driver_create_file - create sysfs file for driver. 97 * @drv: driver. 98 * @attr: driver attribute descriptor. 99 */ 100 int driver_create_file(struct device_driver *drv, 101 const struct driver_attribute *attr) 102 { 103 int error; 104 105 if (drv) 106 error = sysfs_create_file(&drv->p->kobj, &attr->attr); 107 else 108 error = -EINVAL; 109 return error; 110 } 111 EXPORT_SYMBOL_GPL(driver_create_file); 112 113 /** 114 * driver_remove_file - remove sysfs file for driver. 115 * @drv: driver. 116 * @attr: driver attribute descriptor. 117 */ 118 void driver_remove_file(struct device_driver *drv, 119 const struct driver_attribute *attr) 120 { 121 if (drv) 122 sysfs_remove_file(&drv->p->kobj, &attr->attr); 123 } 124 EXPORT_SYMBOL_GPL(driver_remove_file); 125 126 int driver_add_groups(struct device_driver *drv, 127 const struct attribute_group **groups) 128 { 129 return sysfs_create_groups(&drv->p->kobj, groups); 130 } 131 132 void driver_remove_groups(struct device_driver *drv, 133 const struct attribute_group **groups) 134 { 135 sysfs_remove_groups(&drv->p->kobj, groups); 136 } 137 138 /** 139 * driver_register - register driver with bus 140 * @drv: driver to register 141 * 142 * We pass off most of the work to the bus_add_driver() call, 143 * since most of the things we have to do deal with the bus 144 * structures. 145 */ 146 int driver_register(struct device_driver *drv) 147 { 148 int ret; 149 struct device_driver *other; 150 151 BUG_ON(!drv->bus->p); 152 153 if ((drv->bus->probe && drv->probe) || 154 (drv->bus->remove && drv->remove) || 155 (drv->bus->shutdown && drv->shutdown)) 156 printk(KERN_WARNING "Driver '%s' needs updating - please use " 157 "bus_type methods\n", drv->name); 158 159 other = driver_find(drv->name, drv->bus); 160 if (other) { 161 printk(KERN_ERR "Error: Driver '%s' is already registered, " 162 "aborting...\n", drv->name); 163 return -EBUSY; 164 } 165 166 ret = bus_add_driver(drv); 167 if (ret) 168 return ret; 169 ret = driver_add_groups(drv, drv->groups); 170 if (ret) { 171 bus_remove_driver(drv); 172 return ret; 173 } 174 kobject_uevent(&drv->p->kobj, KOBJ_ADD); 175 176 return ret; 177 } 178 EXPORT_SYMBOL_GPL(driver_register); 179 180 /** 181 * driver_unregister - remove driver from system. 182 * @drv: driver. 183 * 184 * Again, we pass off most of the work to the bus-level call. 185 */ 186 void driver_unregister(struct device_driver *drv) 187 { 188 if (!drv || !drv->p) { 189 WARN(1, "Unexpected driver unregister!\n"); 190 return; 191 } 192 driver_remove_groups(drv, drv->groups); 193 bus_remove_driver(drv); 194 } 195 EXPORT_SYMBOL_GPL(driver_unregister); 196 197 /** 198 * driver_find - locate driver on a bus by its name. 199 * @name: name of the driver. 200 * @bus: bus to scan for the driver. 201 * 202 * Call kset_find_obj() to iterate over list of drivers on 203 * a bus to find driver by name. Return driver if found. 204 * 205 * This routine provides no locking to prevent the driver it returns 206 * from being unregistered or unloaded while the caller is using it. 207 * The caller is responsible for preventing this. 208 */ 209 struct device_driver *driver_find(const char *name, struct bus_type *bus) 210 { 211 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); 212 struct driver_private *priv; 213 214 if (k) { 215 /* Drop reference added by kset_find_obj() */ 216 kobject_put(k); 217 priv = to_driver(k); 218 return priv->driver; 219 } 220 return NULL; 221 } 222 EXPORT_SYMBOL_GPL(driver_find); 223