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

Configure Feed

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

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