1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2019-2020 Intel Corporation 4 * 5 * Please see Documentation/driver-api/auxiliary_bus.rst for more information. 6 */ 7 8 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 9 10 #include <linux/device.h> 11 #include <linux/init.h> 12 #include <linux/slab.h> 13 #include <linux/module.h> 14 #include <linux/pm_domain.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/string.h> 17 #include <linux/auxiliary_bus.h> 18 19 static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id, 20 const struct auxiliary_device *auxdev) 21 { 22 for (; id->name[0]; id++) { 23 const char *p = strrchr(dev_name(&auxdev->dev), '.'); 24 int match_size; 25 26 if (!p) 27 continue; 28 match_size = p - dev_name(&auxdev->dev); 29 30 /* use dev_name(&auxdev->dev) prefix before last '.' char to match to */ 31 if (strlen(id->name) == match_size && 32 !strncmp(dev_name(&auxdev->dev), id->name, match_size)) 33 return id; 34 } 35 return NULL; 36 } 37 38 static int auxiliary_match(struct device *dev, struct device_driver *drv) 39 { 40 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 41 struct auxiliary_driver *auxdrv = to_auxiliary_drv(drv); 42 43 return !!auxiliary_match_id(auxdrv->id_table, auxdev); 44 } 45 46 static int auxiliary_uevent(struct device *dev, struct kobj_uevent_env *env) 47 { 48 const char *name, *p; 49 50 name = dev_name(dev); 51 p = strrchr(name, '.'); 52 53 return add_uevent_var(env, "MODALIAS=%s%.*s", AUXILIARY_MODULE_PREFIX, 54 (int)(p - name), name); 55 } 56 57 static const struct dev_pm_ops auxiliary_dev_pm_ops = { 58 SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) 59 SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume) 60 }; 61 62 static int auxiliary_bus_probe(struct device *dev) 63 { 64 struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 65 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 66 int ret; 67 68 ret = dev_pm_domain_attach(dev, true); 69 if (ret) { 70 dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret); 71 return ret; 72 } 73 74 ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev)); 75 if (ret) 76 dev_pm_domain_detach(dev, true); 77 78 return ret; 79 } 80 81 static int auxiliary_bus_remove(struct device *dev) 82 { 83 struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 84 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 85 86 if (auxdrv->remove) 87 auxdrv->remove(auxdev); 88 dev_pm_domain_detach(dev, true); 89 90 return 0; 91 } 92 93 static void auxiliary_bus_shutdown(struct device *dev) 94 { 95 struct auxiliary_driver *auxdrv = NULL; 96 struct auxiliary_device *auxdev; 97 98 if (dev->driver) { 99 auxdrv = to_auxiliary_drv(dev->driver); 100 auxdev = to_auxiliary_dev(dev); 101 } 102 103 if (auxdrv && auxdrv->shutdown) 104 auxdrv->shutdown(auxdev); 105 } 106 107 static struct bus_type auxiliary_bus_type = { 108 .name = "auxiliary", 109 .probe = auxiliary_bus_probe, 110 .remove = auxiliary_bus_remove, 111 .shutdown = auxiliary_bus_shutdown, 112 .match = auxiliary_match, 113 .uevent = auxiliary_uevent, 114 .pm = &auxiliary_dev_pm_ops, 115 }; 116 117 /** 118 * auxiliary_device_init - check auxiliary_device and initialize 119 * @auxdev: auxiliary device struct 120 * 121 * This is the first step in the two-step process to register an 122 * auxiliary_device. 123 * 124 * When this function returns an error code, then the device_initialize will 125 * *not* have been performed, and the caller will be responsible to free any 126 * memory allocated for the auxiliary_device in the error path directly. 127 * 128 * It returns 0 on success. On success, the device_initialize has been 129 * performed. After this point any error unwinding will need to include a call 130 * to auxiliary_device_uninit(). In this post-initialize error scenario, a call 131 * to the device's .release callback will be triggered, and all memory clean-up 132 * is expected to be handled there. 133 */ 134 int auxiliary_device_init(struct auxiliary_device *auxdev) 135 { 136 struct device *dev = &auxdev->dev; 137 138 if (!dev->parent) { 139 pr_err("auxiliary_device has a NULL dev->parent\n"); 140 return -EINVAL; 141 } 142 143 if (!auxdev->name) { 144 pr_err("auxiliary_device has a NULL name\n"); 145 return -EINVAL; 146 } 147 148 dev->bus = &auxiliary_bus_type; 149 device_initialize(&auxdev->dev); 150 return 0; 151 } 152 EXPORT_SYMBOL_GPL(auxiliary_device_init); 153 154 /** 155 * __auxiliary_device_add - add an auxiliary bus device 156 * @auxdev: auxiliary bus device to add to the bus 157 * @modname: name of the parent device's driver module 158 * 159 * This is the second step in the two-step process to register an 160 * auxiliary_device. 161 * 162 * This function must be called after a successful call to 163 * auxiliary_device_init(), which will perform the device_initialize. This 164 * means that if this returns an error code, then a call to 165 * auxiliary_device_uninit() must be performed so that the .release callback 166 * will be triggered to free the memory associated with the auxiliary_device. 167 * 168 * The expectation is that users will call the "auxiliary_device_add" macro so 169 * that the caller's KBUILD_MODNAME is automatically inserted for the modname 170 * parameter. Only if a user requires a custom name would this version be 171 * called directly. 172 */ 173 int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname) 174 { 175 struct device *dev = &auxdev->dev; 176 int ret; 177 178 if (!modname) { 179 dev_err(dev, "auxiliary device modname is NULL\n"); 180 return -EINVAL; 181 } 182 183 ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id); 184 if (ret) { 185 dev_err(dev, "auxiliary device dev_set_name failed: %d\n", ret); 186 return ret; 187 } 188 189 ret = device_add(dev); 190 if (ret) 191 dev_err(dev, "adding auxiliary device failed!: %d\n", ret); 192 193 return ret; 194 } 195 EXPORT_SYMBOL_GPL(__auxiliary_device_add); 196 197 /** 198 * auxiliary_find_device - auxiliary device iterator for locating a particular device. 199 * @start: Device to begin with 200 * @data: Data to pass to match function 201 * @match: Callback function to check device 202 * 203 * This function returns a reference to a device that is 'found' 204 * for later use, as determined by the @match callback. 205 * 206 * The callback should return 0 if the device doesn't match and non-zero 207 * if it does. If the callback returns non-zero, this function will 208 * return to the caller and not iterate over any more devices. 209 */ 210 struct auxiliary_device *auxiliary_find_device(struct device *start, 211 const void *data, 212 int (*match)(struct device *dev, const void *data)) 213 { 214 struct device *dev; 215 216 dev = bus_find_device(&auxiliary_bus_type, start, data, match); 217 if (!dev) 218 return NULL; 219 220 return to_auxiliary_dev(dev); 221 } 222 EXPORT_SYMBOL_GPL(auxiliary_find_device); 223 224 /** 225 * __auxiliary_driver_register - register a driver for auxiliary bus devices 226 * @auxdrv: auxiliary_driver structure 227 * @owner: owning module/driver 228 * @modname: KBUILD_MODNAME for parent driver 229 */ 230 int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, 231 struct module *owner, const char *modname) 232 { 233 if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table)) 234 return -EINVAL; 235 236 if (auxdrv->name) 237 auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", modname, 238 auxdrv->name); 239 else 240 auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", modname); 241 if (!auxdrv->driver.name) 242 return -ENOMEM; 243 244 auxdrv->driver.owner = owner; 245 auxdrv->driver.bus = &auxiliary_bus_type; 246 auxdrv->driver.mod_name = modname; 247 248 return driver_register(&auxdrv->driver); 249 } 250 EXPORT_SYMBOL_GPL(__auxiliary_driver_register); 251 252 /** 253 * auxiliary_driver_unregister - unregister a driver 254 * @auxdrv: auxiliary_driver structure 255 */ 256 void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) 257 { 258 driver_unregister(&auxdrv->driver); 259 kfree(auxdrv->driver.name); 260 } 261 EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); 262 263 static int __init auxiliary_bus_init(void) 264 { 265 return bus_register(&auxiliary_bus_type); 266 } 267 268 static void __exit auxiliary_bus_exit(void) 269 { 270 bus_unregister(&auxiliary_bus_type); 271 } 272 273 module_init(auxiliary_bus_init); 274 module_exit(auxiliary_bus_exit); 275 276 MODULE_LICENSE("GPL v2"); 277 MODULE_DESCRIPTION("Auxiliary Bus"); 278 MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>"); 279 MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>"); 280