aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c108
1 files changed, 81 insertions, 27 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 9f6f11ca0ab6..319a73be4180 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/kthread.h>
20 21
21#include "base.h" 22#include "base.h"
22#include "power/power.h" 23#include "power/power.h"
@@ -63,44 +64,35 @@ int device_bind_driver(struct device *dev)
63 return ret; 64 return ret;
64} 65}
65 66
66/** 67struct stupid_thread_structure {
67 * driver_probe_device - attempt to bind device & driver. 68 struct device_driver *drv;
68 * @drv: driver. 69 struct device *dev;
69 * @dev: device. 70};
70 * 71
71 * First, we call the bus's match function, if one present, which 72static atomic_t probe_count = ATOMIC_INIT(0);
72 * should compare the device IDs the driver supports with the 73static int really_probe(void *void_data)
73 * device IDs of the device. Note we don't do this ourselves
74 * because we don't know the format of the ID structures, nor what
75 * is to be considered a match and what is not.
76 *
77 * This function returns 1 if a match is found, an error if one
78 * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
79 *
80 * This function must be called with @dev->sem held. When called
81 * for a USB interface, @dev->parent->sem must be held as well.
82 */
83int driver_probe_device(struct device_driver * drv, struct device * dev)
84{ 74{
75 struct stupid_thread_structure *data = void_data;
76 struct device_driver *drv = data->drv;
77 struct device *dev = data->dev;
85 int ret = 0; 78 int ret = 0;
86 79
87 if (drv->bus->match && !drv->bus->match(dev, drv)) 80 atomic_inc(&probe_count);
88 goto Done; 81 pr_debug("%s: Probing driver %s with device %s\n",
82 drv->bus->name, drv->name, dev->bus_id);
89 83
90 pr_debug("%s: Matched Device %s with Driver %s\n",
91 drv->bus->name, dev->bus_id, drv->name);
92 dev->driver = drv; 84 dev->driver = drv;
93 if (dev->bus->probe) { 85 if (dev->bus->probe) {
94 ret = dev->bus->probe(dev); 86 ret = dev->bus->probe(dev);
95 if (ret) { 87 if (ret) {
96 dev->driver = NULL; 88 dev->driver = NULL;
97 goto ProbeFailed; 89 goto probe_failed;
98 } 90 }
99 } else if (drv->probe) { 91 } else if (drv->probe) {
100 ret = drv->probe(dev); 92 ret = drv->probe(dev);
101 if (ret) { 93 if (ret) {
102 dev->driver = NULL; 94 dev->driver = NULL;
103 goto ProbeFailed; 95 goto probe_failed;
104 } 96 }
105 } 97 }
106 if (device_bind_driver(dev)) { 98 if (device_bind_driver(dev)) {
@@ -111,9 +103,9 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
111 ret = 1; 103 ret = 1;
112 pr_debug("%s: Bound Device %s to Driver %s\n", 104 pr_debug("%s: Bound Device %s to Driver %s\n",
113 drv->bus->name, dev->bus_id, drv->name); 105 drv->bus->name, dev->bus_id, drv->name);
114 goto Done; 106 goto done;
115 107
116 ProbeFailed: 108probe_failed:
117 if (ret == -ENODEV || ret == -ENXIO) { 109 if (ret == -ENODEV || ret == -ENXIO) {
118 /* Driver matched, but didn't support device 110 /* Driver matched, but didn't support device
119 * or device not found. 111 * or device not found.
@@ -126,7 +118,69 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
126 "%s: probe of %s failed with error %d\n", 118 "%s: probe of %s failed with error %d\n",
127 drv->name, dev->bus_id, ret); 119 drv->name, dev->bus_id, ret);
128 } 120 }
129 Done: 121done:
122 kfree(data);
123 atomic_dec(&probe_count);
124 return ret;
125}
126
127/**
128 * driver_probe_done
129 * Determine if the probe sequence is finished or not.
130 *
131 * Should somehow figure out how to use a semaphore, not an atomic variable...
132 */
133int driver_probe_done(void)
134{
135 pr_debug("%s: probe_count = %d\n", __FUNCTION__,
136 atomic_read(&probe_count));
137 if (atomic_read(&probe_count))
138 return -EBUSY;
139 return 0;
140}
141
142/**
143 * driver_probe_device - attempt to bind device & driver together
144 * @drv: driver to bind a device to
145 * @dev: device to try to bind to the driver
146 *
147 * First, we call the bus's match function, if one present, which should
148 * compare the device IDs the driver supports with the device IDs of the
149 * device. Note we don't do this ourselves because we don't know the
150 * format of the ID structures, nor what is to be considered a match and
151 * what is not.
152 *
153 * This function returns 1 if a match is found, an error if one occurs
154 * (that is not -ENODEV or -ENXIO), and 0 otherwise.
155 *
156 * This function must be called with @dev->sem held. When called for a
157 * USB interface, @dev->parent->sem must be held as well.
158 */
159int driver_probe_device(struct device_driver * drv, struct device * dev)
160{
161 struct stupid_thread_structure *data;
162 struct task_struct *probe_task;
163 int ret = 0;
164
165 if (drv->bus->match && !drv->bus->match(dev, drv))
166 goto done;
167
168 pr_debug("%s: Matched Device %s with Driver %s\n",
169 drv->bus->name, dev->bus_id, drv->name);
170
171 data = kmalloc(sizeof(*data), GFP_KERNEL);
172 data->drv = drv;
173 data->dev = dev;
174
175 if (drv->multithread_probe) {
176 probe_task = kthread_run(really_probe, data,
177 "probe-%s", dev->bus_id);
178 if (IS_ERR(probe_task))
179 ret = PTR_ERR(probe_task);
180 } else
181 ret = really_probe(data);
182
183done:
130 return ret; 184 return ret;
131} 185}
132 186