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 if (!drv->bus->p) { 152 pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n", 153 drv->name, drv->bus->name); 154 return -EINVAL; 155 } 156 157 if ((drv->bus->probe && drv->probe) || 158 (drv->bus->remove && drv->remove) || 159 (drv->bus->shutdown && drv->shutdown)) 160 printk(KERN_WARNING "Driver '%s' needs updating - please use " 161 "bus_type methods\n", drv->name); 162 163 other = driver_find(drv->name, drv->bus); 164 if (other) { 165 printk(KERN_ERR "Error: Driver '%s' is already registered, " 166 "aborting...\n", drv->name); 167 return -EBUSY; 168 } 169 170 ret = bus_add_driver(drv); 171 if (ret) 172 return ret; 173 ret = driver_add_groups(drv, drv->groups); 174 if (ret) { 175 bus_remove_driver(drv); 176 return ret; 177 } 178 kobject_uevent(&drv->p->kobj, KOBJ_ADD); 179 180 return ret; 181 } 182 EXPORT_SYMBOL_GPL(driver_register); 183 184 /** 185 * driver_unregister - remove driver from system. 186 * @drv: driver. 187 * 188 * Again, we pass off most of the work to the bus-level call. 189 */ 190 void driver_unregister(struct device_driver *drv) 191 { 192 if (!drv || !drv->p) { 193 WARN(1, "Unexpected driver unregister!\n"); 194 return; 195 } 196 driver_remove_groups(drv, drv->groups); 197 bus_remove_driver(drv); 198 } 199 EXPORT_SYMBOL_GPL(driver_unregister); 200 201 /** 202 * driver_find - locate driver on a bus by its name. 203 * @name: name of the driver. 204 * @bus: bus to scan for the driver. 205 * 206 * Call kset_find_obj() to iterate over list of drivers on 207 * a bus to find driver by name. Return driver if found. 208 * 209 * This routine provides no locking to prevent the driver it returns 210 * from being unregistered or unloaded while the caller is using it. 211 * The caller is responsible for preventing this. 212 */ 213 struct device_driver *driver_find(const char *name, struct bus_type *bus) 214 { 215 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); 216 struct driver_private *priv; 217 218 if (k) { 219 /* Drop reference added by kset_find_obj() */ 220 kobject_put(k); 221 priv = to_driver(k); 222 return priv->driver; 223 } 224 return NULL; 225 } 226 EXPORT_SYMBOL_GPL(driver_find); 227