diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/base |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/base')
28 files changed, 5835 insertions, 0 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig new file mode 100644 index 000000000000..934149c1512b --- /dev/null +++ b/drivers/base/Kconfig | |||
@@ -0,0 +1,40 @@ | |||
1 | menu "Generic Driver Options" | ||
2 | |||
3 | config STANDALONE | ||
4 | bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL | ||
5 | default y | ||
6 | help | ||
7 | Select this option if you don't have magic firmware for drivers that | ||
8 | need it. | ||
9 | |||
10 | If unsure, say Y. | ||
11 | |||
12 | config PREVENT_FIRMWARE_BUILD | ||
13 | bool "Prevent firmware from being built" | ||
14 | default y | ||
15 | help | ||
16 | Say yes to avoid building firmware. Firmware is usually shipped | ||
17 | with the driver, and only when updating the firmware a rebuild | ||
18 | should be made. | ||
19 | If unsure say Y here. | ||
20 | |||
21 | config FW_LOADER | ||
22 | tristate "Hotplug firmware loading support" | ||
23 | select HOTPLUG | ||
24 | ---help--- | ||
25 | This option is provided for the case where no in-kernel-tree modules | ||
26 | require hotplug firmware loading support, but a module built outside | ||
27 | the kernel tree does. | ||
28 | |||
29 | config DEBUG_DRIVER | ||
30 | bool "Driver Core verbose debug messages" | ||
31 | depends on DEBUG_KERNEL | ||
32 | help | ||
33 | Say Y here if you want the Driver core to produce a bunch of | ||
34 | debug messages to the system log. Select this if you are having a | ||
35 | problem with the driver core and want to see more of what is | ||
36 | going on. | ||
37 | |||
38 | If you are unsure about this, say N here. | ||
39 | |||
40 | endmenu | ||
diff --git a/drivers/base/Makefile b/drivers/base/Makefile new file mode 100644 index 000000000000..6662b545e0a9 --- /dev/null +++ b/drivers/base/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # Makefile for the Linux device tree | ||
2 | |||
3 | obj-y := core.o sys.o interface.o bus.o \ | ||
4 | driver.o class.o class_simple.o platform.o \ | ||
5 | cpu.o firmware.o init.o map.o dmapool.o \ | ||
6 | attribute_container.o transport_class.o | ||
7 | obj-y += power/ | ||
8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o | ||
9 | obj-$(CONFIG_NUMA) += node.o | ||
10 | |||
11 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | ||
12 | EXTRA_CFLAGS += -DDEBUG | ||
13 | endif | ||
14 | |||
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c new file mode 100644 index 000000000000..ec615d854be9 --- /dev/null +++ b/drivers/base/attribute_container.c | |||
@@ -0,0 +1,376 @@ | |||
1 | /* | ||
2 | * attribute_container.c - implementation of a simple container for classes | ||
3 | * | ||
4 | * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com> | ||
5 | * | ||
6 | * This file is licensed under GPLv2 | ||
7 | * | ||
8 | * The basic idea here is to enable a device to be attached to an | ||
9 | * aritrary numer of classes without having to allocate storage for them. | ||
10 | * Instead, the contained classes select the devices they need to attach | ||
11 | * to via a matching function. | ||
12 | */ | ||
13 | |||
14 | #include <linux/attribute_container.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | /* This is a private structure used to tie the classdev and the | ||
23 | * container .. it should never be visible outside this file */ | ||
24 | struct internal_container { | ||
25 | struct list_head node; | ||
26 | struct attribute_container *cont; | ||
27 | struct class_device classdev; | ||
28 | }; | ||
29 | |||
30 | /** | ||
31 | * attribute_container_classdev_to_container - given a classdev, return the container | ||
32 | * | ||
33 | * @classdev: the class device created by attribute_container_add_device. | ||
34 | * | ||
35 | * Returns the container associated with this classdev. | ||
36 | */ | ||
37 | struct attribute_container * | ||
38 | attribute_container_classdev_to_container(struct class_device *classdev) | ||
39 | { | ||
40 | struct internal_container *ic = | ||
41 | container_of(classdev, struct internal_container, classdev); | ||
42 | return ic->cont; | ||
43 | } | ||
44 | EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container); | ||
45 | |||
46 | static struct list_head attribute_container_list; | ||
47 | |||
48 | static DECLARE_MUTEX(attribute_container_mutex); | ||
49 | |||
50 | /** | ||
51 | * attribute_container_register - register an attribute container | ||
52 | * | ||
53 | * @cont: The container to register. This must be allocated by the | ||
54 | * callee and should also be zeroed by it. | ||
55 | */ | ||
56 | int | ||
57 | attribute_container_register(struct attribute_container *cont) | ||
58 | { | ||
59 | INIT_LIST_HEAD(&cont->node); | ||
60 | INIT_LIST_HEAD(&cont->containers); | ||
61 | |||
62 | down(&attribute_container_mutex); | ||
63 | list_add_tail(&cont->node, &attribute_container_list); | ||
64 | up(&attribute_container_mutex); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | EXPORT_SYMBOL_GPL(attribute_container_register); | ||
69 | |||
70 | /** | ||
71 | * attribute_container_unregister - remove a container registration | ||
72 | * | ||
73 | * @cont: previously registered container to remove | ||
74 | */ | ||
75 | int | ||
76 | attribute_container_unregister(struct attribute_container *cont) | ||
77 | { | ||
78 | int retval = -EBUSY; | ||
79 | down(&attribute_container_mutex); | ||
80 | if (!list_empty(&cont->containers)) | ||
81 | goto out; | ||
82 | retval = 0; | ||
83 | list_del(&cont->node); | ||
84 | out: | ||
85 | up(&attribute_container_mutex); | ||
86 | return retval; | ||
87 | |||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(attribute_container_unregister); | ||
90 | |||
91 | /* private function used as class release */ | ||
92 | static void attribute_container_release(struct class_device *classdev) | ||
93 | { | ||
94 | struct internal_container *ic | ||
95 | = container_of(classdev, struct internal_container, classdev); | ||
96 | struct device *dev = classdev->dev; | ||
97 | |||
98 | kfree(ic); | ||
99 | put_device(dev); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * attribute_container_add_device - see if any container is interested in dev | ||
104 | * | ||
105 | * @dev: device to add attributes to | ||
106 | * @fn: function to trigger addition of class device. | ||
107 | * | ||
108 | * This function allocates storage for the class device(s) to be | ||
109 | * attached to dev (one for each matching attribute_container). If no | ||
110 | * fn is provided, the code will simply register the class device via | ||
111 | * class_device_add. If a function is provided, it is expected to add | ||
112 | * the class device at the appropriate time. One of the things that | ||
113 | * might be necessary is to allocate and initialise the classdev and | ||
114 | * then add it a later time. To do this, call this routine for | ||
115 | * allocation and initialisation and then use | ||
116 | * attribute_container_device_trigger() to call class_device_add() on | ||
117 | * it. Note: after this, the class device contains a reference to dev | ||
118 | * which is not relinquished until the release of the classdev. | ||
119 | */ | ||
120 | void | ||
121 | attribute_container_add_device(struct device *dev, | ||
122 | int (*fn)(struct attribute_container *, | ||
123 | struct device *, | ||
124 | struct class_device *)) | ||
125 | { | ||
126 | struct attribute_container *cont; | ||
127 | |||
128 | down(&attribute_container_mutex); | ||
129 | list_for_each_entry(cont, &attribute_container_list, node) { | ||
130 | struct internal_container *ic; | ||
131 | |||
132 | if (attribute_container_no_classdevs(cont)) | ||
133 | continue; | ||
134 | |||
135 | if (!cont->match(cont, dev)) | ||
136 | continue; | ||
137 | ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL); | ||
138 | if (!ic) { | ||
139 | dev_printk(KERN_ERR, dev, "failed to allocate class container\n"); | ||
140 | continue; | ||
141 | } | ||
142 | memset(ic, 0, sizeof(struct internal_container)); | ||
143 | INIT_LIST_HEAD(&ic->node); | ||
144 | ic->cont = cont; | ||
145 | class_device_initialize(&ic->classdev); | ||
146 | ic->classdev.dev = get_device(dev); | ||
147 | ic->classdev.class = cont->class; | ||
148 | cont->class->release = attribute_container_release; | ||
149 | strcpy(ic->classdev.class_id, dev->bus_id); | ||
150 | if (fn) | ||
151 | fn(cont, dev, &ic->classdev); | ||
152 | else | ||
153 | attribute_container_add_class_device(&ic->classdev); | ||
154 | list_add_tail(&ic->node, &cont->containers); | ||
155 | } | ||
156 | up(&attribute_container_mutex); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * attribute_container_remove_device - make device eligible for removal. | ||
161 | * | ||
162 | * @dev: The generic device | ||
163 | * @fn: A function to call to remove the device | ||
164 | * | ||
165 | * This routine triggers device removal. If fn is NULL, then it is | ||
166 | * simply done via class_device_unregister (note that if something | ||
167 | * still has a reference to the classdev, then the memory occupied | ||
168 | * will not be freed until the classdev is released). If you want a | ||
169 | * two phase release: remove from visibility and then delete the | ||
170 | * device, then you should use this routine with a fn that calls | ||
171 | * class_device_del() and then use | ||
172 | * attribute_container_device_trigger() to do the final put on the | ||
173 | * classdev. | ||
174 | */ | ||
175 | void | ||
176 | attribute_container_remove_device(struct device *dev, | ||
177 | void (*fn)(struct attribute_container *, | ||
178 | struct device *, | ||
179 | struct class_device *)) | ||
180 | { | ||
181 | struct attribute_container *cont; | ||
182 | |||
183 | down(&attribute_container_mutex); | ||
184 | list_for_each_entry(cont, &attribute_container_list, node) { | ||
185 | struct internal_container *ic, *tmp; | ||
186 | |||
187 | if (attribute_container_no_classdevs(cont)) | ||
188 | continue; | ||
189 | |||
190 | if (!cont->match(cont, dev)) | ||
191 | continue; | ||
192 | list_for_each_entry_safe(ic, tmp, &cont->containers, node) { | ||
193 | if (dev != ic->classdev.dev) | ||
194 | continue; | ||
195 | list_del(&ic->node); | ||
196 | if (fn) | ||
197 | fn(cont, dev, &ic->classdev); | ||
198 | else { | ||
199 | attribute_container_remove_attrs(&ic->classdev); | ||
200 | class_device_unregister(&ic->classdev); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | up(&attribute_container_mutex); | ||
205 | } | ||
206 | EXPORT_SYMBOL_GPL(attribute_container_remove_device); | ||
207 | |||
208 | /** | ||
209 | * attribute_container_device_trigger - execute a trigger for each matching classdev | ||
210 | * | ||
211 | * @dev: The generic device to run the trigger for | ||
212 | * @fn the function to execute for each classdev. | ||
213 | * | ||
214 | * This funcion is for executing a trigger when you need to know both | ||
215 | * the container and the classdev. If you only care about the | ||
216 | * container, then use attribute_container_trigger() instead. | ||
217 | */ | ||
218 | void | ||
219 | attribute_container_device_trigger(struct device *dev, | ||
220 | int (*fn)(struct attribute_container *, | ||
221 | struct device *, | ||
222 | struct class_device *)) | ||
223 | { | ||
224 | struct attribute_container *cont; | ||
225 | |||
226 | down(&attribute_container_mutex); | ||
227 | list_for_each_entry(cont, &attribute_container_list, node) { | ||
228 | struct internal_container *ic, *tmp; | ||
229 | |||
230 | if (!cont->match(cont, dev)) | ||
231 | continue; | ||
232 | |||
233 | list_for_each_entry_safe(ic, tmp, &cont->containers, node) { | ||
234 | if (dev == ic->classdev.dev) | ||
235 | fn(cont, dev, &ic->classdev); | ||
236 | } | ||
237 | } | ||
238 | up(&attribute_container_mutex); | ||
239 | } | ||
240 | EXPORT_SYMBOL_GPL(attribute_container_device_trigger); | ||
241 | |||
242 | /** | ||
243 | * attribute_container_trigger - trigger a function for each matching container | ||
244 | * | ||
245 | * @dev: The generic device to activate the trigger for | ||
246 | * @fn: the function to trigger | ||
247 | * | ||
248 | * This routine triggers a function that only needs to know the | ||
249 | * matching containers (not the classdev) associated with a device. | ||
250 | * It is more lightweight than attribute_container_device_trigger, so | ||
251 | * should be used in preference unless the triggering function | ||
252 | * actually needs to know the classdev. | ||
253 | */ | ||
254 | void | ||
255 | attribute_container_trigger(struct device *dev, | ||
256 | int (*fn)(struct attribute_container *, | ||
257 | struct device *)) | ||
258 | { | ||
259 | struct attribute_container *cont; | ||
260 | |||
261 | down(&attribute_container_mutex); | ||
262 | list_for_each_entry(cont, &attribute_container_list, node) { | ||
263 | if (cont->match(cont, dev)) | ||
264 | fn(cont, dev); | ||
265 | } | ||
266 | up(&attribute_container_mutex); | ||
267 | } | ||
268 | EXPORT_SYMBOL_GPL(attribute_container_trigger); | ||
269 | |||
270 | /** | ||
271 | * attribute_container_add_attrs - add attributes | ||
272 | * | ||
273 | * @classdev: The class device | ||
274 | * | ||
275 | * This simply creates all the class device sysfs files from the | ||
276 | * attributes listed in the container | ||
277 | */ | ||
278 | int | ||
279 | attribute_container_add_attrs(struct class_device *classdev) | ||
280 | { | ||
281 | struct attribute_container *cont = | ||
282 | attribute_container_classdev_to_container(classdev); | ||
283 | struct class_device_attribute **attrs = cont->attrs; | ||
284 | int i, error; | ||
285 | |||
286 | if (!attrs) | ||
287 | return 0; | ||
288 | |||
289 | for (i = 0; attrs[i]; i++) { | ||
290 | error = class_device_create_file(classdev, attrs[i]); | ||
291 | if (error) | ||
292 | return error; | ||
293 | } | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | EXPORT_SYMBOL_GPL(attribute_container_add_attrs); | ||
298 | |||
299 | /** | ||
300 | * attribute_container_add_class_device - same function as class_device_add | ||
301 | * | ||
302 | * @classdev: the class device to add | ||
303 | * | ||
304 | * This performs essentially the same function as class_device_add except for | ||
305 | * attribute containers, namely add the classdev to the system and then | ||
306 | * create the attribute files | ||
307 | */ | ||
308 | int | ||
309 | attribute_container_add_class_device(struct class_device *classdev) | ||
310 | { | ||
311 | int error = class_device_add(classdev); | ||
312 | if (error) | ||
313 | return error; | ||
314 | return attribute_container_add_attrs(classdev); | ||
315 | } | ||
316 | EXPORT_SYMBOL_GPL(attribute_container_add_class_device); | ||
317 | |||
318 | /** | ||
319 | * attribute_container_add_class_device_adapter - simple adapter for triggers | ||
320 | * | ||
321 | * This function is identical to attribute_container_add_class_device except | ||
322 | * that it is designed to be called from the triggers | ||
323 | */ | ||
324 | int | ||
325 | attribute_container_add_class_device_adapter(struct attribute_container *cont, | ||
326 | struct device *dev, | ||
327 | struct class_device *classdev) | ||
328 | { | ||
329 | return attribute_container_add_class_device(classdev); | ||
330 | } | ||
331 | EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter); | ||
332 | |||
333 | /** | ||
334 | * attribute_container_remove_attrs - remove any attribute files | ||
335 | * | ||
336 | * @classdev: The class device to remove the files from | ||
337 | * | ||
338 | */ | ||
339 | void | ||
340 | attribute_container_remove_attrs(struct class_device *classdev) | ||
341 | { | ||
342 | struct attribute_container *cont = | ||
343 | attribute_container_classdev_to_container(classdev); | ||
344 | struct class_device_attribute **attrs = cont->attrs; | ||
345 | int i; | ||
346 | |||
347 | if (!attrs) | ||
348 | return; | ||
349 | |||
350 | for (i = 0; attrs[i]; i++) | ||
351 | class_device_remove_file(classdev, attrs[i]); | ||
352 | } | ||
353 | EXPORT_SYMBOL_GPL(attribute_container_remove_attrs); | ||
354 | |||
355 | /** | ||
356 | * attribute_container_class_device_del - equivalent of class_device_del | ||
357 | * | ||
358 | * @classdev: the class device | ||
359 | * | ||
360 | * This function simply removes all the attribute files and then calls | ||
361 | * class_device_del. | ||
362 | */ | ||
363 | void | ||
364 | attribute_container_class_device_del(struct class_device *classdev) | ||
365 | { | ||
366 | attribute_container_remove_attrs(classdev); | ||
367 | class_device_del(classdev); | ||
368 | } | ||
369 | EXPORT_SYMBOL_GPL(attribute_container_class_device_del); | ||
370 | |||
371 | int __init | ||
372 | attribute_container_init(void) | ||
373 | { | ||
374 | INIT_LIST_HEAD(&attribute_container_list); | ||
375 | return 0; | ||
376 | } | ||
diff --git a/drivers/base/base.h b/drivers/base/base.h new file mode 100644 index 000000000000..8d1e8bd48632 --- /dev/null +++ b/drivers/base/base.h | |||
@@ -0,0 +1,18 @@ | |||
1 | extern int bus_add_device(struct device * dev); | ||
2 | extern void bus_remove_device(struct device * dev); | ||
3 | |||
4 | extern int bus_add_driver(struct device_driver *); | ||
5 | extern void bus_remove_driver(struct device_driver *); | ||
6 | |||
7 | static inline struct class_device *to_class_dev(struct kobject *obj) | ||
8 | { | ||
9 | return container_of(obj, struct class_device, kobj); | ||
10 | } | ||
11 | |||
12 | static inline | ||
13 | struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) | ||
14 | { | ||
15 | return container_of(_attr, struct class_device_attribute, attr); | ||
16 | } | ||
17 | |||
18 | |||
diff --git a/drivers/base/bus.c b/drivers/base/bus.c new file mode 100644 index 000000000000..f4fa27315fb4 --- /dev/null +++ b/drivers/base/bus.c | |||
@@ -0,0 +1,770 @@ | |||
1 | /* | ||
2 | * bus.c - bus driver management | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/string.h> | ||
17 | #include "base.h" | ||
18 | #include "power/power.h" | ||
19 | |||
20 | #define to_dev(node) container_of(node, struct device, bus_list) | ||
21 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) | ||
22 | |||
23 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | ||
24 | #define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj) | ||
25 | |||
26 | /* | ||
27 | * sysfs bindings for drivers | ||
28 | */ | ||
29 | |||
30 | #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) | ||
31 | #define to_driver(obj) container_of(obj, struct device_driver, kobj) | ||
32 | |||
33 | |||
34 | static ssize_t | ||
35 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
36 | { | ||
37 | struct driver_attribute * drv_attr = to_drv_attr(attr); | ||
38 | struct device_driver * drv = to_driver(kobj); | ||
39 | ssize_t ret = 0; | ||
40 | |||
41 | if (drv_attr->show) | ||
42 | ret = drv_attr->show(drv, buf); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | static ssize_t | ||
47 | drv_attr_store(struct kobject * kobj, struct attribute * attr, | ||
48 | const char * buf, size_t count) | ||
49 | { | ||
50 | struct driver_attribute * drv_attr = to_drv_attr(attr); | ||
51 | struct device_driver * drv = to_driver(kobj); | ||
52 | ssize_t ret = 0; | ||
53 | |||
54 | if (drv_attr->store) | ||
55 | ret = drv_attr->store(drv, buf, count); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static struct sysfs_ops driver_sysfs_ops = { | ||
60 | .show = drv_attr_show, | ||
61 | .store = drv_attr_store, | ||
62 | }; | ||
63 | |||
64 | |||
65 | static void driver_release(struct kobject * kobj) | ||
66 | { | ||
67 | struct device_driver * drv = to_driver(kobj); | ||
68 | complete(&drv->unloaded); | ||
69 | } | ||
70 | |||
71 | static struct kobj_type ktype_driver = { | ||
72 | .sysfs_ops = &driver_sysfs_ops, | ||
73 | .release = driver_release, | ||
74 | }; | ||
75 | |||
76 | |||
77 | /* | ||
78 | * sysfs bindings for buses | ||
79 | */ | ||
80 | |||
81 | |||
82 | static ssize_t | ||
83 | bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
84 | { | ||
85 | struct bus_attribute * bus_attr = to_bus_attr(attr); | ||
86 | struct bus_type * bus = to_bus(kobj); | ||
87 | ssize_t ret = 0; | ||
88 | |||
89 | if (bus_attr->show) | ||
90 | ret = bus_attr->show(bus, buf); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static ssize_t | ||
95 | bus_attr_store(struct kobject * kobj, struct attribute * attr, | ||
96 | const char * buf, size_t count) | ||
97 | { | ||
98 | struct bus_attribute * bus_attr = to_bus_attr(attr); | ||
99 | struct bus_type * bus = to_bus(kobj); | ||
100 | ssize_t ret = 0; | ||
101 | |||
102 | if (bus_attr->store) | ||
103 | ret = bus_attr->store(bus, buf, count); | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static struct sysfs_ops bus_sysfs_ops = { | ||
108 | .show = bus_attr_show, | ||
109 | .store = bus_attr_store, | ||
110 | }; | ||
111 | |||
112 | int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) | ||
113 | { | ||
114 | int error; | ||
115 | if (get_bus(bus)) { | ||
116 | error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr); | ||
117 | put_bus(bus); | ||
118 | } else | ||
119 | error = -EINVAL; | ||
120 | return error; | ||
121 | } | ||
122 | |||
123 | void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) | ||
124 | { | ||
125 | if (get_bus(bus)) { | ||
126 | sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr); | ||
127 | put_bus(bus); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | static struct kobj_type ktype_bus = { | ||
132 | .sysfs_ops = &bus_sysfs_ops, | ||
133 | |||
134 | }; | ||
135 | |||
136 | decl_subsys(bus, &ktype_bus, NULL); | ||
137 | |||
138 | static int __bus_for_each_dev(struct bus_type *bus, struct device *start, | ||
139 | void *data, int (*fn)(struct device *, void *)) | ||
140 | { | ||
141 | struct list_head *head; | ||
142 | struct device *dev; | ||
143 | int error = 0; | ||
144 | |||
145 | if (!(bus = get_bus(bus))) | ||
146 | return -EINVAL; | ||
147 | |||
148 | head = &bus->devices.list; | ||
149 | dev = list_prepare_entry(start, head, bus_list); | ||
150 | list_for_each_entry_continue(dev, head, bus_list) { | ||
151 | get_device(dev); | ||
152 | error = fn(dev, data); | ||
153 | put_device(dev); | ||
154 | if (error) | ||
155 | break; | ||
156 | } | ||
157 | put_bus(bus); | ||
158 | return error; | ||
159 | } | ||
160 | |||
161 | static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | ||
162 | void * data, int (*fn)(struct device_driver *, void *)) | ||
163 | { | ||
164 | struct list_head *head; | ||
165 | struct device_driver *drv; | ||
166 | int error = 0; | ||
167 | |||
168 | if (!(bus = get_bus(bus))) | ||
169 | return -EINVAL; | ||
170 | |||
171 | head = &bus->drivers.list; | ||
172 | drv = list_prepare_entry(start, head, kobj.entry); | ||
173 | list_for_each_entry_continue(drv, head, kobj.entry) { | ||
174 | get_driver(drv); | ||
175 | error = fn(drv, data); | ||
176 | put_driver(drv); | ||
177 | if (error) | ||
178 | break; | ||
179 | } | ||
180 | put_bus(bus); | ||
181 | return error; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * bus_for_each_dev - device iterator. | ||
186 | * @bus: bus type. | ||
187 | * @start: device to start iterating from. | ||
188 | * @data: data for the callback. | ||
189 | * @fn: function to be called for each device. | ||
190 | * | ||
191 | * Iterate over @bus's list of devices, and call @fn for each, | ||
192 | * passing it @data. If @start is not NULL, we use that device to | ||
193 | * begin iterating from. | ||
194 | * | ||
195 | * We check the return of @fn each time. If it returns anything | ||
196 | * other than 0, we break out and return that value. | ||
197 | * | ||
198 | * NOTE: The device that returns a non-zero value is not retained | ||
199 | * in any way, nor is its refcount incremented. If the caller needs | ||
200 | * to retain this data, it should do, and increment the reference | ||
201 | * count in the supplied callback. | ||
202 | */ | ||
203 | |||
204 | int bus_for_each_dev(struct bus_type * bus, struct device * start, | ||
205 | void * data, int (*fn)(struct device *, void *)) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | down_read(&bus->subsys.rwsem); | ||
210 | ret = __bus_for_each_dev(bus, start, data, fn); | ||
211 | up_read(&bus->subsys.rwsem); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * bus_for_each_drv - driver iterator | ||
217 | * @bus: bus we're dealing with. | ||
218 | * @start: driver to start iterating on. | ||
219 | * @data: data to pass to the callback. | ||
220 | * @fn: function to call for each driver. | ||
221 | * | ||
222 | * This is nearly identical to the device iterator above. | ||
223 | * We iterate over each driver that belongs to @bus, and call | ||
224 | * @fn for each. If @fn returns anything but 0, we break out | ||
225 | * and return it. If @start is not NULL, we use it as the head | ||
226 | * of the list. | ||
227 | * | ||
228 | * NOTE: we don't return the driver that returns a non-zero | ||
229 | * value, nor do we leave the reference count incremented for that | ||
230 | * driver. If the caller needs to know that info, it must set it | ||
231 | * in the callback. It must also be sure to increment the refcount | ||
232 | * so it doesn't disappear before returning to the caller. | ||
233 | */ | ||
234 | |||
235 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | ||
236 | void * data, int (*fn)(struct device_driver *, void *)) | ||
237 | { | ||
238 | int ret; | ||
239 | |||
240 | down_read(&bus->subsys.rwsem); | ||
241 | ret = __bus_for_each_drv(bus, start, data, fn); | ||
242 | up_read(&bus->subsys.rwsem); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * device_bind_driver - bind a driver to one device. | ||
248 | * @dev: device. | ||
249 | * | ||
250 | * Allow manual attachment of a driver to a device. | ||
251 | * Caller must have already set @dev->driver. | ||
252 | * | ||
253 | * Note that this does not modify the bus reference count | ||
254 | * nor take the bus's rwsem. Please verify those are accounted | ||
255 | * for before calling this. (It is ok to call with no other effort | ||
256 | * from a driver's probe() method.) | ||
257 | */ | ||
258 | |||
259 | void device_bind_driver(struct device * dev) | ||
260 | { | ||
261 | pr_debug("bound device '%s' to driver '%s'\n", | ||
262 | dev->bus_id, dev->driver->name); | ||
263 | list_add_tail(&dev->driver_list, &dev->driver->devices); | ||
264 | sysfs_create_link(&dev->driver->kobj, &dev->kobj, | ||
265 | kobject_name(&dev->kobj)); | ||
266 | sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); | ||
267 | } | ||
268 | |||
269 | |||
270 | /** | ||
271 | * driver_probe_device - attempt to bind device & driver. | ||
272 | * @drv: driver. | ||
273 | * @dev: device. | ||
274 | * | ||
275 | * First, we call the bus's match function, if one present, which | ||
276 | * should compare the device IDs the driver supports with the | ||
277 | * device IDs of the device. Note we don't do this ourselves | ||
278 | * because we don't know the format of the ID structures, nor what | ||
279 | * is to be considered a match and what is not. | ||
280 | * | ||
281 | * If we find a match, we call @drv->probe(@dev) if it exists, and | ||
282 | * call device_bind_driver() above. | ||
283 | */ | ||
284 | int driver_probe_device(struct device_driver * drv, struct device * dev) | ||
285 | { | ||
286 | if (drv->bus->match && !drv->bus->match(dev, drv)) | ||
287 | return -ENODEV; | ||
288 | |||
289 | dev->driver = drv; | ||
290 | if (drv->probe) { | ||
291 | int error = drv->probe(dev); | ||
292 | if (error) { | ||
293 | dev->driver = NULL; | ||
294 | return error; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | device_bind_driver(dev); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * device_attach - try to attach device to a driver. | ||
305 | * @dev: device. | ||
306 | * | ||
307 | * Walk the list of drivers that the bus has and call | ||
308 | * driver_probe_device() for each pair. If a compatible | ||
309 | * pair is found, break out and return. | ||
310 | */ | ||
311 | int device_attach(struct device * dev) | ||
312 | { | ||
313 | struct bus_type * bus = dev->bus; | ||
314 | struct list_head * entry; | ||
315 | int error; | ||
316 | |||
317 | if (dev->driver) { | ||
318 | device_bind_driver(dev); | ||
319 | return 1; | ||
320 | } | ||
321 | |||
322 | if (bus->match) { | ||
323 | list_for_each(entry, &bus->drivers.list) { | ||
324 | struct device_driver * drv = to_drv(entry); | ||
325 | error = driver_probe_device(drv, dev); | ||
326 | if (!error) | ||
327 | /* success, driver matched */ | ||
328 | return 1; | ||
329 | if (error != -ENODEV && error != -ENXIO) | ||
330 | /* driver matched but the probe failed */ | ||
331 | printk(KERN_WARNING | ||
332 | "%s: probe of %s failed with error %d\n", | ||
333 | drv->name, dev->bus_id, error); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * driver_attach - try to bind driver to devices. | ||
343 | * @drv: driver. | ||
344 | * | ||
345 | * Walk the list of devices that the bus has on it and try to | ||
346 | * match the driver with each one. If driver_probe_device() | ||
347 | * returns 0 and the @dev->driver is set, we've found a | ||
348 | * compatible pair. | ||
349 | * | ||
350 | * Note that we ignore the -ENODEV error from driver_probe_device(), | ||
351 | * since it's perfectly valid for a driver not to bind to any devices. | ||
352 | */ | ||
353 | void driver_attach(struct device_driver * drv) | ||
354 | { | ||
355 | struct bus_type * bus = drv->bus; | ||
356 | struct list_head * entry; | ||
357 | int error; | ||
358 | |||
359 | if (!bus->match) | ||
360 | return; | ||
361 | |||
362 | list_for_each(entry, &bus->devices.list) { | ||
363 | struct device * dev = container_of(entry, struct device, bus_list); | ||
364 | if (!dev->driver) { | ||
365 | error = driver_probe_device(drv, dev); | ||
366 | if (error && (error != -ENODEV)) | ||
367 | /* driver matched but the probe failed */ | ||
368 | printk(KERN_WARNING | ||
369 | "%s: probe of %s failed with error %d\n", | ||
370 | drv->name, dev->bus_id, error); | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | |||
376 | /** | ||
377 | * device_release_driver - manually detach device from driver. | ||
378 | * @dev: device. | ||
379 | * | ||
380 | * Manually detach device from driver. | ||
381 | * Note that this is called without incrementing the bus | ||
382 | * reference count nor taking the bus's rwsem. Be sure that | ||
383 | * those are accounted for before calling this function. | ||
384 | */ | ||
385 | |||
386 | void device_release_driver(struct device * dev) | ||
387 | { | ||
388 | struct device_driver * drv = dev->driver; | ||
389 | if (drv) { | ||
390 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | ||
391 | sysfs_remove_link(&dev->kobj, "driver"); | ||
392 | list_del_init(&dev->driver_list); | ||
393 | device_detach_shutdown(dev); | ||
394 | if (drv->remove) | ||
395 | drv->remove(dev); | ||
396 | dev->driver = NULL; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * driver_detach - detach driver from all devices it controls. | ||
403 | * @drv: driver. | ||
404 | */ | ||
405 | |||
406 | static void driver_detach(struct device_driver * drv) | ||
407 | { | ||
408 | struct list_head * entry, * next; | ||
409 | list_for_each_safe(entry, next, &drv->devices) { | ||
410 | struct device * dev = container_of(entry, struct device, driver_list); | ||
411 | device_release_driver(dev); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static int device_add_attrs(struct bus_type * bus, struct device * dev) | ||
416 | { | ||
417 | int error = 0; | ||
418 | int i; | ||
419 | |||
420 | if (bus->dev_attrs) { | ||
421 | for (i = 0; attr_name(bus->dev_attrs[i]); i++) { | ||
422 | error = device_create_file(dev,&bus->dev_attrs[i]); | ||
423 | if (error) | ||
424 | goto Err; | ||
425 | } | ||
426 | } | ||
427 | Done: | ||
428 | return error; | ||
429 | Err: | ||
430 | while (--i >= 0) | ||
431 | device_remove_file(dev,&bus->dev_attrs[i]); | ||
432 | goto Done; | ||
433 | } | ||
434 | |||
435 | |||
436 | static void device_remove_attrs(struct bus_type * bus, struct device * dev) | ||
437 | { | ||
438 | int i; | ||
439 | |||
440 | if (bus->dev_attrs) { | ||
441 | for (i = 0; attr_name(bus->dev_attrs[i]); i++) | ||
442 | device_remove_file(dev,&bus->dev_attrs[i]); | ||
443 | } | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * bus_add_device - add device to bus | ||
449 | * @dev: device being added | ||
450 | * | ||
451 | * - Add the device to its bus's list of devices. | ||
452 | * - Try to attach to driver. | ||
453 | * - Create link to device's physical location. | ||
454 | */ | ||
455 | int bus_add_device(struct device * dev) | ||
456 | { | ||
457 | struct bus_type * bus = get_bus(dev->bus); | ||
458 | int error = 0; | ||
459 | |||
460 | if (bus) { | ||
461 | down_write(&dev->bus->subsys.rwsem); | ||
462 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); | ||
463 | list_add_tail(&dev->bus_list, &dev->bus->devices.list); | ||
464 | device_attach(dev); | ||
465 | up_write(&dev->bus->subsys.rwsem); | ||
466 | device_add_attrs(bus, dev); | ||
467 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); | ||
468 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); | ||
469 | } | ||
470 | return error; | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * bus_remove_device - remove device from bus | ||
475 | * @dev: device to be removed | ||
476 | * | ||
477 | * - Remove symlink from bus's directory. | ||
478 | * - Delete device from bus's list. | ||
479 | * - Detach from its driver. | ||
480 | * - Drop reference taken in bus_add_device(). | ||
481 | */ | ||
482 | void bus_remove_device(struct device * dev) | ||
483 | { | ||
484 | if (dev->bus) { | ||
485 | sysfs_remove_link(&dev->kobj, "bus"); | ||
486 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | ||
487 | device_remove_attrs(dev->bus, dev); | ||
488 | down_write(&dev->bus->subsys.rwsem); | ||
489 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | ||
490 | device_release_driver(dev); | ||
491 | list_del_init(&dev->bus_list); | ||
492 | up_write(&dev->bus->subsys.rwsem); | ||
493 | put_bus(dev->bus); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv) | ||
498 | { | ||
499 | int error = 0; | ||
500 | int i; | ||
501 | |||
502 | if (bus->drv_attrs) { | ||
503 | for (i = 0; attr_name(bus->drv_attrs[i]); i++) { | ||
504 | error = driver_create_file(drv, &bus->drv_attrs[i]); | ||
505 | if (error) | ||
506 | goto Err; | ||
507 | } | ||
508 | } | ||
509 | Done: | ||
510 | return error; | ||
511 | Err: | ||
512 | while (--i >= 0) | ||
513 | driver_remove_file(drv, &bus->drv_attrs[i]); | ||
514 | goto Done; | ||
515 | } | ||
516 | |||
517 | |||
518 | static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv) | ||
519 | { | ||
520 | int i; | ||
521 | |||
522 | if (bus->drv_attrs) { | ||
523 | for (i = 0; attr_name(bus->drv_attrs[i]); i++) | ||
524 | driver_remove_file(drv, &bus->drv_attrs[i]); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | |||
529 | /** | ||
530 | * bus_add_driver - Add a driver to the bus. | ||
531 | * @drv: driver. | ||
532 | * | ||
533 | */ | ||
534 | int bus_add_driver(struct device_driver * drv) | ||
535 | { | ||
536 | struct bus_type * bus = get_bus(drv->bus); | ||
537 | int error = 0; | ||
538 | |||
539 | if (bus) { | ||
540 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | ||
541 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | ||
542 | if (error) { | ||
543 | put_bus(bus); | ||
544 | return error; | ||
545 | } | ||
546 | drv->kobj.kset = &bus->drivers; | ||
547 | if ((error = kobject_register(&drv->kobj))) { | ||
548 | put_bus(bus); | ||
549 | return error; | ||
550 | } | ||
551 | |||
552 | down_write(&bus->subsys.rwsem); | ||
553 | driver_attach(drv); | ||
554 | up_write(&bus->subsys.rwsem); | ||
555 | module_add_driver(drv->owner, drv); | ||
556 | |||
557 | driver_add_attrs(bus, drv); | ||
558 | } | ||
559 | return error; | ||
560 | } | ||
561 | |||
562 | |||
563 | /** | ||
564 | * bus_remove_driver - delete driver from bus's knowledge. | ||
565 | * @drv: driver. | ||
566 | * | ||
567 | * Detach the driver from the devices it controls, and remove | ||
568 | * it from its bus's list of drivers. Finally, we drop the reference | ||
569 | * to the bus we took in bus_add_driver(). | ||
570 | */ | ||
571 | |||
572 | void bus_remove_driver(struct device_driver * drv) | ||
573 | { | ||
574 | if (drv->bus) { | ||
575 | driver_remove_attrs(drv->bus, drv); | ||
576 | down_write(&drv->bus->subsys.rwsem); | ||
577 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | ||
578 | driver_detach(drv); | ||
579 | up_write(&drv->bus->subsys.rwsem); | ||
580 | module_remove_driver(drv); | ||
581 | kobject_unregister(&drv->kobj); | ||
582 | put_bus(drv->bus); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | |||
587 | /* Helper for bus_rescan_devices's iter */ | ||
588 | static int bus_rescan_devices_helper(struct device *dev, void *data) | ||
589 | { | ||
590 | int *count = data; | ||
591 | |||
592 | if (!dev->driver && device_attach(dev)) | ||
593 | (*count)++; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * bus_rescan_devices - rescan devices on the bus for possible drivers | ||
601 | * @bus: the bus to scan. | ||
602 | * | ||
603 | * This function will look for devices on the bus with no driver | ||
604 | * attached and rescan it against existing drivers to see if it | ||
605 | * matches any. Calls device_attach(). Returns the number of devices | ||
606 | * that were sucessfully bound to a driver. | ||
607 | */ | ||
608 | int bus_rescan_devices(struct bus_type * bus) | ||
609 | { | ||
610 | int count = 0; | ||
611 | |||
612 | down_write(&bus->subsys.rwsem); | ||
613 | __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); | ||
614 | up_write(&bus->subsys.rwsem); | ||
615 | |||
616 | return count; | ||
617 | } | ||
618 | |||
619 | |||
620 | struct bus_type * get_bus(struct bus_type * bus) | ||
621 | { | ||
622 | return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL; | ||
623 | } | ||
624 | |||
625 | void put_bus(struct bus_type * bus) | ||
626 | { | ||
627 | subsys_put(&bus->subsys); | ||
628 | } | ||
629 | |||
630 | |||
631 | /** | ||
632 | * find_bus - locate bus by name. | ||
633 | * @name: name of bus. | ||
634 | * | ||
635 | * Call kset_find_obj() to iterate over list of buses to | ||
636 | * find a bus by name. Return bus if found. | ||
637 | * | ||
638 | * Note that kset_find_obj increments bus' reference count. | ||
639 | */ | ||
640 | |||
641 | struct bus_type * find_bus(char * name) | ||
642 | { | ||
643 | struct kobject * k = kset_find_obj(&bus_subsys.kset, name); | ||
644 | return k ? to_bus(k) : NULL; | ||
645 | } | ||
646 | |||
647 | |||
648 | /** | ||
649 | * bus_add_attrs - Add default attributes for this bus. | ||
650 | * @bus: Bus that has just been registered. | ||
651 | */ | ||
652 | |||
653 | static int bus_add_attrs(struct bus_type * bus) | ||
654 | { | ||
655 | int error = 0; | ||
656 | int i; | ||
657 | |||
658 | if (bus->bus_attrs) { | ||
659 | for (i = 0; attr_name(bus->bus_attrs[i]); i++) { | ||
660 | if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) | ||
661 | goto Err; | ||
662 | } | ||
663 | } | ||
664 | Done: | ||
665 | return error; | ||
666 | Err: | ||
667 | while (--i >= 0) | ||
668 | bus_remove_file(bus,&bus->bus_attrs[i]); | ||
669 | goto Done; | ||
670 | } | ||
671 | |||
672 | static void bus_remove_attrs(struct bus_type * bus) | ||
673 | { | ||
674 | int i; | ||
675 | |||
676 | if (bus->bus_attrs) { | ||
677 | for (i = 0; attr_name(bus->bus_attrs[i]); i++) | ||
678 | bus_remove_file(bus,&bus->bus_attrs[i]); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | /** | ||
683 | * bus_register - register a bus with the system. | ||
684 | * @bus: bus. | ||
685 | * | ||
686 | * Once we have that, we registered the bus with the kobject | ||
687 | * infrastructure, then register the children subsystems it has: | ||
688 | * the devices and drivers that belong to the bus. | ||
689 | */ | ||
690 | int bus_register(struct bus_type * bus) | ||
691 | { | ||
692 | int retval; | ||
693 | |||
694 | retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); | ||
695 | if (retval) | ||
696 | goto out; | ||
697 | |||
698 | subsys_set_kset(bus, bus_subsys); | ||
699 | retval = subsystem_register(&bus->subsys); | ||
700 | if (retval) | ||
701 | goto out; | ||
702 | |||
703 | kobject_set_name(&bus->devices.kobj, "devices"); | ||
704 | bus->devices.subsys = &bus->subsys; | ||
705 | retval = kset_register(&bus->devices); | ||
706 | if (retval) | ||
707 | goto bus_devices_fail; | ||
708 | |||
709 | kobject_set_name(&bus->drivers.kobj, "drivers"); | ||
710 | bus->drivers.subsys = &bus->subsys; | ||
711 | bus->drivers.ktype = &ktype_driver; | ||
712 | retval = kset_register(&bus->drivers); | ||
713 | if (retval) | ||
714 | goto bus_drivers_fail; | ||
715 | bus_add_attrs(bus); | ||
716 | |||
717 | pr_debug("bus type '%s' registered\n", bus->name); | ||
718 | return 0; | ||
719 | |||
720 | bus_drivers_fail: | ||
721 | kset_unregister(&bus->devices); | ||
722 | bus_devices_fail: | ||
723 | subsystem_unregister(&bus->subsys); | ||
724 | out: | ||
725 | return retval; | ||
726 | } | ||
727 | |||
728 | |||
729 | /** | ||
730 | * bus_unregister - remove a bus from the system | ||
731 | * @bus: bus. | ||
732 | * | ||
733 | * Unregister the child subsystems and the bus itself. | ||
734 | * Finally, we call put_bus() to release the refcount | ||
735 | */ | ||
736 | void bus_unregister(struct bus_type * bus) | ||
737 | { | ||
738 | pr_debug("bus %s: unregistering\n", bus->name); | ||
739 | bus_remove_attrs(bus); | ||
740 | kset_unregister(&bus->drivers); | ||
741 | kset_unregister(&bus->devices); | ||
742 | subsystem_unregister(&bus->subsys); | ||
743 | } | ||
744 | |||
745 | int __init buses_init(void) | ||
746 | { | ||
747 | return subsystem_register(&bus_subsys); | ||
748 | } | ||
749 | |||
750 | |||
751 | EXPORT_SYMBOL_GPL(bus_for_each_dev); | ||
752 | EXPORT_SYMBOL_GPL(bus_for_each_drv); | ||
753 | |||
754 | EXPORT_SYMBOL_GPL(driver_probe_device); | ||
755 | EXPORT_SYMBOL_GPL(device_bind_driver); | ||
756 | EXPORT_SYMBOL_GPL(device_release_driver); | ||
757 | EXPORT_SYMBOL_GPL(device_attach); | ||
758 | EXPORT_SYMBOL_GPL(driver_attach); | ||
759 | |||
760 | EXPORT_SYMBOL_GPL(bus_add_device); | ||
761 | EXPORT_SYMBOL_GPL(bus_remove_device); | ||
762 | EXPORT_SYMBOL_GPL(bus_register); | ||
763 | EXPORT_SYMBOL_GPL(bus_unregister); | ||
764 | EXPORT_SYMBOL_GPL(bus_rescan_devices); | ||
765 | EXPORT_SYMBOL_GPL(get_bus); | ||
766 | EXPORT_SYMBOL_GPL(put_bus); | ||
767 | EXPORT_SYMBOL_GPL(find_bus); | ||
768 | |||
769 | EXPORT_SYMBOL_GPL(bus_create_file); | ||
770 | EXPORT_SYMBOL_GPL(bus_remove_file); | ||
diff --git a/drivers/base/class.c b/drivers/base/class.c new file mode 100644 index 000000000000..6bf650fce78c --- /dev/null +++ b/drivers/base/class.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * class.c - basic device class management | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * Copyright (c) 2003-2004 Greg Kroah-Hartman | ||
7 | * Copyright (c) 2003-2004 IBM Corp. | ||
8 | * | ||
9 | * This file is released under the GPLv2 | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/kdev_t.h> | ||
19 | #include "base.h" | ||
20 | |||
21 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) | ||
22 | #define to_class(obj) container_of(obj, struct class, subsys.kset.kobj) | ||
23 | |||
24 | static ssize_t | ||
25 | class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
26 | { | ||
27 | struct class_attribute * class_attr = to_class_attr(attr); | ||
28 | struct class * dc = to_class(kobj); | ||
29 | ssize_t ret = 0; | ||
30 | |||
31 | if (class_attr->show) | ||
32 | ret = class_attr->show(dc, buf); | ||
33 | return ret; | ||
34 | } | ||
35 | |||
36 | static ssize_t | ||
37 | class_attr_store(struct kobject * kobj, struct attribute * attr, | ||
38 | const char * buf, size_t count) | ||
39 | { | ||
40 | struct class_attribute * class_attr = to_class_attr(attr); | ||
41 | struct class * dc = to_class(kobj); | ||
42 | ssize_t ret = 0; | ||
43 | |||
44 | if (class_attr->store) | ||
45 | ret = class_attr->store(dc, buf, count); | ||
46 | return ret; | ||
47 | } | ||
48 | |||
49 | static void class_release(struct kobject * kobj) | ||
50 | { | ||
51 | struct class *class = to_class(kobj); | ||
52 | |||
53 | pr_debug("class '%s': release.\n", class->name); | ||
54 | |||
55 | if (class->class_release) | ||
56 | class->class_release(class); | ||
57 | else | ||
58 | pr_debug("class '%s' does not have a release() function, " | ||
59 | "be careful\n", class->name); | ||
60 | } | ||
61 | |||
62 | static struct sysfs_ops class_sysfs_ops = { | ||
63 | .show = class_attr_show, | ||
64 | .store = class_attr_store, | ||
65 | }; | ||
66 | |||
67 | static struct kobj_type ktype_class = { | ||
68 | .sysfs_ops = &class_sysfs_ops, | ||
69 | .release = class_release, | ||
70 | }; | ||
71 | |||
72 | /* Hotplug events for classes go to the class_obj subsys */ | ||
73 | static decl_subsys(class, &ktype_class, NULL); | ||
74 | |||
75 | |||
76 | int class_create_file(struct class * cls, const struct class_attribute * attr) | ||
77 | { | ||
78 | int error; | ||
79 | if (cls) { | ||
80 | error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr); | ||
81 | } else | ||
82 | error = -EINVAL; | ||
83 | return error; | ||
84 | } | ||
85 | |||
86 | void class_remove_file(struct class * cls, const struct class_attribute * attr) | ||
87 | { | ||
88 | if (cls) | ||
89 | sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); | ||
90 | } | ||
91 | |||
92 | struct class * class_get(struct class * cls) | ||
93 | { | ||
94 | if (cls) | ||
95 | return container_of(subsys_get(&cls->subsys), struct class, subsys); | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | void class_put(struct class * cls) | ||
100 | { | ||
101 | subsys_put(&cls->subsys); | ||
102 | } | ||
103 | |||
104 | |||
105 | static int add_class_attrs(struct class * cls) | ||
106 | { | ||
107 | int i; | ||
108 | int error = 0; | ||
109 | |||
110 | if (cls->class_attrs) { | ||
111 | for (i = 0; attr_name(cls->class_attrs[i]); i++) { | ||
112 | error = class_create_file(cls,&cls->class_attrs[i]); | ||
113 | if (error) | ||
114 | goto Err; | ||
115 | } | ||
116 | } | ||
117 | Done: | ||
118 | return error; | ||
119 | Err: | ||
120 | while (--i >= 0) | ||
121 | class_remove_file(cls,&cls->class_attrs[i]); | ||
122 | goto Done; | ||
123 | } | ||
124 | |||
125 | static void remove_class_attrs(struct class * cls) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | if (cls->class_attrs) { | ||
130 | for (i = 0; attr_name(cls->class_attrs[i]); i++) | ||
131 | class_remove_file(cls,&cls->class_attrs[i]); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | int class_register(struct class * cls) | ||
136 | { | ||
137 | int error; | ||
138 | |||
139 | pr_debug("device class '%s': registering\n", cls->name); | ||
140 | |||
141 | INIT_LIST_HEAD(&cls->children); | ||
142 | INIT_LIST_HEAD(&cls->interfaces); | ||
143 | init_MUTEX(&cls->sem); | ||
144 | error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); | ||
145 | if (error) | ||
146 | return error; | ||
147 | |||
148 | subsys_set_kset(cls, class_subsys); | ||
149 | |||
150 | error = subsystem_register(&cls->subsys); | ||
151 | if (!error) { | ||
152 | error = add_class_attrs(class_get(cls)); | ||
153 | class_put(cls); | ||
154 | } | ||
155 | return error; | ||
156 | } | ||
157 | |||
158 | void class_unregister(struct class * cls) | ||
159 | { | ||
160 | pr_debug("device class '%s': unregistering\n", cls->name); | ||
161 | remove_class_attrs(cls); | ||
162 | subsystem_unregister(&cls->subsys); | ||
163 | } | ||
164 | |||
165 | |||
166 | /* Class Device Stuff */ | ||
167 | |||
168 | int class_device_create_file(struct class_device * class_dev, | ||
169 | const struct class_device_attribute * attr) | ||
170 | { | ||
171 | int error = -EINVAL; | ||
172 | if (class_dev) | ||
173 | error = sysfs_create_file(&class_dev->kobj, &attr->attr); | ||
174 | return error; | ||
175 | } | ||
176 | |||
177 | void class_device_remove_file(struct class_device * class_dev, | ||
178 | const struct class_device_attribute * attr) | ||
179 | { | ||
180 | if (class_dev) | ||
181 | sysfs_remove_file(&class_dev->kobj, &attr->attr); | ||
182 | } | ||
183 | |||
184 | int class_device_create_bin_file(struct class_device *class_dev, | ||
185 | struct bin_attribute *attr) | ||
186 | { | ||
187 | int error = -EINVAL; | ||
188 | if (class_dev) | ||
189 | error = sysfs_create_bin_file(&class_dev->kobj, attr); | ||
190 | return error; | ||
191 | } | ||
192 | |||
193 | void class_device_remove_bin_file(struct class_device *class_dev, | ||
194 | struct bin_attribute *attr) | ||
195 | { | ||
196 | if (class_dev) | ||
197 | sysfs_remove_bin_file(&class_dev->kobj, attr); | ||
198 | } | ||
199 | |||
200 | static ssize_t | ||
201 | class_device_attr_show(struct kobject * kobj, struct attribute * attr, | ||
202 | char * buf) | ||
203 | { | ||
204 | struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr); | ||
205 | struct class_device * cd = to_class_dev(kobj); | ||
206 | ssize_t ret = 0; | ||
207 | |||
208 | if (class_dev_attr->show) | ||
209 | ret = class_dev_attr->show(cd, buf); | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | static ssize_t | ||
214 | class_device_attr_store(struct kobject * kobj, struct attribute * attr, | ||
215 | const char * buf, size_t count) | ||
216 | { | ||
217 | struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr); | ||
218 | struct class_device * cd = to_class_dev(kobj); | ||
219 | ssize_t ret = 0; | ||
220 | |||
221 | if (class_dev_attr->store) | ||
222 | ret = class_dev_attr->store(cd, buf, count); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static struct sysfs_ops class_dev_sysfs_ops = { | ||
227 | .show = class_device_attr_show, | ||
228 | .store = class_device_attr_store, | ||
229 | }; | ||
230 | |||
231 | static void class_dev_release(struct kobject * kobj) | ||
232 | { | ||
233 | struct class_device *cd = to_class_dev(kobj); | ||
234 | struct class * cls = cd->class; | ||
235 | |||
236 | pr_debug("device class '%s': release.\n", cd->class_id); | ||
237 | |||
238 | if (cls->release) | ||
239 | cls->release(cd); | ||
240 | else { | ||
241 | printk(KERN_ERR "Device class '%s' does not have a release() function, " | ||
242 | "it is broken and must be fixed.\n", | ||
243 | cd->class_id); | ||
244 | WARN_ON(1); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static struct kobj_type ktype_class_device = { | ||
249 | .sysfs_ops = &class_dev_sysfs_ops, | ||
250 | .release = class_dev_release, | ||
251 | }; | ||
252 | |||
253 | static int class_hotplug_filter(struct kset *kset, struct kobject *kobj) | ||
254 | { | ||
255 | struct kobj_type *ktype = get_ktype(kobj); | ||
256 | |||
257 | if (ktype == &ktype_class_device) { | ||
258 | struct class_device *class_dev = to_class_dev(kobj); | ||
259 | if (class_dev->class) | ||
260 | return 1; | ||
261 | } | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static char *class_hotplug_name(struct kset *kset, struct kobject *kobj) | ||
266 | { | ||
267 | struct class_device *class_dev = to_class_dev(kobj); | ||
268 | |||
269 | return class_dev->class->name; | ||
270 | } | ||
271 | |||
272 | static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp, | ||
273 | int num_envp, char *buffer, int buffer_size) | ||
274 | { | ||
275 | struct class_device *class_dev = to_class_dev(kobj); | ||
276 | int i = 0; | ||
277 | int length = 0; | ||
278 | int retval = 0; | ||
279 | |||
280 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); | ||
281 | |||
282 | if (class_dev->dev) { | ||
283 | /* add physical device, backing this device */ | ||
284 | struct device *dev = class_dev->dev; | ||
285 | char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); | ||
286 | |||
287 | add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, | ||
288 | &length, "PHYSDEVPATH=%s", path); | ||
289 | kfree(path); | ||
290 | |||
291 | if (dev->bus) | ||
292 | add_hotplug_env_var(envp, num_envp, &i, | ||
293 | buffer, buffer_size, &length, | ||
294 | "PHYSDEVBUS=%s", dev->bus->name); | ||
295 | |||
296 | if (dev->driver) | ||
297 | add_hotplug_env_var(envp, num_envp, &i, | ||
298 | buffer, buffer_size, &length, | ||
299 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
300 | } | ||
301 | |||
302 | if (MAJOR(class_dev->devt)) { | ||
303 | add_hotplug_env_var(envp, num_envp, &i, | ||
304 | buffer, buffer_size, &length, | ||
305 | "MAJOR=%u", MAJOR(class_dev->devt)); | ||
306 | |||
307 | add_hotplug_env_var(envp, num_envp, &i, | ||
308 | buffer, buffer_size, &length, | ||
309 | "MINOR=%u", MINOR(class_dev->devt)); | ||
310 | } | ||
311 | |||
312 | /* terminate, set to next free slot, shrink available space */ | ||
313 | envp[i] = NULL; | ||
314 | envp = &envp[i]; | ||
315 | num_envp -= i; | ||
316 | buffer = &buffer[length]; | ||
317 | buffer_size -= length; | ||
318 | |||
319 | if (class_dev->class->hotplug) { | ||
320 | /* have the bus specific function add its stuff */ | ||
321 | retval = class_dev->class->hotplug (class_dev, envp, num_envp, | ||
322 | buffer, buffer_size); | ||
323 | if (retval) { | ||
324 | pr_debug ("%s - hotplug() returned %d\n", | ||
325 | __FUNCTION__, retval); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return retval; | ||
330 | } | ||
331 | |||
332 | static struct kset_hotplug_ops class_hotplug_ops = { | ||
333 | .filter = class_hotplug_filter, | ||
334 | .name = class_hotplug_name, | ||
335 | .hotplug = class_hotplug, | ||
336 | }; | ||
337 | |||
338 | static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops); | ||
339 | |||
340 | |||
341 | static int class_device_add_attrs(struct class_device * cd) | ||
342 | { | ||
343 | int i; | ||
344 | int error = 0; | ||
345 | struct class * cls = cd->class; | ||
346 | |||
347 | if (cls->class_dev_attrs) { | ||
348 | for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) { | ||
349 | error = class_device_create_file(cd, | ||
350 | &cls->class_dev_attrs[i]); | ||
351 | if (error) | ||
352 | goto Err; | ||
353 | } | ||
354 | } | ||
355 | Done: | ||
356 | return error; | ||
357 | Err: | ||
358 | while (--i >= 0) | ||
359 | class_device_remove_file(cd,&cls->class_dev_attrs[i]); | ||
360 | goto Done; | ||
361 | } | ||
362 | |||
363 | static void class_device_remove_attrs(struct class_device * cd) | ||
364 | { | ||
365 | int i; | ||
366 | struct class * cls = cd->class; | ||
367 | |||
368 | if (cls->class_dev_attrs) { | ||
369 | for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) | ||
370 | class_device_remove_file(cd,&cls->class_dev_attrs[i]); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | static ssize_t show_dev(struct class_device *class_dev, char *buf) | ||
375 | { | ||
376 | return print_dev_t(buf, class_dev->devt); | ||
377 | } | ||
378 | static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); | ||
379 | |||
380 | void class_device_initialize(struct class_device *class_dev) | ||
381 | { | ||
382 | kobj_set_kset_s(class_dev, class_obj_subsys); | ||
383 | kobject_init(&class_dev->kobj); | ||
384 | INIT_LIST_HEAD(&class_dev->node); | ||
385 | } | ||
386 | |||
387 | int class_device_add(struct class_device *class_dev) | ||
388 | { | ||
389 | struct class * parent = NULL; | ||
390 | struct class_interface * class_intf; | ||
391 | int error; | ||
392 | |||
393 | class_dev = class_device_get(class_dev); | ||
394 | if (!class_dev) | ||
395 | return -EINVAL; | ||
396 | |||
397 | if (!strlen(class_dev->class_id)) { | ||
398 | error = -EINVAL; | ||
399 | goto register_done; | ||
400 | } | ||
401 | |||
402 | parent = class_get(class_dev->class); | ||
403 | |||
404 | pr_debug("CLASS: registering class device: ID = '%s'\n", | ||
405 | class_dev->class_id); | ||
406 | |||
407 | /* first, register with generic layer. */ | ||
408 | kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); | ||
409 | if (parent) | ||
410 | class_dev->kobj.parent = &parent->subsys.kset.kobj; | ||
411 | |||
412 | if ((error = kobject_add(&class_dev->kobj))) | ||
413 | goto register_done; | ||
414 | |||
415 | /* now take care of our own registration */ | ||
416 | if (parent) { | ||
417 | down(&parent->sem); | ||
418 | list_add_tail(&class_dev->node, &parent->children); | ||
419 | list_for_each_entry(class_intf, &parent->interfaces, node) | ||
420 | if (class_intf->add) | ||
421 | class_intf->add(class_dev); | ||
422 | up(&parent->sem); | ||
423 | } | ||
424 | |||
425 | if (MAJOR(class_dev->devt)) | ||
426 | class_device_create_file(class_dev, &class_device_attr_dev); | ||
427 | |||
428 | class_device_add_attrs(class_dev); | ||
429 | if (class_dev->dev) | ||
430 | sysfs_create_link(&class_dev->kobj, | ||
431 | &class_dev->dev->kobj, "device"); | ||
432 | |||
433 | register_done: | ||
434 | if (error && parent) | ||
435 | class_put(parent); | ||
436 | class_device_put(class_dev); | ||
437 | return error; | ||
438 | } | ||
439 | |||
440 | int class_device_register(struct class_device *class_dev) | ||
441 | { | ||
442 | class_device_initialize(class_dev); | ||
443 | return class_device_add(class_dev); | ||
444 | } | ||
445 | |||
446 | void class_device_del(struct class_device *class_dev) | ||
447 | { | ||
448 | struct class * parent = class_dev->class; | ||
449 | struct class_interface * class_intf; | ||
450 | |||
451 | if (parent) { | ||
452 | down(&parent->sem); | ||
453 | list_del_init(&class_dev->node); | ||
454 | list_for_each_entry(class_intf, &parent->interfaces, node) | ||
455 | if (class_intf->remove) | ||
456 | class_intf->remove(class_dev); | ||
457 | up(&parent->sem); | ||
458 | } | ||
459 | |||
460 | if (class_dev->dev) | ||
461 | sysfs_remove_link(&class_dev->kobj, "device"); | ||
462 | class_device_remove_attrs(class_dev); | ||
463 | |||
464 | kobject_del(&class_dev->kobj); | ||
465 | |||
466 | if (parent) | ||
467 | class_put(parent); | ||
468 | } | ||
469 | |||
470 | void class_device_unregister(struct class_device *class_dev) | ||
471 | { | ||
472 | pr_debug("CLASS: Unregistering class device. ID = '%s'\n", | ||
473 | class_dev->class_id); | ||
474 | class_device_del(class_dev); | ||
475 | class_device_put(class_dev); | ||
476 | } | ||
477 | |||
478 | int class_device_rename(struct class_device *class_dev, char *new_name) | ||
479 | { | ||
480 | int error = 0; | ||
481 | |||
482 | class_dev = class_device_get(class_dev); | ||
483 | if (!class_dev) | ||
484 | return -EINVAL; | ||
485 | |||
486 | pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, | ||
487 | new_name); | ||
488 | |||
489 | strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); | ||
490 | |||
491 | error = kobject_rename(&class_dev->kobj, new_name); | ||
492 | |||
493 | class_device_put(class_dev); | ||
494 | |||
495 | return error; | ||
496 | } | ||
497 | |||
498 | struct class_device * class_device_get(struct class_device *class_dev) | ||
499 | { | ||
500 | if (class_dev) | ||
501 | return to_class_dev(kobject_get(&class_dev->kobj)); | ||
502 | return NULL; | ||
503 | } | ||
504 | |||
505 | void class_device_put(struct class_device *class_dev) | ||
506 | { | ||
507 | kobject_put(&class_dev->kobj); | ||
508 | } | ||
509 | |||
510 | |||
511 | int class_interface_register(struct class_interface *class_intf) | ||
512 | { | ||
513 | struct class *parent; | ||
514 | struct class_device *class_dev; | ||
515 | |||
516 | if (!class_intf || !class_intf->class) | ||
517 | return -ENODEV; | ||
518 | |||
519 | parent = class_get(class_intf->class); | ||
520 | if (!parent) | ||
521 | return -EINVAL; | ||
522 | |||
523 | down(&parent->sem); | ||
524 | list_add_tail(&class_intf->node, &parent->interfaces); | ||
525 | if (class_intf->add) { | ||
526 | list_for_each_entry(class_dev, &parent->children, node) | ||
527 | class_intf->add(class_dev); | ||
528 | } | ||
529 | up(&parent->sem); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | void class_interface_unregister(struct class_interface *class_intf) | ||
535 | { | ||
536 | struct class * parent = class_intf->class; | ||
537 | struct class_device *class_dev; | ||
538 | |||
539 | if (!parent) | ||
540 | return; | ||
541 | |||
542 | down(&parent->sem); | ||
543 | list_del_init(&class_intf->node); | ||
544 | if (class_intf->remove) { | ||
545 | list_for_each_entry(class_dev, &parent->children, node) | ||
546 | class_intf->remove(class_dev); | ||
547 | } | ||
548 | up(&parent->sem); | ||
549 | |||
550 | class_put(parent); | ||
551 | } | ||
552 | |||
553 | |||
554 | |||
555 | int __init classes_init(void) | ||
556 | { | ||
557 | int retval; | ||
558 | |||
559 | retval = subsystem_register(&class_subsys); | ||
560 | if (retval) | ||
561 | return retval; | ||
562 | |||
563 | /* ick, this is ugly, the things we go through to keep from showing up | ||
564 | * in sysfs... */ | ||
565 | subsystem_init(&class_obj_subsys); | ||
566 | if (!class_obj_subsys.kset.subsys) | ||
567 | class_obj_subsys.kset.subsys = &class_obj_subsys; | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | EXPORT_SYMBOL_GPL(class_create_file); | ||
572 | EXPORT_SYMBOL_GPL(class_remove_file); | ||
573 | EXPORT_SYMBOL_GPL(class_register); | ||
574 | EXPORT_SYMBOL_GPL(class_unregister); | ||
575 | EXPORT_SYMBOL_GPL(class_get); | ||
576 | EXPORT_SYMBOL_GPL(class_put); | ||
577 | |||
578 | EXPORT_SYMBOL_GPL(class_device_register); | ||
579 | EXPORT_SYMBOL_GPL(class_device_unregister); | ||
580 | EXPORT_SYMBOL_GPL(class_device_initialize); | ||
581 | EXPORT_SYMBOL_GPL(class_device_add); | ||
582 | EXPORT_SYMBOL_GPL(class_device_del); | ||
583 | EXPORT_SYMBOL_GPL(class_device_get); | ||
584 | EXPORT_SYMBOL_GPL(class_device_put); | ||
585 | EXPORT_SYMBOL_GPL(class_device_create_file); | ||
586 | EXPORT_SYMBOL_GPL(class_device_remove_file); | ||
587 | EXPORT_SYMBOL_GPL(class_device_create_bin_file); | ||
588 | EXPORT_SYMBOL_GPL(class_device_remove_bin_file); | ||
589 | |||
590 | EXPORT_SYMBOL_GPL(class_interface_register); | ||
591 | EXPORT_SYMBOL_GPL(class_interface_unregister); | ||
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c new file mode 100644 index 000000000000..27699eb20a37 --- /dev/null +++ b/drivers/base/class_simple.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * class_simple.c - a "simple" interface for classes for simple char devices. | ||
3 | * | ||
4 | * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> | ||
5 | * Copyright (c) 2003-2004 IBM Corp. | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | |||
15 | struct class_simple { | ||
16 | struct class class; | ||
17 | }; | ||
18 | #define to_class_simple(d) container_of(d, struct class_simple, class) | ||
19 | |||
20 | struct simple_dev { | ||
21 | struct list_head node; | ||
22 | struct class_device class_dev; | ||
23 | }; | ||
24 | #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) | ||
25 | |||
26 | static LIST_HEAD(simple_dev_list); | ||
27 | static DEFINE_SPINLOCK(simple_dev_list_lock); | ||
28 | |||
29 | static void release_simple_dev(struct class_device *class_dev) | ||
30 | { | ||
31 | struct simple_dev *s_dev = to_simple_dev(class_dev); | ||
32 | kfree(s_dev); | ||
33 | } | ||
34 | |||
35 | static void class_simple_release(struct class *class) | ||
36 | { | ||
37 | struct class_simple *cs = to_class_simple(class); | ||
38 | kfree(cs); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * class_simple_create - create a struct class_simple structure | ||
43 | * @owner: pointer to the module that is to "own" this struct class_simple | ||
44 | * @name: pointer to a string for the name of this class. | ||
45 | * | ||
46 | * This is used to create a struct class_simple pointer that can then be used | ||
47 | * in calls to class_simple_device_add(). This is used when you do not wish to | ||
48 | * create a full blown class support for a type of char devices. | ||
49 | * | ||
50 | * Note, the pointer created here is to be destroyed when finished by making a | ||
51 | * call to class_simple_destroy(). | ||
52 | */ | ||
53 | struct class_simple *class_simple_create(struct module *owner, char *name) | ||
54 | { | ||
55 | struct class_simple *cs; | ||
56 | int retval; | ||
57 | |||
58 | cs = kmalloc(sizeof(*cs), GFP_KERNEL); | ||
59 | if (!cs) { | ||
60 | retval = -ENOMEM; | ||
61 | goto error; | ||
62 | } | ||
63 | memset(cs, 0x00, sizeof(*cs)); | ||
64 | |||
65 | cs->class.name = name; | ||
66 | cs->class.class_release = class_simple_release; | ||
67 | cs->class.release = release_simple_dev; | ||
68 | |||
69 | retval = class_register(&cs->class); | ||
70 | if (retval) | ||
71 | goto error; | ||
72 | |||
73 | return cs; | ||
74 | |||
75 | error: | ||
76 | kfree(cs); | ||
77 | return ERR_PTR(retval); | ||
78 | } | ||
79 | EXPORT_SYMBOL(class_simple_create); | ||
80 | |||
81 | /** | ||
82 | * class_simple_destroy - destroys a struct class_simple structure | ||
83 | * @cs: pointer to the struct class_simple that is to be destroyed | ||
84 | * | ||
85 | * Note, the pointer to be destroyed must have been created with a call to | ||
86 | * class_simple_create(). | ||
87 | */ | ||
88 | void class_simple_destroy(struct class_simple *cs) | ||
89 | { | ||
90 | if ((cs == NULL) || (IS_ERR(cs))) | ||
91 | return; | ||
92 | |||
93 | class_unregister(&cs->class); | ||
94 | } | ||
95 | EXPORT_SYMBOL(class_simple_destroy); | ||
96 | |||
97 | /** | ||
98 | * class_simple_device_add - adds a class device to sysfs for a character driver | ||
99 | * @cs: pointer to the struct class_simple that this device should be registered to. | ||
100 | * @dev: the dev_t for the device to be added. | ||
101 | * @device: a pointer to a struct device that is assiociated with this class device. | ||
102 | * @fmt: string for the class device's name | ||
103 | * | ||
104 | * This function can be used by simple char device classes that do not | ||
105 | * implement their own class device registration. A struct class_device will | ||
106 | * be created in sysfs, registered to the specified class. A "dev" file will | ||
107 | * be created, showing the dev_t for the device. The pointer to the struct | ||
108 | * class_device will be returned from the call. Any further sysfs files that | ||
109 | * might be required can be created using this pointer. | ||
110 | * Note: the struct class_simple passed to this function must have previously been | ||
111 | * created with a call to class_simple_create(). | ||
112 | */ | ||
113 | struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...) | ||
114 | { | ||
115 | va_list args; | ||
116 | struct simple_dev *s_dev = NULL; | ||
117 | int retval; | ||
118 | |||
119 | if ((cs == NULL) || (IS_ERR(cs))) { | ||
120 | retval = -ENODEV; | ||
121 | goto error; | ||
122 | } | ||
123 | |||
124 | s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL); | ||
125 | if (!s_dev) { | ||
126 | retval = -ENOMEM; | ||
127 | goto error; | ||
128 | } | ||
129 | memset(s_dev, 0x00, sizeof(*s_dev)); | ||
130 | |||
131 | s_dev->class_dev.devt = dev; | ||
132 | s_dev->class_dev.dev = device; | ||
133 | s_dev->class_dev.class = &cs->class; | ||
134 | |||
135 | va_start(args, fmt); | ||
136 | vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args); | ||
137 | va_end(args); | ||
138 | retval = class_device_register(&s_dev->class_dev); | ||
139 | if (retval) | ||
140 | goto error; | ||
141 | |||
142 | spin_lock(&simple_dev_list_lock); | ||
143 | list_add(&s_dev->node, &simple_dev_list); | ||
144 | spin_unlock(&simple_dev_list_lock); | ||
145 | |||
146 | return &s_dev->class_dev; | ||
147 | |||
148 | error: | ||
149 | kfree(s_dev); | ||
150 | return ERR_PTR(retval); | ||
151 | } | ||
152 | EXPORT_SYMBOL(class_simple_device_add); | ||
153 | |||
154 | /** | ||
155 | * class_simple_set_hotplug - set the hotplug callback in the embedded struct class | ||
156 | * @cs: pointer to the struct class_simple to hold the pointer | ||
157 | * @hotplug: function pointer to the hotplug function | ||
158 | * | ||
159 | * Implement and set a hotplug function to add environment variables specific to this | ||
160 | * class on the hotplug event. | ||
161 | */ | ||
162 | int class_simple_set_hotplug(struct class_simple *cs, | ||
163 | int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size)) | ||
164 | { | ||
165 | if ((cs == NULL) || (IS_ERR(cs))) | ||
166 | return -ENODEV; | ||
167 | cs->class.hotplug = hotplug; | ||
168 | return 0; | ||
169 | } | ||
170 | EXPORT_SYMBOL(class_simple_set_hotplug); | ||
171 | |||
172 | /** | ||
173 | * class_simple_device_remove - removes a class device that was created with class_simple_device_add() | ||
174 | * @dev: the dev_t of the device that was previously registered. | ||
175 | * | ||
176 | * This call unregisters and cleans up a class device that was created with a | ||
177 | * call to class_device_simple_add() | ||
178 | */ | ||
179 | void class_simple_device_remove(dev_t dev) | ||
180 | { | ||
181 | struct simple_dev *s_dev = NULL; | ||
182 | int found = 0; | ||
183 | |||
184 | spin_lock(&simple_dev_list_lock); | ||
185 | list_for_each_entry(s_dev, &simple_dev_list, node) { | ||
186 | if (s_dev->class_dev.devt == dev) { | ||
187 | found = 1; | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | if (found) { | ||
192 | list_del(&s_dev->node); | ||
193 | spin_unlock(&simple_dev_list_lock); | ||
194 | class_device_unregister(&s_dev->class_dev); | ||
195 | } else { | ||
196 | spin_unlock(&simple_dev_list_lock); | ||
197 | } | ||
198 | } | ||
199 | EXPORT_SYMBOL(class_simple_device_remove); | ||
diff --git a/drivers/base/core.c b/drivers/base/core.c new file mode 100644 index 000000000000..4e6cce8e6d35 --- /dev/null +++ b/drivers/base/core.c | |||
@@ -0,0 +1,439 @@ | |||
1 | /* | ||
2 | * drivers/base/core.c - core driver model code (device registration, etc) | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/string.h> | ||
18 | |||
19 | #include <asm/semaphore.h> | ||
20 | |||
21 | #include "base.h" | ||
22 | #include "power/power.h" | ||
23 | |||
24 | int (*platform_notify)(struct device * dev) = NULL; | ||
25 | int (*platform_notify_remove)(struct device * dev) = NULL; | ||
26 | |||
27 | /* | ||
28 | * sysfs bindings for devices. | ||
29 | */ | ||
30 | |||
31 | #define to_dev(obj) container_of(obj, struct device, kobj) | ||
32 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | ||
33 | |||
34 | extern struct attribute * dev_default_attrs[]; | ||
35 | |||
36 | static ssize_t | ||
37 | dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
38 | { | ||
39 | struct device_attribute * dev_attr = to_dev_attr(attr); | ||
40 | struct device * dev = to_dev(kobj); | ||
41 | ssize_t ret = 0; | ||
42 | |||
43 | if (dev_attr->show) | ||
44 | ret = dev_attr->show(dev, buf); | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | static ssize_t | ||
49 | dev_attr_store(struct kobject * kobj, struct attribute * attr, | ||
50 | const char * buf, size_t count) | ||
51 | { | ||
52 | struct device_attribute * dev_attr = to_dev_attr(attr); | ||
53 | struct device * dev = to_dev(kobj); | ||
54 | ssize_t ret = 0; | ||
55 | |||
56 | if (dev_attr->store) | ||
57 | ret = dev_attr->store(dev, buf, count); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static struct sysfs_ops dev_sysfs_ops = { | ||
62 | .show = dev_attr_show, | ||
63 | .store = dev_attr_store, | ||
64 | }; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * device_release - free device structure. | ||
69 | * @kobj: device's kobject. | ||
70 | * | ||
71 | * This is called once the reference count for the object | ||
72 | * reaches 0. We forward the call to the device's release | ||
73 | * method, which should handle actually freeing the structure. | ||
74 | */ | ||
75 | static void device_release(struct kobject * kobj) | ||
76 | { | ||
77 | struct device * dev = to_dev(kobj); | ||
78 | |||
79 | if (dev->release) | ||
80 | dev->release(dev); | ||
81 | else { | ||
82 | printk(KERN_ERR "Device '%s' does not have a release() function, " | ||
83 | "it is broken and must be fixed.\n", | ||
84 | dev->bus_id); | ||
85 | WARN_ON(1); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static struct kobj_type ktype_device = { | ||
90 | .release = device_release, | ||
91 | .sysfs_ops = &dev_sysfs_ops, | ||
92 | .default_attrs = dev_default_attrs, | ||
93 | }; | ||
94 | |||
95 | |||
96 | static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj) | ||
97 | { | ||
98 | struct kobj_type *ktype = get_ktype(kobj); | ||
99 | |||
100 | if (ktype == &ktype_device) { | ||
101 | struct device *dev = to_dev(kobj); | ||
102 | if (dev->bus) | ||
103 | return 1; | ||
104 | } | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj) | ||
109 | { | ||
110 | struct device *dev = to_dev(kobj); | ||
111 | |||
112 | return dev->bus->name; | ||
113 | } | ||
114 | |||
115 | static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp, | ||
116 | int num_envp, char *buffer, int buffer_size) | ||
117 | { | ||
118 | struct device *dev = to_dev(kobj); | ||
119 | int i = 0; | ||
120 | int length = 0; | ||
121 | int retval = 0; | ||
122 | |||
123 | /* add bus name of physical device */ | ||
124 | if (dev->bus) | ||
125 | add_hotplug_env_var(envp, num_envp, &i, | ||
126 | buffer, buffer_size, &length, | ||
127 | "PHYSDEVBUS=%s", dev->bus->name); | ||
128 | |||
129 | /* add driver name of physical device */ | ||
130 | if (dev->driver) | ||
131 | add_hotplug_env_var(envp, num_envp, &i, | ||
132 | buffer, buffer_size, &length, | ||
133 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
134 | |||
135 | /* terminate, set to next free slot, shrink available space */ | ||
136 | envp[i] = NULL; | ||
137 | envp = &envp[i]; | ||
138 | num_envp -= i; | ||
139 | buffer = &buffer[length]; | ||
140 | buffer_size -= length; | ||
141 | |||
142 | if (dev->bus->hotplug) { | ||
143 | /* have the bus specific function add its stuff */ | ||
144 | retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size); | ||
145 | if (retval) { | ||
146 | pr_debug ("%s - hotplug() returned %d\n", | ||
147 | __FUNCTION__, retval); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | return retval; | ||
152 | } | ||
153 | |||
154 | static struct kset_hotplug_ops device_hotplug_ops = { | ||
155 | .filter = dev_hotplug_filter, | ||
156 | .name = dev_hotplug_name, | ||
157 | .hotplug = dev_hotplug, | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * device_subsys - structure to be registered with kobject core. | ||
162 | */ | ||
163 | |||
164 | decl_subsys(devices, &ktype_device, &device_hotplug_ops); | ||
165 | |||
166 | |||
167 | /** | ||
168 | * device_create_file - create sysfs attribute file for device. | ||
169 | * @dev: device. | ||
170 | * @attr: device attribute descriptor. | ||
171 | */ | ||
172 | |||
173 | int device_create_file(struct device * dev, struct device_attribute * attr) | ||
174 | { | ||
175 | int error = 0; | ||
176 | if (get_device(dev)) { | ||
177 | error = sysfs_create_file(&dev->kobj, &attr->attr); | ||
178 | put_device(dev); | ||
179 | } | ||
180 | return error; | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * device_remove_file - remove sysfs attribute file. | ||
185 | * @dev: device. | ||
186 | * @attr: device attribute descriptor. | ||
187 | */ | ||
188 | |||
189 | void device_remove_file(struct device * dev, struct device_attribute * attr) | ||
190 | { | ||
191 | if (get_device(dev)) { | ||
192 | sysfs_remove_file(&dev->kobj, &attr->attr); | ||
193 | put_device(dev); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | |||
198 | /** | ||
199 | * device_initialize - init device structure. | ||
200 | * @dev: device. | ||
201 | * | ||
202 | * This prepares the device for use by other layers, | ||
203 | * including adding it to the device hierarchy. | ||
204 | * It is the first half of device_register(), if called by | ||
205 | * that, though it can also be called separately, so one | ||
206 | * may use @dev's fields (e.g. the refcount). | ||
207 | */ | ||
208 | |||
209 | void device_initialize(struct device *dev) | ||
210 | { | ||
211 | kobj_set_kset_s(dev, devices_subsys); | ||
212 | kobject_init(&dev->kobj); | ||
213 | INIT_LIST_HEAD(&dev->node); | ||
214 | INIT_LIST_HEAD(&dev->children); | ||
215 | INIT_LIST_HEAD(&dev->driver_list); | ||
216 | INIT_LIST_HEAD(&dev->bus_list); | ||
217 | INIT_LIST_HEAD(&dev->dma_pools); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * device_add - add device to device hierarchy. | ||
222 | * @dev: device. | ||
223 | * | ||
224 | * This is part 2 of device_register(), though may be called | ||
225 | * separately _iff_ device_initialize() has been called separately. | ||
226 | * | ||
227 | * This adds it to the kobject hierarchy via kobject_add(), adds it | ||
228 | * to the global and sibling lists for the device, then | ||
229 | * adds it to the other relevant subsystems of the driver model. | ||
230 | */ | ||
231 | int device_add(struct device *dev) | ||
232 | { | ||
233 | struct device *parent = NULL; | ||
234 | int error = -EINVAL; | ||
235 | |||
236 | dev = get_device(dev); | ||
237 | if (!dev || !strlen(dev->bus_id)) | ||
238 | goto Error; | ||
239 | |||
240 | parent = get_device(dev->parent); | ||
241 | |||
242 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); | ||
243 | |||
244 | /* first, register with generic layer. */ | ||
245 | kobject_set_name(&dev->kobj, "%s", dev->bus_id); | ||
246 | if (parent) | ||
247 | dev->kobj.parent = &parent->kobj; | ||
248 | |||
249 | if ((error = kobject_add(&dev->kobj))) | ||
250 | goto Error; | ||
251 | if ((error = device_pm_add(dev))) | ||
252 | goto PMError; | ||
253 | if ((error = bus_add_device(dev))) | ||
254 | goto BusError; | ||
255 | down_write(&devices_subsys.rwsem); | ||
256 | if (parent) | ||
257 | list_add_tail(&dev->node, &parent->children); | ||
258 | up_write(&devices_subsys.rwsem); | ||
259 | |||
260 | /* notify platform of device entry */ | ||
261 | if (platform_notify) | ||
262 | platform_notify(dev); | ||
263 | Done: | ||
264 | put_device(dev); | ||
265 | return error; | ||
266 | BusError: | ||
267 | device_pm_remove(dev); | ||
268 | PMError: | ||
269 | kobject_del(&dev->kobj); | ||
270 | Error: | ||
271 | if (parent) | ||
272 | put_device(parent); | ||
273 | goto Done; | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * device_register - register a device with the system. | ||
279 | * @dev: pointer to the device structure | ||
280 | * | ||
281 | * This happens in two clean steps - initialize the device | ||
282 | * and add it to the system. The two steps can be called | ||
283 | * separately, but this is the easiest and most common. | ||
284 | * I.e. you should only call the two helpers separately if | ||
285 | * have a clearly defined need to use and refcount the device | ||
286 | * before it is added to the hierarchy. | ||
287 | */ | ||
288 | |||
289 | int device_register(struct device *dev) | ||
290 | { | ||
291 | device_initialize(dev); | ||
292 | return device_add(dev); | ||
293 | } | ||
294 | |||
295 | |||
296 | /** | ||
297 | * get_device - increment reference count for device. | ||
298 | * @dev: device. | ||
299 | * | ||
300 | * This simply forwards the call to kobject_get(), though | ||
301 | * we do take care to provide for the case that we get a NULL | ||
302 | * pointer passed in. | ||
303 | */ | ||
304 | |||
305 | struct device * get_device(struct device * dev) | ||
306 | { | ||
307 | return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * put_device - decrement reference count. | ||
313 | * @dev: device in question. | ||
314 | */ | ||
315 | void put_device(struct device * dev) | ||
316 | { | ||
317 | if (dev) | ||
318 | kobject_put(&dev->kobj); | ||
319 | } | ||
320 | |||
321 | |||
322 | /** | ||
323 | * device_del - delete device from system. | ||
324 | * @dev: device. | ||
325 | * | ||
326 | * This is the first part of the device unregistration | ||
327 | * sequence. This removes the device from the lists we control | ||
328 | * from here, has it removed from the other driver model | ||
329 | * subsystems it was added to in device_add(), and removes it | ||
330 | * from the kobject hierarchy. | ||
331 | * | ||
332 | * NOTE: this should be called manually _iff_ device_add() was | ||
333 | * also called manually. | ||
334 | */ | ||
335 | |||
336 | void device_del(struct device * dev) | ||
337 | { | ||
338 | struct device * parent = dev->parent; | ||
339 | |||
340 | down_write(&devices_subsys.rwsem); | ||
341 | if (parent) | ||
342 | list_del_init(&dev->node); | ||
343 | up_write(&devices_subsys.rwsem); | ||
344 | |||
345 | /* Notify the platform of the removal, in case they | ||
346 | * need to do anything... | ||
347 | */ | ||
348 | if (platform_notify_remove) | ||
349 | platform_notify_remove(dev); | ||
350 | bus_remove_device(dev); | ||
351 | device_pm_remove(dev); | ||
352 | kobject_del(&dev->kobj); | ||
353 | if (parent) | ||
354 | put_device(parent); | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * device_unregister - unregister device from system. | ||
359 | * @dev: device going away. | ||
360 | * | ||
361 | * We do this in two parts, like we do device_register(). First, | ||
362 | * we remove it from all the subsystems with device_del(), then | ||
363 | * we decrement the reference count via put_device(). If that | ||
364 | * is the final reference count, the device will be cleaned up | ||
365 | * via device_release() above. Otherwise, the structure will | ||
366 | * stick around until the final reference to the device is dropped. | ||
367 | */ | ||
368 | void device_unregister(struct device * dev) | ||
369 | { | ||
370 | pr_debug("DEV: Unregistering device. ID = '%s'\n", dev->bus_id); | ||
371 | device_del(dev); | ||
372 | put_device(dev); | ||
373 | } | ||
374 | |||
375 | |||
376 | /** | ||
377 | * device_for_each_child - device child iterator. | ||
378 | * @dev: parent struct device. | ||
379 | * @data: data for the callback. | ||
380 | * @fn: function to be called for each device. | ||
381 | * | ||
382 | * Iterate over @dev's child devices, and call @fn for each, | ||
383 | * passing it @data. | ||
384 | * | ||
385 | * We check the return of @fn each time. If it returns anything | ||
386 | * other than 0, we break out and return that value. | ||
387 | */ | ||
388 | int device_for_each_child(struct device * dev, void * data, | ||
389 | int (*fn)(struct device *, void *)) | ||
390 | { | ||
391 | struct device * child; | ||
392 | int error = 0; | ||
393 | |||
394 | down_read(&devices_subsys.rwsem); | ||
395 | list_for_each_entry(child, &dev->children, node) { | ||
396 | if((error = fn(child, data))) | ||
397 | break; | ||
398 | } | ||
399 | up_read(&devices_subsys.rwsem); | ||
400 | return error; | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * device_find - locate device on a bus by name. | ||
405 | * @name: name of the device. | ||
406 | * @bus: bus to scan for the device. | ||
407 | * | ||
408 | * Call kset_find_obj() to iterate over list of devices on | ||
409 | * a bus to find device by name. Return device if found. | ||
410 | * | ||
411 | * Note that kset_find_obj increments device's reference count. | ||
412 | */ | ||
413 | struct device *device_find(const char *name, struct bus_type *bus) | ||
414 | { | ||
415 | struct kobject *k = kset_find_obj(&bus->devices, name); | ||
416 | if (k) | ||
417 | return to_dev(k); | ||
418 | return NULL; | ||
419 | } | ||
420 | |||
421 | int __init devices_init(void) | ||
422 | { | ||
423 | return subsystem_register(&devices_subsys); | ||
424 | } | ||
425 | |||
426 | EXPORT_SYMBOL_GPL(device_for_each_child); | ||
427 | |||
428 | EXPORT_SYMBOL_GPL(device_initialize); | ||
429 | EXPORT_SYMBOL_GPL(device_add); | ||
430 | EXPORT_SYMBOL_GPL(device_register); | ||
431 | |||
432 | EXPORT_SYMBOL_GPL(device_del); | ||
433 | EXPORT_SYMBOL_GPL(device_unregister); | ||
434 | EXPORT_SYMBOL_GPL(get_device); | ||
435 | EXPORT_SYMBOL_GPL(put_device); | ||
436 | EXPORT_SYMBOL_GPL(device_find); | ||
437 | |||
438 | EXPORT_SYMBOL_GPL(device_create_file); | ||
439 | EXPORT_SYMBOL_GPL(device_remove_file); | ||
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c new file mode 100644 index 000000000000..6ef3069b5710 --- /dev/null +++ b/drivers/base/cpu.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * drivers/base/cpu.c - basic CPU class support | ||
3 | */ | ||
4 | |||
5 | #include <linux/sysdev.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/cpu.h> | ||
9 | #include <linux/topology.h> | ||
10 | #include <linux/device.h> | ||
11 | |||
12 | |||
13 | struct sysdev_class cpu_sysdev_class = { | ||
14 | set_kset_name("cpu"), | ||
15 | }; | ||
16 | EXPORT_SYMBOL(cpu_sysdev_class); | ||
17 | |||
18 | #ifdef CONFIG_HOTPLUG_CPU | ||
19 | static ssize_t show_online(struct sys_device *dev, char *buf) | ||
20 | { | ||
21 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | ||
22 | |||
23 | return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); | ||
24 | } | ||
25 | |||
26 | static ssize_t store_online(struct sys_device *dev, const char *buf, | ||
27 | size_t count) | ||
28 | { | ||
29 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | ||
30 | ssize_t ret; | ||
31 | |||
32 | switch (buf[0]) { | ||
33 | case '0': | ||
34 | ret = cpu_down(cpu->sysdev.id); | ||
35 | if (!ret) | ||
36 | kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); | ||
37 | break; | ||
38 | case '1': | ||
39 | ret = cpu_up(cpu->sysdev.id); | ||
40 | break; | ||
41 | default: | ||
42 | ret = -EINVAL; | ||
43 | } | ||
44 | |||
45 | if (ret >= 0) | ||
46 | ret = count; | ||
47 | return ret; | ||
48 | } | ||
49 | static SYSDEV_ATTR(online, 0600, show_online, store_online); | ||
50 | |||
51 | static void __devinit register_cpu_control(struct cpu *cpu) | ||
52 | { | ||
53 | sysdev_create_file(&cpu->sysdev, &attr_online); | ||
54 | } | ||
55 | void unregister_cpu(struct cpu *cpu, struct node *root) | ||
56 | { | ||
57 | |||
58 | if (root) | ||
59 | sysfs_remove_link(&root->sysdev.kobj, | ||
60 | kobject_name(&cpu->sysdev.kobj)); | ||
61 | sysdev_remove_file(&cpu->sysdev, &attr_online); | ||
62 | |||
63 | sysdev_unregister(&cpu->sysdev); | ||
64 | |||
65 | return; | ||
66 | } | ||
67 | #else /* ... !CONFIG_HOTPLUG_CPU */ | ||
68 | static inline void register_cpu_control(struct cpu *cpu) | ||
69 | { | ||
70 | } | ||
71 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
72 | |||
73 | /* | ||
74 | * register_cpu - Setup a driverfs device for a CPU. | ||
75 | * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to | ||
76 | * generate a control file in sysfs for this CPU. | ||
77 | * @num - CPU number to use when creating the device. | ||
78 | * | ||
79 | * Initialize and register the CPU device. | ||
80 | */ | ||
81 | int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) | ||
82 | { | ||
83 | int error; | ||
84 | |||
85 | cpu->node_id = cpu_to_node(num); | ||
86 | cpu->sysdev.id = num; | ||
87 | cpu->sysdev.cls = &cpu_sysdev_class; | ||
88 | |||
89 | error = sysdev_register(&cpu->sysdev); | ||
90 | if (!error && root) | ||
91 | error = sysfs_create_link(&root->sysdev.kobj, | ||
92 | &cpu->sysdev.kobj, | ||
93 | kobject_name(&cpu->sysdev.kobj)); | ||
94 | if (!error && !cpu->no_control) | ||
95 | register_cpu_control(cpu); | ||
96 | return error; | ||
97 | } | ||
98 | |||
99 | |||
100 | |||
101 | int __init cpu_dev_init(void) | ||
102 | { | ||
103 | return sysdev_class_register(&cpu_sysdev_class); | ||
104 | } | ||
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c new file mode 100644 index 000000000000..f48833df61a2 --- /dev/null +++ b/drivers/base/dmapool.c | |||
@@ -0,0 +1,414 @@ | |||
1 | |||
2 | #include <linux/device.h> | ||
3 | #include <linux/mm.h> | ||
4 | #include <asm/io.h> /* Needed for i386 to build */ | ||
5 | #include <asm/scatterlist.h> /* Needed for i386 to build */ | ||
6 | #include <linux/dma-mapping.h> | ||
7 | #include <linux/dmapool.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/module.h> | ||
10 | |||
11 | /* | ||
12 | * Pool allocator ... wraps the dma_alloc_coherent page allocator, so | ||
13 | * small blocks are easily used by drivers for bus mastering controllers. | ||
14 | * This should probably be sharing the guts of the slab allocator. | ||
15 | */ | ||
16 | |||
17 | struct dma_pool { /* the pool */ | ||
18 | struct list_head page_list; | ||
19 | spinlock_t lock; | ||
20 | size_t blocks_per_page; | ||
21 | size_t size; | ||
22 | struct device *dev; | ||
23 | size_t allocation; | ||
24 | char name [32]; | ||
25 | wait_queue_head_t waitq; | ||
26 | struct list_head pools; | ||
27 | }; | ||
28 | |||
29 | struct dma_page { /* cacheable header for 'allocation' bytes */ | ||
30 | struct list_head page_list; | ||
31 | void *vaddr; | ||
32 | dma_addr_t dma; | ||
33 | unsigned in_use; | ||
34 | unsigned long bitmap [0]; | ||
35 | }; | ||
36 | |||
37 | #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) | ||
38 | #define POOL_POISON_FREED 0xa7 /* !inuse */ | ||
39 | #define POOL_POISON_ALLOCATED 0xa9 /* !initted */ | ||
40 | |||
41 | static DECLARE_MUTEX (pools_lock); | ||
42 | |||
43 | static ssize_t | ||
44 | show_pools (struct device *dev, char *buf) | ||
45 | { | ||
46 | unsigned temp; | ||
47 | unsigned size; | ||
48 | char *next; | ||
49 | struct dma_page *page; | ||
50 | struct dma_pool *pool; | ||
51 | |||
52 | next = buf; | ||
53 | size = PAGE_SIZE; | ||
54 | |||
55 | temp = scnprintf(next, size, "poolinfo - 0.1\n"); | ||
56 | size -= temp; | ||
57 | next += temp; | ||
58 | |||
59 | down (&pools_lock); | ||
60 | list_for_each_entry(pool, &dev->dma_pools, pools) { | ||
61 | unsigned pages = 0; | ||
62 | unsigned blocks = 0; | ||
63 | |||
64 | list_for_each_entry(page, &pool->page_list, page_list) { | ||
65 | pages++; | ||
66 | blocks += page->in_use; | ||
67 | } | ||
68 | |||
69 | /* per-pool info, no real statistics yet */ | ||
70 | temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n", | ||
71 | pool->name, | ||
72 | blocks, pages * pool->blocks_per_page, | ||
73 | pool->size, pages); | ||
74 | size -= temp; | ||
75 | next += temp; | ||
76 | } | ||
77 | up (&pools_lock); | ||
78 | |||
79 | return PAGE_SIZE - size; | ||
80 | } | ||
81 | static DEVICE_ATTR (pools, S_IRUGO, show_pools, NULL); | ||
82 | |||
83 | /** | ||
84 | * dma_pool_create - Creates a pool of consistent memory blocks, for dma. | ||
85 | * @name: name of pool, for diagnostics | ||
86 | * @dev: device that will be doing the DMA | ||
87 | * @size: size of the blocks in this pool. | ||
88 | * @align: alignment requirement for blocks; must be a power of two | ||
89 | * @allocation: returned blocks won't cross this boundary (or zero) | ||
90 | * Context: !in_interrupt() | ||
91 | * | ||
92 | * Returns a dma allocation pool with the requested characteristics, or | ||
93 | * null if one can't be created. Given one of these pools, dma_pool_alloc() | ||
94 | * may be used to allocate memory. Such memory will all have "consistent" | ||
95 | * DMA mappings, accessible by the device and its driver without using | ||
96 | * cache flushing primitives. The actual size of blocks allocated may be | ||
97 | * larger than requested because of alignment. | ||
98 | * | ||
99 | * If allocation is nonzero, objects returned from dma_pool_alloc() won't | ||
100 | * cross that size boundary. This is useful for devices which have | ||
101 | * addressing restrictions on individual DMA transfers, such as not crossing | ||
102 | * boundaries of 4KBytes. | ||
103 | */ | ||
104 | struct dma_pool * | ||
105 | dma_pool_create (const char *name, struct device *dev, | ||
106 | size_t size, size_t align, size_t allocation) | ||
107 | { | ||
108 | struct dma_pool *retval; | ||
109 | |||
110 | if (align == 0) | ||
111 | align = 1; | ||
112 | if (size == 0) | ||
113 | return NULL; | ||
114 | else if (size < align) | ||
115 | size = align; | ||
116 | else if ((size % align) != 0) { | ||
117 | size += align + 1; | ||
118 | size &= ~(align - 1); | ||
119 | } | ||
120 | |||
121 | if (allocation == 0) { | ||
122 | if (PAGE_SIZE < size) | ||
123 | allocation = size; | ||
124 | else | ||
125 | allocation = PAGE_SIZE; | ||
126 | // FIXME: round up for less fragmentation | ||
127 | } else if (allocation < size) | ||
128 | return NULL; | ||
129 | |||
130 | if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL))) | ||
131 | return retval; | ||
132 | |||
133 | strlcpy (retval->name, name, sizeof retval->name); | ||
134 | |||
135 | retval->dev = dev; | ||
136 | |||
137 | INIT_LIST_HEAD (&retval->page_list); | ||
138 | spin_lock_init (&retval->lock); | ||
139 | retval->size = size; | ||
140 | retval->allocation = allocation; | ||
141 | retval->blocks_per_page = allocation / size; | ||
142 | init_waitqueue_head (&retval->waitq); | ||
143 | |||
144 | if (dev) { | ||
145 | down (&pools_lock); | ||
146 | if (list_empty (&dev->dma_pools)) | ||
147 | device_create_file (dev, &dev_attr_pools); | ||
148 | /* note: not currently insisting "name" be unique */ | ||
149 | list_add (&retval->pools, &dev->dma_pools); | ||
150 | up (&pools_lock); | ||
151 | } else | ||
152 | INIT_LIST_HEAD (&retval->pools); | ||
153 | |||
154 | return retval; | ||
155 | } | ||
156 | |||
157 | |||
158 | static struct dma_page * | ||
159 | pool_alloc_page (struct dma_pool *pool, unsigned int __nocast mem_flags) | ||
160 | { | ||
161 | struct dma_page *page; | ||
162 | int mapsize; | ||
163 | |||
164 | mapsize = pool->blocks_per_page; | ||
165 | mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
166 | mapsize *= sizeof (long); | ||
167 | |||
168 | page = (struct dma_page *) kmalloc (mapsize + sizeof *page, mem_flags); | ||
169 | if (!page) | ||
170 | return NULL; | ||
171 | page->vaddr = dma_alloc_coherent (pool->dev, | ||
172 | pool->allocation, | ||
173 | &page->dma, | ||
174 | mem_flags); | ||
175 | if (page->vaddr) { | ||
176 | memset (page->bitmap, 0xff, mapsize); // bit set == free | ||
177 | #ifdef CONFIG_DEBUG_SLAB | ||
178 | memset (page->vaddr, POOL_POISON_FREED, pool->allocation); | ||
179 | #endif | ||
180 | list_add (&page->page_list, &pool->page_list); | ||
181 | page->in_use = 0; | ||
182 | } else { | ||
183 | kfree (page); | ||
184 | page = NULL; | ||
185 | } | ||
186 | return page; | ||
187 | } | ||
188 | |||
189 | |||
190 | static inline int | ||
191 | is_page_busy (int blocks, unsigned long *bitmap) | ||
192 | { | ||
193 | while (blocks > 0) { | ||
194 | if (*bitmap++ != ~0UL) | ||
195 | return 1; | ||
196 | blocks -= BITS_PER_LONG; | ||
197 | } | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void | ||
202 | pool_free_page (struct dma_pool *pool, struct dma_page *page) | ||
203 | { | ||
204 | dma_addr_t dma = page->dma; | ||
205 | |||
206 | #ifdef CONFIG_DEBUG_SLAB | ||
207 | memset (page->vaddr, POOL_POISON_FREED, pool->allocation); | ||
208 | #endif | ||
209 | dma_free_coherent (pool->dev, pool->allocation, page->vaddr, dma); | ||
210 | list_del (&page->page_list); | ||
211 | kfree (page); | ||
212 | } | ||
213 | |||
214 | |||
215 | /** | ||
216 | * dma_pool_destroy - destroys a pool of dma memory blocks. | ||
217 | * @pool: dma pool that will be destroyed | ||
218 | * Context: !in_interrupt() | ||
219 | * | ||
220 | * Caller guarantees that no more memory from the pool is in use, | ||
221 | * and that nothing will try to use the pool after this call. | ||
222 | */ | ||
223 | void | ||
224 | dma_pool_destroy (struct dma_pool *pool) | ||
225 | { | ||
226 | down (&pools_lock); | ||
227 | list_del (&pool->pools); | ||
228 | if (pool->dev && list_empty (&pool->dev->dma_pools)) | ||
229 | device_remove_file (pool->dev, &dev_attr_pools); | ||
230 | up (&pools_lock); | ||
231 | |||
232 | while (!list_empty (&pool->page_list)) { | ||
233 | struct dma_page *page; | ||
234 | page = list_entry (pool->page_list.next, | ||
235 | struct dma_page, page_list); | ||
236 | if (is_page_busy (pool->blocks_per_page, page->bitmap)) { | ||
237 | if (pool->dev) | ||
238 | dev_err(pool->dev, "dma_pool_destroy %s, %p busy\n", | ||
239 | pool->name, page->vaddr); | ||
240 | else | ||
241 | printk (KERN_ERR "dma_pool_destroy %s, %p busy\n", | ||
242 | pool->name, page->vaddr); | ||
243 | /* leak the still-in-use consistent memory */ | ||
244 | list_del (&page->page_list); | ||
245 | kfree (page); | ||
246 | } else | ||
247 | pool_free_page (pool, page); | ||
248 | } | ||
249 | |||
250 | kfree (pool); | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * dma_pool_alloc - get a block of consistent memory | ||
256 | * @pool: dma pool that will produce the block | ||
257 | * @mem_flags: GFP_* bitmask | ||
258 | * @handle: pointer to dma address of block | ||
259 | * | ||
260 | * This returns the kernel virtual address of a currently unused block, | ||
261 | * and reports its dma address through the handle. | ||
262 | * If such a memory block can't be allocated, null is returned. | ||
263 | */ | ||
264 | void * | ||
265 | dma_pool_alloc (struct dma_pool *pool, int mem_flags, dma_addr_t *handle) | ||
266 | { | ||
267 | unsigned long flags; | ||
268 | struct dma_page *page; | ||
269 | int map, block; | ||
270 | size_t offset; | ||
271 | void *retval; | ||
272 | |||
273 | restart: | ||
274 | spin_lock_irqsave (&pool->lock, flags); | ||
275 | list_for_each_entry(page, &pool->page_list, page_list) { | ||
276 | int i; | ||
277 | /* only cachable accesses here ... */ | ||
278 | for (map = 0, i = 0; | ||
279 | i < pool->blocks_per_page; | ||
280 | i += BITS_PER_LONG, map++) { | ||
281 | if (page->bitmap [map] == 0) | ||
282 | continue; | ||
283 | block = ffz (~ page->bitmap [map]); | ||
284 | if ((i + block) < pool->blocks_per_page) { | ||
285 | clear_bit (block, &page->bitmap [map]); | ||
286 | offset = (BITS_PER_LONG * map) + block; | ||
287 | offset *= pool->size; | ||
288 | goto ready; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | if (!(page = pool_alloc_page (pool, SLAB_ATOMIC))) { | ||
293 | if (mem_flags & __GFP_WAIT) { | ||
294 | DECLARE_WAITQUEUE (wait, current); | ||
295 | |||
296 | current->state = TASK_INTERRUPTIBLE; | ||
297 | add_wait_queue (&pool->waitq, &wait); | ||
298 | spin_unlock_irqrestore (&pool->lock, flags); | ||
299 | |||
300 | schedule_timeout (POOL_TIMEOUT_JIFFIES); | ||
301 | |||
302 | remove_wait_queue (&pool->waitq, &wait); | ||
303 | goto restart; | ||
304 | } | ||
305 | retval = NULL; | ||
306 | goto done; | ||
307 | } | ||
308 | |||
309 | clear_bit (0, &page->bitmap [0]); | ||
310 | offset = 0; | ||
311 | ready: | ||
312 | page->in_use++; | ||
313 | retval = offset + page->vaddr; | ||
314 | *handle = offset + page->dma; | ||
315 | #ifdef CONFIG_DEBUG_SLAB | ||
316 | memset (retval, POOL_POISON_ALLOCATED, pool->size); | ||
317 | #endif | ||
318 | done: | ||
319 | spin_unlock_irqrestore (&pool->lock, flags); | ||
320 | return retval; | ||
321 | } | ||
322 | |||
323 | |||
324 | static struct dma_page * | ||
325 | pool_find_page (struct dma_pool *pool, dma_addr_t dma) | ||
326 | { | ||
327 | unsigned long flags; | ||
328 | struct dma_page *page; | ||
329 | |||
330 | spin_lock_irqsave (&pool->lock, flags); | ||
331 | list_for_each_entry(page, &pool->page_list, page_list) { | ||
332 | if (dma < page->dma) | ||
333 | continue; | ||
334 | if (dma < (page->dma + pool->allocation)) | ||
335 | goto done; | ||
336 | } | ||
337 | page = NULL; | ||
338 | done: | ||
339 | spin_unlock_irqrestore (&pool->lock, flags); | ||
340 | return page; | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
345 | * dma_pool_free - put block back into dma pool | ||
346 | * @pool: the dma pool holding the block | ||
347 | * @vaddr: virtual address of block | ||
348 | * @dma: dma address of block | ||
349 | * | ||
350 | * Caller promises neither device nor driver will again touch this block | ||
351 | * unless it is first re-allocated. | ||
352 | */ | ||
353 | void | ||
354 | dma_pool_free (struct dma_pool *pool, void *vaddr, dma_addr_t dma) | ||
355 | { | ||
356 | struct dma_page *page; | ||
357 | unsigned long flags; | ||
358 | int map, block; | ||
359 | |||
360 | if ((page = pool_find_page (pool, dma)) == 0) { | ||
361 | if (pool->dev) | ||
362 | dev_err(pool->dev, "dma_pool_free %s, %p/%lx (bad dma)\n", | ||
363 | pool->name, vaddr, (unsigned long) dma); | ||
364 | else | ||
365 | printk (KERN_ERR "dma_pool_free %s, %p/%lx (bad dma)\n", | ||
366 | pool->name, vaddr, (unsigned long) dma); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | block = dma - page->dma; | ||
371 | block /= pool->size; | ||
372 | map = block / BITS_PER_LONG; | ||
373 | block %= BITS_PER_LONG; | ||
374 | |||
375 | #ifdef CONFIG_DEBUG_SLAB | ||
376 | if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { | ||
377 | if (pool->dev) | ||
378 | dev_err(pool->dev, "dma_pool_free %s, %p (bad vaddr)/%Lx\n", | ||
379 | pool->name, vaddr, (unsigned long long) dma); | ||
380 | else | ||
381 | printk (KERN_ERR "dma_pool_free %s, %p (bad vaddr)/%Lx\n", | ||
382 | pool->name, vaddr, (unsigned long long) dma); | ||
383 | return; | ||
384 | } | ||
385 | if (page->bitmap [map] & (1UL << block)) { | ||
386 | if (pool->dev) | ||
387 | dev_err(pool->dev, "dma_pool_free %s, dma %Lx already free\n", | ||
388 | pool->name, (unsigned long long)dma); | ||
389 | else | ||
390 | printk (KERN_ERR "dma_pool_free %s, dma %Lx already free\n", | ||
391 | pool->name, (unsigned long long)dma); | ||
392 | return; | ||
393 | } | ||
394 | memset (vaddr, POOL_POISON_FREED, pool->size); | ||
395 | #endif | ||
396 | |||
397 | spin_lock_irqsave (&pool->lock, flags); | ||
398 | page->in_use--; | ||
399 | set_bit (block, &page->bitmap [map]); | ||
400 | if (waitqueue_active (&pool->waitq)) | ||
401 | wake_up (&pool->waitq); | ||
402 | /* | ||
403 | * Resist a temptation to do | ||
404 | * if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page); | ||
405 | * Better have a few empty pages hang around. | ||
406 | */ | ||
407 | spin_unlock_irqrestore (&pool->lock, flags); | ||
408 | } | ||
409 | |||
410 | |||
411 | EXPORT_SYMBOL (dma_pool_create); | ||
412 | EXPORT_SYMBOL (dma_pool_destroy); | ||
413 | EXPORT_SYMBOL (dma_pool_alloc); | ||
414 | EXPORT_SYMBOL (dma_pool_free); | ||
diff --git a/drivers/base/driver.c b/drivers/base/driver.c new file mode 100644 index 000000000000..3b269f7e5213 --- /dev/null +++ b/drivers/base/driver.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * driver.c - centralized device driver management | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/string.h> | ||
16 | #include "base.h" | ||
17 | |||
18 | #define to_dev(node) container_of(node, struct device, driver_list) | ||
19 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) | ||
20 | |||
21 | /** | ||
22 | * driver_create_file - create sysfs file for driver. | ||
23 | * @drv: driver. | ||
24 | * @attr: driver attribute descriptor. | ||
25 | */ | ||
26 | |||
27 | int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) | ||
28 | { | ||
29 | int error; | ||
30 | if (get_driver(drv)) { | ||
31 | error = sysfs_create_file(&drv->kobj, &attr->attr); | ||
32 | put_driver(drv); | ||
33 | } else | ||
34 | error = -EINVAL; | ||
35 | return error; | ||
36 | } | ||
37 | |||
38 | |||
39 | /** | ||
40 | * driver_remove_file - remove sysfs file for driver. | ||
41 | * @drv: driver. | ||
42 | * @attr: driver attribute descriptor. | ||
43 | */ | ||
44 | |||
45 | void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) | ||
46 | { | ||
47 | if (get_driver(drv)) { | ||
48 | sysfs_remove_file(&drv->kobj, &attr->attr); | ||
49 | put_driver(drv); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | |||
54 | /** | ||
55 | * get_driver - increment driver reference count. | ||
56 | * @drv: driver. | ||
57 | */ | ||
58 | struct device_driver * get_driver(struct device_driver * drv) | ||
59 | { | ||
60 | return drv ? to_drv(kobject_get(&drv->kobj)) : NULL; | ||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * put_driver - decrement driver's refcount. | ||
66 | * @drv: driver. | ||
67 | */ | ||
68 | void put_driver(struct device_driver * drv) | ||
69 | { | ||
70 | kobject_put(&drv->kobj); | ||
71 | } | ||
72 | |||
73 | |||
74 | /** | ||
75 | * driver_register - register driver with bus | ||
76 | * @drv: driver to register | ||
77 | * | ||
78 | * We pass off most of the work to the bus_add_driver() call, | ||
79 | * since most of the things we have to do deal with the bus | ||
80 | * structures. | ||
81 | * | ||
82 | * The one interesting aspect is that we setup @drv->unloaded | ||
83 | * as a completion that gets complete when the driver reference | ||
84 | * count reaches 0. | ||
85 | */ | ||
86 | int driver_register(struct device_driver * drv) | ||
87 | { | ||
88 | INIT_LIST_HEAD(&drv->devices); | ||
89 | init_completion(&drv->unloaded); | ||
90 | return bus_add_driver(drv); | ||
91 | } | ||
92 | |||
93 | |||
94 | /** | ||
95 | * driver_unregister - remove driver from system. | ||
96 | * @drv: driver. | ||
97 | * | ||
98 | * Again, we pass off most of the work to the bus-level call. | ||
99 | * | ||
100 | * Though, once that is done, we wait until @drv->unloaded is completed. | ||
101 | * This will block until the driver refcount reaches 0, and it is | ||
102 | * released. Only modular drivers will call this function, and we | ||
103 | * have to guarantee that it won't complete, letting the driver | ||
104 | * unload until all references are gone. | ||
105 | */ | ||
106 | |||
107 | void driver_unregister(struct device_driver * drv) | ||
108 | { | ||
109 | bus_remove_driver(drv); | ||
110 | wait_for_completion(&drv->unloaded); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * driver_find - locate driver on a bus by its name. | ||
115 | * @name: name of the driver. | ||
116 | * @bus: bus to scan for the driver. | ||
117 | * | ||
118 | * Call kset_find_obj() to iterate over list of drivers on | ||
119 | * a bus to find driver by name. Return driver if found. | ||
120 | * | ||
121 | * Note that kset_find_obj increments driver's reference count. | ||
122 | */ | ||
123 | struct device_driver *driver_find(const char *name, struct bus_type *bus) | ||
124 | { | ||
125 | struct kobject *k = kset_find_obj(&bus->drivers, name); | ||
126 | if (k) | ||
127 | return to_drv(k); | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | EXPORT_SYMBOL_GPL(driver_register); | ||
132 | EXPORT_SYMBOL_GPL(driver_unregister); | ||
133 | EXPORT_SYMBOL_GPL(get_driver); | ||
134 | EXPORT_SYMBOL_GPL(put_driver); | ||
135 | EXPORT_SYMBOL_GPL(driver_find); | ||
136 | |||
137 | EXPORT_SYMBOL_GPL(driver_create_file); | ||
138 | EXPORT_SYMBOL_GPL(driver_remove_file); | ||
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c new file mode 100644 index 000000000000..88ab044932f2 --- /dev/null +++ b/drivers/base/firmware.c | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * firmware.c - firmware subsystem hoohaw. | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/kobject.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | |||
15 | static decl_subsys(firmware, NULL, NULL); | ||
16 | |||
17 | int firmware_register(struct subsystem * s) | ||
18 | { | ||
19 | kset_set_kset_s(s, firmware_subsys); | ||
20 | return subsystem_register(s); | ||
21 | } | ||
22 | |||
23 | void firmware_unregister(struct subsystem * s) | ||
24 | { | ||
25 | subsystem_unregister(s); | ||
26 | } | ||
27 | |||
28 | int __init firmware_init(void) | ||
29 | { | ||
30 | return subsystem_register(&firmware_subsys); | ||
31 | } | ||
32 | |||
33 | EXPORT_SYMBOL_GPL(firmware_register); | ||
34 | EXPORT_SYMBOL_GPL(firmware_unregister); | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c new file mode 100644 index 000000000000..26c9464af80a --- /dev/null +++ b/drivers/base/firmware_class.c | |||
@@ -0,0 +1,583 @@ | |||
1 | /* | ||
2 | * firmware_class.c - Multi purpose firmware loading support | ||
3 | * | ||
4 | * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org> | ||
5 | * | ||
6 | * Please see Documentation/firmware_class/ for more information. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/timer.h> | ||
14 | #include <linux/vmalloc.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <asm/semaphore.h> | ||
18 | |||
19 | #include <linux/firmware.h> | ||
20 | #include "base.h" | ||
21 | |||
22 | MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); | ||
23 | MODULE_DESCRIPTION("Multi purpose firmware loading support"); | ||
24 | MODULE_LICENSE("GPL"); | ||
25 | |||
26 | enum { | ||
27 | FW_STATUS_LOADING, | ||
28 | FW_STATUS_DONE, | ||
29 | FW_STATUS_ABORT, | ||
30 | FW_STATUS_READY, | ||
31 | }; | ||
32 | |||
33 | static int loading_timeout = 10; /* In seconds */ | ||
34 | |||
35 | /* fw_lock could be moved to 'struct firmware_priv' but since it is just | ||
36 | * guarding for corner cases a global lock should be OK */ | ||
37 | static DECLARE_MUTEX(fw_lock); | ||
38 | |||
39 | struct firmware_priv { | ||
40 | char fw_id[FIRMWARE_NAME_MAX]; | ||
41 | struct completion completion; | ||
42 | struct bin_attribute attr_data; | ||
43 | struct firmware *fw; | ||
44 | unsigned long status; | ||
45 | int alloc_size; | ||
46 | struct timer_list timeout; | ||
47 | }; | ||
48 | |||
49 | static inline void | ||
50 | fw_load_abort(struct firmware_priv *fw_priv) | ||
51 | { | ||
52 | set_bit(FW_STATUS_ABORT, &fw_priv->status); | ||
53 | wmb(); | ||
54 | complete(&fw_priv->completion); | ||
55 | } | ||
56 | |||
57 | static ssize_t | ||
58 | firmware_timeout_show(struct class *class, char *buf) | ||
59 | { | ||
60 | return sprintf(buf, "%d\n", loading_timeout); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * firmware_timeout_store: | ||
65 | * Description: | ||
66 | * Sets the number of seconds to wait for the firmware. Once | ||
67 | * this expires an error will be return to the driver and no | ||
68 | * firmware will be provided. | ||
69 | * | ||
70 | * Note: zero means 'wait for ever' | ||
71 | * | ||
72 | **/ | ||
73 | static ssize_t | ||
74 | firmware_timeout_store(struct class *class, const char *buf, size_t count) | ||
75 | { | ||
76 | loading_timeout = simple_strtol(buf, NULL, 10); | ||
77 | return count; | ||
78 | } | ||
79 | |||
80 | static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); | ||
81 | |||
82 | static void fw_class_dev_release(struct class_device *class_dev); | ||
83 | int firmware_class_hotplug(struct class_device *dev, char **envp, | ||
84 | int num_envp, char *buffer, int buffer_size); | ||
85 | |||
86 | static struct class firmware_class = { | ||
87 | .name = "firmware", | ||
88 | .hotplug = firmware_class_hotplug, | ||
89 | .release = fw_class_dev_release, | ||
90 | }; | ||
91 | |||
92 | int | ||
93 | firmware_class_hotplug(struct class_device *class_dev, char **envp, | ||
94 | int num_envp, char *buffer, int buffer_size) | ||
95 | { | ||
96 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
97 | int i = 0, len = 0; | ||
98 | |||
99 | if (!test_bit(FW_STATUS_READY, &fw_priv->status)) | ||
100 | return -ENODEV; | ||
101 | |||
102 | if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, | ||
103 | "FIRMWARE=%s", fw_priv->fw_id)) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | envp[i] = NULL; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static ssize_t | ||
112 | firmware_loading_show(struct class_device *class_dev, char *buf) | ||
113 | { | ||
114 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
115 | int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); | ||
116 | return sprintf(buf, "%d\n", loading); | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * firmware_loading_store: - loading control file | ||
121 | * Description: | ||
122 | * The relevant values are: | ||
123 | * | ||
124 | * 1: Start a load, discarding any previous partial load. | ||
125 | * 0: Conclude the load and handle the data to the driver code. | ||
126 | * -1: Conclude the load with an error and discard any written data. | ||
127 | **/ | ||
128 | static ssize_t | ||
129 | firmware_loading_store(struct class_device *class_dev, | ||
130 | const char *buf, size_t count) | ||
131 | { | ||
132 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
133 | int loading = simple_strtol(buf, NULL, 10); | ||
134 | |||
135 | switch (loading) { | ||
136 | case 1: | ||
137 | down(&fw_lock); | ||
138 | vfree(fw_priv->fw->data); | ||
139 | fw_priv->fw->data = NULL; | ||
140 | fw_priv->fw->size = 0; | ||
141 | fw_priv->alloc_size = 0; | ||
142 | set_bit(FW_STATUS_LOADING, &fw_priv->status); | ||
143 | up(&fw_lock); | ||
144 | break; | ||
145 | case 0: | ||
146 | if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { | ||
147 | complete(&fw_priv->completion); | ||
148 | clear_bit(FW_STATUS_LOADING, &fw_priv->status); | ||
149 | break; | ||
150 | } | ||
151 | /* fallthrough */ | ||
152 | default: | ||
153 | printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__, | ||
154 | loading); | ||
155 | /* fallthrough */ | ||
156 | case -1: | ||
157 | fw_load_abort(fw_priv); | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | return count; | ||
162 | } | ||
163 | |||
164 | static CLASS_DEVICE_ATTR(loading, 0644, | ||
165 | firmware_loading_show, firmware_loading_store); | ||
166 | |||
167 | static ssize_t | ||
168 | firmware_data_read(struct kobject *kobj, | ||
169 | char *buffer, loff_t offset, size_t count) | ||
170 | { | ||
171 | struct class_device *class_dev = to_class_dev(kobj); | ||
172 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
173 | struct firmware *fw; | ||
174 | ssize_t ret_count = count; | ||
175 | |||
176 | down(&fw_lock); | ||
177 | fw = fw_priv->fw; | ||
178 | if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { | ||
179 | ret_count = -ENODEV; | ||
180 | goto out; | ||
181 | } | ||
182 | if (offset > fw->size) { | ||
183 | ret_count = 0; | ||
184 | goto out; | ||
185 | } | ||
186 | if (offset + ret_count > fw->size) | ||
187 | ret_count = fw->size - offset; | ||
188 | |||
189 | memcpy(buffer, fw->data + offset, ret_count); | ||
190 | out: | ||
191 | up(&fw_lock); | ||
192 | return ret_count; | ||
193 | } | ||
194 | static int | ||
195 | fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | ||
196 | { | ||
197 | u8 *new_data; | ||
198 | |||
199 | if (min_size <= fw_priv->alloc_size) | ||
200 | return 0; | ||
201 | |||
202 | new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE); | ||
203 | if (!new_data) { | ||
204 | printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); | ||
205 | /* Make sure that we don't keep incomplete data */ | ||
206 | fw_load_abort(fw_priv); | ||
207 | return -ENOMEM; | ||
208 | } | ||
209 | fw_priv->alloc_size += PAGE_SIZE; | ||
210 | if (fw_priv->fw->data) { | ||
211 | memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); | ||
212 | vfree(fw_priv->fw->data); | ||
213 | } | ||
214 | fw_priv->fw->data = new_data; | ||
215 | BUG_ON(min_size > fw_priv->alloc_size); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * firmware_data_write: | ||
221 | * | ||
222 | * Description: | ||
223 | * | ||
224 | * Data written to the 'data' attribute will be later handled to | ||
225 | * the driver as a firmware image. | ||
226 | **/ | ||
227 | static ssize_t | ||
228 | firmware_data_write(struct kobject *kobj, | ||
229 | char *buffer, loff_t offset, size_t count) | ||
230 | { | ||
231 | struct class_device *class_dev = to_class_dev(kobj); | ||
232 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
233 | struct firmware *fw; | ||
234 | ssize_t retval; | ||
235 | |||
236 | if (!capable(CAP_SYS_RAWIO)) | ||
237 | return -EPERM; | ||
238 | down(&fw_lock); | ||
239 | fw = fw_priv->fw; | ||
240 | if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { | ||
241 | retval = -ENODEV; | ||
242 | goto out; | ||
243 | } | ||
244 | retval = fw_realloc_buffer(fw_priv, offset + count); | ||
245 | if (retval) | ||
246 | goto out; | ||
247 | |||
248 | memcpy(fw->data + offset, buffer, count); | ||
249 | |||
250 | fw->size = max_t(size_t, offset + count, fw->size); | ||
251 | retval = count; | ||
252 | out: | ||
253 | up(&fw_lock); | ||
254 | return retval; | ||
255 | } | ||
256 | static struct bin_attribute firmware_attr_data_tmpl = { | ||
257 | .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, | ||
258 | .size = 0, | ||
259 | .read = firmware_data_read, | ||
260 | .write = firmware_data_write, | ||
261 | }; | ||
262 | |||
263 | static void | ||
264 | fw_class_dev_release(struct class_device *class_dev) | ||
265 | { | ||
266 | struct firmware_priv *fw_priv = class_get_devdata(class_dev); | ||
267 | |||
268 | kfree(fw_priv); | ||
269 | kfree(class_dev); | ||
270 | |||
271 | module_put(THIS_MODULE); | ||
272 | } | ||
273 | |||
274 | static void | ||
275 | firmware_class_timeout(u_long data) | ||
276 | { | ||
277 | struct firmware_priv *fw_priv = (struct firmware_priv *) data; | ||
278 | fw_load_abort(fw_priv); | ||
279 | } | ||
280 | |||
281 | static inline void | ||
282 | fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) | ||
283 | { | ||
284 | /* XXX warning we should watch out for name collisions */ | ||
285 | strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); | ||
286 | } | ||
287 | |||
288 | static int | ||
289 | fw_register_class_device(struct class_device **class_dev_p, | ||
290 | const char *fw_name, struct device *device) | ||
291 | { | ||
292 | int retval; | ||
293 | struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), | ||
294 | GFP_KERNEL); | ||
295 | struct class_device *class_dev = kmalloc(sizeof (struct class_device), | ||
296 | GFP_KERNEL); | ||
297 | |||
298 | *class_dev_p = NULL; | ||
299 | |||
300 | if (!fw_priv || !class_dev) { | ||
301 | printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); | ||
302 | retval = -ENOMEM; | ||
303 | goto error_kfree; | ||
304 | } | ||
305 | memset(fw_priv, 0, sizeof (*fw_priv)); | ||
306 | memset(class_dev, 0, sizeof (*class_dev)); | ||
307 | |||
308 | init_completion(&fw_priv->completion); | ||
309 | fw_priv->attr_data = firmware_attr_data_tmpl; | ||
310 | strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); | ||
311 | |||
312 | fw_priv->timeout.function = firmware_class_timeout; | ||
313 | fw_priv->timeout.data = (u_long) fw_priv; | ||
314 | init_timer(&fw_priv->timeout); | ||
315 | |||
316 | fw_setup_class_device_id(class_dev, device); | ||
317 | class_dev->dev = device; | ||
318 | class_dev->class = &firmware_class; | ||
319 | class_set_devdata(class_dev, fw_priv); | ||
320 | retval = class_device_register(class_dev); | ||
321 | if (retval) { | ||
322 | printk(KERN_ERR "%s: class_device_register failed\n", | ||
323 | __FUNCTION__); | ||
324 | goto error_kfree; | ||
325 | } | ||
326 | *class_dev_p = class_dev; | ||
327 | return 0; | ||
328 | |||
329 | error_kfree: | ||
330 | kfree(fw_priv); | ||
331 | kfree(class_dev); | ||
332 | return retval; | ||
333 | } | ||
334 | |||
335 | static int | ||
336 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | ||
337 | const char *fw_name, struct device *device) | ||
338 | { | ||
339 | struct class_device *class_dev; | ||
340 | struct firmware_priv *fw_priv; | ||
341 | int retval; | ||
342 | |||
343 | *class_dev_p = NULL; | ||
344 | retval = fw_register_class_device(&class_dev, fw_name, device); | ||
345 | if (retval) | ||
346 | goto out; | ||
347 | |||
348 | /* Need to pin this module until class device is destroyed */ | ||
349 | __module_get(THIS_MODULE); | ||
350 | |||
351 | fw_priv = class_get_devdata(class_dev); | ||
352 | |||
353 | fw_priv->fw = fw; | ||
354 | retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); | ||
355 | if (retval) { | ||
356 | printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", | ||
357 | __FUNCTION__); | ||
358 | goto error_unreg; | ||
359 | } | ||
360 | |||
361 | retval = class_device_create_file(class_dev, | ||
362 | &class_device_attr_loading); | ||
363 | if (retval) { | ||
364 | printk(KERN_ERR "%s: class_device_create_file failed\n", | ||
365 | __FUNCTION__); | ||
366 | goto error_unreg; | ||
367 | } | ||
368 | |||
369 | set_bit(FW_STATUS_READY, &fw_priv->status); | ||
370 | *class_dev_p = class_dev; | ||
371 | goto out; | ||
372 | |||
373 | error_unreg: | ||
374 | class_device_unregister(class_dev); | ||
375 | out: | ||
376 | return retval; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * request_firmware: - request firmware to hotplug and wait for it | ||
381 | * Description: | ||
382 | * @firmware will be used to return a firmware image by the name | ||
383 | * of @name for device @device. | ||
384 | * | ||
385 | * Should be called from user context where sleeping is allowed. | ||
386 | * | ||
387 | * @name will be use as $FIRMWARE in the hotplug environment and | ||
388 | * should be distinctive enough not to be confused with any other | ||
389 | * firmware image for this or any other device. | ||
390 | **/ | ||
391 | int | ||
392 | request_firmware(const struct firmware **firmware_p, const char *name, | ||
393 | struct device *device) | ||
394 | { | ||
395 | struct class_device *class_dev; | ||
396 | struct firmware_priv *fw_priv; | ||
397 | struct firmware *firmware; | ||
398 | int retval; | ||
399 | |||
400 | if (!firmware_p) | ||
401 | return -EINVAL; | ||
402 | |||
403 | *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL); | ||
404 | if (!firmware) { | ||
405 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | ||
406 | __FUNCTION__); | ||
407 | retval = -ENOMEM; | ||
408 | goto out; | ||
409 | } | ||
410 | memset(firmware, 0, sizeof (*firmware)); | ||
411 | |||
412 | retval = fw_setup_class_device(firmware, &class_dev, name, device); | ||
413 | if (retval) | ||
414 | goto error_kfree_fw; | ||
415 | |||
416 | fw_priv = class_get_devdata(class_dev); | ||
417 | |||
418 | if (loading_timeout) { | ||
419 | fw_priv->timeout.expires = jiffies + loading_timeout * HZ; | ||
420 | add_timer(&fw_priv->timeout); | ||
421 | } | ||
422 | |||
423 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | ||
424 | wait_for_completion(&fw_priv->completion); | ||
425 | set_bit(FW_STATUS_DONE, &fw_priv->status); | ||
426 | |||
427 | del_timer_sync(&fw_priv->timeout); | ||
428 | |||
429 | down(&fw_lock); | ||
430 | if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { | ||
431 | retval = -ENOENT; | ||
432 | release_firmware(fw_priv->fw); | ||
433 | *firmware_p = NULL; | ||
434 | } | ||
435 | fw_priv->fw = NULL; | ||
436 | up(&fw_lock); | ||
437 | class_device_unregister(class_dev); | ||
438 | goto out; | ||
439 | |||
440 | error_kfree_fw: | ||
441 | kfree(firmware); | ||
442 | *firmware_p = NULL; | ||
443 | out: | ||
444 | return retval; | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * release_firmware: - release the resource associated with a firmware image | ||
449 | **/ | ||
450 | void | ||
451 | release_firmware(const struct firmware *fw) | ||
452 | { | ||
453 | if (fw) { | ||
454 | vfree(fw->data); | ||
455 | kfree(fw); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * register_firmware: - provide a firmware image for later usage | ||
461 | * | ||
462 | * Description: | ||
463 | * Make sure that @data will be available by requesting firmware @name. | ||
464 | * | ||
465 | * Note: This will not be possible until some kind of persistence | ||
466 | * is available. | ||
467 | **/ | ||
468 | void | ||
469 | register_firmware(const char *name, const u8 *data, size_t size) | ||
470 | { | ||
471 | /* This is meaningless without firmware caching, so until we | ||
472 | * decide if firmware caching is reasonable just leave it as a | ||
473 | * noop */ | ||
474 | } | ||
475 | |||
476 | /* Async support */ | ||
477 | struct firmware_work { | ||
478 | struct work_struct work; | ||
479 | struct module *module; | ||
480 | const char *name; | ||
481 | struct device *device; | ||
482 | void *context; | ||
483 | void (*cont)(const struct firmware *fw, void *context); | ||
484 | }; | ||
485 | |||
486 | static int | ||
487 | request_firmware_work_func(void *arg) | ||
488 | { | ||
489 | struct firmware_work *fw_work = arg; | ||
490 | const struct firmware *fw; | ||
491 | if (!arg) { | ||
492 | WARN_ON(1); | ||
493 | return 0; | ||
494 | } | ||
495 | daemonize("%s/%s", "firmware", fw_work->name); | ||
496 | request_firmware(&fw, fw_work->name, fw_work->device); | ||
497 | fw_work->cont(fw, fw_work->context); | ||
498 | release_firmware(fw); | ||
499 | module_put(fw_work->module); | ||
500 | kfree(fw_work); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * request_firmware_nowait: | ||
506 | * | ||
507 | * Description: | ||
508 | * Asynchronous variant of request_firmware() for contexts where | ||
509 | * it is not possible to sleep. | ||
510 | * | ||
511 | * @cont will be called asynchronously when the firmware request is over. | ||
512 | * | ||
513 | * @context will be passed over to @cont. | ||
514 | * | ||
515 | * @fw may be %NULL if firmware request fails. | ||
516 | * | ||
517 | **/ | ||
518 | int | ||
519 | request_firmware_nowait( | ||
520 | struct module *module, | ||
521 | const char *name, struct device *device, void *context, | ||
522 | void (*cont)(const struct firmware *fw, void *context)) | ||
523 | { | ||
524 | struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), | ||
525 | GFP_ATOMIC); | ||
526 | int ret; | ||
527 | |||
528 | if (!fw_work) | ||
529 | return -ENOMEM; | ||
530 | if (!try_module_get(module)) { | ||
531 | kfree(fw_work); | ||
532 | return -EFAULT; | ||
533 | } | ||
534 | |||
535 | *fw_work = (struct firmware_work) { | ||
536 | .module = module, | ||
537 | .name = name, | ||
538 | .device = device, | ||
539 | .context = context, | ||
540 | .cont = cont, | ||
541 | }; | ||
542 | |||
543 | ret = kernel_thread(request_firmware_work_func, fw_work, | ||
544 | CLONE_FS | CLONE_FILES); | ||
545 | |||
546 | if (ret < 0) { | ||
547 | fw_work->cont(NULL, fw_work->context); | ||
548 | return ret; | ||
549 | } | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static int __init | ||
554 | firmware_class_init(void) | ||
555 | { | ||
556 | int error; | ||
557 | error = class_register(&firmware_class); | ||
558 | if (error) { | ||
559 | printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__); | ||
560 | return error; | ||
561 | } | ||
562 | error = class_create_file(&firmware_class, &class_attr_timeout); | ||
563 | if (error) { | ||
564 | printk(KERN_ERR "%s: class_create_file failed\n", | ||
565 | __FUNCTION__); | ||
566 | class_unregister(&firmware_class); | ||
567 | } | ||
568 | return error; | ||
569 | |||
570 | } | ||
571 | static void __exit | ||
572 | firmware_class_exit(void) | ||
573 | { | ||
574 | class_unregister(&firmware_class); | ||
575 | } | ||
576 | |||
577 | module_init(firmware_class_init); | ||
578 | module_exit(firmware_class_exit); | ||
579 | |||
580 | EXPORT_SYMBOL(release_firmware); | ||
581 | EXPORT_SYMBOL(request_firmware); | ||
582 | EXPORT_SYMBOL(request_firmware_nowait); | ||
583 | EXPORT_SYMBOL(register_firmware); | ||
diff --git a/drivers/base/init.c b/drivers/base/init.c new file mode 100644 index 000000000000..a76ae5a221f3 --- /dev/null +++ b/drivers/base/init.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 2002-3 Patrick Mochel | ||
4 | * Copyright (c) 2002-3 Open Source Development Labs | ||
5 | * | ||
6 | * This file is released under the GPLv2 | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/init.h> | ||
12 | |||
13 | extern int devices_init(void); | ||
14 | extern int buses_init(void); | ||
15 | extern int classes_init(void); | ||
16 | extern int firmware_init(void); | ||
17 | extern int platform_bus_init(void); | ||
18 | extern int system_bus_init(void); | ||
19 | extern int cpu_dev_init(void); | ||
20 | extern int attribute_container_init(void); | ||
21 | /** | ||
22 | * driver_init - initialize driver model. | ||
23 | * | ||
24 | * Call the driver model init functions to initialize their | ||
25 | * subsystems. Called early from init/main.c. | ||
26 | */ | ||
27 | |||
28 | void __init driver_init(void) | ||
29 | { | ||
30 | /* These are the core pieces */ | ||
31 | devices_init(); | ||
32 | buses_init(); | ||
33 | classes_init(); | ||
34 | firmware_init(); | ||
35 | |||
36 | /* These are also core pieces, but must come after the | ||
37 | * core core pieces. | ||
38 | */ | ||
39 | platform_bus_init(); | ||
40 | system_bus_init(); | ||
41 | cpu_dev_init(); | ||
42 | attribute_container_init(); | ||
43 | } | ||
diff --git a/drivers/base/interface.c b/drivers/base/interface.c new file mode 100644 index 000000000000..bd515843a0cb --- /dev/null +++ b/drivers/base/interface.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * drivers/base/interface.c - common driverfs interface that's exported to | ||
3 | * the world for all devices. | ||
4 | * | ||
5 | * Copyright (c) 2002-3 Patrick Mochel | ||
6 | * Copyright (c) 2002-3 Open Source Development Labs | ||
7 | * | ||
8 | * This file is released under the GPLv2 | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/string.h> | ||
16 | |||
17 | /** | ||
18 | * detach_state - control the default power state for the device. | ||
19 | * | ||
20 | * This is the state the device enters when it's driver module is | ||
21 | * unloaded. The value is an unsigned integer, in the range of 0-4. | ||
22 | * '0' indicates 'On', so no action will be taken when the driver is | ||
23 | * unloaded. This is the default behavior. | ||
24 | * '4' indicates 'Off', meaning the driver core will call the driver's | ||
25 | * shutdown method to quiesce the device. | ||
26 | * 1-3 indicate a low-power state for the device to enter via the | ||
27 | * driver's suspend method. | ||
28 | */ | ||
29 | |||
30 | static ssize_t detach_show(struct device * dev, char * buf) | ||
31 | { | ||
32 | return sprintf(buf, "%u\n", dev->detach_state); | ||
33 | } | ||
34 | |||
35 | static ssize_t detach_store(struct device * dev, const char * buf, size_t n) | ||
36 | { | ||
37 | u32 state; | ||
38 | state = simple_strtoul(buf, NULL, 10); | ||
39 | if (state > 4) | ||
40 | return -EINVAL; | ||
41 | dev->detach_state = state; | ||
42 | return n; | ||
43 | } | ||
44 | |||
45 | static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store); | ||
46 | |||
47 | |||
48 | struct attribute * dev_default_attrs[] = { | ||
49 | &dev_attr_detach_state.attr, | ||
50 | NULL, | ||
51 | }; | ||
diff --git a/drivers/base/map.c b/drivers/base/map.c new file mode 100644 index 000000000000..2f455d86793c --- /dev/null +++ b/drivers/base/map.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * linux/drivers/base/map.c | ||
3 | * | ||
4 | * (C) Copyright Al Viro 2002,2003 | ||
5 | * Released under GPL v2. | ||
6 | * | ||
7 | * NOTE: data structure needs to be changed. It works, but for large dev_t | ||
8 | * it will be too slow. It is isolated, though, so these changes will be | ||
9 | * local to that file. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/kdev_t.h> | ||
15 | #include <linux/kobject.h> | ||
16 | #include <linux/kobj_map.h> | ||
17 | |||
18 | struct kobj_map { | ||
19 | struct probe { | ||
20 | struct probe *next; | ||
21 | dev_t dev; | ||
22 | unsigned long range; | ||
23 | struct module *owner; | ||
24 | kobj_probe_t *get; | ||
25 | int (*lock)(dev_t, void *); | ||
26 | void *data; | ||
27 | } *probes[255]; | ||
28 | struct semaphore *sem; | ||
29 | }; | ||
30 | |||
31 | int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, | ||
32 | struct module *module, kobj_probe_t *probe, | ||
33 | int (*lock)(dev_t, void *), void *data) | ||
34 | { | ||
35 | unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; | ||
36 | unsigned index = MAJOR(dev); | ||
37 | unsigned i; | ||
38 | struct probe *p; | ||
39 | |||
40 | if (n > 255) | ||
41 | n = 255; | ||
42 | |||
43 | p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL); | ||
44 | |||
45 | if (p == NULL) | ||
46 | return -ENOMEM; | ||
47 | |||
48 | for (i = 0; i < n; i++, p++) { | ||
49 | p->owner = module; | ||
50 | p->get = probe; | ||
51 | p->lock = lock; | ||
52 | p->dev = dev; | ||
53 | p->range = range; | ||
54 | p->data = data; | ||
55 | } | ||
56 | down(domain->sem); | ||
57 | for (i = 0, p -= n; i < n; i++, p++, index++) { | ||
58 | struct probe **s = &domain->probes[index % 255]; | ||
59 | while (*s && (*s)->range < range) | ||
60 | s = &(*s)->next; | ||
61 | p->next = *s; | ||
62 | *s = p; | ||
63 | } | ||
64 | up(domain->sem); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) | ||
69 | { | ||
70 | unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; | ||
71 | unsigned index = MAJOR(dev); | ||
72 | unsigned i; | ||
73 | struct probe *found = NULL; | ||
74 | |||
75 | if (n > 255) | ||
76 | n = 255; | ||
77 | |||
78 | down(domain->sem); | ||
79 | for (i = 0; i < n; i++, index++) { | ||
80 | struct probe **s; | ||
81 | for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { | ||
82 | struct probe *p = *s; | ||
83 | if (p->dev == dev && p->range == range) { | ||
84 | *s = p->next; | ||
85 | if (!found) | ||
86 | found = p; | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | up(domain->sem); | ||
92 | kfree(found); | ||
93 | } | ||
94 | |||
95 | struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) | ||
96 | { | ||
97 | struct kobject *kobj; | ||
98 | struct probe *p; | ||
99 | unsigned long best = ~0UL; | ||
100 | |||
101 | retry: | ||
102 | down(domain->sem); | ||
103 | for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { | ||
104 | struct kobject *(*probe)(dev_t, int *, void *); | ||
105 | struct module *owner; | ||
106 | void *data; | ||
107 | |||
108 | if (p->dev > dev || p->dev + p->range - 1 < dev) | ||
109 | continue; | ||
110 | if (p->range - 1 >= best) | ||
111 | break; | ||
112 | if (!try_module_get(p->owner)) | ||
113 | continue; | ||
114 | owner = p->owner; | ||
115 | data = p->data; | ||
116 | probe = p->get; | ||
117 | best = p->range - 1; | ||
118 | *index = dev - p->dev; | ||
119 | if (p->lock && p->lock(dev, data) < 0) { | ||
120 | module_put(owner); | ||
121 | continue; | ||
122 | } | ||
123 | up(domain->sem); | ||
124 | kobj = probe(dev, index, data); | ||
125 | /* Currently ->owner protects _only_ ->probe() itself. */ | ||
126 | module_put(owner); | ||
127 | if (kobj) | ||
128 | return kobj; | ||
129 | goto retry; | ||
130 | } | ||
131 | up(domain->sem); | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) | ||
136 | { | ||
137 | struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); | ||
138 | struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL); | ||
139 | int i; | ||
140 | |||
141 | if ((p == NULL) || (base == NULL)) { | ||
142 | kfree(p); | ||
143 | kfree(base); | ||
144 | return NULL; | ||
145 | } | ||
146 | |||
147 | memset(base, 0, sizeof(struct probe)); | ||
148 | base->dev = 1; | ||
149 | base->range = ~0; | ||
150 | base->get = base_probe; | ||
151 | for (i = 0; i < 255; i++) | ||
152 | p->probes[i] = base; | ||
153 | p->sem = sem; | ||
154 | return p; | ||
155 | } | ||
diff --git a/drivers/base/node.c b/drivers/base/node.c new file mode 100644 index 000000000000..583d57ec49a8 --- /dev/null +++ b/drivers/base/node.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * drivers/base/node.c - basic Node class support | ||
3 | */ | ||
4 | |||
5 | #include <linux/sysdev.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/mm.h> | ||
9 | #include <linux/node.h> | ||
10 | #include <linux/hugetlb.h> | ||
11 | #include <linux/cpumask.h> | ||
12 | #include <linux/topology.h> | ||
13 | #include <linux/nodemask.h> | ||
14 | |||
15 | static struct sysdev_class node_class = { | ||
16 | set_kset_name("node"), | ||
17 | }; | ||
18 | |||
19 | |||
20 | static ssize_t node_read_cpumap(struct sys_device * dev, char * buf) | ||
21 | { | ||
22 | struct node *node_dev = to_node(dev); | ||
23 | cpumask_t mask = node_to_cpumask(node_dev->sysdev.id); | ||
24 | int len; | ||
25 | |||
26 | /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */ | ||
27 | BUILD_BUG_ON(MAX_NUMNODES/4 > PAGE_SIZE/2); | ||
28 | |||
29 | len = cpumask_scnprintf(buf, PAGE_SIZE-1, mask); | ||
30 | len += sprintf(buf + len, "\n"); | ||
31 | return len; | ||
32 | } | ||
33 | |||
34 | static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL); | ||
35 | |||
36 | #define K(x) ((x) << (PAGE_SHIFT - 10)) | ||
37 | static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | ||
38 | { | ||
39 | int n; | ||
40 | int nid = dev->id; | ||
41 | struct sysinfo i; | ||
42 | unsigned long inactive; | ||
43 | unsigned long active; | ||
44 | unsigned long free; | ||
45 | |||
46 | si_meminfo_node(&i, nid); | ||
47 | __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); | ||
48 | |||
49 | n = sprintf(buf, "\n" | ||
50 | "Node %d MemTotal: %8lu kB\n" | ||
51 | "Node %d MemFree: %8lu kB\n" | ||
52 | "Node %d MemUsed: %8lu kB\n" | ||
53 | "Node %d Active: %8lu kB\n" | ||
54 | "Node %d Inactive: %8lu kB\n" | ||
55 | "Node %d HighTotal: %8lu kB\n" | ||
56 | "Node %d HighFree: %8lu kB\n" | ||
57 | "Node %d LowTotal: %8lu kB\n" | ||
58 | "Node %d LowFree: %8lu kB\n", | ||
59 | nid, K(i.totalram), | ||
60 | nid, K(i.freeram), | ||
61 | nid, K(i.totalram - i.freeram), | ||
62 | nid, K(active), | ||
63 | nid, K(inactive), | ||
64 | nid, K(i.totalhigh), | ||
65 | nid, K(i.freehigh), | ||
66 | nid, K(i.totalram - i.totalhigh), | ||
67 | nid, K(i.freeram - i.freehigh)); | ||
68 | n += hugetlb_report_node_meminfo(nid, buf + n); | ||
69 | return n; | ||
70 | } | ||
71 | |||
72 | #undef K | ||
73 | static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); | ||
74 | |||
75 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | ||
76 | { | ||
77 | unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign; | ||
78 | unsigned long local_node, other_node; | ||
79 | int i, cpu; | ||
80 | pg_data_t *pg = NODE_DATA(dev->id); | ||
81 | numa_hit = 0; | ||
82 | numa_miss = 0; | ||
83 | interleave_hit = 0; | ||
84 | numa_foreign = 0; | ||
85 | local_node = 0; | ||
86 | other_node = 0; | ||
87 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
88 | struct zone *z = &pg->node_zones[i]; | ||
89 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
90 | struct per_cpu_pageset *ps = &z->pageset[cpu]; | ||
91 | numa_hit += ps->numa_hit; | ||
92 | numa_miss += ps->numa_miss; | ||
93 | numa_foreign += ps->numa_foreign; | ||
94 | interleave_hit += ps->interleave_hit; | ||
95 | local_node += ps->local_node; | ||
96 | other_node += ps->other_node; | ||
97 | } | ||
98 | } | ||
99 | return sprintf(buf, | ||
100 | "numa_hit %lu\n" | ||
101 | "numa_miss %lu\n" | ||
102 | "numa_foreign %lu\n" | ||
103 | "interleave_hit %lu\n" | ||
104 | "local_node %lu\n" | ||
105 | "other_node %lu\n", | ||
106 | numa_hit, | ||
107 | numa_miss, | ||
108 | numa_foreign, | ||
109 | interleave_hit, | ||
110 | local_node, | ||
111 | other_node); | ||
112 | } | ||
113 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | ||
114 | |||
115 | static ssize_t node_read_distance(struct sys_device * dev, char * buf) | ||
116 | { | ||
117 | int nid = dev->id; | ||
118 | int len = 0; | ||
119 | int i; | ||
120 | |||
121 | /* buf currently PAGE_SIZE, need ~4 chars per node */ | ||
122 | BUILD_BUG_ON(MAX_NUMNODES*4 > PAGE_SIZE/2); | ||
123 | |||
124 | for_each_online_node(i) | ||
125 | len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i)); | ||
126 | |||
127 | len += sprintf(buf + len, "\n"); | ||
128 | return len; | ||
129 | } | ||
130 | static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); | ||
131 | |||
132 | |||
133 | /* | ||
134 | * register_node - Setup a driverfs device for a node. | ||
135 | * @num - Node number to use when creating the device. | ||
136 | * | ||
137 | * Initialize and register the node device. | ||
138 | */ | ||
139 | int __init register_node(struct node *node, int num, struct node *parent) | ||
140 | { | ||
141 | int error; | ||
142 | |||
143 | node->sysdev.id = num; | ||
144 | node->sysdev.cls = &node_class; | ||
145 | error = sysdev_register(&node->sysdev); | ||
146 | |||
147 | if (!error){ | ||
148 | sysdev_create_file(&node->sysdev, &attr_cpumap); | ||
149 | sysdev_create_file(&node->sysdev, &attr_meminfo); | ||
150 | sysdev_create_file(&node->sysdev, &attr_numastat); | ||
151 | sysdev_create_file(&node->sysdev, &attr_distance); | ||
152 | } | ||
153 | return error; | ||
154 | } | ||
155 | |||
156 | |||
157 | int __init register_node_type(void) | ||
158 | { | ||
159 | return sysdev_class_register(&node_class); | ||
160 | } | ||
161 | postcore_initcall(register_node_type); | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c new file mode 100644 index 000000000000..996cbb4d5087 --- /dev/null +++ b/drivers/base/platform.c | |||
@@ -0,0 +1,350 @@ | |||
1 | /* | ||
2 | * platform.c - platform 'pseudo' bus for legacy devices | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * Copyright (c) 2002-3 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | * Please see Documentation/driver-model/platform.txt for more | ||
10 | * information. | ||
11 | */ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/bootmem.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | struct device platform_bus = { | ||
21 | .bus_id = "platform", | ||
22 | }; | ||
23 | |||
24 | /** | ||
25 | * platform_get_resource - get a resource for a device | ||
26 | * @dev: platform device | ||
27 | * @type: resource type | ||
28 | * @num: resource index | ||
29 | */ | ||
30 | struct resource * | ||
31 | platform_get_resource(struct platform_device *dev, unsigned int type, | ||
32 | unsigned int num) | ||
33 | { | ||
34 | int i; | ||
35 | |||
36 | for (i = 0; i < dev->num_resources; i++) { | ||
37 | struct resource *r = &dev->resource[i]; | ||
38 | |||
39 | if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| | ||
40 | IORESOURCE_IRQ|IORESOURCE_DMA)) | ||
41 | == type) | ||
42 | if (num-- == 0) | ||
43 | return r; | ||
44 | } | ||
45 | return NULL; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * platform_get_irq - get an IRQ for a device | ||
50 | * @dev: platform device | ||
51 | * @num: IRQ number index | ||
52 | */ | ||
53 | int platform_get_irq(struct platform_device *dev, unsigned int num) | ||
54 | { | ||
55 | struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); | ||
56 | |||
57 | return r ? r->start : 0; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * platform_get_resource_byname - get a resource for a device by name | ||
62 | * @dev: platform device | ||
63 | * @type: resource type | ||
64 | * @name: resource name | ||
65 | */ | ||
66 | struct resource * | ||
67 | platform_get_resource_byname(struct platform_device *dev, unsigned int type, | ||
68 | char *name) | ||
69 | { | ||
70 | int i; | ||
71 | |||
72 | for (i = 0; i < dev->num_resources; i++) { | ||
73 | struct resource *r = &dev->resource[i]; | ||
74 | |||
75 | if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| | ||
76 | IORESOURCE_IRQ|IORESOURCE_DMA)) == type) | ||
77 | if (!strcmp(r->name, name)) | ||
78 | return r; | ||
79 | } | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * platform_get_irq - get an IRQ for a device | ||
85 | * @dev: platform device | ||
86 | * @name: IRQ name | ||
87 | */ | ||
88 | int platform_get_irq_byname(struct platform_device *dev, char *name) | ||
89 | { | ||
90 | struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); | ||
91 | |||
92 | return r ? r->start : 0; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * platform_add_devices - add a numbers of platform devices | ||
97 | * @devs: array of platform devices to add | ||
98 | * @num: number of platform devices in array | ||
99 | */ | ||
100 | int platform_add_devices(struct platform_device **devs, int num) | ||
101 | { | ||
102 | int i, ret = 0; | ||
103 | |||
104 | for (i = 0; i < num; i++) { | ||
105 | ret = platform_device_register(devs[i]); | ||
106 | if (ret) { | ||
107 | while (--i >= 0) | ||
108 | platform_device_unregister(devs[i]); | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * platform_device_register - add a platform-level device | ||
118 | * @dev: platform device we're adding | ||
119 | * | ||
120 | */ | ||
121 | int platform_device_register(struct platform_device * pdev) | ||
122 | { | ||
123 | int i, ret = 0; | ||
124 | |||
125 | if (!pdev) | ||
126 | return -EINVAL; | ||
127 | |||
128 | if (!pdev->dev.parent) | ||
129 | pdev->dev.parent = &platform_bus; | ||
130 | |||
131 | pdev->dev.bus = &platform_bus_type; | ||
132 | |||
133 | if (pdev->id != -1) | ||
134 | snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id); | ||
135 | else | ||
136 | strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); | ||
137 | |||
138 | for (i = 0; i < pdev->num_resources; i++) { | ||
139 | struct resource *p, *r = &pdev->resource[i]; | ||
140 | |||
141 | if (r->name == NULL) | ||
142 | r->name = pdev->dev.bus_id; | ||
143 | |||
144 | p = r->parent; | ||
145 | if (!p) { | ||
146 | if (r->flags & IORESOURCE_MEM) | ||
147 | p = &iomem_resource; | ||
148 | else if (r->flags & IORESOURCE_IO) | ||
149 | p = &ioport_resource; | ||
150 | } | ||
151 | |||
152 | if (p && request_resource(p, r)) { | ||
153 | printk(KERN_ERR | ||
154 | "%s: failed to claim resource %d\n", | ||
155 | pdev->dev.bus_id, i); | ||
156 | ret = -EBUSY; | ||
157 | goto failed; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | pr_debug("Registering platform device '%s'. Parent at %s\n", | ||
162 | pdev->dev.bus_id, pdev->dev.parent->bus_id); | ||
163 | |||
164 | ret = device_register(&pdev->dev); | ||
165 | if (ret == 0) | ||
166 | return ret; | ||
167 | |||
168 | failed: | ||
169 | while (--i >= 0) | ||
170 | if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO)) | ||
171 | release_resource(&pdev->resource[i]); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * platform_device_unregister - remove a platform-level device | ||
177 | * @dev: platform device we're removing | ||
178 | * | ||
179 | * Note that this function will also release all memory- and port-based | ||
180 | * resources owned by the device (@dev->resource). | ||
181 | */ | ||
182 | void platform_device_unregister(struct platform_device * pdev) | ||
183 | { | ||
184 | int i; | ||
185 | |||
186 | if (pdev) { | ||
187 | for (i = 0; i < pdev->num_resources; i++) { | ||
188 | struct resource *r = &pdev->resource[i]; | ||
189 | if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) | ||
190 | release_resource(r); | ||
191 | } | ||
192 | |||
193 | device_unregister(&pdev->dev); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | struct platform_object { | ||
198 | struct platform_device pdev; | ||
199 | struct resource resources[0]; | ||
200 | }; | ||
201 | |||
202 | static void platform_device_release_simple(struct device *dev) | ||
203 | { | ||
204 | struct platform_device *pdev = to_platform_device(dev); | ||
205 | |||
206 | kfree(container_of(pdev, struct platform_object, pdev)); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * platform_device_register_simple | ||
211 | * @name: base name of the device we're adding | ||
212 | * @id: instance id | ||
213 | * @res: set of resources that needs to be allocated for the device | ||
214 | * @num: number of resources | ||
215 | * | ||
216 | * This function creates a simple platform device that requires minimal | ||
217 | * resource and memory management. Canned release function freeing | ||
218 | * memory allocated for the device allows drivers using such devices | ||
219 | * to be unloaded iwithout waiting for the last reference to the device | ||
220 | * to be dropped. | ||
221 | */ | ||
222 | struct platform_device *platform_device_register_simple(char *name, unsigned int id, | ||
223 | struct resource *res, unsigned int num) | ||
224 | { | ||
225 | struct platform_object *pobj; | ||
226 | int retval; | ||
227 | |||
228 | pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL); | ||
229 | if (!pobj) { | ||
230 | retval = -ENOMEM; | ||
231 | goto error; | ||
232 | } | ||
233 | |||
234 | memset(pobj, 0, sizeof(*pobj)); | ||
235 | pobj->pdev.name = name; | ||
236 | pobj->pdev.id = id; | ||
237 | pobj->pdev.dev.release = platform_device_release_simple; | ||
238 | |||
239 | if (num) { | ||
240 | memcpy(pobj->resources, res, sizeof(struct resource) * num); | ||
241 | pobj->pdev.resource = pobj->resources; | ||
242 | pobj->pdev.num_resources = num; | ||
243 | } | ||
244 | |||
245 | retval = platform_device_register(&pobj->pdev); | ||
246 | if (retval) | ||
247 | goto error; | ||
248 | |||
249 | return &pobj->pdev; | ||
250 | |||
251 | error: | ||
252 | kfree(pobj); | ||
253 | return ERR_PTR(retval); | ||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * platform_match - bind platform device to platform driver. | ||
259 | * @dev: device. | ||
260 | * @drv: driver. | ||
261 | * | ||
262 | * Platform device IDs are assumed to be encoded like this: | ||
263 | * "<name><instance>", where <name> is a short description of the | ||
264 | * type of device, like "pci" or "floppy", and <instance> is the | ||
265 | * enumerated instance of the device, like '0' or '42'. | ||
266 | * Driver IDs are simply "<name>". | ||
267 | * So, extract the <name> from the platform_device structure, | ||
268 | * and compare it against the name of the driver. Return whether | ||
269 | * they match or not. | ||
270 | */ | ||
271 | |||
272 | static int platform_match(struct device * dev, struct device_driver * drv) | ||
273 | { | ||
274 | struct platform_device *pdev = container_of(dev, struct platform_device, dev); | ||
275 | |||
276 | return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); | ||
277 | } | ||
278 | |||
279 | static int platform_suspend(struct device * dev, pm_message_t state) | ||
280 | { | ||
281 | int ret = 0; | ||
282 | |||
283 | if (dev->driver && dev->driver->suspend) { | ||
284 | ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE); | ||
285 | if (ret == 0) | ||
286 | ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE); | ||
287 | if (ret == 0) | ||
288 | ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN); | ||
289 | } | ||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static int platform_resume(struct device * dev) | ||
294 | { | ||
295 | int ret = 0; | ||
296 | |||
297 | if (dev->driver && dev->driver->resume) { | ||
298 | ret = dev->driver->resume(dev, RESUME_POWER_ON); | ||
299 | if (ret == 0) | ||
300 | ret = dev->driver->resume(dev, RESUME_RESTORE_STATE); | ||
301 | if (ret == 0) | ||
302 | ret = dev->driver->resume(dev, RESUME_ENABLE); | ||
303 | } | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | struct bus_type platform_bus_type = { | ||
308 | .name = "platform", | ||
309 | .match = platform_match, | ||
310 | .suspend = platform_suspend, | ||
311 | .resume = platform_resume, | ||
312 | }; | ||
313 | |||
314 | int __init platform_bus_init(void) | ||
315 | { | ||
316 | device_register(&platform_bus); | ||
317 | return bus_register(&platform_bus_type); | ||
318 | } | ||
319 | |||
320 | #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK | ||
321 | u64 dma_get_required_mask(struct device *dev) | ||
322 | { | ||
323 | u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT); | ||
324 | u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT)); | ||
325 | u64 mask; | ||
326 | |||
327 | if (!high_totalram) { | ||
328 | /* convert to mask just covering totalram */ | ||
329 | low_totalram = (1 << (fls(low_totalram) - 1)); | ||
330 | low_totalram += low_totalram - 1; | ||
331 | mask = low_totalram; | ||
332 | } else { | ||
333 | high_totalram = (1 << (fls(high_totalram) - 1)); | ||
334 | high_totalram += high_totalram - 1; | ||
335 | mask = (((u64)high_totalram) << 32) + 0xffffffff; | ||
336 | } | ||
337 | return mask & *dev->dma_mask; | ||
338 | } | ||
339 | EXPORT_SYMBOL_GPL(dma_get_required_mask); | ||
340 | #endif | ||
341 | |||
342 | EXPORT_SYMBOL_GPL(platform_bus); | ||
343 | EXPORT_SYMBOL_GPL(platform_bus_type); | ||
344 | EXPORT_SYMBOL_GPL(platform_device_register); | ||
345 | EXPORT_SYMBOL_GPL(platform_device_register_simple); | ||
346 | EXPORT_SYMBOL_GPL(platform_device_unregister); | ||
347 | EXPORT_SYMBOL_GPL(platform_get_irq); | ||
348 | EXPORT_SYMBOL_GPL(platform_get_resource); | ||
349 | EXPORT_SYMBOL_GPL(platform_get_irq_byname); | ||
350 | EXPORT_SYMBOL_GPL(platform_get_resource_byname); | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile new file mode 100644 index 000000000000..c0219ad94aca --- /dev/null +++ b/drivers/base/power/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | obj-y := shutdown.o | ||
2 | obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o | ||
3 | |||
4 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | ||
5 | EXTRA_CFLAGS += -DDEBUG | ||
6 | endif | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c new file mode 100644 index 000000000000..15e6a8f951f1 --- /dev/null +++ b/drivers/base/power/main.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * drivers/base/power/main.c - Where the driver meets power management. | ||
3 | * | ||
4 | * Copyright (c) 2003 Patrick Mochel | ||
5 | * Copyright (c) 2003 Open Source Development Lab | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | * | ||
10 | * The driver model core calls device_pm_add() when a device is registered. | ||
11 | * This will intialize the embedded device_pm_info object in the device | ||
12 | * and add it to the list of power-controlled devices. sysfs entries for | ||
13 | * controlling device power management will also be added. | ||
14 | * | ||
15 | * A different set of lists than the global subsystem list are used to | ||
16 | * keep track of power info because we use different lists to hold | ||
17 | * devices based on what stage of the power management process they | ||
18 | * are in. The power domain dependencies may also differ from the | ||
19 | * ancestral dependencies that the subsystem list maintains. | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/device.h> | ||
24 | #include "power.h" | ||
25 | |||
26 | LIST_HEAD(dpm_active); | ||
27 | LIST_HEAD(dpm_off); | ||
28 | LIST_HEAD(dpm_off_irq); | ||
29 | |||
30 | DECLARE_MUTEX(dpm_sem); | ||
31 | DECLARE_MUTEX(dpm_list_sem); | ||
32 | |||
33 | /* | ||
34 | * PM Reference Counting. | ||
35 | */ | ||
36 | |||
37 | static inline void device_pm_hold(struct device * dev) | ||
38 | { | ||
39 | if (dev) | ||
40 | atomic_inc(&dev->power.pm_users); | ||
41 | } | ||
42 | |||
43 | static inline void device_pm_release(struct device * dev) | ||
44 | { | ||
45 | if (dev) | ||
46 | atomic_dec(&dev->power.pm_users); | ||
47 | } | ||
48 | |||
49 | |||
50 | /** | ||
51 | * device_pm_set_parent - Specify power dependency. | ||
52 | * @dev: Device who needs power. | ||
53 | * @parent: Device that supplies power. | ||
54 | * | ||
55 | * This function is used to manually describe a power-dependency | ||
56 | * relationship. It may be used to specify a transversal relationship | ||
57 | * (where the power supplier is not the physical (or electrical) | ||
58 | * ancestor of a specific device. | ||
59 | * The effect of this is that the supplier will not be powered down | ||
60 | * before the power dependent. | ||
61 | */ | ||
62 | |||
63 | void device_pm_set_parent(struct device * dev, struct device * parent) | ||
64 | { | ||
65 | struct device * old_parent = dev->power.pm_parent; | ||
66 | device_pm_release(old_parent); | ||
67 | dev->power.pm_parent = parent; | ||
68 | device_pm_hold(parent); | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(device_pm_set_parent); | ||
71 | |||
72 | int device_pm_add(struct device * dev) | ||
73 | { | ||
74 | int error; | ||
75 | |||
76 | pr_debug("PM: Adding info for %s:%s\n", | ||
77 | dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); | ||
78 | atomic_set(&dev->power.pm_users, 0); | ||
79 | down(&dpm_list_sem); | ||
80 | list_add_tail(&dev->power.entry, &dpm_active); | ||
81 | device_pm_set_parent(dev, dev->parent); | ||
82 | if ((error = dpm_sysfs_add(dev))) | ||
83 | list_del(&dev->power.entry); | ||
84 | up(&dpm_list_sem); | ||
85 | return error; | ||
86 | } | ||
87 | |||
88 | void device_pm_remove(struct device * dev) | ||
89 | { | ||
90 | pr_debug("PM: Removing info for %s:%s\n", | ||
91 | dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); | ||
92 | down(&dpm_list_sem); | ||
93 | dpm_sysfs_remove(dev); | ||
94 | device_pm_release(dev->power.pm_parent); | ||
95 | list_del_init(&dev->power.entry); | ||
96 | up(&dpm_list_sem); | ||
97 | } | ||
98 | |||
99 | |||
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h new file mode 100644 index 000000000000..e5eda746f2a6 --- /dev/null +++ b/drivers/base/power/power.h | |||
@@ -0,0 +1,106 @@ | |||
1 | |||
2 | |||
3 | enum { | ||
4 | DEVICE_PM_ON, | ||
5 | DEVICE_PM1, | ||
6 | DEVICE_PM2, | ||
7 | DEVICE_PM3, | ||
8 | DEVICE_PM_OFF, | ||
9 | }; | ||
10 | |||
11 | /* | ||
12 | * shutdown.c | ||
13 | */ | ||
14 | |||
15 | extern int device_detach_shutdown(struct device *); | ||
16 | extern void device_shutdown(void); | ||
17 | |||
18 | |||
19 | #ifdef CONFIG_PM | ||
20 | |||
21 | /* | ||
22 | * main.c | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Used to synchronize global power management operations. | ||
27 | */ | ||
28 | extern struct semaphore dpm_sem; | ||
29 | |||
30 | /* | ||
31 | * Used to serialize changes to the dpm_* lists. | ||
32 | */ | ||
33 | extern struct semaphore dpm_list_sem; | ||
34 | |||
35 | /* | ||
36 | * The PM lists. | ||
37 | */ | ||
38 | extern struct list_head dpm_active; | ||
39 | extern struct list_head dpm_off; | ||
40 | extern struct list_head dpm_off_irq; | ||
41 | |||
42 | |||
43 | static inline struct dev_pm_info * to_pm_info(struct list_head * entry) | ||
44 | { | ||
45 | return container_of(entry, struct dev_pm_info, entry); | ||
46 | } | ||
47 | |||
48 | static inline struct device * to_device(struct list_head * entry) | ||
49 | { | ||
50 | return container_of(to_pm_info(entry), struct device, power); | ||
51 | } | ||
52 | |||
53 | extern int device_pm_add(struct device *); | ||
54 | extern void device_pm_remove(struct device *); | ||
55 | |||
56 | /* | ||
57 | * sysfs.c | ||
58 | */ | ||
59 | |||
60 | extern int dpm_sysfs_add(struct device *); | ||
61 | extern void dpm_sysfs_remove(struct device *); | ||
62 | |||
63 | /* | ||
64 | * resume.c | ||
65 | */ | ||
66 | |||
67 | extern void dpm_resume(void); | ||
68 | extern void dpm_power_up(void); | ||
69 | extern int resume_device(struct device *); | ||
70 | |||
71 | /* | ||
72 | * suspend.c | ||
73 | */ | ||
74 | extern int suspend_device(struct device *, pm_message_t); | ||
75 | |||
76 | |||
77 | /* | ||
78 | * runtime.c | ||
79 | */ | ||
80 | |||
81 | extern int dpm_runtime_suspend(struct device *, pm_message_t); | ||
82 | extern void dpm_runtime_resume(struct device *); | ||
83 | |||
84 | #else /* CONFIG_PM */ | ||
85 | |||
86 | |||
87 | static inline int device_pm_add(struct device * dev) | ||
88 | { | ||
89 | return 0; | ||
90 | } | ||
91 | static inline void device_pm_remove(struct device * dev) | ||
92 | { | ||
93 | |||
94 | } | ||
95 | |||
96 | static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static inline void dpm_runtime_resume(struct device * dev) | ||
102 | { | ||
103 | |||
104 | } | ||
105 | |||
106 | #endif | ||
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c new file mode 100644 index 000000000000..f8f5055754d6 --- /dev/null +++ b/drivers/base/power/resume.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * resume.c - Functions for waking devices up. | ||
3 | * | ||
4 | * Copyright (c) 2003 Patrick Mochel | ||
5 | * Copyright (c) 2003 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/device.h> | ||
12 | #include "power.h" | ||
13 | |||
14 | extern int sysdev_resume(void); | ||
15 | |||
16 | |||
17 | /** | ||
18 | * resume_device - Restore state for one device. | ||
19 | * @dev: Device. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | int resume_device(struct device * dev) | ||
24 | { | ||
25 | if (dev->bus && dev->bus->resume) | ||
26 | return dev->bus->resume(dev); | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | |||
31 | |||
32 | void dpm_resume(void) | ||
33 | { | ||
34 | down(&dpm_list_sem); | ||
35 | while(!list_empty(&dpm_off)) { | ||
36 | struct list_head * entry = dpm_off.next; | ||
37 | struct device * dev = to_device(entry); | ||
38 | |||
39 | get_device(dev); | ||
40 | list_del_init(entry); | ||
41 | list_add_tail(entry, &dpm_active); | ||
42 | |||
43 | up(&dpm_list_sem); | ||
44 | if (!dev->power.prev_state) | ||
45 | resume_device(dev); | ||
46 | down(&dpm_list_sem); | ||
47 | put_device(dev); | ||
48 | } | ||
49 | up(&dpm_list_sem); | ||
50 | } | ||
51 | |||
52 | |||
53 | /** | ||
54 | * device_resume - Restore state of each device in system. | ||
55 | * | ||
56 | * Walk the dpm_off list, remove each entry, resume the device, | ||
57 | * then add it to the dpm_active list. | ||
58 | */ | ||
59 | |||
60 | void device_resume(void) | ||
61 | { | ||
62 | down(&dpm_sem); | ||
63 | dpm_resume(); | ||
64 | up(&dpm_sem); | ||
65 | } | ||
66 | |||
67 | EXPORT_SYMBOL_GPL(device_resume); | ||
68 | |||
69 | |||
70 | /** | ||
71 | * device_power_up_irq - Power on some devices. | ||
72 | * | ||
73 | * Walk the dpm_off_irq list and power each device up. This | ||
74 | * is used for devices that required they be powered down with | ||
75 | * interrupts disabled. As devices are powered on, they are moved to | ||
76 | * the dpm_suspended list. | ||
77 | * | ||
78 | * Interrupts must be disabled when calling this. | ||
79 | */ | ||
80 | |||
81 | void dpm_power_up(void) | ||
82 | { | ||
83 | while(!list_empty(&dpm_off_irq)) { | ||
84 | struct list_head * entry = dpm_off_irq.next; | ||
85 | struct device * dev = to_device(entry); | ||
86 | |||
87 | get_device(dev); | ||
88 | list_del_init(entry); | ||
89 | list_add_tail(entry, &dpm_active); | ||
90 | resume_device(dev); | ||
91 | put_device(dev); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * device_pm_power_up - Turn on all devices that need special attention. | ||
98 | * | ||
99 | * Power on system devices then devices that required we shut them down | ||
100 | * with interrupts disabled. | ||
101 | * Called with interrupts disabled. | ||
102 | */ | ||
103 | |||
104 | void device_power_up(void) | ||
105 | { | ||
106 | sysdev_resume(); | ||
107 | dpm_power_up(); | ||
108 | } | ||
109 | |||
110 | EXPORT_SYMBOL_GPL(device_power_up); | ||
111 | |||
112 | |||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c new file mode 100644 index 000000000000..325962d80191 --- /dev/null +++ b/drivers/base/power/runtime.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * drivers/base/power/runtime.c - Handling dynamic device power management. | ||
3 | * | ||
4 | * Copyright (c) 2003 Patrick Mochel | ||
5 | * Copyright (c) 2003 Open Source Development Lab | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include "power.h" | ||
11 | |||
12 | |||
13 | static void runtime_resume(struct device * dev) | ||
14 | { | ||
15 | dev_dbg(dev, "resuming\n"); | ||
16 | if (!dev->power.power_state) | ||
17 | return; | ||
18 | if (!resume_device(dev)) | ||
19 | dev->power.power_state = 0; | ||
20 | } | ||
21 | |||
22 | |||
23 | /** | ||
24 | * dpm_runtime_resume - Power one device back on. | ||
25 | * @dev: Device. | ||
26 | * | ||
27 | * Bring one device back to the on state by first powering it | ||
28 | * on, then restoring state. We only operate on devices that aren't | ||
29 | * already on. | ||
30 | * FIXME: We need to handle devices that are in an unknown state. | ||
31 | */ | ||
32 | |||
33 | void dpm_runtime_resume(struct device * dev) | ||
34 | { | ||
35 | down(&dpm_sem); | ||
36 | runtime_resume(dev); | ||
37 | up(&dpm_sem); | ||
38 | } | ||
39 | |||
40 | |||
41 | /** | ||
42 | * dpm_runtime_suspend - Put one device in low-power state. | ||
43 | * @dev: Device. | ||
44 | * @state: State to enter. | ||
45 | */ | ||
46 | |||
47 | int dpm_runtime_suspend(struct device * dev, pm_message_t state) | ||
48 | { | ||
49 | int error = 0; | ||
50 | |||
51 | down(&dpm_sem); | ||
52 | if (dev->power.power_state == state) | ||
53 | goto Done; | ||
54 | |||
55 | if (dev->power.power_state) | ||
56 | runtime_resume(dev); | ||
57 | |||
58 | if (!(error = suspend_device(dev, state))) | ||
59 | dev->power.power_state = state; | ||
60 | Done: | ||
61 | up(&dpm_sem); | ||
62 | return error; | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * dpm_set_power_state - Update power_state field. | ||
68 | * @dev: Device. | ||
69 | * @state: Power state device is in. | ||
70 | * | ||
71 | * This is an update mechanism for drivers to notify the core | ||
72 | * what power state a device is in. Device probing code may not | ||
73 | * always be able to tell, but we need accurate information to | ||
74 | * work reliably. | ||
75 | */ | ||
76 | void dpm_set_power_state(struct device * dev, pm_message_t state) | ||
77 | { | ||
78 | down(&dpm_sem); | ||
79 | dev->power.power_state = state; | ||
80 | up(&dpm_sem); | ||
81 | } | ||
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c new file mode 100644 index 000000000000..d1e023fbe169 --- /dev/null +++ b/drivers/base/power/shutdown.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * shutdown.c - power management functions for the device tree. | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * 2002-3 Open Source Development Lab | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <asm/semaphore.h> | ||
14 | |||
15 | #include "power.h" | ||
16 | |||
17 | #define to_dev(node) container_of(node, struct device, kobj.entry) | ||
18 | |||
19 | extern struct subsystem devices_subsys; | ||
20 | |||
21 | |||
22 | int device_detach_shutdown(struct device * dev) | ||
23 | { | ||
24 | if (!dev->detach_state) | ||
25 | return 0; | ||
26 | |||
27 | if (dev->detach_state == DEVICE_PM_OFF) { | ||
28 | if (dev->driver && dev->driver->shutdown) | ||
29 | dev->driver->shutdown(dev); | ||
30 | return 0; | ||
31 | } | ||
32 | return dpm_runtime_suspend(dev, dev->detach_state); | ||
33 | } | ||
34 | |||
35 | |||
36 | /** | ||
37 | * We handle system devices differently - we suspend and shut them | ||
38 | * down last and resume them first. That way, we don't do anything stupid like | ||
39 | * shutting down the interrupt controller before any devices.. | ||
40 | * | ||
41 | * Note that there are not different stages for power management calls - | ||
42 | * they only get one called once when interrupts are disabled. | ||
43 | */ | ||
44 | |||
45 | extern int sysdev_shutdown(void); | ||
46 | |||
47 | /** | ||
48 | * device_shutdown - call ->shutdown() on each device to shutdown. | ||
49 | */ | ||
50 | void device_shutdown(void) | ||
51 | { | ||
52 | struct device * dev; | ||
53 | |||
54 | down_write(&devices_subsys.rwsem); | ||
55 | list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) { | ||
56 | pr_debug("shutting down %s: ", dev->bus_id); | ||
57 | if (dev->driver && dev->driver->shutdown) { | ||
58 | pr_debug("Ok\n"); | ||
59 | dev->driver->shutdown(dev); | ||
60 | } else | ||
61 | pr_debug("Ignored.\n"); | ||
62 | } | ||
63 | up_write(&devices_subsys.rwsem); | ||
64 | |||
65 | sysdev_shutdown(); | ||
66 | } | ||
67 | |||
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c new file mode 100644 index 000000000000..a0b5cf689e63 --- /dev/null +++ b/drivers/base/power/suspend.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * suspend.c - Functions for putting devices to sleep. | ||
3 | * | ||
4 | * Copyright (c) 2003 Patrick Mochel | ||
5 | * Copyright (c) 2003 Open Source Development Labs | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/device.h> | ||
12 | #include "power.h" | ||
13 | |||
14 | extern int sysdev_suspend(pm_message_t state); | ||
15 | |||
16 | /* | ||
17 | * The entries in the dpm_active list are in a depth first order, simply | ||
18 | * because children are guaranteed to be discovered after parents, and | ||
19 | * are inserted at the back of the list on discovery. | ||
20 | * | ||
21 | * All list on the suspend path are done in reverse order, so we operate | ||
22 | * on the leaves of the device tree (or forests, depending on how you want | ||
23 | * to look at it ;) first. As nodes are removed from the back of the list, | ||
24 | * they are inserted into the front of their destintation lists. | ||
25 | * | ||
26 | * Things are the reverse on the resume path - iterations are done in | ||
27 | * forward order, and nodes are inserted at the back of their destination | ||
28 | * lists. This way, the ancestors will be accessed before their descendents. | ||
29 | */ | ||
30 | |||
31 | |||
32 | /** | ||
33 | * suspend_device - Save state of one device. | ||
34 | * @dev: Device. | ||
35 | * @state: Power state device is entering. | ||
36 | */ | ||
37 | |||
38 | int suspend_device(struct device * dev, pm_message_t state) | ||
39 | { | ||
40 | int error = 0; | ||
41 | |||
42 | dev_dbg(dev, "suspending\n"); | ||
43 | |||
44 | dev->power.prev_state = dev->power.power_state; | ||
45 | |||
46 | if (dev->bus && dev->bus->suspend && !dev->power.power_state) | ||
47 | error = dev->bus->suspend(dev, state); | ||
48 | |||
49 | return error; | ||
50 | } | ||
51 | |||
52 | |||
53 | /** | ||
54 | * device_suspend - Save state and stop all devices in system. | ||
55 | * @state: Power state to put each device in. | ||
56 | * | ||
57 | * Walk the dpm_active list, call ->suspend() for each device, and move | ||
58 | * it to dpm_off. | ||
59 | * Check the return value for each. If it returns 0, then we move the | ||
60 | * the device to the dpm_off list. If it returns -EAGAIN, we move it to | ||
61 | * the dpm_off_irq list. If we get a different error, try and back out. | ||
62 | * | ||
63 | * If we hit a failure with any of the devices, call device_resume() | ||
64 | * above to bring the suspended devices back to life. | ||
65 | * | ||
66 | */ | ||
67 | |||
68 | int device_suspend(pm_message_t state) | ||
69 | { | ||
70 | int error = 0; | ||
71 | |||
72 | down(&dpm_sem); | ||
73 | down(&dpm_list_sem); | ||
74 | while (!list_empty(&dpm_active) && error == 0) { | ||
75 | struct list_head * entry = dpm_active.prev; | ||
76 | struct device * dev = to_device(entry); | ||
77 | |||
78 | get_device(dev); | ||
79 | up(&dpm_list_sem); | ||
80 | |||
81 | error = suspend_device(dev, state); | ||
82 | |||
83 | down(&dpm_list_sem); | ||
84 | |||
85 | /* Check if the device got removed */ | ||
86 | if (!list_empty(&dev->power.entry)) { | ||
87 | /* Move it to the dpm_off or dpm_off_irq list */ | ||
88 | if (!error) { | ||
89 | list_del(&dev->power.entry); | ||
90 | list_add(&dev->power.entry, &dpm_off); | ||
91 | } else if (error == -EAGAIN) { | ||
92 | list_del(&dev->power.entry); | ||
93 | list_add(&dev->power.entry, &dpm_off_irq); | ||
94 | error = 0; | ||
95 | } | ||
96 | } | ||
97 | if (error) | ||
98 | printk(KERN_ERR "Could not suspend device %s: " | ||
99 | "error %d\n", kobject_name(&dev->kobj), error); | ||
100 | put_device(dev); | ||
101 | } | ||
102 | up(&dpm_list_sem); | ||
103 | if (error) | ||
104 | dpm_resume(); | ||
105 | up(&dpm_sem); | ||
106 | return error; | ||
107 | } | ||
108 | |||
109 | EXPORT_SYMBOL_GPL(device_suspend); | ||
110 | |||
111 | |||
112 | /** | ||
113 | * device_power_down - Shut down special devices. | ||
114 | * @state: Power state to enter. | ||
115 | * | ||
116 | * Walk the dpm_off_irq list, calling ->power_down() for each device that | ||
117 | * couldn't power down the device with interrupts enabled. When we're | ||
118 | * done, power down system devices. | ||
119 | */ | ||
120 | |||
121 | int device_power_down(pm_message_t state) | ||
122 | { | ||
123 | int error = 0; | ||
124 | struct device * dev; | ||
125 | |||
126 | list_for_each_entry_reverse(dev, &dpm_off_irq, power.entry) { | ||
127 | if ((error = suspend_device(dev, state))) | ||
128 | break; | ||
129 | } | ||
130 | if (error) | ||
131 | goto Error; | ||
132 | if ((error = sysdev_suspend(state))) | ||
133 | goto Error; | ||
134 | Done: | ||
135 | return error; | ||
136 | Error: | ||
137 | printk(KERN_ERR "Could not power down device %s: " | ||
138 | "error %d\n", kobject_name(&dev->kobj), error); | ||
139 | dpm_power_up(); | ||
140 | goto Done; | ||
141 | } | ||
142 | |||
143 | EXPORT_SYMBOL_GPL(device_power_down); | ||
144 | |||
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c new file mode 100644 index 000000000000..6ac96349a8e8 --- /dev/null +++ b/drivers/base/power/sysfs.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * drivers/base/power/sysfs.c - sysfs entries for device PM | ||
3 | */ | ||
4 | |||
5 | #include <linux/device.h> | ||
6 | #include "power.h" | ||
7 | |||
8 | |||
9 | /** | ||
10 | * state - Control current power state of device | ||
11 | * | ||
12 | * show() returns the current power state of the device. '0' indicates | ||
13 | * the device is on. Other values (1-3) indicate the device is in a low | ||
14 | * power state. | ||
15 | * | ||
16 | * store() sets the current power state, which is an integer value | ||
17 | * between 0-3. If the device is on ('0'), and the value written is | ||
18 | * greater than 0, then the device is placed directly into the low-power | ||
19 | * state (via its driver's ->suspend() method). | ||
20 | * If the device is currently in a low-power state, and the value is 0, | ||
21 | * the device is powered back on (via the ->resume() method). | ||
22 | * If the device is in a low-power state, and a different low-power state | ||
23 | * is requested, the device is first resumed, then suspended into the new | ||
24 | * low-power state. | ||
25 | */ | ||
26 | |||
27 | static ssize_t state_show(struct device * dev, char * buf) | ||
28 | { | ||
29 | return sprintf(buf, "%u\n", dev->power.power_state); | ||
30 | } | ||
31 | |||
32 | static ssize_t state_store(struct device * dev, const char * buf, size_t n) | ||
33 | { | ||
34 | u32 state; | ||
35 | char * rest; | ||
36 | int error = 0; | ||
37 | |||
38 | state = simple_strtoul(buf, &rest, 10); | ||
39 | if (*rest) | ||
40 | return -EINVAL; | ||
41 | if (state) | ||
42 | error = dpm_runtime_suspend(dev, state); | ||
43 | else | ||
44 | dpm_runtime_resume(dev); | ||
45 | return error ? error : n; | ||
46 | } | ||
47 | |||
48 | static DEVICE_ATTR(state, 0644, state_show, state_store); | ||
49 | |||
50 | |||
51 | static struct attribute * power_attrs[] = { | ||
52 | &dev_attr_state.attr, | ||
53 | NULL, | ||
54 | }; | ||
55 | static struct attribute_group pm_attr_group = { | ||
56 | .name = "power", | ||
57 | .attrs = power_attrs, | ||
58 | }; | ||
59 | |||
60 | int dpm_sysfs_add(struct device * dev) | ||
61 | { | ||
62 | return sysfs_create_group(&dev->kobj, &pm_attr_group); | ||
63 | } | ||
64 | |||
65 | void dpm_sysfs_remove(struct device * dev) | ||
66 | { | ||
67 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
68 | } | ||
diff --git a/drivers/base/sys.c b/drivers/base/sys.c new file mode 100644 index 000000000000..cff5a6a2c784 --- /dev/null +++ b/drivers/base/sys.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc) | ||
3 | * | ||
4 | * Copyright (c) 2002-3 Patrick Mochel | ||
5 | * 2002-3 Open Source Development Lab | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | * This exports a 'system' bus type. | ||
10 | * By default, a 'sys' bus gets added to the root of the system. There will | ||
11 | * always be core system devices. Devices can use sysdev_register() to | ||
12 | * add themselves as children of the system bus. | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/sysdev.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/string.h> | ||
23 | |||
24 | |||
25 | extern struct subsystem devices_subsys; | ||
26 | |||
27 | #define to_sysdev(k) container_of(k, struct sys_device, kobj) | ||
28 | #define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr) | ||
29 | |||
30 | |||
31 | static ssize_t | ||
32 | sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) | ||
33 | { | ||
34 | struct sys_device * sysdev = to_sysdev(kobj); | ||
35 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); | ||
36 | |||
37 | if (sysdev_attr->show) | ||
38 | return sysdev_attr->show(sysdev, buffer); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | |||
43 | static ssize_t | ||
44 | sysdev_store(struct kobject * kobj, struct attribute * attr, | ||
45 | const char * buffer, size_t count) | ||
46 | { | ||
47 | struct sys_device * sysdev = to_sysdev(kobj); | ||
48 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); | ||
49 | |||
50 | if (sysdev_attr->store) | ||
51 | return sysdev_attr->store(sysdev, buffer, count); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static struct sysfs_ops sysfs_ops = { | ||
56 | .show = sysdev_show, | ||
57 | .store = sysdev_store, | ||
58 | }; | ||
59 | |||
60 | static struct kobj_type ktype_sysdev = { | ||
61 | .sysfs_ops = &sysfs_ops, | ||
62 | }; | ||
63 | |||
64 | |||
65 | int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a) | ||
66 | { | ||
67 | return sysfs_create_file(&s->kobj, &a->attr); | ||
68 | } | ||
69 | |||
70 | |||
71 | void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) | ||
72 | { | ||
73 | sysfs_remove_file(&s->kobj, &a->attr); | ||
74 | } | ||
75 | |||
76 | EXPORT_SYMBOL_GPL(sysdev_create_file); | ||
77 | EXPORT_SYMBOL_GPL(sysdev_remove_file); | ||
78 | |||
79 | /* | ||
80 | * declare system_subsys | ||
81 | */ | ||
82 | static decl_subsys(system, &ktype_sysdev, NULL); | ||
83 | |||
84 | int sysdev_class_register(struct sysdev_class * cls) | ||
85 | { | ||
86 | pr_debug("Registering sysdev class '%s'\n", | ||
87 | kobject_name(&cls->kset.kobj)); | ||
88 | INIT_LIST_HEAD(&cls->drivers); | ||
89 | cls->kset.subsys = &system_subsys; | ||
90 | kset_set_kset_s(cls, system_subsys); | ||
91 | return kset_register(&cls->kset); | ||
92 | } | ||
93 | |||
94 | void sysdev_class_unregister(struct sysdev_class * cls) | ||
95 | { | ||
96 | pr_debug("Unregistering sysdev class '%s'\n", | ||
97 | kobject_name(&cls->kset.kobj)); | ||
98 | kset_unregister(&cls->kset); | ||
99 | } | ||
100 | |||
101 | EXPORT_SYMBOL_GPL(sysdev_class_register); | ||
102 | EXPORT_SYMBOL_GPL(sysdev_class_unregister); | ||
103 | |||
104 | |||
105 | static LIST_HEAD(sysdev_drivers); | ||
106 | static DECLARE_MUTEX(sysdev_drivers_lock); | ||
107 | |||
108 | /** | ||
109 | * sysdev_driver_register - Register auxillary driver | ||
110 | * @cls: Device class driver belongs to. | ||
111 | * @drv: Driver. | ||
112 | * | ||
113 | * If @cls is valid, then @drv is inserted into @cls->drivers to be | ||
114 | * called on each operation on devices of that class. The refcount | ||
115 | * of @cls is incremented. | ||
116 | * Otherwise, @drv is inserted into sysdev_drivers, and called for | ||
117 | * each device. | ||
118 | */ | ||
119 | |||
120 | int sysdev_driver_register(struct sysdev_class * cls, | ||
121 | struct sysdev_driver * drv) | ||
122 | { | ||
123 | down(&sysdev_drivers_lock); | ||
124 | if (cls && kset_get(&cls->kset)) { | ||
125 | list_add_tail(&drv->entry, &cls->drivers); | ||
126 | |||
127 | /* If devices of this class already exist, tell the driver */ | ||
128 | if (drv->add) { | ||
129 | struct sys_device *dev; | ||
130 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) | ||
131 | drv->add(dev); | ||
132 | } | ||
133 | } else | ||
134 | list_add_tail(&drv->entry, &sysdev_drivers); | ||
135 | up(&sysdev_drivers_lock); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | |||
140 | /** | ||
141 | * sysdev_driver_unregister - Remove an auxillary driver. | ||
142 | * @cls: Class driver belongs to. | ||
143 | * @drv: Driver. | ||
144 | */ | ||
145 | void sysdev_driver_unregister(struct sysdev_class * cls, | ||
146 | struct sysdev_driver * drv) | ||
147 | { | ||
148 | down(&sysdev_drivers_lock); | ||
149 | list_del_init(&drv->entry); | ||
150 | if (cls) { | ||
151 | if (drv->remove) { | ||
152 | struct sys_device *dev; | ||
153 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) | ||
154 | drv->remove(dev); | ||
155 | } | ||
156 | kset_put(&cls->kset); | ||
157 | } | ||
158 | up(&sysdev_drivers_lock); | ||
159 | } | ||
160 | |||
161 | EXPORT_SYMBOL_GPL(sysdev_driver_register); | ||
162 | EXPORT_SYMBOL_GPL(sysdev_driver_unregister); | ||
163 | |||
164 | |||
165 | |||
166 | /** | ||
167 | * sysdev_register - add a system device to the tree | ||
168 | * @sysdev: device in question | ||
169 | * | ||
170 | */ | ||
171 | int sysdev_register(struct sys_device * sysdev) | ||
172 | { | ||
173 | int error; | ||
174 | struct sysdev_class * cls = sysdev->cls; | ||
175 | |||
176 | if (!cls) | ||
177 | return -EINVAL; | ||
178 | |||
179 | /* Make sure the kset is set */ | ||
180 | sysdev->kobj.kset = &cls->kset; | ||
181 | |||
182 | /* But make sure we point to the right type for sysfs translation */ | ||
183 | sysdev->kobj.ktype = &ktype_sysdev; | ||
184 | error = kobject_set_name(&sysdev->kobj, "%s%d", | ||
185 | kobject_name(&cls->kset.kobj), sysdev->id); | ||
186 | if (error) | ||
187 | return error; | ||
188 | |||
189 | pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); | ||
190 | |||
191 | /* Register the object */ | ||
192 | error = kobject_register(&sysdev->kobj); | ||
193 | |||
194 | if (!error) { | ||
195 | struct sysdev_driver * drv; | ||
196 | |||
197 | down(&sysdev_drivers_lock); | ||
198 | /* Generic notification is implicit, because it's that | ||
199 | * code that should have called us. | ||
200 | */ | ||
201 | |||
202 | /* Notify global drivers */ | ||
203 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
204 | if (drv->add) | ||
205 | drv->add(sysdev); | ||
206 | } | ||
207 | |||
208 | /* Notify class auxillary drivers */ | ||
209 | list_for_each_entry(drv, &cls->drivers, entry) { | ||
210 | if (drv->add) | ||
211 | drv->add(sysdev); | ||
212 | } | ||
213 | up(&sysdev_drivers_lock); | ||
214 | } | ||
215 | return error; | ||
216 | } | ||
217 | |||
218 | void sysdev_unregister(struct sys_device * sysdev) | ||
219 | { | ||
220 | struct sysdev_driver * drv; | ||
221 | |||
222 | down(&sysdev_drivers_lock); | ||
223 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
224 | if (drv->remove) | ||
225 | drv->remove(sysdev); | ||
226 | } | ||
227 | |||
228 | list_for_each_entry(drv, &sysdev->cls->drivers, entry) { | ||
229 | if (drv->remove) | ||
230 | drv->remove(sysdev); | ||
231 | } | ||
232 | up(&sysdev_drivers_lock); | ||
233 | |||
234 | kobject_unregister(&sysdev->kobj); | ||
235 | } | ||
236 | |||
237 | |||
238 | |||
239 | /** | ||
240 | * sysdev_shutdown - Shut down all system devices. | ||
241 | * | ||
242 | * Loop over each class of system devices, and the devices in each | ||
243 | * of those classes. For each device, we call the shutdown method for | ||
244 | * each driver registered for the device - the globals, the auxillaries, | ||
245 | * and the class driver. | ||
246 | * | ||
247 | * Note: The list is iterated in reverse order, so that we shut down | ||
248 | * child devices before we shut down thier parents. The list ordering | ||
249 | * is guaranteed by virtue of the fact that child devices are registered | ||
250 | * after their parents. | ||
251 | */ | ||
252 | |||
253 | void sysdev_shutdown(void) | ||
254 | { | ||
255 | struct sysdev_class * cls; | ||
256 | |||
257 | pr_debug("Shutting Down System Devices\n"); | ||
258 | |||
259 | down(&sysdev_drivers_lock); | ||
260 | list_for_each_entry_reverse(cls, &system_subsys.kset.list, | ||
261 | kset.kobj.entry) { | ||
262 | struct sys_device * sysdev; | ||
263 | |||
264 | pr_debug("Shutting down type '%s':\n", | ||
265 | kobject_name(&cls->kset.kobj)); | ||
266 | |||
267 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { | ||
268 | struct sysdev_driver * drv; | ||
269 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | ||
270 | |||
271 | /* Call global drivers first. */ | ||
272 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
273 | if (drv->shutdown) | ||
274 | drv->shutdown(sysdev); | ||
275 | } | ||
276 | |||
277 | /* Call auxillary drivers next. */ | ||
278 | list_for_each_entry(drv, &cls->drivers, entry) { | ||
279 | if (drv->shutdown) | ||
280 | drv->shutdown(sysdev); | ||
281 | } | ||
282 | |||
283 | /* Now call the generic one */ | ||
284 | if (cls->shutdown) | ||
285 | cls->shutdown(sysdev); | ||
286 | } | ||
287 | } | ||
288 | up(&sysdev_drivers_lock); | ||
289 | } | ||
290 | |||
291 | |||
292 | /** | ||
293 | * sysdev_suspend - Suspend all system devices. | ||
294 | * @state: Power state to enter. | ||
295 | * | ||
296 | * We perform an almost identical operation as sys_device_shutdown() | ||
297 | * above, though calling ->suspend() instead. Interrupts are disabled | ||
298 | * when this called. Devices are responsible for both saving state and | ||
299 | * quiescing or powering down the device. | ||
300 | * | ||
301 | * This is only called by the device PM core, so we let them handle | ||
302 | * all synchronization. | ||
303 | */ | ||
304 | |||
305 | int sysdev_suspend(u32 state) | ||
306 | { | ||
307 | struct sysdev_class * cls; | ||
308 | |||
309 | pr_debug("Suspending System Devices\n"); | ||
310 | |||
311 | list_for_each_entry_reverse(cls, &system_subsys.kset.list, | ||
312 | kset.kobj.entry) { | ||
313 | struct sys_device * sysdev; | ||
314 | |||
315 | pr_debug("Suspending type '%s':\n", | ||
316 | kobject_name(&cls->kset.kobj)); | ||
317 | |||
318 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { | ||
319 | struct sysdev_driver * drv; | ||
320 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | ||
321 | |||
322 | /* Call global drivers first. */ | ||
323 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
324 | if (drv->suspend) | ||
325 | drv->suspend(sysdev, state); | ||
326 | } | ||
327 | |||
328 | /* Call auxillary drivers next. */ | ||
329 | list_for_each_entry(drv, &cls->drivers, entry) { | ||
330 | if (drv->suspend) | ||
331 | drv->suspend(sysdev, state); | ||
332 | } | ||
333 | |||
334 | /* Now call the generic one */ | ||
335 | if (cls->suspend) | ||
336 | cls->suspend(sysdev, state); | ||
337 | } | ||
338 | } | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * sysdev_resume - Bring system devices back to life. | ||
345 | * | ||
346 | * Similar to sys_device_suspend(), but we iterate the list forwards | ||
347 | * to guarantee that parent devices are resumed before their children. | ||
348 | * | ||
349 | * Note: Interrupts are disabled when called. | ||
350 | */ | ||
351 | |||
352 | int sysdev_resume(void) | ||
353 | { | ||
354 | struct sysdev_class * cls; | ||
355 | |||
356 | pr_debug("Resuming System Devices\n"); | ||
357 | |||
358 | list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) { | ||
359 | struct sys_device * sysdev; | ||
360 | |||
361 | pr_debug("Resuming type '%s':\n", | ||
362 | kobject_name(&cls->kset.kobj)); | ||
363 | |||
364 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { | ||
365 | struct sysdev_driver * drv; | ||
366 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | ||
367 | |||
368 | /* First, call the class-specific one */ | ||
369 | if (cls->resume) | ||
370 | cls->resume(sysdev); | ||
371 | |||
372 | /* Call auxillary drivers next. */ | ||
373 | list_for_each_entry(drv, &cls->drivers, entry) { | ||
374 | if (drv->resume) | ||
375 | drv->resume(sysdev); | ||
376 | } | ||
377 | |||
378 | /* Call global drivers. */ | ||
379 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
380 | if (drv->resume) | ||
381 | drv->resume(sysdev); | ||
382 | } | ||
383 | |||
384 | } | ||
385 | } | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | |||
390 | int __init system_bus_init(void) | ||
391 | { | ||
392 | system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj; | ||
393 | return subsystem_register(&system_subsys); | ||
394 | } | ||
395 | |||
396 | EXPORT_SYMBOL_GPL(sysdev_register); | ||
397 | EXPORT_SYMBOL_GPL(sysdev_unregister); | ||
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c new file mode 100644 index 000000000000..6c2b447a3336 --- /dev/null +++ b/drivers/base/transport_class.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * transport_class.c - implementation of generic transport classes | ||
3 | * using attribute_containers | ||
4 | * | ||
5 | * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com> | ||
6 | * | ||
7 | * This file is licensed under GPLv2 | ||
8 | * | ||
9 | * The basic idea here is to allow any "device controller" (which | ||
10 | * would most often be a Host Bus Adapter" to use the services of one | ||
11 | * or more tranport classes for performing transport specific | ||
12 | * services. Transport specific services are things that the generic | ||
13 | * command layer doesn't want to know about (speed settings, line | ||
14 | * condidtioning, etc), but which the user might be interested in. | ||
15 | * Thus, the HBA's use the routines exported by the transport classes | ||
16 | * to perform these functions. The transport classes export certain | ||
17 | * values to the user via sysfs using attribute containers. | ||
18 | * | ||
19 | * Note: because not every HBA will care about every transport | ||
20 | * attribute, there's a many to one relationship that goes like this: | ||
21 | * | ||
22 | * transport class<-----attribute container<----class device | ||
23 | * | ||
24 | * Usually the attribute container is per-HBA, but the design doesn't | ||
25 | * mandate that. Although most of the services will be specific to | ||
26 | * the actual external storage connection used by the HBA, the generic | ||
27 | * transport class is framed entirely in terms of generic devices to | ||
28 | * allow it to be used by any physical HBA in the system. | ||
29 | */ | ||
30 | #include <linux/attribute_container.h> | ||
31 | #include <linux/transport_class.h> | ||
32 | |||
33 | /** | ||
34 | * transport_class_register - register an initial transport class | ||
35 | * | ||
36 | * @tclass: a pointer to the transport class structure to be initialised | ||
37 | * | ||
38 | * The transport class contains an embedded class which is used to | ||
39 | * identify it. The caller should initialise this structure with | ||
40 | * zeros and then generic class must have been initialised with the | ||
41 | * actual transport class unique name. There's a macro | ||
42 | * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must | ||
43 | * be registered). | ||
44 | * | ||
45 | * Returns 0 on success or error on failure. | ||
46 | */ | ||
47 | int transport_class_register(struct transport_class *tclass) | ||
48 | { | ||
49 | return class_register(&tclass->class); | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(transport_class_register); | ||
52 | |||
53 | /** | ||
54 | * transport_class_unregister - unregister a previously registered class | ||
55 | * | ||
56 | * @tclass: The transport class to unregister | ||
57 | * | ||
58 | * Must be called prior to deallocating the memory for the transport | ||
59 | * class. | ||
60 | */ | ||
61 | void transport_class_unregister(struct transport_class *tclass) | ||
62 | { | ||
63 | class_unregister(&tclass->class); | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(transport_class_unregister); | ||
66 | |||
67 | static int anon_transport_dummy_function(struct device *dev) | ||
68 | { | ||
69 | /* do nothing */ | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * anon_transport_class_register - register an anonymous class | ||
75 | * | ||
76 | * @atc: The anon transport class to register | ||
77 | * | ||
78 | * The anonymous transport class contains both a transport class and a | ||
79 | * container. The idea of an anonymous class is that it never | ||
80 | * actually has any device attributes associated with it (and thus | ||
81 | * saves on container storage). So it can only be used for triggering | ||
82 | * events. Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to | ||
83 | * initialise the anon transport class storage. | ||
84 | */ | ||
85 | int anon_transport_class_register(struct anon_transport_class *atc) | ||
86 | { | ||
87 | int error; | ||
88 | atc->container.class = &atc->tclass.class; | ||
89 | attribute_container_set_no_classdevs(&atc->container); | ||
90 | error = attribute_container_register(&atc->container); | ||
91 | if (error) | ||
92 | return error; | ||
93 | atc->tclass.setup = anon_transport_dummy_function; | ||
94 | atc->tclass.remove = anon_transport_dummy_function; | ||
95 | return 0; | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(anon_transport_class_register); | ||
98 | |||
99 | /** | ||
100 | * anon_transport_class_unregister - unregister an anon class | ||
101 | * | ||
102 | * @atc: Pointer to the anon transport class to unregister | ||
103 | * | ||
104 | * Must be called prior to deallocating the memory for the anon | ||
105 | * transport class. | ||
106 | */ | ||
107 | void anon_transport_class_unregister(struct anon_transport_class *atc) | ||
108 | { | ||
109 | attribute_container_unregister(&atc->container); | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(anon_transport_class_unregister); | ||
112 | |||
113 | static int transport_setup_classdev(struct attribute_container *cont, | ||
114 | struct device *dev, | ||
115 | struct class_device *classdev) | ||
116 | { | ||
117 | struct transport_class *tclass = class_to_transport_class(cont->class); | ||
118 | |||
119 | if (tclass->setup) | ||
120 | tclass->setup(dev); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * transport_setup_device - declare a new dev for transport class association | ||
127 | * but don't make it visible yet. | ||
128 | * | ||
129 | * @dev: the generic device representing the entity being added | ||
130 | * | ||
131 | * Usually, dev represents some component in the HBA system (either | ||
132 | * the HBA itself or a device remote across the HBA bus). This | ||
133 | * routine is simply a trigger point to see if any set of transport | ||
134 | * classes wishes to associate with the added device. This allocates | ||
135 | * storage for the class device and initialises it, but does not yet | ||
136 | * add it to the system or add attributes to it (you do this with | ||
137 | * transport_add_device). If you have no need for a separate setup | ||
138 | * and add operations, use transport_register_device (see | ||
139 | * transport_class.h). | ||
140 | */ | ||
141 | |||
142 | void transport_setup_device(struct device *dev) | ||
143 | { | ||
144 | attribute_container_add_device(dev, transport_setup_classdev); | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(transport_setup_device); | ||
147 | |||
148 | static int transport_add_class_device(struct attribute_container *cont, | ||
149 | struct device *dev, | ||
150 | struct class_device *classdev) | ||
151 | { | ||
152 | int error = attribute_container_add_class_device(classdev); | ||
153 | struct transport_container *tcont = | ||
154 | attribute_container_to_transport_container(cont); | ||
155 | |||
156 | if (!error && tcont->statistics) | ||
157 | error = sysfs_create_group(&classdev->kobj, tcont->statistics); | ||
158 | |||
159 | return error; | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * transport_add_device - declare a new dev for transport class association | ||
165 | * | ||
166 | * @dev: the generic device representing the entity being added | ||
167 | * | ||
168 | * Usually, dev represents some component in the HBA system (either | ||
169 | * the HBA itself or a device remote across the HBA bus). This | ||
170 | * routine is simply a trigger point used to add the device to the | ||
171 | * system and register attributes for it. | ||
172 | */ | ||
173 | |||
174 | void transport_add_device(struct device *dev) | ||
175 | { | ||
176 | attribute_container_device_trigger(dev, transport_add_class_device); | ||
177 | } | ||
178 | EXPORT_SYMBOL_GPL(transport_add_device); | ||
179 | |||
180 | static int transport_configure(struct attribute_container *cont, | ||
181 | struct device *dev) | ||
182 | { | ||
183 | struct transport_class *tclass = class_to_transport_class(cont->class); | ||
184 | |||
185 | if (tclass->configure) | ||
186 | tclass->configure(dev); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * transport_configure_device - configure an already set up device | ||
193 | * | ||
194 | * @dev: generic device representing device to be configured | ||
195 | * | ||
196 | * The idea of configure is simply to provide a point within the setup | ||
197 | * process to allow the transport class to extract information from a | ||
198 | * device after it has been setup. This is used in SCSI because we | ||
199 | * have to have a setup device to begin using the HBA, but after we | ||
200 | * send the initial inquiry, we use configure to extract the device | ||
201 | * parameters. The device need not have been added to be configured. | ||
202 | */ | ||
203 | void transport_configure_device(struct device *dev) | ||
204 | { | ||
205 | attribute_container_trigger(dev, transport_configure); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(transport_configure_device); | ||
208 | |||
209 | static int transport_remove_classdev(struct attribute_container *cont, | ||
210 | struct device *dev, | ||
211 | struct class_device *classdev) | ||
212 | { | ||
213 | struct transport_container *tcont = | ||
214 | attribute_container_to_transport_container(cont); | ||
215 | struct transport_class *tclass = class_to_transport_class(cont->class); | ||
216 | |||
217 | if (tclass->remove) | ||
218 | tclass->remove(dev); | ||
219 | |||
220 | if (tclass->remove != anon_transport_dummy_function) { | ||
221 | if (tcont->statistics) | ||
222 | sysfs_remove_group(&classdev->kobj, tcont->statistics); | ||
223 | attribute_container_class_device_del(classdev); | ||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * transport_remove_device - remove the visibility of a device | ||
232 | * | ||
233 | * @dev: generic device to remove | ||
234 | * | ||
235 | * This call removes the visibility of the device (to the user from | ||
236 | * sysfs), but does not destroy it. To eliminate a device entirely | ||
237 | * you must also call transport_destroy_device. If you don't need to | ||
238 | * do remove and destroy as separate operations, use | ||
239 | * transport_unregister_device() (see transport_class.h) which will | ||
240 | * perform both calls for you. | ||
241 | */ | ||
242 | void transport_remove_device(struct device *dev) | ||
243 | { | ||
244 | attribute_container_device_trigger(dev, transport_remove_classdev); | ||
245 | } | ||
246 | EXPORT_SYMBOL_GPL(transport_remove_device); | ||
247 | |||
248 | static void transport_destroy_classdev(struct attribute_container *cont, | ||
249 | struct device *dev, | ||
250 | struct class_device *classdev) | ||
251 | { | ||
252 | struct transport_class *tclass = class_to_transport_class(cont->class); | ||
253 | |||
254 | if (tclass->remove != anon_transport_dummy_function) | ||
255 | class_device_put(classdev); | ||
256 | } | ||
257 | |||
258 | |||
259 | /** | ||
260 | * transport_destroy_device - destroy a removed device | ||
261 | * | ||
262 | * @dev: device to eliminate from the transport class. | ||
263 | * | ||
264 | * This call triggers the elimination of storage associated with the | ||
265 | * transport classdev. Note: all it really does is relinquish a | ||
266 | * reference to the classdev. The memory will not be freed until the | ||
267 | * last reference goes to zero. Note also that the classdev retains a | ||
268 | * reference count on dev, so dev too will remain for as long as the | ||
269 | * transport class device remains around. | ||
270 | */ | ||
271 | void transport_destroy_device(struct device *dev) | ||
272 | { | ||
273 | attribute_container_remove_device(dev, transport_destroy_classdev); | ||
274 | } | ||
275 | EXPORT_SYMBOL_GPL(transport_destroy_device); | ||