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 20 static 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 39 static 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 47 static 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 58 static 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 63 static 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 82 static int 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 return 0; 92 } 93 94 static void auxiliary_bus_shutdown(struct device *dev) 95 { 96 struct auxiliary_driver *auxdrv = NULL; 97 struct auxiliary_device *auxdev; 98 99 if (dev->driver) { 100 auxdrv = to_auxiliary_drv(dev->driver); 101 auxdev = to_auxiliary_dev(dev); 102 } 103 104 if (auxdrv && auxdrv->shutdown) 105 auxdrv->shutdown(auxdev); 106 } 107 108 static struct bus_type auxiliary_bus_type = { 109 .name = "auxiliary", 110 .probe = auxiliary_bus_probe, 111 .remove = auxiliary_bus_remove, 112 .shutdown = auxiliary_bus_shutdown, 113 .match = auxiliary_match, 114 .uevent = auxiliary_uevent, 115 .pm = &auxiliary_dev_pm_ops, 116 }; 117 118 /** 119 * auxiliary_device_init - check auxiliary_device and initialize 120 * @auxdev: auxiliary device struct 121 * 122 * This is the first step in the two-step process to register an 123 * auxiliary_device. 124 * 125 * When this function returns an error code, then the device_initialize will 126 * *not* have been performed, and the caller will be responsible to free any 127 * memory allocated for the auxiliary_device in the error path directly. 128 * 129 * It returns 0 on success. On success, the device_initialize has been 130 * performed. After this point any error unwinding will need to include a call 131 * to auxiliary_device_uninit(). In this post-initialize error scenario, a call 132 * to the device's .release callback will be triggered, and all memory clean-up 133 * is expected to be handled there. 134 */ 135 int auxiliary_device_init(struct auxiliary_device *auxdev) 136 { 137 struct device *dev = &auxdev->dev; 138 139 if (!dev->parent) { 140 pr_err("auxiliary_device has a NULL dev->parent\n"); 141 return -EINVAL; 142 } 143 144 if (!auxdev->name) { 145 pr_err("auxiliary_device has a NULL name\n"); 146 return -EINVAL; 147 } 148 149 dev->bus = &auxiliary_bus_type; 150 device_initialize(&auxdev->dev); 151 return 0; 152 } 153 EXPORT_SYMBOL_GPL(auxiliary_device_init); 154 155 /** 156 * __auxiliary_device_add - add an auxiliary bus device 157 * @auxdev: auxiliary bus device to add to the bus 158 * @modname: name of the parent device's driver module 159 * 160 * This is the second step in the two-step process to register an 161 * auxiliary_device. 162 * 163 * This function must be called after a successful call to 164 * auxiliary_device_init(), which will perform the device_initialize. This 165 * means that if this returns an error code, then a call to 166 * auxiliary_device_uninit() must be performed so that the .release callback 167 * will be triggered to free the memory associated with the auxiliary_device. 168 * 169 * The expectation is that users will call the "auxiliary_device_add" macro so 170 * that the caller's KBUILD_MODNAME is automatically inserted for the modname 171 * parameter. Only if a user requires a custom name would this version be 172 * called directly. 173 */ 174 int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname) 175 { 176 struct device *dev = &auxdev->dev; 177 int ret; 178 179 if (!modname) { 180 dev_err(dev, "auxiliary device modname is NULL\n"); 181 return -EINVAL; 182 } 183 184 ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id); 185 if (ret) { 186 dev_err(dev, "auxiliary device dev_set_name failed: %d\n", ret); 187 return ret; 188 } 189 190 ret = device_add(dev); 191 if (ret) 192 dev_err(dev, "adding auxiliary device failed!: %d\n", ret); 193 194 return ret; 195 } 196 EXPORT_SYMBOL_GPL(__auxiliary_device_add); 197 198 /** 199 * auxiliary_find_device - auxiliary device iterator for locating a particular device. 200 * @start: Device to begin with 201 * @data: Data to pass to match function 202 * @match: Callback function to check device 203 * 204 * This function returns a reference to a device that is 'found' 205 * for later use, as determined by the @match callback. 206 * 207 * The callback should return 0 if the device doesn't match and non-zero 208 * if it does. If the callback returns non-zero, this function will 209 * return to the caller and not iterate over any more devices. 210 */ 211 struct auxiliary_device *auxiliary_find_device(struct device *start, 212 const void *data, 213 int (*match)(struct device *dev, const void *data)) 214 { 215 struct device *dev; 216 217 dev = bus_find_device(&auxiliary_bus_type, start, data, match); 218 if (!dev) 219 return NULL; 220 221 return to_auxiliary_dev(dev); 222 } 223 EXPORT_SYMBOL_GPL(auxiliary_find_device); 224 225 /** 226 * __auxiliary_driver_register - register a driver for auxiliary bus devices 227 * @auxdrv: auxiliary_driver structure 228 * @owner: owning module/driver 229 * @modname: KBUILD_MODNAME for parent driver 230 */ 231 int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, 232 struct module *owner, const char *modname) 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 return driver_register(&auxdrv->driver); 250 } 251 EXPORT_SYMBOL_GPL(__auxiliary_driver_register); 252 253 /** 254 * auxiliary_driver_unregister - unregister a driver 255 * @auxdrv: auxiliary_driver structure 256 */ 257 void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) 258 { 259 driver_unregister(&auxdrv->driver); 260 kfree(auxdrv->driver.name); 261 } 262 EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); 263 264 void __init auxiliary_bus_init(void) 265 { 266 WARN_ON(bus_register(&auxiliary_bus_type)); 267 } 268 269 MODULE_LICENSE("GPL v2"); 270 MODULE_DESCRIPTION("Auxiliary Bus"); 271 MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>"); 272 MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>"); 273