Blame view
drivers/base/dd.c
10.3 KB
07e4a3e27 [PATCH] Move devi... |
1 |
/* |
4a3ad20cc Driver core: codi... |
2 |
* drivers/base/dd.c - The core device/driver interactions. |
07e4a3e27 [PATCH] Move devi... |
3 |
* |
4a3ad20cc Driver core: codi... |
4 5 6 |
* This file contains the (sometimes tricky) code that controls the * interactions between devices and drivers, which primarily includes * driver binding and unbinding. |
07e4a3e27 [PATCH] Move devi... |
7 |
* |
4a3ad20cc Driver core: codi... |
8 9 10 |
* All of this code used to exist in drivers/base/bus.c, but was * relocated to here in the name of compartmentalization (since it wasn't * strictly code just for the 'struct bus_type'. |
07e4a3e27 [PATCH] Move devi... |
11 |
* |
4a3ad20cc Driver core: codi... |
12 13 |
* Copyright (c) 2002-5 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs |
b40284378 Driver core: move... |
14 15 |
* Copyright (c) 2007-2009 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2007-2009 Novell Inc. |
07e4a3e27 [PATCH] Move devi... |
16 |
* |
4a3ad20cc Driver core: codi... |
17 |
* This file is released under the GPLv2 |
07e4a3e27 [PATCH] Move devi... |
18 19 20 |
*/ #include <linux/device.h> |
216773a78 Consolidate drive... |
21 |
#include <linux/delay.h> |
07e4a3e27 [PATCH] Move devi... |
22 |
#include <linux/module.h> |
d779249ed Driver Core: add ... |
23 |
#include <linux/kthread.h> |
735a7ffb7 [PATCH] drivers: ... |
24 |
#include <linux/wait.h> |
216773a78 Consolidate drive... |
25 |
#include <linux/async.h> |
5e928f77a PM: Introduce cor... |
26 |
#include <linux/pm_runtime.h> |
07e4a3e27 [PATCH] Move devi... |
27 28 29 |
#include "base.h" #include "power/power.h" |
07e4a3e27 [PATCH] Move devi... |
30 |
|
1901fb260 Driver core: fix ... |
31 |
static void driver_bound(struct device *dev) |
07e4a3e27 [PATCH] Move devi... |
32 |
{ |
8940b4f31 driver core: move... |
33 |
if (klist_node_attached(&dev->p->knode_driver)) { |
f86db396f drivers/base: che... |
34 35 |
printk(KERN_WARNING "%s: device %s already bound ", |
2b3a302a0 driver core: repl... |
36 |
__func__, kobject_name(&dev->kobj)); |
1901fb260 Driver core: fix ... |
37 |
return; |
f86db396f drivers/base: che... |
38 |
} |
4c898c7f2 [PATCH] Driver Co... |
39 |
|
1e0b2cf93 driver core: stru... |
40 41 |
pr_debug("driver: '%s': %s: bound to device '%s' ", dev_name(dev), |
2b3a302a0 driver core: repl... |
42 |
__func__, dev->driver->name); |
116af3782 Driver core: add ... |
43 |
|
fbb88fadf driver-core: fix ... |
44 |
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); |
116af3782 Driver core: add ... |
45 |
if (dev->bus) |
c6f7e72a3 driver core: remo... |
46 |
blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
116af3782 Driver core: add ... |
47 |
BUS_NOTIFY_BOUND_DRIVER, dev); |
1901fb260 Driver core: fix ... |
48 49 50 51 52 |
} static int driver_sysfs_add(struct device *dev) { int ret; |
45daef0fd Driver core: Add ... |
53 54 55 |
if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BIND_DRIVER, dev); |
e5dd12784 Driver core: move... |
56 |
ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, |
07e4a3e27 [PATCH] Move devi... |
57 |
kobject_name(&dev->kobj)); |
f86db396f drivers/base: che... |
58 |
if (ret == 0) { |
e5dd12784 Driver core: move... |
59 |
ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj, |
f86db396f drivers/base: che... |
60 61 |
"driver"); if (ret) |
e5dd12784 Driver core: move... |
62 |
sysfs_remove_link(&dev->driver->p->kobj, |
f86db396f drivers/base: che... |
63 64 65 |
kobject_name(&dev->kobj)); } return ret; |
07e4a3e27 [PATCH] Move devi... |
66 |
} |
1901fb260 Driver core: fix ... |
67 68 69 70 71 |
static void driver_sysfs_remove(struct device *dev) { struct device_driver *drv = dev->driver; if (drv) { |
e5dd12784 Driver core: move... |
72 |
sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj)); |
1901fb260 Driver core: fix ... |
73 74 75 76 77 |
sysfs_remove_link(&dev->kobj, "driver"); } } /** |
4a3ad20cc Driver core: codi... |
78 79 |
* device_bind_driver - bind a driver to one device. * @dev: device. |
1901fb260 Driver core: fix ... |
80 |
* |
4a3ad20cc Driver core: codi... |
81 82 |
* Allow manual attachment of a driver to a device. * Caller must have already set @dev->driver. |
1901fb260 Driver core: fix ... |
83 |
* |
4a3ad20cc Driver core: codi... |
84 85 86 87 |
* Note that this does not modify the bus reference count * nor take the bus's rwsem. Please verify those are accounted * for before calling this. (It is ok to call with no other effort * from a driver's probe() method.) |
1901fb260 Driver core: fix ... |
88 |
* |
8e9394ce2 Driver core: crea... |
89 |
* This function must be called with the device lock held. |
1901fb260 Driver core: fix ... |
90 91 92 |
*/ int device_bind_driver(struct device *dev) { |
cb986b749 driver core: Chan... |
93 94 95 96 97 98 |
int ret; ret = driver_sysfs_add(dev); if (!ret) driver_bound(dev); return ret; |
1901fb260 Driver core: fix ... |
99 |
} |
4a3ad20cc Driver core: codi... |
100 |
EXPORT_SYMBOL_GPL(device_bind_driver); |
1901fb260 Driver core: fix ... |
101 |
|
d779249ed Driver Core: add ... |
102 |
static atomic_t probe_count = ATOMIC_INIT(0); |
735a7ffb7 [PATCH] drivers: ... |
103 |
static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); |
21c7f30b1 driver core: per-... |
104 |
static int really_probe(struct device *dev, struct device_driver *drv) |
07e4a3e27 [PATCH] Move devi... |
105 |
{ |
0d3e5a2e3 [PATCH] Driver Co... |
106 |
int ret = 0; |
07e4a3e27 [PATCH] Move devi... |
107 |
|
d779249ed Driver Core: add ... |
108 |
atomic_inc(&probe_count); |
7dc72b284 Driver core: clea... |
109 110 |
pr_debug("bus: '%s': %s: probing driver %s with device %s ", |
1e0b2cf93 driver core: stru... |
111 |
drv->bus->name, __func__, drv->name, dev_name(dev)); |
9ac7849e3 devres: device re... |
112 |
WARN_ON(!list_empty(&dev->devres_head)); |
07e4a3e27 [PATCH] Move devi... |
113 |
|
07e4a3e27 [PATCH] Move devi... |
114 |
dev->driver = drv; |
1901fb260 Driver core: fix ... |
115 116 117 |
if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed ", |
1e0b2cf93 driver core: stru... |
118 |
__func__, dev_name(dev)); |
1901fb260 Driver core: fix ... |
119 120 |
goto probe_failed; } |
594c8281f [PATCH] Add bus_t... |
121 122 |
if (dev->bus->probe) { ret = dev->bus->probe(dev); |
1901fb260 Driver core: fix ... |
123 |
if (ret) |
d779249ed Driver Core: add ... |
124 |
goto probe_failed; |
594c8281f [PATCH] Add bus_t... |
125 |
} else if (drv->probe) { |
0d3e5a2e3 [PATCH] Driver Co... |
126 |
ret = drv->probe(dev); |
1901fb260 Driver core: fix ... |
127 |
if (ret) |
d779249ed Driver Core: add ... |
128 |
goto probe_failed; |
f86db396f drivers/base: che... |
129 |
} |
1901fb260 Driver core: fix ... |
130 131 |
driver_bound(dev); |
0d3e5a2e3 [PATCH] Driver Co... |
132 |
ret = 1; |
7dc72b284 Driver core: clea... |
133 134 |
pr_debug("bus: '%s': %s: bound device %s to driver %s ", |
1e0b2cf93 driver core: stru... |
135 |
drv->bus->name, __func__, dev_name(dev), drv->name); |
d779249ed Driver Core: add ... |
136 |
goto done; |
0d3e5a2e3 [PATCH] Driver Co... |
137 |
|
d779249ed Driver Core: add ... |
138 |
probe_failed: |
9ac7849e3 devres: device re... |
139 |
devres_release_all(dev); |
1901fb260 Driver core: fix ... |
140 141 |
driver_sysfs_remove(dev); dev->driver = NULL; |
c578abbc2 driver core: Don'... |
142 |
if (ret != -ENODEV && ret != -ENXIO) { |
0d3e5a2e3 [PATCH] Driver Co... |
143 144 145 146 |
/* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d ", |
1e0b2cf93 driver core: stru... |
147 |
drv->name, dev_name(dev), ret); |
bcbe4f94d drivers: base: pr... |
148 149 150 151 |
} else { pr_debug("%s: probe of %s rejects match %d ", drv->name, dev_name(dev), ret); |
0d3e5a2e3 [PATCH] Driver Co... |
152 |
} |
c578abbc2 driver core: Don'... |
153 154 155 156 157 |
/* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0; |
d779249ed Driver Core: add ... |
158 |
done: |
d779249ed Driver Core: add ... |
159 |
atomic_dec(&probe_count); |
735a7ffb7 [PATCH] drivers: ... |
160 |
wake_up(&probe_waitqueue); |
d779249ed Driver Core: add ... |
161 162 163 164 165 166 167 168 169 170 171 |
return ret; } /** * driver_probe_done * Determine if the probe sequence is finished or not. * * Should somehow figure out how to use a semaphore, not an atomic variable... */ int driver_probe_done(void) { |
2b3a302a0 driver core: repl... |
172 173 |
pr_debug("%s: probe_count = %d ", __func__, |
d779249ed Driver Core: add ... |
174 175 176 177 178 179 180 |
atomic_read(&probe_count)); if (atomic_read(&probe_count)) return -EBUSY; return 0; } /** |
216773a78 Consolidate drive... |
181 182 |
* wait_for_device_probe * Wait for device probing to be completed. |
216773a78 Consolidate drive... |
183 |
*/ |
b23530ebc driver core: remo... |
184 |
void wait_for_device_probe(void) |
216773a78 Consolidate drive... |
185 186 |
{ /* wait for the known devices to complete their probing */ |
b23530ebc driver core: remo... |
187 |
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); |
216773a78 Consolidate drive... |
188 |
async_synchronize_full(); |
216773a78 Consolidate drive... |
189 |
} |
d4d5291c8 driver synchroniz... |
190 |
EXPORT_SYMBOL_GPL(wait_for_device_probe); |
216773a78 Consolidate drive... |
191 192 |
/** |
d779249ed Driver Core: add ... |
193 194 195 196 |
* driver_probe_device - attempt to bind device & driver together * @drv: driver to bind a device to * @dev: device to try to bind to the driver * |
49b420a13 driver core: chec... |
197 |
* This function returns -ENODEV if the device is not registered, |
af901ca18 tree-wide: fix as... |
198 |
* 1 if the device is bound successfully and 0 otherwise. |
d779249ed Driver Core: add ... |
199 |
* |
8e9394ce2 Driver core: crea... |
200 201 |
* This function must be called with @dev lock held. When called for a * USB interface, @dev->parent lock must be held as well. |
d779249ed Driver Core: add ... |
202 |
*/ |
4a3ad20cc Driver core: codi... |
203 |
int driver_probe_device(struct device_driver *drv, struct device *dev) |
d779249ed Driver Core: add ... |
204 |
{ |
d779249ed Driver Core: add ... |
205 |
int ret = 0; |
f2eaae197 Driver core: Fix ... |
206 207 |
if (!device_is_registered(dev)) return -ENODEV; |
d779249ed Driver Core: add ... |
208 |
|
7dc72b284 Driver core: clea... |
209 210 |
pr_debug("bus: '%s': %s: matched device %s with driver %s ", |
1e0b2cf93 driver core: stru... |
211 |
drv->bus->name, __func__, dev_name(dev), drv->name); |
d779249ed Driver Core: add ... |
212 |
|
5e928f77a PM: Introduce cor... |
213 214 |
pm_runtime_get_noresume(dev); pm_runtime_barrier(dev); |
21c7f30b1 driver core: per-... |
215 |
ret = really_probe(dev, drv); |
5e928f77a PM: Introduce cor... |
216 |
pm_runtime_put_sync(dev); |
d779249ed Driver Core: add ... |
217 |
|
0d3e5a2e3 [PATCH] Driver Co... |
218 |
return ret; |
07e4a3e27 [PATCH] Move devi... |
219 |
} |
4a3ad20cc Driver core: codi... |
220 |
static int __device_attach(struct device_driver *drv, void *data) |
2287c322b [PATCH] Use bus_f... |
221 |
{ |
4a3ad20cc Driver core: codi... |
222 |
struct device *dev = data; |
49b420a13 driver core: chec... |
223 224 225 |
if (!driver_match_device(drv, dev)) return 0; |
0d3e5a2e3 [PATCH] Driver Co... |
226 |
return driver_probe_device(drv, dev); |
2287c322b [PATCH] Use bus_f... |
227 |
} |
07e4a3e27 [PATCH] Move devi... |
228 |
/** |
4a3ad20cc Driver core: codi... |
229 230 |
* device_attach - try to attach device to a driver. * @dev: device. |
07e4a3e27 [PATCH] Move devi... |
231 |
* |
4a3ad20cc Driver core: codi... |
232 233 234 |
* Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. |
0d3e5a2e3 [PATCH] Driver Co... |
235 |
* |
4a3ad20cc Driver core: codi... |
236 |
* Returns 1 if the device was bound to a driver; |
59a3cd7f9 Driver core: fix ... |
237 |
* 0 if no matching driver was found; |
4a3ad20cc Driver core: codi... |
238 |
* -ENODEV if the device is not registered. |
bf74ad5bc [PATCH] Hold the ... |
239 |
* |
8e9394ce2 Driver core: crea... |
240 |
* When called for a USB interface, @dev->parent lock must be held. |
07e4a3e27 [PATCH] Move devi... |
241 |
*/ |
4a3ad20cc Driver core: codi... |
242 |
int device_attach(struct device *dev) |
07e4a3e27 [PATCH] Move devi... |
243 |
{ |
0d3e5a2e3 [PATCH] Driver Co... |
244 |
int ret = 0; |
8e9394ce2 Driver core: crea... |
245 |
device_lock(dev); |
07e4a3e27 [PATCH] Move devi... |
246 |
if (dev->driver) { |
8497d6a21 driver-core: fix ... |
247 248 249 250 |
if (klist_node_attached(&dev->p->knode_driver)) { ret = 1; goto out_unlock; } |
f86db396f drivers/base: che... |
251 252 253 |
ret = device_bind_driver(dev); if (ret == 0) ret = 1; |
c6a46696f driver core: don'... |
254 255 256 257 |
else { dev->driver = NULL; ret = 0; } |
21c7f30b1 driver core: per-... |
258 |
} else { |
5e928f77a PM: Introduce cor... |
259 |
pm_runtime_get_noresume(dev); |
5adc55da4 PCI: remove the b... |
260 |
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
5e928f77a PM: Introduce cor... |
261 |
pm_runtime_put_sync(dev); |
21c7f30b1 driver core: per-... |
262 |
} |
8497d6a21 driver-core: fix ... |
263 |
out_unlock: |
8e9394ce2 Driver core: crea... |
264 |
device_unlock(dev); |
0d3e5a2e3 [PATCH] Driver Co... |
265 |
return ret; |
2287c322b [PATCH] Use bus_f... |
266 |
} |
4a3ad20cc Driver core: codi... |
267 |
EXPORT_SYMBOL_GPL(device_attach); |
2287c322b [PATCH] Use bus_f... |
268 |
|
4a3ad20cc Driver core: codi... |
269 |
static int __driver_attach(struct device *dev, void *data) |
2287c322b [PATCH] Use bus_f... |
270 |
{ |
4a3ad20cc Driver core: codi... |
271 |
struct device_driver *drv = data; |
0d3e5a2e3 [PATCH] Driver Co... |
272 273 274 275 276 277 278 279 280 281 |
/* * Lock device and try to bind to it. We drop the error * here and always return 0, because we need to keep trying * to bind to devices and some drivers will return an error * simply if it didn't support the device. * * driver_probe_device() will spit a warning if there * is an error. */ |
49b420a13 driver core: chec... |
282 |
if (!driver_match_device(drv, dev)) |
6cd495860 device model: Do ... |
283 |
return 0; |
bf74ad5bc [PATCH] Hold the ... |
284 |
if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
285 286 |
device_lock(dev->parent); device_lock(dev); |
0d3e5a2e3 [PATCH] Driver Co... |
287 288 |
if (!dev->driver) driver_probe_device(drv, dev); |
8e9394ce2 Driver core: crea... |
289 |
device_unlock(dev); |
bf74ad5bc [PATCH] Hold the ... |
290 |
if (dev->parent) |
8e9394ce2 Driver core: crea... |
291 |
device_unlock(dev->parent); |
0d3e5a2e3 [PATCH] Driver Co... |
292 |
|
07e4a3e27 [PATCH] Move devi... |
293 294 295 296 |
return 0; } /** |
4a3ad20cc Driver core: codi... |
297 298 |
* driver_attach - try to bind driver to devices. * @drv: driver. |
07e4a3e27 [PATCH] Move devi... |
299 |
* |
4a3ad20cc Driver core: codi... |
300 301 302 303 |
* Walk the list of devices that the bus has on it and try to * match the driver with each one. If driver_probe_device() * returns 0 and the @dev->driver is set, we've found a * compatible pair. |
07e4a3e27 [PATCH] Move devi... |
304 |
*/ |
4a3ad20cc Driver core: codi... |
305 |
int driver_attach(struct device_driver *drv) |
07e4a3e27 [PATCH] Move devi... |
306 |
{ |
f86db396f drivers/base: che... |
307 |
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); |
07e4a3e27 [PATCH] Move devi... |
308 |
} |
4a3ad20cc Driver core: codi... |
309 |
EXPORT_SYMBOL_GPL(driver_attach); |
07e4a3e27 [PATCH] Move devi... |
310 |
|
ab71c6f07 driver core: fix ... |
311 |
/* |
8e9394ce2 Driver core: crea... |
312 313 |
* __device_release_driver() must be called with @dev lock held. * When called for a USB interface, @dev->parent lock must be held as well. |
07e4a3e27 [PATCH] Move devi... |
314 |
*/ |
4a3ad20cc Driver core: codi... |
315 |
static void __device_release_driver(struct device *dev) |
07e4a3e27 [PATCH] Move devi... |
316 |
{ |
4a3ad20cc Driver core: codi... |
317 |
struct device_driver *drv; |
07e4a3e27 [PATCH] Move devi... |
318 |
|
ef2c51746 Driver core: fix ... |
319 |
drv = dev->driver; |
c95a6b057 [PATCH] driver co... |
320 |
if (drv) { |
e1866b33b PM / Runtime: Rew... |
321 |
pm_runtime_get_sync(dev); |
5e928f77a PM: Introduce cor... |
322 |
|
1901fb260 Driver core: fix ... |
323 |
driver_sysfs_remove(dev); |
0d3e5a2e3 [PATCH] Driver Co... |
324 |
|
116af3782 Driver core: add ... |
325 |
if (dev->bus) |
c6f7e72a3 driver core: remo... |
326 |
blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
116af3782 Driver core: add ... |
327 328 |
BUS_NOTIFY_UNBIND_DRIVER, dev); |
e1866b33b PM / Runtime: Rew... |
329 |
pm_runtime_put_sync(dev); |
0f836ca4c [PATCH] driver co... |
330 |
if (dev->bus && dev->bus->remove) |
594c8281f [PATCH] Add bus_t... |
331 332 |
dev->bus->remove(dev); else if (drv->remove) |
0d3e5a2e3 [PATCH] Driver Co... |
333 |
drv->remove(dev); |
9ac7849e3 devres: device re... |
334 |
devres_release_all(dev); |
0d3e5a2e3 [PATCH] Driver Co... |
335 |
dev->driver = NULL; |
8940b4f31 driver core: move... |
336 |
klist_remove(&dev->p->knode_driver); |
309b7d60a driver core: add ... |
337 338 339 340 |
if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_UNBOUND_DRIVER, dev); |
5e928f77a PM: Introduce cor... |
341 |
|
0d3e5a2e3 [PATCH] Driver Co... |
342 |
} |
07e4a3e27 [PATCH] Move devi... |
343 |
} |
ab71c6f07 driver core: fix ... |
344 |
/** |
4a3ad20cc Driver core: codi... |
345 346 |
* device_release_driver - manually detach device from driver. * @dev: device. |
ab71c6f07 driver core: fix ... |
347 |
* |
4a3ad20cc Driver core: codi... |
348 |
* Manually detach device from driver. |
8e9394ce2 Driver core: crea... |
349 |
* When called for a USB interface, @dev->parent lock must be held. |
ab71c6f07 driver core: fix ... |
350 |
*/ |
4a3ad20cc Driver core: codi... |
351 |
void device_release_driver(struct device *dev) |
94e7b1c5f [PATCH] Add a kli... |
352 |
{ |
c95a6b057 [PATCH] driver co... |
353 354 355 356 357 |
/* * If anyone calls device_release_driver() recursively from * within their ->remove callback for the same device, they * will deadlock right here. */ |
8e9394ce2 Driver core: crea... |
358 |
device_lock(dev); |
c95a6b057 [PATCH] driver co... |
359 |
__device_release_driver(dev); |
8e9394ce2 Driver core: crea... |
360 |
device_unlock(dev); |
94e7b1c5f [PATCH] Add a kli... |
361 |
} |
4a3ad20cc Driver core: codi... |
362 |
EXPORT_SYMBOL_GPL(device_release_driver); |
c95a6b057 [PATCH] driver co... |
363 |
|
07e4a3e27 [PATCH] Move devi... |
364 365 366 367 |
/** * driver_detach - detach driver from all devices it controls. * @drv: driver. */ |
4a3ad20cc Driver core: codi... |
368 |
void driver_detach(struct device_driver *drv) |
07e4a3e27 [PATCH] Move devi... |
369 |
{ |
8940b4f31 driver core: move... |
370 |
struct device_private *dev_prv; |
4a3ad20cc Driver core: codi... |
371 |
struct device *dev; |
c95a6b057 [PATCH] driver co... |
372 373 |
for (;;) { |
e5dd12784 Driver core: move... |
374 375 376 |
spin_lock(&drv->p->klist_devices.k_lock); if (list_empty(&drv->p->klist_devices.k_list)) { spin_unlock(&drv->p->klist_devices.k_lock); |
c95a6b057 [PATCH] driver co... |
377 378 |
break; } |
8940b4f31 driver core: move... |
379 380 381 382 |
dev_prv = list_entry(drv->p->klist_devices.k_list.prev, struct device_private, knode_driver.n_node); dev = dev_prv->device; |
c95a6b057 [PATCH] driver co... |
383 |
get_device(dev); |
e5dd12784 Driver core: move... |
384 |
spin_unlock(&drv->p->klist_devices.k_lock); |
c95a6b057 [PATCH] driver co... |
385 |
|
bf74ad5bc [PATCH] Hold the ... |
386 |
if (dev->parent) /* Needed for USB */ |
8e9394ce2 Driver core: crea... |
387 388 |
device_lock(dev->parent); device_lock(dev); |
c95a6b057 [PATCH] driver co... |
389 390 |
if (dev->driver == drv) __device_release_driver(dev); |
8e9394ce2 Driver core: crea... |
391 |
device_unlock(dev); |
bf74ad5bc [PATCH] Hold the ... |
392 |
if (dev->parent) |
8e9394ce2 Driver core: crea... |
393 |
device_unlock(dev->parent); |
c95a6b057 [PATCH] driver co... |
394 395 |
put_device(dev); } |
07e4a3e27 [PATCH] Move devi... |
396 |
} |
b40284378 Driver core: move... |
397 398 399 400 401 402 403 404 405 406 407 408 |
/* * These exports can't be _GPL due to .h files using this within them, and it * might break something that was previously working... */ void *dev_get_drvdata(const struct device *dev) { if (dev && dev->p) return dev->p->driver_data; return NULL; } EXPORT_SYMBOL(dev_get_drvdata); |
c87050824 driver core: let ... |
409 |
int dev_set_drvdata(struct device *dev, void *data) |
b40284378 Driver core: move... |
410 411 |
{ int error; |
b40284378 Driver core: move... |
412 413 414 |
if (!dev->p) { error = device_private_init(dev); if (error) |
c87050824 driver core: let ... |
415 |
return error; |
b40284378 Driver core: move... |
416 417 |
} dev->p->driver_data = data; |
c87050824 driver core: let ... |
418 |
return 0; |
b40284378 Driver core: move... |
419 420 |
} EXPORT_SYMBOL(dev_set_drvdata); |