Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/driver.c
26378 views
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 <[email protected]>
8
* Copyright (c) 2007 Novell Inc.
9
*/
10
11
#include <linux/device/driver.h>
12
#include <linux/device.h>
13
#include <linux/module.h>
14
#include <linux/errno.h>
15
#include <linux/slab.h>
16
#include <linux/string.h>
17
#include <linux/sysfs.h>
18
#include "base.h"
19
20
static struct device *next_device(struct klist_iter *i)
21
{
22
struct klist_node *n = klist_next(i);
23
struct device *dev = NULL;
24
struct device_private *dev_prv;
25
26
if (n) {
27
dev_prv = to_device_private_driver(n);
28
dev = dev_prv->device;
29
}
30
return dev;
31
}
32
33
/**
34
* driver_set_override() - Helper to set or clear driver override.
35
* @dev: Device to change
36
* @override: Address of string to change (e.g. &device->driver_override);
37
* The contents will be freed and hold newly allocated override.
38
* @s: NUL-terminated string, new driver name to force a match, pass empty
39
* string to clear it ("" or "\n", where the latter is only for sysfs
40
* interface).
41
* @len: length of @s
42
*
43
* Helper to set or clear driver override in a device, intended for the cases
44
* when the driver_override field is allocated by driver/bus code.
45
*
46
* Returns: 0 on success or a negative error code on failure.
47
*/
48
int driver_set_override(struct device *dev, const char **override,
49
const char *s, size_t len)
50
{
51
const char *new, *old;
52
char *cp;
53
54
if (!override || !s)
55
return -EINVAL;
56
57
/*
58
* The stored value will be used in sysfs show callback (sysfs_emit()),
59
* which has a length limit of PAGE_SIZE and adds a trailing newline.
60
* Thus we can store one character less to avoid truncation during sysfs
61
* show.
62
*/
63
if (len >= (PAGE_SIZE - 1))
64
return -EINVAL;
65
66
/*
67
* Compute the real length of the string in case userspace sends us a
68
* bunch of \0 characters like python likes to do.
69
*/
70
len = strlen(s);
71
72
if (!len) {
73
/* Empty string passed - clear override */
74
device_lock(dev);
75
old = *override;
76
*override = NULL;
77
device_unlock(dev);
78
kfree(old);
79
80
return 0;
81
}
82
83
cp = strnchr(s, len, '\n');
84
if (cp)
85
len = cp - s;
86
87
new = kstrndup(s, len, GFP_KERNEL);
88
if (!new)
89
return -ENOMEM;
90
91
device_lock(dev);
92
old = *override;
93
if (cp != s) {
94
*override = new;
95
} else {
96
/* "\n" passed - clear override */
97
kfree(new);
98
*override = NULL;
99
}
100
device_unlock(dev);
101
102
kfree(old);
103
104
return 0;
105
}
106
EXPORT_SYMBOL_GPL(driver_set_override);
107
108
/**
109
* driver_for_each_device - Iterator for devices bound to a driver.
110
* @drv: Driver we're iterating.
111
* @start: Device to begin with
112
* @data: Data to pass to the callback.
113
* @fn: Function to call for each device.
114
*
115
* Iterate over the @drv's list of devices calling @fn for each one.
116
*/
117
int driver_for_each_device(struct device_driver *drv, struct device *start,
118
void *data, device_iter_t fn)
119
{
120
struct klist_iter i;
121
struct device *dev;
122
int error = 0;
123
124
if (!drv)
125
return -EINVAL;
126
127
klist_iter_init_node(&drv->p->klist_devices, &i,
128
start ? &start->p->knode_driver : NULL);
129
while (!error && (dev = next_device(&i)))
130
error = fn(dev, data);
131
klist_iter_exit(&i);
132
return error;
133
}
134
EXPORT_SYMBOL_GPL(driver_for_each_device);
135
136
/**
137
* driver_find_device - device iterator for locating a particular device.
138
* @drv: The device's driver
139
* @start: Device to begin with
140
* @data: Data to pass to match function
141
* @match: Callback function to check device
142
*
143
* This is similar to the driver_for_each_device() function above, but
144
* it returns a reference to a device that is 'found' for later use, as
145
* determined by the @match callback.
146
*
147
* The callback should return 0 if the device doesn't match and non-zero
148
* if it does. If the callback returns non-zero, this function will
149
* return to the caller and not iterate over any more devices.
150
*/
151
struct device *driver_find_device(const struct device_driver *drv,
152
struct device *start, const void *data,
153
device_match_t match)
154
{
155
struct klist_iter i;
156
struct device *dev;
157
158
if (!drv || !drv->p)
159
return NULL;
160
161
klist_iter_init_node(&drv->p->klist_devices, &i,
162
(start ? &start->p->knode_driver : NULL));
163
while ((dev = next_device(&i))) {
164
if (match(dev, data)) {
165
get_device(dev);
166
break;
167
}
168
}
169
klist_iter_exit(&i);
170
return dev;
171
}
172
EXPORT_SYMBOL_GPL(driver_find_device);
173
174
/**
175
* driver_create_file - create sysfs file for driver.
176
* @drv: driver.
177
* @attr: driver attribute descriptor.
178
*/
179
int driver_create_file(const struct device_driver *drv,
180
const struct driver_attribute *attr)
181
{
182
int error;
183
184
if (drv)
185
error = sysfs_create_file(&drv->p->kobj, &attr->attr);
186
else
187
error = -EINVAL;
188
return error;
189
}
190
EXPORT_SYMBOL_GPL(driver_create_file);
191
192
/**
193
* driver_remove_file - remove sysfs file for driver.
194
* @drv: driver.
195
* @attr: driver attribute descriptor.
196
*/
197
void driver_remove_file(const struct device_driver *drv,
198
const struct driver_attribute *attr)
199
{
200
if (drv)
201
sysfs_remove_file(&drv->p->kobj, &attr->attr);
202
}
203
EXPORT_SYMBOL_GPL(driver_remove_file);
204
205
int driver_add_groups(const struct device_driver *drv,
206
const struct attribute_group **groups)
207
{
208
return sysfs_create_groups(&drv->p->kobj, groups);
209
}
210
211
void driver_remove_groups(const struct device_driver *drv,
212
const struct attribute_group **groups)
213
{
214
sysfs_remove_groups(&drv->p->kobj, groups);
215
}
216
217
/**
218
* driver_register - register driver with bus
219
* @drv: driver to register
220
*
221
* We pass off most of the work to the bus_add_driver() call,
222
* since most of the things we have to do deal with the bus
223
* structures.
224
*/
225
int driver_register(struct device_driver *drv)
226
{
227
int ret;
228
struct device_driver *other;
229
230
if (!bus_is_registered(drv->bus)) {
231
pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",
232
drv->name, drv->bus->name);
233
return -EINVAL;
234
}
235
236
if ((drv->bus->probe && drv->probe) ||
237
(drv->bus->remove && drv->remove) ||
238
(drv->bus->shutdown && drv->shutdown))
239
pr_warn("Driver '%s' needs updating - please use "
240
"bus_type methods\n", drv->name);
241
242
other = driver_find(drv->name, drv->bus);
243
if (other) {
244
pr_err("Error: Driver '%s' is already registered, "
245
"aborting...\n", drv->name);
246
return -EBUSY;
247
}
248
249
ret = bus_add_driver(drv);
250
if (ret)
251
return ret;
252
ret = driver_add_groups(drv, drv->groups);
253
if (ret) {
254
bus_remove_driver(drv);
255
return ret;
256
}
257
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
258
deferred_probe_extend_timeout();
259
260
return ret;
261
}
262
EXPORT_SYMBOL_GPL(driver_register);
263
264
/**
265
* driver_unregister - remove driver from system.
266
* @drv: driver.
267
*
268
* Again, we pass off most of the work to the bus-level call.
269
*/
270
void driver_unregister(struct device_driver *drv)
271
{
272
if (!drv || !drv->p) {
273
WARN(1, "Unexpected driver unregister!\n");
274
return;
275
}
276
driver_remove_groups(drv, drv->groups);
277
bus_remove_driver(drv);
278
}
279
EXPORT_SYMBOL_GPL(driver_unregister);
280
281