Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.11 279 lines 8.0 kB view raw
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 19static 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 38static 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 46static 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 57static 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 62static 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 81static 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 93static 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 107static 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 */ 134int 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} 152EXPORT_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 */ 173int __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} 195EXPORT_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 */ 210struct 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} 222EXPORT_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 */ 230int __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} 250EXPORT_SYMBOL_GPL(__auxiliary_driver_register); 251 252/** 253 * auxiliary_driver_unregister - unregister a driver 254 * @auxdrv: auxiliary_driver structure 255 */ 256void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) 257{ 258 driver_unregister(&auxdrv->driver); 259 kfree(auxdrv->driver.name); 260} 261EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); 262 263static int __init auxiliary_bus_init(void) 264{ 265 return bus_register(&auxiliary_bus_type); 266} 267 268static void __exit auxiliary_bus_exit(void) 269{ 270 bus_unregister(&auxiliary_bus_type); 271} 272 273module_init(auxiliary_bus_init); 274module_exit(auxiliary_bus_exit); 275 276MODULE_LICENSE("GPL v2"); 277MODULE_DESCRIPTION("Auxiliary Bus"); 278MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>"); 279MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>");