Commit e105b8bfc769b0545b6f0f395179d1e43cbee822
Committed by
Greg Kroah-Hartman
1 parent
93ded9b8fd
Exists in
master
and in
7 other branches
sysfs: add /sys/dev/{char,block} to lookup sysfs path by major:minor
Why?: There are occasions where userspace would like to access sysfs attributes for a device but it may not know how sysfs has named the device or the path. For example what is the sysfs path for /dev/disk/by-id/ata-ST3160827AS_5MT004CK? With this change a call to stat(2) returns the major:minor then userspace can see that /sys/dev/block/8:32 links to /sys/block/sdc. What are the alternatives?: 1/ Add an ioctl to return the path: Doable, but sysfs is meant to reduce the need to proliferate ioctl interfaces into the kernel, so this seems counter productive. 2/ Use udev to create these symlinks: Also doable, but it adds a udev dependency to utilities that might be running in a limited environment like an initramfs. 3/ Do a full-tree search of sysfs. [kay.sievers@vrfy.org: fix duplicate registrations] [kay.sievers@vrfy.org: cleanup suggestions] Cc: Neil Brown <neilb@suse.de> Cc: Tejun Heo <htejun@gmail.com> Acked-by: Kay Sievers <kay.sievers@vrfy.org> Reviewed-by: SL Baur <steve@xemacs.org> Acked-by: Kay Sievers <kay.sievers@vrfy.org> Acked-by: Mark Lord <lkml@rtr.ca> Acked-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 7 changed files with 124 additions and 2 deletions Inline Diff
Documentation/ABI/testing/sysfs-dev
File was created | 1 | What: /sys/dev | |
2 | Date: April 2008 | ||
3 | KernelVersion: 2.6.26 | ||
4 | Contact: Dan Williams <dan.j.williams@intel.com> | ||
5 | Description: The /sys/dev tree provides a method to look up the sysfs | ||
6 | path for a device using the information returned from | ||
7 | stat(2). There are two directories, 'block' and 'char', | ||
8 | beneath /sys/dev containing symbolic links with names of | ||
9 | the form "<major>:<minor>". These links point to the | ||
10 | corresponding sysfs path for the given device. | ||
11 | |||
12 | Example: | ||
13 | $ readlink /sys/dev/block/8:32 | ||
14 | ../../block/sdc | ||
15 | |||
16 | Entries in /sys/dev/char and /sys/dev/block will be | ||
17 | dynamically created and destroyed as devices enter and | ||
18 | leave the system. | ||
19 | |||
20 | Users: mdadm <linux-raid@vger.kernel.org> | ||
21 |
Documentation/filesystems/sysfs.txt
1 | 1 | ||
2 | sysfs - _The_ filesystem for exporting kernel objects. | 2 | sysfs - _The_ filesystem for exporting kernel objects. |
3 | 3 | ||
4 | Patrick Mochel <mochel@osdl.org> | 4 | Patrick Mochel <mochel@osdl.org> |
5 | 5 | ||
6 | 10 January 2003 | 6 | 10 January 2003 |
7 | 7 | ||
8 | 8 | ||
9 | What it is: | 9 | What it is: |
10 | ~~~~~~~~~~~ | 10 | ~~~~~~~~~~~ |
11 | 11 | ||
12 | sysfs is a ram-based filesystem initially based on ramfs. It provides | 12 | sysfs is a ram-based filesystem initially based on ramfs. It provides |
13 | a means to export kernel data structures, their attributes, and the | 13 | a means to export kernel data structures, their attributes, and the |
14 | linkages between them to userspace. | 14 | linkages between them to userspace. |
15 | 15 | ||
16 | sysfs is tied inherently to the kobject infrastructure. Please read | 16 | sysfs is tied inherently to the kobject infrastructure. Please read |
17 | Documentation/kobject.txt for more information concerning the kobject | 17 | Documentation/kobject.txt for more information concerning the kobject |
18 | interface. | 18 | interface. |
19 | 19 | ||
20 | 20 | ||
21 | Using sysfs | 21 | Using sysfs |
22 | ~~~~~~~~~~~ | 22 | ~~~~~~~~~~~ |
23 | 23 | ||
24 | sysfs is always compiled in. You can access it by doing: | 24 | sysfs is always compiled in. You can access it by doing: |
25 | 25 | ||
26 | mount -t sysfs sysfs /sys | 26 | mount -t sysfs sysfs /sys |
27 | 27 | ||
28 | 28 | ||
29 | Directory Creation | 29 | Directory Creation |
30 | ~~~~~~~~~~~~~~~~~~ | 30 | ~~~~~~~~~~~~~~~~~~ |
31 | 31 | ||
32 | For every kobject that is registered with the system, a directory is | 32 | For every kobject that is registered with the system, a directory is |
33 | created for it in sysfs. That directory is created as a subdirectory | 33 | created for it in sysfs. That directory is created as a subdirectory |
34 | of the kobject's parent, expressing internal object hierarchies to | 34 | of the kobject's parent, expressing internal object hierarchies to |
35 | userspace. Top-level directories in sysfs represent the common | 35 | userspace. Top-level directories in sysfs represent the common |
36 | ancestors of object hierarchies; i.e. the subsystems the objects | 36 | ancestors of object hierarchies; i.e. the subsystems the objects |
37 | belong to. | 37 | belong to. |
38 | 38 | ||
39 | Sysfs internally stores the kobject that owns the directory in the | 39 | Sysfs internally stores the kobject that owns the directory in the |
40 | ->d_fsdata pointer of the directory's dentry. This allows sysfs to do | 40 | ->d_fsdata pointer of the directory's dentry. This allows sysfs to do |
41 | reference counting directly on the kobject when the file is opened and | 41 | reference counting directly on the kobject when the file is opened and |
42 | closed. | 42 | closed. |
43 | 43 | ||
44 | 44 | ||
45 | Attributes | 45 | Attributes |
46 | ~~~~~~~~~~ | 46 | ~~~~~~~~~~ |
47 | 47 | ||
48 | Attributes can be exported for kobjects in the form of regular files in | 48 | Attributes can be exported for kobjects in the form of regular files in |
49 | the filesystem. Sysfs forwards file I/O operations to methods defined | 49 | the filesystem. Sysfs forwards file I/O operations to methods defined |
50 | for the attributes, providing a means to read and write kernel | 50 | for the attributes, providing a means to read and write kernel |
51 | attributes. | 51 | attributes. |
52 | 52 | ||
53 | Attributes should be ASCII text files, preferably with only one value | 53 | Attributes should be ASCII text files, preferably with only one value |
54 | per file. It is noted that it may not be efficient to contain only one | 54 | per file. It is noted that it may not be efficient to contain only one |
55 | value per file, so it is socially acceptable to express an array of | 55 | value per file, so it is socially acceptable to express an array of |
56 | values of the same type. | 56 | values of the same type. |
57 | 57 | ||
58 | Mixing types, expressing multiple lines of data, and doing fancy | 58 | Mixing types, expressing multiple lines of data, and doing fancy |
59 | formatting of data is heavily frowned upon. Doing these things may get | 59 | formatting of data is heavily frowned upon. Doing these things may get |
60 | you publically humiliated and your code rewritten without notice. | 60 | you publically humiliated and your code rewritten without notice. |
61 | 61 | ||
62 | 62 | ||
63 | An attribute definition is simply: | 63 | An attribute definition is simply: |
64 | 64 | ||
65 | struct attribute { | 65 | struct attribute { |
66 | char * name; | 66 | char * name; |
67 | mode_t mode; | 67 | mode_t mode; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | 70 | ||
71 | int sysfs_create_file(struct kobject * kobj, struct attribute * attr); | 71 | int sysfs_create_file(struct kobject * kobj, struct attribute * attr); |
72 | void sysfs_remove_file(struct kobject * kobj, struct attribute * attr); | 72 | void sysfs_remove_file(struct kobject * kobj, struct attribute * attr); |
73 | 73 | ||
74 | 74 | ||
75 | A bare attribute contains no means to read or write the value of the | 75 | A bare attribute contains no means to read or write the value of the |
76 | attribute. Subsystems are encouraged to define their own attribute | 76 | attribute. Subsystems are encouraged to define their own attribute |
77 | structure and wrapper functions for adding and removing attributes for | 77 | structure and wrapper functions for adding and removing attributes for |
78 | a specific object type. | 78 | a specific object type. |
79 | 79 | ||
80 | For example, the driver model defines struct device_attribute like: | 80 | For example, the driver model defines struct device_attribute like: |
81 | 81 | ||
82 | struct device_attribute { | 82 | struct device_attribute { |
83 | struct attribute attr; | 83 | struct attribute attr; |
84 | ssize_t (*show)(struct device * dev, char * buf); | 84 | ssize_t (*show)(struct device * dev, char * buf); |
85 | ssize_t (*store)(struct device * dev, const char * buf); | 85 | ssize_t (*store)(struct device * dev, const char * buf); |
86 | }; | 86 | }; |
87 | 87 | ||
88 | int device_create_file(struct device *, struct device_attribute *); | 88 | int device_create_file(struct device *, struct device_attribute *); |
89 | void device_remove_file(struct device *, struct device_attribute *); | 89 | void device_remove_file(struct device *, struct device_attribute *); |
90 | 90 | ||
91 | It also defines this helper for defining device attributes: | 91 | It also defines this helper for defining device attributes: |
92 | 92 | ||
93 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ | 93 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ |
94 | struct device_attribute dev_attr_##_name = { \ | 94 | struct device_attribute dev_attr_##_name = { \ |
95 | .attr = {.name = __stringify(_name) , .mode = _mode }, \ | 95 | .attr = {.name = __stringify(_name) , .mode = _mode }, \ |
96 | .show = _show, \ | 96 | .show = _show, \ |
97 | .store = _store, \ | 97 | .store = _store, \ |
98 | }; | 98 | }; |
99 | 99 | ||
100 | For example, declaring | 100 | For example, declaring |
101 | 101 | ||
102 | static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); | 102 | static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); |
103 | 103 | ||
104 | is equivalent to doing: | 104 | is equivalent to doing: |
105 | 105 | ||
106 | static struct device_attribute dev_attr_foo = { | 106 | static struct device_attribute dev_attr_foo = { |
107 | .attr = { | 107 | .attr = { |
108 | .name = "foo", | 108 | .name = "foo", |
109 | .mode = S_IWUSR | S_IRUGO, | 109 | .mode = S_IWUSR | S_IRUGO, |
110 | }, | 110 | }, |
111 | .show = show_foo, | 111 | .show = show_foo, |
112 | .store = store_foo, | 112 | .store = store_foo, |
113 | }; | 113 | }; |
114 | 114 | ||
115 | 115 | ||
116 | Subsystem-Specific Callbacks | 116 | Subsystem-Specific Callbacks |
117 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 117 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
118 | 118 | ||
119 | When a subsystem defines a new attribute type, it must implement a | 119 | When a subsystem defines a new attribute type, it must implement a |
120 | set of sysfs operations for forwarding read and write calls to the | 120 | set of sysfs operations for forwarding read and write calls to the |
121 | show and store methods of the attribute owners. | 121 | show and store methods of the attribute owners. |
122 | 122 | ||
123 | struct sysfs_ops { | 123 | struct sysfs_ops { |
124 | ssize_t (*show)(struct kobject *, struct attribute *, char *); | 124 | ssize_t (*show)(struct kobject *, struct attribute *, char *); |
125 | ssize_t (*store)(struct kobject *, struct attribute *, const char *); | 125 | ssize_t (*store)(struct kobject *, struct attribute *, const char *); |
126 | }; | 126 | }; |
127 | 127 | ||
128 | [ Subsystems should have already defined a struct kobj_type as a | 128 | [ Subsystems should have already defined a struct kobj_type as a |
129 | descriptor for this type, which is where the sysfs_ops pointer is | 129 | descriptor for this type, which is where the sysfs_ops pointer is |
130 | stored. See the kobject documentation for more information. ] | 130 | stored. See the kobject documentation for more information. ] |
131 | 131 | ||
132 | When a file is read or written, sysfs calls the appropriate method | 132 | When a file is read or written, sysfs calls the appropriate method |
133 | for the type. The method then translates the generic struct kobject | 133 | for the type. The method then translates the generic struct kobject |
134 | and struct attribute pointers to the appropriate pointer types, and | 134 | and struct attribute pointers to the appropriate pointer types, and |
135 | calls the associated methods. | 135 | calls the associated methods. |
136 | 136 | ||
137 | 137 | ||
138 | To illustrate: | 138 | To illustrate: |
139 | 139 | ||
140 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 140 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
141 | #define to_dev(d) container_of(d, struct device, kobj) | 141 | #define to_dev(d) container_of(d, struct device, kobj) |
142 | 142 | ||
143 | static ssize_t | 143 | static ssize_t |
144 | dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 144 | dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
145 | { | 145 | { |
146 | struct device_attribute * dev_attr = to_dev_attr(attr); | 146 | struct device_attribute * dev_attr = to_dev_attr(attr); |
147 | struct device * dev = to_dev(kobj); | 147 | struct device * dev = to_dev(kobj); |
148 | ssize_t ret = 0; | 148 | ssize_t ret = 0; |
149 | 149 | ||
150 | if (dev_attr->show) | 150 | if (dev_attr->show) |
151 | ret = dev_attr->show(dev, buf); | 151 | ret = dev_attr->show(dev, buf); |
152 | return ret; | 152 | return ret; |
153 | } | 153 | } |
154 | 154 | ||
155 | 155 | ||
156 | 156 | ||
157 | Reading/Writing Attribute Data | 157 | Reading/Writing Attribute Data |
158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
159 | 159 | ||
160 | To read or write attributes, show() or store() methods must be | 160 | To read or write attributes, show() or store() methods must be |
161 | specified when declaring the attribute. The method types should be as | 161 | specified when declaring the attribute. The method types should be as |
162 | simple as those defined for device attributes: | 162 | simple as those defined for device attributes: |
163 | 163 | ||
164 | ssize_t (*show)(struct device * dev, char * buf); | 164 | ssize_t (*show)(struct device * dev, char * buf); |
165 | ssize_t (*store)(struct device * dev, const char * buf); | 165 | ssize_t (*store)(struct device * dev, const char * buf); |
166 | 166 | ||
167 | IOW, they should take only an object and a buffer as parameters. | 167 | IOW, they should take only an object and a buffer as parameters. |
168 | 168 | ||
169 | 169 | ||
170 | sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the | 170 | sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the |
171 | method. Sysfs will call the method exactly once for each read or | 171 | method. Sysfs will call the method exactly once for each read or |
172 | write. This forces the following behavior on the method | 172 | write. This forces the following behavior on the method |
173 | implementations: | 173 | implementations: |
174 | 174 | ||
175 | - On read(2), the show() method should fill the entire buffer. | 175 | - On read(2), the show() method should fill the entire buffer. |
176 | Recall that an attribute should only be exporting one value, or an | 176 | Recall that an attribute should only be exporting one value, or an |
177 | array of similar values, so this shouldn't be that expensive. | 177 | array of similar values, so this shouldn't be that expensive. |
178 | 178 | ||
179 | This allows userspace to do partial reads and forward seeks | 179 | This allows userspace to do partial reads and forward seeks |
180 | arbitrarily over the entire file at will. If userspace seeks back to | 180 | arbitrarily over the entire file at will. If userspace seeks back to |
181 | zero or does a pread(2) with an offset of '0' the show() method will | 181 | zero or does a pread(2) with an offset of '0' the show() method will |
182 | be called again, rearmed, to fill the buffer. | 182 | be called again, rearmed, to fill the buffer. |
183 | 183 | ||
184 | - On write(2), sysfs expects the entire buffer to be passed during the | 184 | - On write(2), sysfs expects the entire buffer to be passed during the |
185 | first write. Sysfs then passes the entire buffer to the store() | 185 | first write. Sysfs then passes the entire buffer to the store() |
186 | method. | 186 | method. |
187 | 187 | ||
188 | When writing sysfs files, userspace processes should first read the | 188 | When writing sysfs files, userspace processes should first read the |
189 | entire file, modify the values it wishes to change, then write the | 189 | entire file, modify the values it wishes to change, then write the |
190 | entire buffer back. | 190 | entire buffer back. |
191 | 191 | ||
192 | Attribute method implementations should operate on an identical | 192 | Attribute method implementations should operate on an identical |
193 | buffer when reading and writing values. | 193 | buffer when reading and writing values. |
194 | 194 | ||
195 | Other notes: | 195 | Other notes: |
196 | 196 | ||
197 | - Writing causes the show() method to be rearmed regardless of current | 197 | - Writing causes the show() method to be rearmed regardless of current |
198 | file position. | 198 | file position. |
199 | 199 | ||
200 | - The buffer will always be PAGE_SIZE bytes in length. On i386, this | 200 | - The buffer will always be PAGE_SIZE bytes in length. On i386, this |
201 | is 4096. | 201 | is 4096. |
202 | 202 | ||
203 | - show() methods should return the number of bytes printed into the | 203 | - show() methods should return the number of bytes printed into the |
204 | buffer. This is the return value of snprintf(). | 204 | buffer. This is the return value of snprintf(). |
205 | 205 | ||
206 | - show() should always use snprintf(). | 206 | - show() should always use snprintf(). |
207 | 207 | ||
208 | - store() should return the number of bytes used from the buffer. This | 208 | - store() should return the number of bytes used from the buffer. This |
209 | can be done using strlen(). | 209 | can be done using strlen(). |
210 | 210 | ||
211 | - show() or store() can always return errors. If a bad value comes | 211 | - show() or store() can always return errors. If a bad value comes |
212 | through, be sure to return an error. | 212 | through, be sure to return an error. |
213 | 213 | ||
214 | - The object passed to the methods will be pinned in memory via sysfs | 214 | - The object passed to the methods will be pinned in memory via sysfs |
215 | referencing counting its embedded object. However, the physical | 215 | referencing counting its embedded object. However, the physical |
216 | entity (e.g. device) the object represents may not be present. Be | 216 | entity (e.g. device) the object represents may not be present. Be |
217 | sure to have a way to check this, if necessary. | 217 | sure to have a way to check this, if necessary. |
218 | 218 | ||
219 | 219 | ||
220 | A very simple (and naive) implementation of a device attribute is: | 220 | A very simple (and naive) implementation of a device attribute is: |
221 | 221 | ||
222 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | 222 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) |
223 | { | 223 | { |
224 | return snprintf(buf, PAGE_SIZE, "%s\n", dev->name); | 224 | return snprintf(buf, PAGE_SIZE, "%s\n", dev->name); |
225 | } | 225 | } |
226 | 226 | ||
227 | static ssize_t store_name(struct device * dev, const char * buf) | 227 | static ssize_t store_name(struct device * dev, const char * buf) |
228 | { | 228 | { |
229 | sscanf(buf, "%20s", dev->name); | 229 | sscanf(buf, "%20s", dev->name); |
230 | return strnlen(buf, PAGE_SIZE); | 230 | return strnlen(buf, PAGE_SIZE); |
231 | } | 231 | } |
232 | 232 | ||
233 | static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); | 233 | static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); |
234 | 234 | ||
235 | 235 | ||
236 | (Note that the real implementation doesn't allow userspace to set the | 236 | (Note that the real implementation doesn't allow userspace to set the |
237 | name for a device.) | 237 | name for a device.) |
238 | 238 | ||
239 | 239 | ||
240 | Top Level Directory Layout | 240 | Top Level Directory Layout |
241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
242 | 242 | ||
243 | The sysfs directory arrangement exposes the relationship of kernel | 243 | The sysfs directory arrangement exposes the relationship of kernel |
244 | data structures. | 244 | data structures. |
245 | 245 | ||
246 | The top level sysfs directory looks like: | 246 | The top level sysfs directory looks like: |
247 | 247 | ||
248 | block/ | 248 | block/ |
249 | bus/ | 249 | bus/ |
250 | class/ | 250 | class/ |
251 | dev/ | ||
251 | devices/ | 252 | devices/ |
252 | firmware/ | 253 | firmware/ |
253 | net/ | 254 | net/ |
254 | fs/ | 255 | fs/ |
255 | 256 | ||
256 | devices/ contains a filesystem representation of the device tree. It maps | 257 | devices/ contains a filesystem representation of the device tree. It maps |
257 | directly to the internal kernel device tree, which is a hierarchy of | 258 | directly to the internal kernel device tree, which is a hierarchy of |
258 | struct device. | 259 | struct device. |
259 | 260 | ||
260 | bus/ contains flat directory layout of the various bus types in the | 261 | bus/ contains flat directory layout of the various bus types in the |
261 | kernel. Each bus's directory contains two subdirectories: | 262 | kernel. Each bus's directory contains two subdirectories: |
262 | 263 | ||
263 | devices/ | 264 | devices/ |
264 | drivers/ | 265 | drivers/ |
265 | 266 | ||
266 | devices/ contains symlinks for each device discovered in the system | 267 | devices/ contains symlinks for each device discovered in the system |
267 | that point to the device's directory under root/. | 268 | that point to the device's directory under root/. |
268 | 269 | ||
269 | drivers/ contains a directory for each device driver that is loaded | 270 | drivers/ contains a directory for each device driver that is loaded |
270 | for devices on that particular bus (this assumes that drivers do not | 271 | for devices on that particular bus (this assumes that drivers do not |
271 | span multiple bus types). | 272 | span multiple bus types). |
272 | 273 | ||
273 | fs/ contains a directory for some filesystems. Currently each | 274 | fs/ contains a directory for some filesystems. Currently each |
274 | filesystem wanting to export attributes must create its own hierarchy | 275 | filesystem wanting to export attributes must create its own hierarchy |
275 | below fs/ (see ./fuse.txt for an example). | 276 | below fs/ (see ./fuse.txt for an example). |
276 | 277 | ||
278 | dev/ contains two directories char/ and block/. Inside these two | ||
279 | directories there are symlinks named <major>:<minor>. These symlinks | ||
280 | point to the sysfs directory for the given device. /sys/dev provides a | ||
281 | quick way to lookup the sysfs interface for a device from the result of | ||
282 | a stat(2) operation. | ||
277 | 283 | ||
278 | More information can driver-model specific features can be found in | 284 | More information can driver-model specific features can be found in |
279 | Documentation/driver-model/. | 285 | Documentation/driver-model/. |
280 | 286 | ||
281 | 287 | ||
282 | TODO: Finish this section. | 288 | TODO: Finish this section. |
283 | 289 | ||
284 | 290 | ||
285 | Current Interfaces | 291 | Current Interfaces |
286 | ~~~~~~~~~~~~~~~~~~ | 292 | ~~~~~~~~~~~~~~~~~~ |
287 | 293 | ||
288 | The following interface layers currently exist in sysfs: | 294 | The following interface layers currently exist in sysfs: |
289 | 295 | ||
290 | 296 | ||
291 | - devices (include/linux/device.h) | 297 | - devices (include/linux/device.h) |
292 | ---------------------------------- | 298 | ---------------------------------- |
293 | Structure: | 299 | Structure: |
294 | 300 | ||
295 | struct device_attribute { | 301 | struct device_attribute { |
296 | struct attribute attr; | 302 | struct attribute attr; |
297 | ssize_t (*show)(struct device * dev, char * buf); | 303 | ssize_t (*show)(struct device * dev, char * buf); |
298 | ssize_t (*store)(struct device * dev, const char * buf); | 304 | ssize_t (*store)(struct device * dev, const char * buf); |
299 | }; | 305 | }; |
300 | 306 | ||
301 | Declaring: | 307 | Declaring: |
302 | 308 | ||
303 | DEVICE_ATTR(_name, _str, _mode, _show, _store); | 309 | DEVICE_ATTR(_name, _str, _mode, _show, _store); |
304 | 310 | ||
305 | Creation/Removal: | 311 | Creation/Removal: |
306 | 312 | ||
307 | int device_create_file(struct device *device, struct device_attribute * attr); | 313 | int device_create_file(struct device *device, struct device_attribute * attr); |
308 | void device_remove_file(struct device * dev, struct device_attribute * attr); | 314 | void device_remove_file(struct device * dev, struct device_attribute * attr); |
309 | 315 | ||
310 | 316 | ||
311 | - bus drivers (include/linux/device.h) | 317 | - bus drivers (include/linux/device.h) |
312 | -------------------------------------- | 318 | -------------------------------------- |
313 | Structure: | 319 | Structure: |
314 | 320 | ||
315 | struct bus_attribute { | 321 | struct bus_attribute { |
316 | struct attribute attr; | 322 | struct attribute attr; |
317 | ssize_t (*show)(struct bus_type *, char * buf); | 323 | ssize_t (*show)(struct bus_type *, char * buf); |
318 | ssize_t (*store)(struct bus_type *, const char * buf); | 324 | ssize_t (*store)(struct bus_type *, const char * buf); |
319 | }; | 325 | }; |
320 | 326 | ||
321 | Declaring: | 327 | Declaring: |
322 | 328 | ||
323 | BUS_ATTR(_name, _mode, _show, _store) | 329 | BUS_ATTR(_name, _mode, _show, _store) |
324 | 330 | ||
325 | Creation/Removal: | 331 | Creation/Removal: |
326 | 332 | ||
327 | int bus_create_file(struct bus_type *, struct bus_attribute *); | 333 | int bus_create_file(struct bus_type *, struct bus_attribute *); |
328 | void bus_remove_file(struct bus_type *, struct bus_attribute *); | 334 | void bus_remove_file(struct bus_type *, struct bus_attribute *); |
329 | 335 | ||
330 | 336 | ||
331 | - device drivers (include/linux/device.h) | 337 | - device drivers (include/linux/device.h) |
332 | ----------------------------------------- | 338 | ----------------------------------------- |
333 | 339 | ||
334 | Structure: | 340 | Structure: |
335 | 341 | ||
336 | struct driver_attribute { | 342 | struct driver_attribute { |
337 | struct attribute attr; | 343 | struct attribute attr; |
338 | ssize_t (*show)(struct device_driver *, char * buf); | 344 | ssize_t (*show)(struct device_driver *, char * buf); |
339 | ssize_t (*store)(struct device_driver *, const char * buf); | 345 | ssize_t (*store)(struct device_driver *, const char * buf); |
340 | }; | 346 | }; |
341 | 347 | ||
342 | Declaring: | 348 | Declaring: |
343 | 349 | ||
344 | DRIVER_ATTR(_name, _mode, _show, _store) | 350 | DRIVER_ATTR(_name, _mode, _show, _store) |
345 | 351 | ||
346 | Creation/Removal: | 352 | Creation/Removal: |
347 | 353 | ||
348 | int driver_create_file(struct device_driver *, struct driver_attribute *); | 354 | int driver_create_file(struct device_driver *, struct driver_attribute *); |
349 | void driver_remove_file(struct device_driver *, struct driver_attribute *); | 355 | void driver_remove_file(struct device_driver *, struct driver_attribute *); |
350 | 356 | ||
351 | 357 | ||
352 | 358 |
block/genhd.c
1 | /* | 1 | /* |
2 | * gendisk handling | 2 | * gendisk handling |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/fs.h> | 6 | #include <linux/fs.h> |
7 | #include <linux/genhd.h> | 7 | #include <linux/genhd.h> |
8 | #include <linux/kdev_t.h> | 8 | #include <linux/kdev_t.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/seq_file.h> | 13 | #include <linux/seq_file.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/kmod.h> | 15 | #include <linux/kmod.h> |
16 | #include <linux/kobj_map.h> | 16 | #include <linux/kobj_map.h> |
17 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
18 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
19 | 19 | ||
20 | #include "blk.h" | 20 | #include "blk.h" |
21 | 21 | ||
22 | static DEFINE_MUTEX(block_class_lock); | 22 | static DEFINE_MUTEX(block_class_lock); |
23 | #ifndef CONFIG_SYSFS_DEPRECATED | 23 | #ifndef CONFIG_SYSFS_DEPRECATED |
24 | struct kobject *block_depr; | 24 | struct kobject *block_depr; |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | static struct device_type disk_type; | 27 | static struct device_type disk_type; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Can be deleted altogether. Later. | 30 | * Can be deleted altogether. Later. |
31 | * | 31 | * |
32 | */ | 32 | */ |
33 | static struct blk_major_name { | 33 | static struct blk_major_name { |
34 | struct blk_major_name *next; | 34 | struct blk_major_name *next; |
35 | int major; | 35 | int major; |
36 | char name[16]; | 36 | char name[16]; |
37 | } *major_names[BLKDEV_MAJOR_HASH_SIZE]; | 37 | } *major_names[BLKDEV_MAJOR_HASH_SIZE]; |
38 | 38 | ||
39 | /* index in the above - for now: assume no multimajor ranges */ | 39 | /* index in the above - for now: assume no multimajor ranges */ |
40 | static inline int major_to_index(int major) | 40 | static inline int major_to_index(int major) |
41 | { | 41 | { |
42 | return major % BLKDEV_MAJOR_HASH_SIZE; | 42 | return major % BLKDEV_MAJOR_HASH_SIZE; |
43 | } | 43 | } |
44 | 44 | ||
45 | #ifdef CONFIG_PROC_FS | 45 | #ifdef CONFIG_PROC_FS |
46 | void blkdev_show(struct seq_file *f, off_t offset) | 46 | void blkdev_show(struct seq_file *f, off_t offset) |
47 | { | 47 | { |
48 | struct blk_major_name *dp; | 48 | struct blk_major_name *dp; |
49 | 49 | ||
50 | if (offset < BLKDEV_MAJOR_HASH_SIZE) { | 50 | if (offset < BLKDEV_MAJOR_HASH_SIZE) { |
51 | mutex_lock(&block_class_lock); | 51 | mutex_lock(&block_class_lock); |
52 | for (dp = major_names[offset]; dp; dp = dp->next) | 52 | for (dp = major_names[offset]; dp; dp = dp->next) |
53 | seq_printf(f, "%3d %s\n", dp->major, dp->name); | 53 | seq_printf(f, "%3d %s\n", dp->major, dp->name); |
54 | mutex_unlock(&block_class_lock); | 54 | mutex_unlock(&block_class_lock); |
55 | } | 55 | } |
56 | } | 56 | } |
57 | #endif /* CONFIG_PROC_FS */ | 57 | #endif /* CONFIG_PROC_FS */ |
58 | 58 | ||
59 | int register_blkdev(unsigned int major, const char *name) | 59 | int register_blkdev(unsigned int major, const char *name) |
60 | { | 60 | { |
61 | struct blk_major_name **n, *p; | 61 | struct blk_major_name **n, *p; |
62 | int index, ret = 0; | 62 | int index, ret = 0; |
63 | 63 | ||
64 | mutex_lock(&block_class_lock); | 64 | mutex_lock(&block_class_lock); |
65 | 65 | ||
66 | /* temporary */ | 66 | /* temporary */ |
67 | if (major == 0) { | 67 | if (major == 0) { |
68 | for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) { | 68 | for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) { |
69 | if (major_names[index] == NULL) | 69 | if (major_names[index] == NULL) |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | 72 | ||
73 | if (index == 0) { | 73 | if (index == 0) { |
74 | printk("register_blkdev: failed to get major for %s\n", | 74 | printk("register_blkdev: failed to get major for %s\n", |
75 | name); | 75 | name); |
76 | ret = -EBUSY; | 76 | ret = -EBUSY; |
77 | goto out; | 77 | goto out; |
78 | } | 78 | } |
79 | major = index; | 79 | major = index; |
80 | ret = major; | 80 | ret = major; |
81 | } | 81 | } |
82 | 82 | ||
83 | p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); | 83 | p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); |
84 | if (p == NULL) { | 84 | if (p == NULL) { |
85 | ret = -ENOMEM; | 85 | ret = -ENOMEM; |
86 | goto out; | 86 | goto out; |
87 | } | 87 | } |
88 | 88 | ||
89 | p->major = major; | 89 | p->major = major; |
90 | strlcpy(p->name, name, sizeof(p->name)); | 90 | strlcpy(p->name, name, sizeof(p->name)); |
91 | p->next = NULL; | 91 | p->next = NULL; |
92 | index = major_to_index(major); | 92 | index = major_to_index(major); |
93 | 93 | ||
94 | for (n = &major_names[index]; *n; n = &(*n)->next) { | 94 | for (n = &major_names[index]; *n; n = &(*n)->next) { |
95 | if ((*n)->major == major) | 95 | if ((*n)->major == major) |
96 | break; | 96 | break; |
97 | } | 97 | } |
98 | if (!*n) | 98 | if (!*n) |
99 | *n = p; | 99 | *n = p; |
100 | else | 100 | else |
101 | ret = -EBUSY; | 101 | ret = -EBUSY; |
102 | 102 | ||
103 | if (ret < 0) { | 103 | if (ret < 0) { |
104 | printk("register_blkdev: cannot get major %d for %s\n", | 104 | printk("register_blkdev: cannot get major %d for %s\n", |
105 | major, name); | 105 | major, name); |
106 | kfree(p); | 106 | kfree(p); |
107 | } | 107 | } |
108 | out: | 108 | out: |
109 | mutex_unlock(&block_class_lock); | 109 | mutex_unlock(&block_class_lock); |
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | 112 | ||
113 | EXPORT_SYMBOL(register_blkdev); | 113 | EXPORT_SYMBOL(register_blkdev); |
114 | 114 | ||
115 | void unregister_blkdev(unsigned int major, const char *name) | 115 | void unregister_blkdev(unsigned int major, const char *name) |
116 | { | 116 | { |
117 | struct blk_major_name **n; | 117 | struct blk_major_name **n; |
118 | struct blk_major_name *p = NULL; | 118 | struct blk_major_name *p = NULL; |
119 | int index = major_to_index(major); | 119 | int index = major_to_index(major); |
120 | 120 | ||
121 | mutex_lock(&block_class_lock); | 121 | mutex_lock(&block_class_lock); |
122 | for (n = &major_names[index]; *n; n = &(*n)->next) | 122 | for (n = &major_names[index]; *n; n = &(*n)->next) |
123 | if ((*n)->major == major) | 123 | if ((*n)->major == major) |
124 | break; | 124 | break; |
125 | if (!*n || strcmp((*n)->name, name)) { | 125 | if (!*n || strcmp((*n)->name, name)) { |
126 | WARN_ON(1); | 126 | WARN_ON(1); |
127 | } else { | 127 | } else { |
128 | p = *n; | 128 | p = *n; |
129 | *n = p->next; | 129 | *n = p->next; |
130 | } | 130 | } |
131 | mutex_unlock(&block_class_lock); | 131 | mutex_unlock(&block_class_lock); |
132 | kfree(p); | 132 | kfree(p); |
133 | } | 133 | } |
134 | 134 | ||
135 | EXPORT_SYMBOL(unregister_blkdev); | 135 | EXPORT_SYMBOL(unregister_blkdev); |
136 | 136 | ||
137 | static struct kobj_map *bdev_map; | 137 | static struct kobj_map *bdev_map; |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * Register device numbers dev..(dev+range-1) | 140 | * Register device numbers dev..(dev+range-1) |
141 | * range must be nonzero | 141 | * range must be nonzero |
142 | * The hash chain is sorted on range, so that subranges can override. | 142 | * The hash chain is sorted on range, so that subranges can override. |
143 | */ | 143 | */ |
144 | void blk_register_region(dev_t devt, unsigned long range, struct module *module, | 144 | void blk_register_region(dev_t devt, unsigned long range, struct module *module, |
145 | struct kobject *(*probe)(dev_t, int *, void *), | 145 | struct kobject *(*probe)(dev_t, int *, void *), |
146 | int (*lock)(dev_t, void *), void *data) | 146 | int (*lock)(dev_t, void *), void *data) |
147 | { | 147 | { |
148 | kobj_map(bdev_map, devt, range, module, probe, lock, data); | 148 | kobj_map(bdev_map, devt, range, module, probe, lock, data); |
149 | } | 149 | } |
150 | 150 | ||
151 | EXPORT_SYMBOL(blk_register_region); | 151 | EXPORT_SYMBOL(blk_register_region); |
152 | 152 | ||
153 | void blk_unregister_region(dev_t devt, unsigned long range) | 153 | void blk_unregister_region(dev_t devt, unsigned long range) |
154 | { | 154 | { |
155 | kobj_unmap(bdev_map, devt, range); | 155 | kobj_unmap(bdev_map, devt, range); |
156 | } | 156 | } |
157 | 157 | ||
158 | EXPORT_SYMBOL(blk_unregister_region); | 158 | EXPORT_SYMBOL(blk_unregister_region); |
159 | 159 | ||
160 | static struct kobject *exact_match(dev_t devt, int *part, void *data) | 160 | static struct kobject *exact_match(dev_t devt, int *part, void *data) |
161 | { | 161 | { |
162 | struct gendisk *p = data; | 162 | struct gendisk *p = data; |
163 | 163 | ||
164 | return &p->dev.kobj; | 164 | return &p->dev.kobj; |
165 | } | 165 | } |
166 | 166 | ||
167 | static int exact_lock(dev_t devt, void *data) | 167 | static int exact_lock(dev_t devt, void *data) |
168 | { | 168 | { |
169 | struct gendisk *p = data; | 169 | struct gendisk *p = data; |
170 | 170 | ||
171 | if (!get_disk(p)) | 171 | if (!get_disk(p)) |
172 | return -1; | 172 | return -1; |
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | /** | 176 | /** |
177 | * add_disk - add partitioning information to kernel list | 177 | * add_disk - add partitioning information to kernel list |
178 | * @disk: per-device partitioning information | 178 | * @disk: per-device partitioning information |
179 | * | 179 | * |
180 | * This function registers the partitioning information in @disk | 180 | * This function registers the partitioning information in @disk |
181 | * with the kernel. | 181 | * with the kernel. |
182 | */ | 182 | */ |
183 | void add_disk(struct gendisk *disk) | 183 | void add_disk(struct gendisk *disk) |
184 | { | 184 | { |
185 | struct backing_dev_info *bdi; | 185 | struct backing_dev_info *bdi; |
186 | 186 | ||
187 | disk->flags |= GENHD_FL_UP; | 187 | disk->flags |= GENHD_FL_UP; |
188 | blk_register_region(MKDEV(disk->major, disk->first_minor), | 188 | blk_register_region(MKDEV(disk->major, disk->first_minor), |
189 | disk->minors, NULL, exact_match, exact_lock, disk); | 189 | disk->minors, NULL, exact_match, exact_lock, disk); |
190 | register_disk(disk); | 190 | register_disk(disk); |
191 | blk_register_queue(disk); | 191 | blk_register_queue(disk); |
192 | blk_register_filter(disk); | 192 | blk_register_filter(disk); |
193 | 193 | ||
194 | bdi = &disk->queue->backing_dev_info; | 194 | bdi = &disk->queue->backing_dev_info; |
195 | bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); | 195 | bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); |
196 | sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); | 196 | sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); |
197 | } | 197 | } |
198 | 198 | ||
199 | EXPORT_SYMBOL(add_disk); | 199 | EXPORT_SYMBOL(add_disk); |
200 | EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ | 200 | EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ |
201 | 201 | ||
202 | void unlink_gendisk(struct gendisk *disk) | 202 | void unlink_gendisk(struct gendisk *disk) |
203 | { | 203 | { |
204 | blk_unregister_filter(disk); | 204 | blk_unregister_filter(disk); |
205 | sysfs_remove_link(&disk->dev.kobj, "bdi"); | 205 | sysfs_remove_link(&disk->dev.kobj, "bdi"); |
206 | bdi_unregister(&disk->queue->backing_dev_info); | 206 | bdi_unregister(&disk->queue->backing_dev_info); |
207 | blk_unregister_queue(disk); | 207 | blk_unregister_queue(disk); |
208 | blk_unregister_region(MKDEV(disk->major, disk->first_minor), | 208 | blk_unregister_region(MKDEV(disk->major, disk->first_minor), |
209 | disk->minors); | 209 | disk->minors); |
210 | } | 210 | } |
211 | 211 | ||
212 | /** | 212 | /** |
213 | * get_gendisk - get partitioning information for a given device | 213 | * get_gendisk - get partitioning information for a given device |
214 | * @dev: device to get partitioning information for | 214 | * @dev: device to get partitioning information for |
215 | * | 215 | * |
216 | * This function gets the structure containing partitioning | 216 | * This function gets the structure containing partitioning |
217 | * information for the given device @dev. | 217 | * information for the given device @dev. |
218 | */ | 218 | */ |
219 | struct gendisk *get_gendisk(dev_t devt, int *part) | 219 | struct gendisk *get_gendisk(dev_t devt, int *part) |
220 | { | 220 | { |
221 | struct kobject *kobj = kobj_lookup(bdev_map, devt, part); | 221 | struct kobject *kobj = kobj_lookup(bdev_map, devt, part); |
222 | struct device *dev = kobj_to_dev(kobj); | 222 | struct device *dev = kobj_to_dev(kobj); |
223 | 223 | ||
224 | return kobj ? dev_to_disk(dev) : NULL; | 224 | return kobj ? dev_to_disk(dev) : NULL; |
225 | } | 225 | } |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * print a full list of all partitions - intended for places where the root | 228 | * print a full list of all partitions - intended for places where the root |
229 | * filesystem can't be mounted and thus to give the victim some idea of what | 229 | * filesystem can't be mounted and thus to give the victim some idea of what |
230 | * went wrong | 230 | * went wrong |
231 | */ | 231 | */ |
232 | void __init printk_all_partitions(void) | 232 | void __init printk_all_partitions(void) |
233 | { | 233 | { |
234 | struct device *dev; | 234 | struct device *dev; |
235 | struct gendisk *sgp; | 235 | struct gendisk *sgp; |
236 | char buf[BDEVNAME_SIZE]; | 236 | char buf[BDEVNAME_SIZE]; |
237 | int n; | 237 | int n; |
238 | 238 | ||
239 | mutex_lock(&block_class_lock); | 239 | mutex_lock(&block_class_lock); |
240 | /* For each block device... */ | 240 | /* For each block device... */ |
241 | list_for_each_entry(dev, &block_class.devices, node) { | 241 | list_for_each_entry(dev, &block_class.devices, node) { |
242 | if (dev->type != &disk_type) | 242 | if (dev->type != &disk_type) |
243 | continue; | 243 | continue; |
244 | sgp = dev_to_disk(dev); | 244 | sgp = dev_to_disk(dev); |
245 | /* | 245 | /* |
246 | * Don't show empty devices or things that have been surpressed | 246 | * Don't show empty devices or things that have been surpressed |
247 | */ | 247 | */ |
248 | if (get_capacity(sgp) == 0 || | 248 | if (get_capacity(sgp) == 0 || |
249 | (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) | 249 | (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) |
250 | continue; | 250 | continue; |
251 | 251 | ||
252 | /* | 252 | /* |
253 | * Note, unlike /proc/partitions, I am showing the numbers in | 253 | * Note, unlike /proc/partitions, I am showing the numbers in |
254 | * hex - the same format as the root= option takes. | 254 | * hex - the same format as the root= option takes. |
255 | */ | 255 | */ |
256 | printk("%02x%02x %10llu %s", | 256 | printk("%02x%02x %10llu %s", |
257 | sgp->major, sgp->first_minor, | 257 | sgp->major, sgp->first_minor, |
258 | (unsigned long long)get_capacity(sgp) >> 1, | 258 | (unsigned long long)get_capacity(sgp) >> 1, |
259 | disk_name(sgp, 0, buf)); | 259 | disk_name(sgp, 0, buf)); |
260 | if (sgp->driverfs_dev != NULL && | 260 | if (sgp->driverfs_dev != NULL && |
261 | sgp->driverfs_dev->driver != NULL) | 261 | sgp->driverfs_dev->driver != NULL) |
262 | printk(" driver: %s\n", | 262 | printk(" driver: %s\n", |
263 | sgp->driverfs_dev->driver->name); | 263 | sgp->driverfs_dev->driver->name); |
264 | else | 264 | else |
265 | printk(" (driver?)\n"); | 265 | printk(" (driver?)\n"); |
266 | 266 | ||
267 | /* now show the partitions */ | 267 | /* now show the partitions */ |
268 | for (n = 0; n < sgp->minors - 1; ++n) { | 268 | for (n = 0; n < sgp->minors - 1; ++n) { |
269 | if (sgp->part[n] == NULL) | 269 | if (sgp->part[n] == NULL) |
270 | continue; | 270 | continue; |
271 | if (sgp->part[n]->nr_sects == 0) | 271 | if (sgp->part[n]->nr_sects == 0) |
272 | continue; | 272 | continue; |
273 | printk(" %02x%02x %10llu %s\n", | 273 | printk(" %02x%02x %10llu %s\n", |
274 | sgp->major, n + 1 + sgp->first_minor, | 274 | sgp->major, n + 1 + sgp->first_minor, |
275 | (unsigned long long)sgp->part[n]->nr_sects >> 1, | 275 | (unsigned long long)sgp->part[n]->nr_sects >> 1, |
276 | disk_name(sgp, n + 1, buf)); | 276 | disk_name(sgp, n + 1, buf)); |
277 | } | 277 | } |
278 | } | 278 | } |
279 | 279 | ||
280 | mutex_unlock(&block_class_lock); | 280 | mutex_unlock(&block_class_lock); |
281 | } | 281 | } |
282 | 282 | ||
283 | #ifdef CONFIG_PROC_FS | 283 | #ifdef CONFIG_PROC_FS |
284 | /* iterator */ | 284 | /* iterator */ |
285 | static void *part_start(struct seq_file *part, loff_t *pos) | 285 | static void *part_start(struct seq_file *part, loff_t *pos) |
286 | { | 286 | { |
287 | loff_t k = *pos; | 287 | loff_t k = *pos; |
288 | struct device *dev; | 288 | struct device *dev; |
289 | 289 | ||
290 | mutex_lock(&block_class_lock); | 290 | mutex_lock(&block_class_lock); |
291 | list_for_each_entry(dev, &block_class.devices, node) { | 291 | list_for_each_entry(dev, &block_class.devices, node) { |
292 | if (dev->type != &disk_type) | 292 | if (dev->type != &disk_type) |
293 | continue; | 293 | continue; |
294 | if (!k--) | 294 | if (!k--) |
295 | return dev_to_disk(dev); | 295 | return dev_to_disk(dev); |
296 | } | 296 | } |
297 | return NULL; | 297 | return NULL; |
298 | } | 298 | } |
299 | 299 | ||
300 | static void *part_next(struct seq_file *part, void *v, loff_t *pos) | 300 | static void *part_next(struct seq_file *part, void *v, loff_t *pos) |
301 | { | 301 | { |
302 | struct gendisk *gp = v; | 302 | struct gendisk *gp = v; |
303 | struct device *dev; | 303 | struct device *dev; |
304 | ++*pos; | 304 | ++*pos; |
305 | list_for_each_entry(dev, &gp->dev.node, node) { | 305 | list_for_each_entry(dev, &gp->dev.node, node) { |
306 | if (&dev->node == &block_class.devices) | 306 | if (&dev->node == &block_class.devices) |
307 | return NULL; | 307 | return NULL; |
308 | if (dev->type == &disk_type) | 308 | if (dev->type == &disk_type) |
309 | return dev_to_disk(dev); | 309 | return dev_to_disk(dev); |
310 | } | 310 | } |
311 | return NULL; | 311 | return NULL; |
312 | } | 312 | } |
313 | 313 | ||
314 | static void part_stop(struct seq_file *part, void *v) | 314 | static void part_stop(struct seq_file *part, void *v) |
315 | { | 315 | { |
316 | mutex_unlock(&block_class_lock); | 316 | mutex_unlock(&block_class_lock); |
317 | } | 317 | } |
318 | 318 | ||
319 | static int show_partition(struct seq_file *part, void *v) | 319 | static int show_partition(struct seq_file *part, void *v) |
320 | { | 320 | { |
321 | struct gendisk *sgp = v; | 321 | struct gendisk *sgp = v; |
322 | int n; | 322 | int n; |
323 | char buf[BDEVNAME_SIZE]; | 323 | char buf[BDEVNAME_SIZE]; |
324 | 324 | ||
325 | if (&sgp->dev.node == block_class.devices.next) | 325 | if (&sgp->dev.node == block_class.devices.next) |
326 | seq_puts(part, "major minor #blocks name\n\n"); | 326 | seq_puts(part, "major minor #blocks name\n\n"); |
327 | 327 | ||
328 | /* Don't show non-partitionable removeable devices or empty devices */ | 328 | /* Don't show non-partitionable removeable devices or empty devices */ |
329 | if (!get_capacity(sgp) || | 329 | if (!get_capacity(sgp) || |
330 | (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) | 330 | (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) |
331 | return 0; | 331 | return 0; |
332 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) | 332 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) |
333 | return 0; | 333 | return 0; |
334 | 334 | ||
335 | /* show the full disk and all non-0 size partitions of it */ | 335 | /* show the full disk and all non-0 size partitions of it */ |
336 | seq_printf(part, "%4d %4d %10llu %s\n", | 336 | seq_printf(part, "%4d %4d %10llu %s\n", |
337 | sgp->major, sgp->first_minor, | 337 | sgp->major, sgp->first_minor, |
338 | (unsigned long long)get_capacity(sgp) >> 1, | 338 | (unsigned long long)get_capacity(sgp) >> 1, |
339 | disk_name(sgp, 0, buf)); | 339 | disk_name(sgp, 0, buf)); |
340 | for (n = 0; n < sgp->minors - 1; n++) { | 340 | for (n = 0; n < sgp->minors - 1; n++) { |
341 | if (!sgp->part[n]) | 341 | if (!sgp->part[n]) |
342 | continue; | 342 | continue; |
343 | if (sgp->part[n]->nr_sects == 0) | 343 | if (sgp->part[n]->nr_sects == 0) |
344 | continue; | 344 | continue; |
345 | seq_printf(part, "%4d %4d %10llu %s\n", | 345 | seq_printf(part, "%4d %4d %10llu %s\n", |
346 | sgp->major, n + 1 + sgp->first_minor, | 346 | sgp->major, n + 1 + sgp->first_minor, |
347 | (unsigned long long)sgp->part[n]->nr_sects >> 1 , | 347 | (unsigned long long)sgp->part[n]->nr_sects >> 1 , |
348 | disk_name(sgp, n + 1, buf)); | 348 | disk_name(sgp, n + 1, buf)); |
349 | } | 349 | } |
350 | 350 | ||
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
353 | 353 | ||
354 | const struct seq_operations partitions_op = { | 354 | const struct seq_operations partitions_op = { |
355 | .start = part_start, | 355 | .start = part_start, |
356 | .next = part_next, | 356 | .next = part_next, |
357 | .stop = part_stop, | 357 | .stop = part_stop, |
358 | .show = show_partition | 358 | .show = show_partition |
359 | }; | 359 | }; |
360 | #endif | 360 | #endif |
361 | 361 | ||
362 | 362 | ||
363 | static struct kobject *base_probe(dev_t devt, int *part, void *data) | 363 | static struct kobject *base_probe(dev_t devt, int *part, void *data) |
364 | { | 364 | { |
365 | if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) | 365 | if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) |
366 | /* Make old-style 2.4 aliases work */ | 366 | /* Make old-style 2.4 aliases work */ |
367 | request_module("block-major-%d", MAJOR(devt)); | 367 | request_module("block-major-%d", MAJOR(devt)); |
368 | return NULL; | 368 | return NULL; |
369 | } | 369 | } |
370 | 370 | ||
371 | static int __init genhd_device_init(void) | 371 | static int __init genhd_device_init(void) |
372 | { | 372 | { |
373 | int error = class_register(&block_class); | 373 | int error; |
374 | |||
375 | block_class.dev_kobj = sysfs_dev_block_kobj; | ||
376 | error = class_register(&block_class); | ||
374 | if (unlikely(error)) | 377 | if (unlikely(error)) |
375 | return error; | 378 | return error; |
376 | bdev_map = kobj_map_init(base_probe, &block_class_lock); | 379 | bdev_map = kobj_map_init(base_probe, &block_class_lock); |
377 | blk_dev_init(); | 380 | blk_dev_init(); |
378 | 381 | ||
379 | #ifndef CONFIG_SYSFS_DEPRECATED | 382 | #ifndef CONFIG_SYSFS_DEPRECATED |
380 | /* create top-level block dir */ | 383 | /* create top-level block dir */ |
381 | block_depr = kobject_create_and_add("block", NULL); | 384 | block_depr = kobject_create_and_add("block", NULL); |
382 | #endif | 385 | #endif |
383 | return 0; | 386 | return 0; |
384 | } | 387 | } |
385 | 388 | ||
386 | subsys_initcall(genhd_device_init); | 389 | subsys_initcall(genhd_device_init); |
387 | 390 | ||
388 | static ssize_t disk_range_show(struct device *dev, | 391 | static ssize_t disk_range_show(struct device *dev, |
389 | struct device_attribute *attr, char *buf) | 392 | struct device_attribute *attr, char *buf) |
390 | { | 393 | { |
391 | struct gendisk *disk = dev_to_disk(dev); | 394 | struct gendisk *disk = dev_to_disk(dev); |
392 | 395 | ||
393 | return sprintf(buf, "%d\n", disk->minors); | 396 | return sprintf(buf, "%d\n", disk->minors); |
394 | } | 397 | } |
395 | 398 | ||
396 | static ssize_t disk_removable_show(struct device *dev, | 399 | static ssize_t disk_removable_show(struct device *dev, |
397 | struct device_attribute *attr, char *buf) | 400 | struct device_attribute *attr, char *buf) |
398 | { | 401 | { |
399 | struct gendisk *disk = dev_to_disk(dev); | 402 | struct gendisk *disk = dev_to_disk(dev); |
400 | 403 | ||
401 | return sprintf(buf, "%d\n", | 404 | return sprintf(buf, "%d\n", |
402 | (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); | 405 | (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); |
403 | } | 406 | } |
404 | 407 | ||
405 | static ssize_t disk_ro_show(struct device *dev, | 408 | static ssize_t disk_ro_show(struct device *dev, |
406 | struct device_attribute *attr, char *buf) | 409 | struct device_attribute *attr, char *buf) |
407 | { | 410 | { |
408 | struct gendisk *disk = dev_to_disk(dev); | 411 | struct gendisk *disk = dev_to_disk(dev); |
409 | 412 | ||
410 | return sprintf(buf, "%d\n", disk->policy ? 1 : 0); | 413 | return sprintf(buf, "%d\n", disk->policy ? 1 : 0); |
411 | } | 414 | } |
412 | 415 | ||
413 | static ssize_t disk_size_show(struct device *dev, | 416 | static ssize_t disk_size_show(struct device *dev, |
414 | struct device_attribute *attr, char *buf) | 417 | struct device_attribute *attr, char *buf) |
415 | { | 418 | { |
416 | struct gendisk *disk = dev_to_disk(dev); | 419 | struct gendisk *disk = dev_to_disk(dev); |
417 | 420 | ||
418 | return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk)); | 421 | return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk)); |
419 | } | 422 | } |
420 | 423 | ||
421 | static ssize_t disk_capability_show(struct device *dev, | 424 | static ssize_t disk_capability_show(struct device *dev, |
422 | struct device_attribute *attr, char *buf) | 425 | struct device_attribute *attr, char *buf) |
423 | { | 426 | { |
424 | struct gendisk *disk = dev_to_disk(dev); | 427 | struct gendisk *disk = dev_to_disk(dev); |
425 | 428 | ||
426 | return sprintf(buf, "%x\n", disk->flags); | 429 | return sprintf(buf, "%x\n", disk->flags); |
427 | } | 430 | } |
428 | 431 | ||
429 | static ssize_t disk_stat_show(struct device *dev, | 432 | static ssize_t disk_stat_show(struct device *dev, |
430 | struct device_attribute *attr, char *buf) | 433 | struct device_attribute *attr, char *buf) |
431 | { | 434 | { |
432 | struct gendisk *disk = dev_to_disk(dev); | 435 | struct gendisk *disk = dev_to_disk(dev); |
433 | 436 | ||
434 | preempt_disable(); | 437 | preempt_disable(); |
435 | disk_round_stats(disk); | 438 | disk_round_stats(disk); |
436 | preempt_enable(); | 439 | preempt_enable(); |
437 | return sprintf(buf, | 440 | return sprintf(buf, |
438 | "%8lu %8lu %8llu %8u " | 441 | "%8lu %8lu %8llu %8u " |
439 | "%8lu %8lu %8llu %8u " | 442 | "%8lu %8lu %8llu %8u " |
440 | "%8u %8u %8u" | 443 | "%8u %8u %8u" |
441 | "\n", | 444 | "\n", |
442 | disk_stat_read(disk, ios[READ]), | 445 | disk_stat_read(disk, ios[READ]), |
443 | disk_stat_read(disk, merges[READ]), | 446 | disk_stat_read(disk, merges[READ]), |
444 | (unsigned long long)disk_stat_read(disk, sectors[READ]), | 447 | (unsigned long long)disk_stat_read(disk, sectors[READ]), |
445 | jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), | 448 | jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), |
446 | disk_stat_read(disk, ios[WRITE]), | 449 | disk_stat_read(disk, ios[WRITE]), |
447 | disk_stat_read(disk, merges[WRITE]), | 450 | disk_stat_read(disk, merges[WRITE]), |
448 | (unsigned long long)disk_stat_read(disk, sectors[WRITE]), | 451 | (unsigned long long)disk_stat_read(disk, sectors[WRITE]), |
449 | jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), | 452 | jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), |
450 | disk->in_flight, | 453 | disk->in_flight, |
451 | jiffies_to_msecs(disk_stat_read(disk, io_ticks)), | 454 | jiffies_to_msecs(disk_stat_read(disk, io_ticks)), |
452 | jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); | 455 | jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); |
453 | } | 456 | } |
454 | 457 | ||
455 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 458 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
456 | static ssize_t disk_fail_show(struct device *dev, | 459 | static ssize_t disk_fail_show(struct device *dev, |
457 | struct device_attribute *attr, char *buf) | 460 | struct device_attribute *attr, char *buf) |
458 | { | 461 | { |
459 | struct gendisk *disk = dev_to_disk(dev); | 462 | struct gendisk *disk = dev_to_disk(dev); |
460 | 463 | ||
461 | return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); | 464 | return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); |
462 | } | 465 | } |
463 | 466 | ||
464 | static ssize_t disk_fail_store(struct device *dev, | 467 | static ssize_t disk_fail_store(struct device *dev, |
465 | struct device_attribute *attr, | 468 | struct device_attribute *attr, |
466 | const char *buf, size_t count) | 469 | const char *buf, size_t count) |
467 | { | 470 | { |
468 | struct gendisk *disk = dev_to_disk(dev); | 471 | struct gendisk *disk = dev_to_disk(dev); |
469 | int i; | 472 | int i; |
470 | 473 | ||
471 | if (count > 0 && sscanf(buf, "%d", &i) > 0) { | 474 | if (count > 0 && sscanf(buf, "%d", &i) > 0) { |
472 | if (i == 0) | 475 | if (i == 0) |
473 | disk->flags &= ~GENHD_FL_FAIL; | 476 | disk->flags &= ~GENHD_FL_FAIL; |
474 | else | 477 | else |
475 | disk->flags |= GENHD_FL_FAIL; | 478 | disk->flags |= GENHD_FL_FAIL; |
476 | } | 479 | } |
477 | 480 | ||
478 | return count; | 481 | return count; |
479 | } | 482 | } |
480 | 483 | ||
481 | #endif | 484 | #endif |
482 | 485 | ||
483 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); | 486 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); |
484 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); | 487 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); |
485 | static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); | 488 | static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); |
486 | static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); | 489 | static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); |
487 | static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); | 490 | static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); |
488 | static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); | 491 | static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); |
489 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 492 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
490 | static struct device_attribute dev_attr_fail = | 493 | static struct device_attribute dev_attr_fail = |
491 | __ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store); | 494 | __ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store); |
492 | #endif | 495 | #endif |
493 | 496 | ||
494 | static struct attribute *disk_attrs[] = { | 497 | static struct attribute *disk_attrs[] = { |
495 | &dev_attr_range.attr, | 498 | &dev_attr_range.attr, |
496 | &dev_attr_removable.attr, | 499 | &dev_attr_removable.attr, |
497 | &dev_attr_ro.attr, | 500 | &dev_attr_ro.attr, |
498 | &dev_attr_size.attr, | 501 | &dev_attr_size.attr, |
499 | &dev_attr_capability.attr, | 502 | &dev_attr_capability.attr, |
500 | &dev_attr_stat.attr, | 503 | &dev_attr_stat.attr, |
501 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 504 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
502 | &dev_attr_fail.attr, | 505 | &dev_attr_fail.attr, |
503 | #endif | 506 | #endif |
504 | NULL | 507 | NULL |
505 | }; | 508 | }; |
506 | 509 | ||
507 | static struct attribute_group disk_attr_group = { | 510 | static struct attribute_group disk_attr_group = { |
508 | .attrs = disk_attrs, | 511 | .attrs = disk_attrs, |
509 | }; | 512 | }; |
510 | 513 | ||
511 | static struct attribute_group *disk_attr_groups[] = { | 514 | static struct attribute_group *disk_attr_groups[] = { |
512 | &disk_attr_group, | 515 | &disk_attr_group, |
513 | NULL | 516 | NULL |
514 | }; | 517 | }; |
515 | 518 | ||
516 | static void disk_release(struct device *dev) | 519 | static void disk_release(struct device *dev) |
517 | { | 520 | { |
518 | struct gendisk *disk = dev_to_disk(dev); | 521 | struct gendisk *disk = dev_to_disk(dev); |
519 | 522 | ||
520 | kfree(disk->random); | 523 | kfree(disk->random); |
521 | kfree(disk->part); | 524 | kfree(disk->part); |
522 | free_disk_stats(disk); | 525 | free_disk_stats(disk); |
523 | kfree(disk); | 526 | kfree(disk); |
524 | } | 527 | } |
525 | struct class block_class = { | 528 | struct class block_class = { |
526 | .name = "block", | 529 | .name = "block", |
527 | }; | 530 | }; |
528 | 531 | ||
529 | static struct device_type disk_type = { | 532 | static struct device_type disk_type = { |
530 | .name = "disk", | 533 | .name = "disk", |
531 | .groups = disk_attr_groups, | 534 | .groups = disk_attr_groups, |
532 | .release = disk_release, | 535 | .release = disk_release, |
533 | }; | 536 | }; |
534 | 537 | ||
535 | /* | 538 | /* |
536 | * aggregate disk stat collector. Uses the same stats that the sysfs | 539 | * aggregate disk stat collector. Uses the same stats that the sysfs |
537 | * entries do, above, but makes them available through one seq_file. | 540 | * entries do, above, but makes them available through one seq_file. |
538 | * | 541 | * |
539 | * The output looks suspiciously like /proc/partitions with a bunch of | 542 | * The output looks suspiciously like /proc/partitions with a bunch of |
540 | * extra fields. | 543 | * extra fields. |
541 | */ | 544 | */ |
542 | 545 | ||
543 | static void *diskstats_start(struct seq_file *part, loff_t *pos) | 546 | static void *diskstats_start(struct seq_file *part, loff_t *pos) |
544 | { | 547 | { |
545 | loff_t k = *pos; | 548 | loff_t k = *pos; |
546 | struct device *dev; | 549 | struct device *dev; |
547 | 550 | ||
548 | mutex_lock(&block_class_lock); | 551 | mutex_lock(&block_class_lock); |
549 | list_for_each_entry(dev, &block_class.devices, node) { | 552 | list_for_each_entry(dev, &block_class.devices, node) { |
550 | if (dev->type != &disk_type) | 553 | if (dev->type != &disk_type) |
551 | continue; | 554 | continue; |
552 | if (!k--) | 555 | if (!k--) |
553 | return dev_to_disk(dev); | 556 | return dev_to_disk(dev); |
554 | } | 557 | } |
555 | return NULL; | 558 | return NULL; |
556 | } | 559 | } |
557 | 560 | ||
558 | static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) | 561 | static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) |
559 | { | 562 | { |
560 | struct gendisk *gp = v; | 563 | struct gendisk *gp = v; |
561 | struct device *dev; | 564 | struct device *dev; |
562 | 565 | ||
563 | ++*pos; | 566 | ++*pos; |
564 | list_for_each_entry(dev, &gp->dev.node, node) { | 567 | list_for_each_entry(dev, &gp->dev.node, node) { |
565 | if (&dev->node == &block_class.devices) | 568 | if (&dev->node == &block_class.devices) |
566 | return NULL; | 569 | return NULL; |
567 | if (dev->type == &disk_type) | 570 | if (dev->type == &disk_type) |
568 | return dev_to_disk(dev); | 571 | return dev_to_disk(dev); |
569 | } | 572 | } |
570 | return NULL; | 573 | return NULL; |
571 | } | 574 | } |
572 | 575 | ||
573 | static void diskstats_stop(struct seq_file *part, void *v) | 576 | static void diskstats_stop(struct seq_file *part, void *v) |
574 | { | 577 | { |
575 | mutex_unlock(&block_class_lock); | 578 | mutex_unlock(&block_class_lock); |
576 | } | 579 | } |
577 | 580 | ||
578 | static int diskstats_show(struct seq_file *s, void *v) | 581 | static int diskstats_show(struct seq_file *s, void *v) |
579 | { | 582 | { |
580 | struct gendisk *gp = v; | 583 | struct gendisk *gp = v; |
581 | char buf[BDEVNAME_SIZE]; | 584 | char buf[BDEVNAME_SIZE]; |
582 | int n = 0; | 585 | int n = 0; |
583 | 586 | ||
584 | /* | 587 | /* |
585 | if (&gp->dev.kobj.entry == block_class.devices.next) | 588 | if (&gp->dev.kobj.entry == block_class.devices.next) |
586 | seq_puts(s, "major minor name" | 589 | seq_puts(s, "major minor name" |
587 | " rio rmerge rsect ruse wio wmerge " | 590 | " rio rmerge rsect ruse wio wmerge " |
588 | "wsect wuse running use aveq" | 591 | "wsect wuse running use aveq" |
589 | "\n\n"); | 592 | "\n\n"); |
590 | */ | 593 | */ |
591 | 594 | ||
592 | preempt_disable(); | 595 | preempt_disable(); |
593 | disk_round_stats(gp); | 596 | disk_round_stats(gp); |
594 | preempt_enable(); | 597 | preempt_enable(); |
595 | seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", | 598 | seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", |
596 | gp->major, n + gp->first_minor, disk_name(gp, n, buf), | 599 | gp->major, n + gp->first_minor, disk_name(gp, n, buf), |
597 | disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), | 600 | disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), |
598 | (unsigned long long)disk_stat_read(gp, sectors[0]), | 601 | (unsigned long long)disk_stat_read(gp, sectors[0]), |
599 | jiffies_to_msecs(disk_stat_read(gp, ticks[0])), | 602 | jiffies_to_msecs(disk_stat_read(gp, ticks[0])), |
600 | disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), | 603 | disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), |
601 | (unsigned long long)disk_stat_read(gp, sectors[1]), | 604 | (unsigned long long)disk_stat_read(gp, sectors[1]), |
602 | jiffies_to_msecs(disk_stat_read(gp, ticks[1])), | 605 | jiffies_to_msecs(disk_stat_read(gp, ticks[1])), |
603 | gp->in_flight, | 606 | gp->in_flight, |
604 | jiffies_to_msecs(disk_stat_read(gp, io_ticks)), | 607 | jiffies_to_msecs(disk_stat_read(gp, io_ticks)), |
605 | jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); | 608 | jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); |
606 | 609 | ||
607 | /* now show all non-0 size partitions of it */ | 610 | /* now show all non-0 size partitions of it */ |
608 | for (n = 0; n < gp->minors - 1; n++) { | 611 | for (n = 0; n < gp->minors - 1; n++) { |
609 | struct hd_struct *hd = gp->part[n]; | 612 | struct hd_struct *hd = gp->part[n]; |
610 | 613 | ||
611 | if (!hd || !hd->nr_sects) | 614 | if (!hd || !hd->nr_sects) |
612 | continue; | 615 | continue; |
613 | 616 | ||
614 | preempt_disable(); | 617 | preempt_disable(); |
615 | part_round_stats(hd); | 618 | part_round_stats(hd); |
616 | preempt_enable(); | 619 | preempt_enable(); |
617 | seq_printf(s, "%4d %4d %s %lu %lu %llu " | 620 | seq_printf(s, "%4d %4d %s %lu %lu %llu " |
618 | "%u %lu %lu %llu %u %u %u %u\n", | 621 | "%u %lu %lu %llu %u %u %u %u\n", |
619 | gp->major, n + gp->first_minor + 1, | 622 | gp->major, n + gp->first_minor + 1, |
620 | disk_name(gp, n + 1, buf), | 623 | disk_name(gp, n + 1, buf), |
621 | part_stat_read(hd, ios[0]), | 624 | part_stat_read(hd, ios[0]), |
622 | part_stat_read(hd, merges[0]), | 625 | part_stat_read(hd, merges[0]), |
623 | (unsigned long long)part_stat_read(hd, sectors[0]), | 626 | (unsigned long long)part_stat_read(hd, sectors[0]), |
624 | jiffies_to_msecs(part_stat_read(hd, ticks[0])), | 627 | jiffies_to_msecs(part_stat_read(hd, ticks[0])), |
625 | part_stat_read(hd, ios[1]), | 628 | part_stat_read(hd, ios[1]), |
626 | part_stat_read(hd, merges[1]), | 629 | part_stat_read(hd, merges[1]), |
627 | (unsigned long long)part_stat_read(hd, sectors[1]), | 630 | (unsigned long long)part_stat_read(hd, sectors[1]), |
628 | jiffies_to_msecs(part_stat_read(hd, ticks[1])), | 631 | jiffies_to_msecs(part_stat_read(hd, ticks[1])), |
629 | hd->in_flight, | 632 | hd->in_flight, |
630 | jiffies_to_msecs(part_stat_read(hd, io_ticks)), | 633 | jiffies_to_msecs(part_stat_read(hd, io_ticks)), |
631 | jiffies_to_msecs(part_stat_read(hd, time_in_queue)) | 634 | jiffies_to_msecs(part_stat_read(hd, time_in_queue)) |
632 | ); | 635 | ); |
633 | } | 636 | } |
634 | 637 | ||
635 | return 0; | 638 | return 0; |
636 | } | 639 | } |
637 | 640 | ||
638 | const struct seq_operations diskstats_op = { | 641 | const struct seq_operations diskstats_op = { |
639 | .start = diskstats_start, | 642 | .start = diskstats_start, |
640 | .next = diskstats_next, | 643 | .next = diskstats_next, |
641 | .stop = diskstats_stop, | 644 | .stop = diskstats_stop, |
642 | .show = diskstats_show | 645 | .show = diskstats_show |
643 | }; | 646 | }; |
644 | 647 | ||
645 | static void media_change_notify_thread(struct work_struct *work) | 648 | static void media_change_notify_thread(struct work_struct *work) |
646 | { | 649 | { |
647 | struct gendisk *gd = container_of(work, struct gendisk, async_notify); | 650 | struct gendisk *gd = container_of(work, struct gendisk, async_notify); |
648 | char event[] = "MEDIA_CHANGE=1"; | 651 | char event[] = "MEDIA_CHANGE=1"; |
649 | char *envp[] = { event, NULL }; | 652 | char *envp[] = { event, NULL }; |
650 | 653 | ||
651 | /* | 654 | /* |
652 | * set enviroment vars to indicate which event this is for | 655 | * set enviroment vars to indicate which event this is for |
653 | * so that user space will know to go check the media status. | 656 | * so that user space will know to go check the media status. |
654 | */ | 657 | */ |
655 | kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp); | 658 | kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp); |
656 | put_device(gd->driverfs_dev); | 659 | put_device(gd->driverfs_dev); |
657 | } | 660 | } |
658 | 661 | ||
659 | #if 0 | 662 | #if 0 |
660 | void genhd_media_change_notify(struct gendisk *disk) | 663 | void genhd_media_change_notify(struct gendisk *disk) |
661 | { | 664 | { |
662 | get_device(disk->driverfs_dev); | 665 | get_device(disk->driverfs_dev); |
663 | schedule_work(&disk->async_notify); | 666 | schedule_work(&disk->async_notify); |
664 | } | 667 | } |
665 | EXPORT_SYMBOL_GPL(genhd_media_change_notify); | 668 | EXPORT_SYMBOL_GPL(genhd_media_change_notify); |
666 | #endif /* 0 */ | 669 | #endif /* 0 */ |
667 | 670 | ||
668 | dev_t blk_lookup_devt(const char *name, int part) | 671 | dev_t blk_lookup_devt(const char *name, int part) |
669 | { | 672 | { |
670 | struct device *dev; | 673 | struct device *dev; |
671 | dev_t devt = MKDEV(0, 0); | 674 | dev_t devt = MKDEV(0, 0); |
672 | 675 | ||
673 | mutex_lock(&block_class_lock); | 676 | mutex_lock(&block_class_lock); |
674 | list_for_each_entry(dev, &block_class.devices, node) { | 677 | list_for_each_entry(dev, &block_class.devices, node) { |
675 | if (dev->type != &disk_type) | 678 | if (dev->type != &disk_type) |
676 | continue; | 679 | continue; |
677 | if (strcmp(dev->bus_id, name) == 0) { | 680 | if (strcmp(dev->bus_id, name) == 0) { |
678 | struct gendisk *disk = dev_to_disk(dev); | 681 | struct gendisk *disk = dev_to_disk(dev); |
679 | 682 | ||
680 | if (part < disk->minors) | 683 | if (part < disk->minors) |
681 | devt = MKDEV(MAJOR(dev->devt), | 684 | devt = MKDEV(MAJOR(dev->devt), |
682 | MINOR(dev->devt) + part); | 685 | MINOR(dev->devt) + part); |
683 | break; | 686 | break; |
684 | } | 687 | } |
685 | } | 688 | } |
686 | mutex_unlock(&block_class_lock); | 689 | mutex_unlock(&block_class_lock); |
687 | 690 | ||
688 | return devt; | 691 | return devt; |
689 | } | 692 | } |
690 | EXPORT_SYMBOL(blk_lookup_devt); | 693 | EXPORT_SYMBOL(blk_lookup_devt); |
691 | 694 | ||
692 | struct gendisk *alloc_disk(int minors) | 695 | struct gendisk *alloc_disk(int minors) |
693 | { | 696 | { |
694 | return alloc_disk_node(minors, -1); | 697 | return alloc_disk_node(minors, -1); |
695 | } | 698 | } |
696 | 699 | ||
697 | struct gendisk *alloc_disk_node(int minors, int node_id) | 700 | struct gendisk *alloc_disk_node(int minors, int node_id) |
698 | { | 701 | { |
699 | struct gendisk *disk; | 702 | struct gendisk *disk; |
700 | 703 | ||
701 | disk = kmalloc_node(sizeof(struct gendisk), | 704 | disk = kmalloc_node(sizeof(struct gendisk), |
702 | GFP_KERNEL | __GFP_ZERO, node_id); | 705 | GFP_KERNEL | __GFP_ZERO, node_id); |
703 | if (disk) { | 706 | if (disk) { |
704 | if (!init_disk_stats(disk)) { | 707 | if (!init_disk_stats(disk)) { |
705 | kfree(disk); | 708 | kfree(disk); |
706 | return NULL; | 709 | return NULL; |
707 | } | 710 | } |
708 | if (minors > 1) { | 711 | if (minors > 1) { |
709 | int size = (minors - 1) * sizeof(struct hd_struct *); | 712 | int size = (minors - 1) * sizeof(struct hd_struct *); |
710 | disk->part = kmalloc_node(size, | 713 | disk->part = kmalloc_node(size, |
711 | GFP_KERNEL | __GFP_ZERO, node_id); | 714 | GFP_KERNEL | __GFP_ZERO, node_id); |
712 | if (!disk->part) { | 715 | if (!disk->part) { |
713 | free_disk_stats(disk); | 716 | free_disk_stats(disk); |
714 | kfree(disk); | 717 | kfree(disk); |
715 | return NULL; | 718 | return NULL; |
716 | } | 719 | } |
717 | } | 720 | } |
718 | disk->minors = minors; | 721 | disk->minors = minors; |
719 | rand_initialize_disk(disk); | 722 | rand_initialize_disk(disk); |
720 | disk->dev.class = &block_class; | 723 | disk->dev.class = &block_class; |
721 | disk->dev.type = &disk_type; | 724 | disk->dev.type = &disk_type; |
722 | device_initialize(&disk->dev); | 725 | device_initialize(&disk->dev); |
723 | INIT_WORK(&disk->async_notify, | 726 | INIT_WORK(&disk->async_notify, |
724 | media_change_notify_thread); | 727 | media_change_notify_thread); |
725 | } | 728 | } |
726 | return disk; | 729 | return disk; |
727 | } | 730 | } |
728 | 731 | ||
729 | EXPORT_SYMBOL(alloc_disk); | 732 | EXPORT_SYMBOL(alloc_disk); |
730 | EXPORT_SYMBOL(alloc_disk_node); | 733 | EXPORT_SYMBOL(alloc_disk_node); |
731 | 734 | ||
732 | struct kobject *get_disk(struct gendisk *disk) | 735 | struct kobject *get_disk(struct gendisk *disk) |
733 | { | 736 | { |
734 | struct module *owner; | 737 | struct module *owner; |
735 | struct kobject *kobj; | 738 | struct kobject *kobj; |
736 | 739 | ||
737 | if (!disk->fops) | 740 | if (!disk->fops) |
738 | return NULL; | 741 | return NULL; |
739 | owner = disk->fops->owner; | 742 | owner = disk->fops->owner; |
740 | if (owner && !try_module_get(owner)) | 743 | if (owner && !try_module_get(owner)) |
741 | return NULL; | 744 | return NULL; |
742 | kobj = kobject_get(&disk->dev.kobj); | 745 | kobj = kobject_get(&disk->dev.kobj); |
743 | if (kobj == NULL) { | 746 | if (kobj == NULL) { |
744 | module_put(owner); | 747 | module_put(owner); |
745 | return NULL; | 748 | return NULL; |
746 | } | 749 | } |
747 | return kobj; | 750 | return kobj; |
748 | 751 | ||
749 | } | 752 | } |
750 | 753 | ||
751 | EXPORT_SYMBOL(get_disk); | 754 | EXPORT_SYMBOL(get_disk); |
752 | 755 | ||
753 | void put_disk(struct gendisk *disk) | 756 | void put_disk(struct gendisk *disk) |
754 | { | 757 | { |
755 | if (disk) | 758 | if (disk) |
756 | kobject_put(&disk->dev.kobj); | 759 | kobject_put(&disk->dev.kobj); |
757 | } | 760 | } |
758 | 761 | ||
759 | EXPORT_SYMBOL(put_disk); | 762 | EXPORT_SYMBOL(put_disk); |
760 | 763 | ||
761 | void set_device_ro(struct block_device *bdev, int flag) | 764 | void set_device_ro(struct block_device *bdev, int flag) |
762 | { | 765 | { |
763 | if (bdev->bd_contains != bdev) | 766 | if (bdev->bd_contains != bdev) |
764 | bdev->bd_part->policy = flag; | 767 | bdev->bd_part->policy = flag; |
765 | else | 768 | else |
766 | bdev->bd_disk->policy = flag; | 769 | bdev->bd_disk->policy = flag; |
767 | } | 770 | } |
768 | 771 | ||
769 | EXPORT_SYMBOL(set_device_ro); | 772 | EXPORT_SYMBOL(set_device_ro); |
770 | 773 | ||
771 | void set_disk_ro(struct gendisk *disk, int flag) | 774 | void set_disk_ro(struct gendisk *disk, int flag) |
772 | { | 775 | { |
773 | int i; | 776 | int i; |
774 | disk->policy = flag; | 777 | disk->policy = flag; |
775 | for (i = 0; i < disk->minors - 1; i++) | 778 | for (i = 0; i < disk->minors - 1; i++) |
776 | if (disk->part[i]) disk->part[i]->policy = flag; | 779 | if (disk->part[i]) disk->part[i]->policy = flag; |
777 | } | 780 | } |
778 | 781 | ||
779 | EXPORT_SYMBOL(set_disk_ro); | 782 | EXPORT_SYMBOL(set_disk_ro); |
780 | 783 | ||
781 | int bdev_read_only(struct block_device *bdev) | 784 | int bdev_read_only(struct block_device *bdev) |
782 | { | 785 | { |
783 | if (!bdev) | 786 | if (!bdev) |
784 | return 0; | 787 | return 0; |
785 | else if (bdev->bd_contains != bdev) | 788 | else if (bdev->bd_contains != bdev) |
786 | return bdev->bd_part->policy; | 789 | return bdev->bd_part->policy; |
787 | else | 790 | else |
788 | return bdev->bd_disk->policy; | 791 | return bdev->bd_disk->policy; |
789 | } | 792 | } |
790 | 793 | ||
791 | EXPORT_SYMBOL(bdev_read_only); | 794 | EXPORT_SYMBOL(bdev_read_only); |
792 | 795 | ||
793 | int invalidate_partition(struct gendisk *disk, int index) | 796 | int invalidate_partition(struct gendisk *disk, int index) |
794 | { | 797 | { |
795 | int res = 0; | 798 | int res = 0; |
796 | struct block_device *bdev = bdget_disk(disk, index); | 799 | struct block_device *bdev = bdget_disk(disk, index); |
797 | if (bdev) { | 800 | if (bdev) { |
798 | fsync_bdev(bdev); | 801 | fsync_bdev(bdev); |
799 | res = __invalidate_device(bdev); | 802 | res = __invalidate_device(bdev); |
800 | bdput(bdev); | 803 | bdput(bdev); |
801 | } | 804 | } |
802 | return res; | 805 | return res; |
803 | } | 806 | } |
804 | 807 | ||
805 | EXPORT_SYMBOL(invalidate_partition); | 808 | EXPORT_SYMBOL(invalidate_partition); |
806 | 809 |
drivers/base/class.c
1 | /* | 1 | /* |
2 | * class.c - basic device class management | 2 | * class.c - basic device class management |
3 | * | 3 | * |
4 | * Copyright (c) 2002-3 Patrick Mochel | 4 | * Copyright (c) 2002-3 Patrick Mochel |
5 | * Copyright (c) 2002-3 Open Source Development Labs | 5 | * Copyright (c) 2002-3 Open Source Development Labs |
6 | * Copyright (c) 2003-2004 Greg Kroah-Hartman | 6 | * Copyright (c) 2003-2004 Greg Kroah-Hartman |
7 | * Copyright (c) 2003-2004 IBM Corp. | 7 | * Copyright (c) 2003-2004 IBM Corp. |
8 | * | 8 | * |
9 | * This file is released under the GPLv2 | 9 | * This file is released under the GPLv2 |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/kdev_t.h> | 17 | #include <linux/kdev_t.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/genhd.h> | 20 | #include <linux/genhd.h> |
21 | #include "base.h" | 21 | #include "base.h" |
22 | 22 | ||
23 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) | 23 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) |
24 | #define to_class(obj) container_of(obj, struct class, subsys.kobj) | 24 | #define to_class(obj) container_of(obj, struct class, subsys.kobj) |
25 | 25 | ||
26 | static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, | 26 | static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, |
27 | char *buf) | 27 | char *buf) |
28 | { | 28 | { |
29 | struct class_attribute *class_attr = to_class_attr(attr); | 29 | struct class_attribute *class_attr = to_class_attr(attr); |
30 | struct class *dc = to_class(kobj); | 30 | struct class *dc = to_class(kobj); |
31 | ssize_t ret = -EIO; | 31 | ssize_t ret = -EIO; |
32 | 32 | ||
33 | if (class_attr->show) | 33 | if (class_attr->show) |
34 | ret = class_attr->show(dc, buf); | 34 | ret = class_attr->show(dc, buf); |
35 | return ret; | 35 | return ret; |
36 | } | 36 | } |
37 | 37 | ||
38 | static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, | 38 | static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, |
39 | const char *buf, size_t count) | 39 | const char *buf, size_t count) |
40 | { | 40 | { |
41 | struct class_attribute *class_attr = to_class_attr(attr); | 41 | struct class_attribute *class_attr = to_class_attr(attr); |
42 | struct class *dc = to_class(kobj); | 42 | struct class *dc = to_class(kobj); |
43 | ssize_t ret = -EIO; | 43 | ssize_t ret = -EIO; |
44 | 44 | ||
45 | if (class_attr->store) | 45 | if (class_attr->store) |
46 | ret = class_attr->store(dc, buf, count); | 46 | ret = class_attr->store(dc, buf, count); |
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
50 | static void class_release(struct kobject *kobj) | 50 | static void class_release(struct kobject *kobj) |
51 | { | 51 | { |
52 | struct class *class = to_class(kobj); | 52 | struct class *class = to_class(kobj); |
53 | 53 | ||
54 | pr_debug("class '%s': release.\n", class->name); | 54 | pr_debug("class '%s': release.\n", class->name); |
55 | 55 | ||
56 | if (class->class_release) | 56 | if (class->class_release) |
57 | class->class_release(class); | 57 | class->class_release(class); |
58 | else | 58 | else |
59 | pr_debug("class '%s' does not have a release() function, " | 59 | pr_debug("class '%s' does not have a release() function, " |
60 | "be careful\n", class->name); | 60 | "be careful\n", class->name); |
61 | } | 61 | } |
62 | 62 | ||
63 | static struct sysfs_ops class_sysfs_ops = { | 63 | static struct sysfs_ops class_sysfs_ops = { |
64 | .show = class_attr_show, | 64 | .show = class_attr_show, |
65 | .store = class_attr_store, | 65 | .store = class_attr_store, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct kobj_type class_ktype = { | 68 | static struct kobj_type class_ktype = { |
69 | .sysfs_ops = &class_sysfs_ops, | 69 | .sysfs_ops = &class_sysfs_ops, |
70 | .release = class_release, | 70 | .release = class_release, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | /* Hotplug events for classes go to the class_obj subsys */ | 73 | /* Hotplug events for classes go to the class_obj subsys */ |
74 | static struct kset *class_kset; | 74 | static struct kset *class_kset; |
75 | 75 | ||
76 | 76 | ||
77 | int class_create_file(struct class *cls, const struct class_attribute *attr) | 77 | int class_create_file(struct class *cls, const struct class_attribute *attr) |
78 | { | 78 | { |
79 | int error; | 79 | int error; |
80 | if (cls) | 80 | if (cls) |
81 | error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); | 81 | error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); |
82 | else | 82 | else |
83 | error = -EINVAL; | 83 | error = -EINVAL; |
84 | return error; | 84 | return error; |
85 | } | 85 | } |
86 | 86 | ||
87 | void class_remove_file(struct class *cls, const struct class_attribute *attr) | 87 | void class_remove_file(struct class *cls, const struct class_attribute *attr) |
88 | { | 88 | { |
89 | if (cls) | 89 | if (cls) |
90 | sysfs_remove_file(&cls->subsys.kobj, &attr->attr); | 90 | sysfs_remove_file(&cls->subsys.kobj, &attr->attr); |
91 | } | 91 | } |
92 | 92 | ||
93 | static struct class *class_get(struct class *cls) | 93 | static struct class *class_get(struct class *cls) |
94 | { | 94 | { |
95 | if (cls) | 95 | if (cls) |
96 | return container_of(kset_get(&cls->subsys), | 96 | return container_of(kset_get(&cls->subsys), |
97 | struct class, subsys); | 97 | struct class, subsys); |
98 | return NULL; | 98 | return NULL; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void class_put(struct class *cls) | 101 | static void class_put(struct class *cls) |
102 | { | 102 | { |
103 | if (cls) | 103 | if (cls) |
104 | kset_put(&cls->subsys); | 104 | kset_put(&cls->subsys); |
105 | } | 105 | } |
106 | 106 | ||
107 | static int add_class_attrs(struct class *cls) | 107 | static int add_class_attrs(struct class *cls) |
108 | { | 108 | { |
109 | int i; | 109 | int i; |
110 | int error = 0; | 110 | int error = 0; |
111 | 111 | ||
112 | if (cls->class_attrs) { | 112 | if (cls->class_attrs) { |
113 | for (i = 0; attr_name(cls->class_attrs[i]); i++) { | 113 | for (i = 0; attr_name(cls->class_attrs[i]); i++) { |
114 | error = class_create_file(cls, &cls->class_attrs[i]); | 114 | error = class_create_file(cls, &cls->class_attrs[i]); |
115 | if (error) | 115 | if (error) |
116 | goto error; | 116 | goto error; |
117 | } | 117 | } |
118 | } | 118 | } |
119 | done: | 119 | done: |
120 | return error; | 120 | return error; |
121 | error: | 121 | error: |
122 | while (--i >= 0) | 122 | while (--i >= 0) |
123 | class_remove_file(cls, &cls->class_attrs[i]); | 123 | class_remove_file(cls, &cls->class_attrs[i]); |
124 | goto done; | 124 | goto done; |
125 | } | 125 | } |
126 | 126 | ||
127 | static void remove_class_attrs(struct class *cls) | 127 | static void remove_class_attrs(struct class *cls) |
128 | { | 128 | { |
129 | int i; | 129 | int i; |
130 | 130 | ||
131 | if (cls->class_attrs) { | 131 | if (cls->class_attrs) { |
132 | for (i = 0; attr_name(cls->class_attrs[i]); i++) | 132 | for (i = 0; attr_name(cls->class_attrs[i]); i++) |
133 | class_remove_file(cls, &cls->class_attrs[i]); | 133 | class_remove_file(cls, &cls->class_attrs[i]); |
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | int class_register(struct class *cls) | 137 | int class_register(struct class *cls) |
138 | { | 138 | { |
139 | int error; | 139 | int error; |
140 | 140 | ||
141 | pr_debug("device class '%s': registering\n", cls->name); | 141 | pr_debug("device class '%s': registering\n", cls->name); |
142 | 142 | ||
143 | INIT_LIST_HEAD(&cls->devices); | 143 | INIT_LIST_HEAD(&cls->devices); |
144 | INIT_LIST_HEAD(&cls->interfaces); | 144 | INIT_LIST_HEAD(&cls->interfaces); |
145 | kset_init(&cls->class_dirs); | 145 | kset_init(&cls->class_dirs); |
146 | init_MUTEX(&cls->sem); | 146 | init_MUTEX(&cls->sem); |
147 | error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name); | 147 | error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name); |
148 | if (error) | 148 | if (error) |
149 | return error; | 149 | return error; |
150 | 150 | ||
151 | /* set the default /sys/dev directory for devices of this class */ | ||
152 | if (!cls->dev_kobj) | ||
153 | cls->dev_kobj = sysfs_dev_char_kobj; | ||
154 | |||
151 | #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) | 155 | #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) |
152 | /* let the block class directory show up in the root of sysfs */ | 156 | /* let the block class directory show up in the root of sysfs */ |
153 | if (cls != &block_class) | 157 | if (cls != &block_class) |
154 | cls->subsys.kobj.kset = class_kset; | 158 | cls->subsys.kobj.kset = class_kset; |
155 | #else | 159 | #else |
156 | cls->subsys.kobj.kset = class_kset; | 160 | cls->subsys.kobj.kset = class_kset; |
157 | #endif | 161 | #endif |
158 | cls->subsys.kobj.ktype = &class_ktype; | 162 | cls->subsys.kobj.ktype = &class_ktype; |
159 | 163 | ||
160 | error = kset_register(&cls->subsys); | 164 | error = kset_register(&cls->subsys); |
161 | if (!error) { | 165 | if (!error) { |
162 | error = add_class_attrs(class_get(cls)); | 166 | error = add_class_attrs(class_get(cls)); |
163 | class_put(cls); | 167 | class_put(cls); |
164 | } | 168 | } |
165 | return error; | 169 | return error; |
166 | } | 170 | } |
167 | 171 | ||
168 | void class_unregister(struct class *cls) | 172 | void class_unregister(struct class *cls) |
169 | { | 173 | { |
170 | pr_debug("device class '%s': unregistering\n", cls->name); | 174 | pr_debug("device class '%s': unregistering\n", cls->name); |
171 | remove_class_attrs(cls); | 175 | remove_class_attrs(cls); |
172 | kset_unregister(&cls->subsys); | 176 | kset_unregister(&cls->subsys); |
173 | } | 177 | } |
174 | 178 | ||
175 | static void class_create_release(struct class *cls) | 179 | static void class_create_release(struct class *cls) |
176 | { | 180 | { |
177 | pr_debug("%s called for %s\n", __func__, cls->name); | 181 | pr_debug("%s called for %s\n", __func__, cls->name); |
178 | kfree(cls); | 182 | kfree(cls); |
179 | } | 183 | } |
180 | 184 | ||
181 | /** | 185 | /** |
182 | * class_create - create a struct class structure | 186 | * class_create - create a struct class structure |
183 | * @owner: pointer to the module that is to "own" this struct class | 187 | * @owner: pointer to the module that is to "own" this struct class |
184 | * @name: pointer to a string for the name of this class. | 188 | * @name: pointer to a string for the name of this class. |
185 | * | 189 | * |
186 | * This is used to create a struct class pointer that can then be used | 190 | * This is used to create a struct class pointer that can then be used |
187 | * in calls to device_create(). | 191 | * in calls to device_create(). |
188 | * | 192 | * |
189 | * Note, the pointer created here is to be destroyed when finished by | 193 | * Note, the pointer created here is to be destroyed when finished by |
190 | * making a call to class_destroy(). | 194 | * making a call to class_destroy(). |
191 | */ | 195 | */ |
192 | struct class *class_create(struct module *owner, const char *name) | 196 | struct class *class_create(struct module *owner, const char *name) |
193 | { | 197 | { |
194 | struct class *cls; | 198 | struct class *cls; |
195 | int retval; | 199 | int retval; |
196 | 200 | ||
197 | cls = kzalloc(sizeof(*cls), GFP_KERNEL); | 201 | cls = kzalloc(sizeof(*cls), GFP_KERNEL); |
198 | if (!cls) { | 202 | if (!cls) { |
199 | retval = -ENOMEM; | 203 | retval = -ENOMEM; |
200 | goto error; | 204 | goto error; |
201 | } | 205 | } |
202 | 206 | ||
203 | cls->name = name; | 207 | cls->name = name; |
204 | cls->owner = owner; | 208 | cls->owner = owner; |
205 | cls->class_release = class_create_release; | 209 | cls->class_release = class_create_release; |
206 | 210 | ||
207 | retval = class_register(cls); | 211 | retval = class_register(cls); |
208 | if (retval) | 212 | if (retval) |
209 | goto error; | 213 | goto error; |
210 | 214 | ||
211 | return cls; | 215 | return cls; |
212 | 216 | ||
213 | error: | 217 | error: |
214 | kfree(cls); | 218 | kfree(cls); |
215 | return ERR_PTR(retval); | 219 | return ERR_PTR(retval); |
216 | } | 220 | } |
217 | 221 | ||
218 | /** | 222 | /** |
219 | * class_destroy - destroys a struct class structure | 223 | * class_destroy - destroys a struct class structure |
220 | * @cls: pointer to the struct class that is to be destroyed | 224 | * @cls: pointer to the struct class that is to be destroyed |
221 | * | 225 | * |
222 | * Note, the pointer to be destroyed must have been created with a call | 226 | * Note, the pointer to be destroyed must have been created with a call |
223 | * to class_create(). | 227 | * to class_create(). |
224 | */ | 228 | */ |
225 | void class_destroy(struct class *cls) | 229 | void class_destroy(struct class *cls) |
226 | { | 230 | { |
227 | if ((cls == NULL) || (IS_ERR(cls))) | 231 | if ((cls == NULL) || (IS_ERR(cls))) |
228 | return; | 232 | return; |
229 | 233 | ||
230 | class_unregister(cls); | 234 | class_unregister(cls); |
231 | } | 235 | } |
232 | 236 | ||
233 | #ifdef CONFIG_SYSFS_DEPRECATED | 237 | #ifdef CONFIG_SYSFS_DEPRECATED |
234 | char *make_class_name(const char *name, struct kobject *kobj) | 238 | char *make_class_name(const char *name, struct kobject *kobj) |
235 | { | 239 | { |
236 | char *class_name; | 240 | char *class_name; |
237 | int size; | 241 | int size; |
238 | 242 | ||
239 | size = strlen(name) + strlen(kobject_name(kobj)) + 2; | 243 | size = strlen(name) + strlen(kobject_name(kobj)) + 2; |
240 | 244 | ||
241 | class_name = kmalloc(size, GFP_KERNEL); | 245 | class_name = kmalloc(size, GFP_KERNEL); |
242 | if (!class_name) | 246 | if (!class_name) |
243 | return NULL; | 247 | return NULL; |
244 | 248 | ||
245 | strcpy(class_name, name); | 249 | strcpy(class_name, name); |
246 | strcat(class_name, ":"); | 250 | strcat(class_name, ":"); |
247 | strcat(class_name, kobject_name(kobj)); | 251 | strcat(class_name, kobject_name(kobj)); |
248 | return class_name; | 252 | return class_name; |
249 | } | 253 | } |
250 | #endif | 254 | #endif |
251 | 255 | ||
252 | /** | 256 | /** |
253 | * class_for_each_device - device iterator | 257 | * class_for_each_device - device iterator |
254 | * @class: the class we're iterating | 258 | * @class: the class we're iterating |
255 | * @data: data for the callback | 259 | * @data: data for the callback |
256 | * @fn: function to be called for each device | 260 | * @fn: function to be called for each device |
257 | * | 261 | * |
258 | * Iterate over @class's list of devices, and call @fn for each, | 262 | * Iterate over @class's list of devices, and call @fn for each, |
259 | * passing it @data. | 263 | * passing it @data. |
260 | * | 264 | * |
261 | * We check the return of @fn each time. If it returns anything | 265 | * We check the return of @fn each time. If it returns anything |
262 | * other than 0, we break out and return that value. | 266 | * other than 0, we break out and return that value. |
263 | * | 267 | * |
264 | * Note, we hold class->sem in this function, so it can not be | 268 | * Note, we hold class->sem in this function, so it can not be |
265 | * re-acquired in @fn, otherwise it will self-deadlocking. For | 269 | * re-acquired in @fn, otherwise it will self-deadlocking. For |
266 | * example, calls to add or remove class members would be verboten. | 270 | * example, calls to add or remove class members would be verboten. |
267 | */ | 271 | */ |
268 | int class_for_each_device(struct class *class, void *data, | 272 | int class_for_each_device(struct class *class, void *data, |
269 | int (*fn)(struct device *, void *)) | 273 | int (*fn)(struct device *, void *)) |
270 | { | 274 | { |
271 | struct device *dev; | 275 | struct device *dev; |
272 | int error = 0; | 276 | int error = 0; |
273 | 277 | ||
274 | if (!class) | 278 | if (!class) |
275 | return -EINVAL; | 279 | return -EINVAL; |
276 | down(&class->sem); | 280 | down(&class->sem); |
277 | list_for_each_entry(dev, &class->devices, node) { | 281 | list_for_each_entry(dev, &class->devices, node) { |
278 | dev = get_device(dev); | 282 | dev = get_device(dev); |
279 | if (dev) { | 283 | if (dev) { |
280 | error = fn(dev, data); | 284 | error = fn(dev, data); |
281 | put_device(dev); | 285 | put_device(dev); |
282 | } else | 286 | } else |
283 | error = -ENODEV; | 287 | error = -ENODEV; |
284 | if (error) | 288 | if (error) |
285 | break; | 289 | break; |
286 | } | 290 | } |
287 | up(&class->sem); | 291 | up(&class->sem); |
288 | 292 | ||
289 | return error; | 293 | return error; |
290 | } | 294 | } |
291 | EXPORT_SYMBOL_GPL(class_for_each_device); | 295 | EXPORT_SYMBOL_GPL(class_for_each_device); |
292 | 296 | ||
293 | /** | 297 | /** |
294 | * class_find_device - device iterator for locating a particular device | 298 | * class_find_device - device iterator for locating a particular device |
295 | * @class: the class we're iterating | 299 | * @class: the class we're iterating |
296 | * @data: data for the match function | 300 | * @data: data for the match function |
297 | * @match: function to check device | 301 | * @match: function to check device |
298 | * | 302 | * |
299 | * This is similar to the class_for_each_dev() function above, but it | 303 | * This is similar to the class_for_each_dev() function above, but it |
300 | * returns a reference to a device that is 'found' for later use, as | 304 | * returns a reference to a device that is 'found' for later use, as |
301 | * determined by the @match callback. | 305 | * determined by the @match callback. |
302 | * | 306 | * |
303 | * The callback should return 0 if the device doesn't match and non-zero | 307 | * The callback should return 0 if the device doesn't match and non-zero |
304 | * if it does. If the callback returns non-zero, this function will | 308 | * if it does. If the callback returns non-zero, this function will |
305 | * return to the caller and not iterate over any more devices. | 309 | * return to the caller and not iterate over any more devices. |
306 | * | 310 | * |
307 | * Note, you will need to drop the reference with put_device() after use. | 311 | * Note, you will need to drop the reference with put_device() after use. |
308 | * | 312 | * |
309 | * We hold class->sem in this function, so it can not be | 313 | * We hold class->sem in this function, so it can not be |
310 | * re-acquired in @match, otherwise it will self-deadlocking. For | 314 | * re-acquired in @match, otherwise it will self-deadlocking. For |
311 | * example, calls to add or remove class members would be verboten. | 315 | * example, calls to add or remove class members would be verboten. |
312 | */ | 316 | */ |
313 | struct device *class_find_device(struct class *class, void *data, | 317 | struct device *class_find_device(struct class *class, void *data, |
314 | int (*match)(struct device *, void *)) | 318 | int (*match)(struct device *, void *)) |
315 | { | 319 | { |
316 | struct device *dev; | 320 | struct device *dev; |
317 | int found = 0; | 321 | int found = 0; |
318 | 322 | ||
319 | if (!class) | 323 | if (!class) |
320 | return NULL; | 324 | return NULL; |
321 | 325 | ||
322 | down(&class->sem); | 326 | down(&class->sem); |
323 | list_for_each_entry(dev, &class->devices, node) { | 327 | list_for_each_entry(dev, &class->devices, node) { |
324 | dev = get_device(dev); | 328 | dev = get_device(dev); |
325 | if (dev) { | 329 | if (dev) { |
326 | if (match(dev, data)) { | 330 | if (match(dev, data)) { |
327 | found = 1; | 331 | found = 1; |
328 | break; | 332 | break; |
329 | } else | 333 | } else |
330 | put_device(dev); | 334 | put_device(dev); |
331 | } else | 335 | } else |
332 | break; | 336 | break; |
333 | } | 337 | } |
334 | up(&class->sem); | 338 | up(&class->sem); |
335 | 339 | ||
336 | return found ? dev : NULL; | 340 | return found ? dev : NULL; |
337 | } | 341 | } |
338 | EXPORT_SYMBOL_GPL(class_find_device); | 342 | EXPORT_SYMBOL_GPL(class_find_device); |
339 | 343 | ||
340 | int class_interface_register(struct class_interface *class_intf) | 344 | int class_interface_register(struct class_interface *class_intf) |
341 | { | 345 | { |
342 | struct class *parent; | 346 | struct class *parent; |
343 | struct device *dev; | 347 | struct device *dev; |
344 | 348 | ||
345 | if (!class_intf || !class_intf->class) | 349 | if (!class_intf || !class_intf->class) |
346 | return -ENODEV; | 350 | return -ENODEV; |
347 | 351 | ||
348 | parent = class_get(class_intf->class); | 352 | parent = class_get(class_intf->class); |
349 | if (!parent) | 353 | if (!parent) |
350 | return -EINVAL; | 354 | return -EINVAL; |
351 | 355 | ||
352 | down(&parent->sem); | 356 | down(&parent->sem); |
353 | list_add_tail(&class_intf->node, &parent->interfaces); | 357 | list_add_tail(&class_intf->node, &parent->interfaces); |
354 | if (class_intf->add_dev) { | 358 | if (class_intf->add_dev) { |
355 | list_for_each_entry(dev, &parent->devices, node) | 359 | list_for_each_entry(dev, &parent->devices, node) |
356 | class_intf->add_dev(dev, class_intf); | 360 | class_intf->add_dev(dev, class_intf); |
357 | } | 361 | } |
358 | up(&parent->sem); | 362 | up(&parent->sem); |
359 | 363 | ||
360 | return 0; | 364 | return 0; |
361 | } | 365 | } |
362 | 366 | ||
363 | void class_interface_unregister(struct class_interface *class_intf) | 367 | void class_interface_unregister(struct class_interface *class_intf) |
364 | { | 368 | { |
365 | struct class *parent = class_intf->class; | 369 | struct class *parent = class_intf->class; |
366 | struct device *dev; | 370 | struct device *dev; |
367 | 371 | ||
368 | if (!parent) | 372 | if (!parent) |
369 | return; | 373 | return; |
370 | 374 | ||
371 | down(&parent->sem); | 375 | down(&parent->sem); |
372 | list_del_init(&class_intf->node); | 376 | list_del_init(&class_intf->node); |
373 | if (class_intf->remove_dev) { | 377 | if (class_intf->remove_dev) { |
374 | list_for_each_entry(dev, &parent->devices, node) | 378 | list_for_each_entry(dev, &parent->devices, node) |
375 | class_intf->remove_dev(dev, class_intf); | 379 | class_intf->remove_dev(dev, class_intf); |
376 | } | 380 | } |
377 | up(&parent->sem); | 381 | up(&parent->sem); |
378 | 382 | ||
379 | class_put(parent); | 383 | class_put(parent); |
380 | } | 384 | } |
381 | 385 | ||
382 | int __init classes_init(void) | 386 | int __init classes_init(void) |
383 | { | 387 | { |
384 | class_kset = kset_create_and_add("class", NULL, NULL); | 388 | class_kset = kset_create_and_add("class", NULL, NULL); |
385 | if (!class_kset) | 389 | if (!class_kset) |
386 | return -ENOMEM; | 390 | return -ENOMEM; |
387 | return 0; | 391 | return 0; |
388 | } | 392 | } |
389 | 393 | ||
390 | EXPORT_SYMBOL_GPL(class_create_file); | 394 | EXPORT_SYMBOL_GPL(class_create_file); |
391 | EXPORT_SYMBOL_GPL(class_remove_file); | 395 | EXPORT_SYMBOL_GPL(class_remove_file); |
392 | EXPORT_SYMBOL_GPL(class_register); | 396 | EXPORT_SYMBOL_GPL(class_register); |
393 | EXPORT_SYMBOL_GPL(class_unregister); | 397 | EXPORT_SYMBOL_GPL(class_unregister); |
394 | EXPORT_SYMBOL_GPL(class_create); | 398 | EXPORT_SYMBOL_GPL(class_create); |
395 | EXPORT_SYMBOL_GPL(class_destroy); | 399 | EXPORT_SYMBOL_GPL(class_destroy); |
396 | 400 | ||
397 | EXPORT_SYMBOL_GPL(class_interface_register); | 401 | EXPORT_SYMBOL_GPL(class_interface_register); |
398 | EXPORT_SYMBOL_GPL(class_interface_unregister); | 402 | EXPORT_SYMBOL_GPL(class_interface_unregister); |
399 | 403 |
drivers/base/core.c
1 | /* | 1 | /* |
2 | * drivers/base/core.c - core driver model code (device registration, etc) | 2 | * drivers/base/core.c - core driver model code (device registration, etc) |
3 | * | 3 | * |
4 | * Copyright (c) 2002-3 Patrick Mochel | 4 | * Copyright (c) 2002-3 Patrick Mochel |
5 | * Copyright (c) 2002-3 Open Source Development Labs | 5 | * Copyright (c) 2002-3 Open Source Development Labs |
6 | * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> | 6 | * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> |
7 | * Copyright (c) 2006 Novell, Inc. | 7 | * Copyright (c) 2006 Novell, Inc. |
8 | * | 8 | * |
9 | * This file is released under the GPLv2 | 9 | * This file is released under the GPLv2 |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/kdev_t.h> | 19 | #include <linux/kdev_t.h> |
20 | #include <linux/notifier.h> | 20 | #include <linux/notifier.h> |
21 | #include <linux/genhd.h> | 21 | #include <linux/genhd.h> |
22 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
23 | #include <linux/semaphore.h> | 23 | #include <linux/semaphore.h> |
24 | 24 | ||
25 | #include "base.h" | 25 | #include "base.h" |
26 | #include "power/power.h" | 26 | #include "power/power.h" |
27 | 27 | ||
28 | int (*platform_notify)(struct device *dev) = NULL; | 28 | int (*platform_notify)(struct device *dev) = NULL; |
29 | int (*platform_notify_remove)(struct device *dev) = NULL; | 29 | int (*platform_notify_remove)(struct device *dev) = NULL; |
30 | static struct kobject *dev_kobj; | ||
31 | struct kobject *sysfs_dev_char_kobj; | ||
32 | struct kobject *sysfs_dev_block_kobj; | ||
30 | 33 | ||
31 | #ifdef CONFIG_BLOCK | 34 | #ifdef CONFIG_BLOCK |
32 | static inline int device_is_not_partition(struct device *dev) | 35 | static inline int device_is_not_partition(struct device *dev) |
33 | { | 36 | { |
34 | return !(dev->type == &part_type); | 37 | return !(dev->type == &part_type); |
35 | } | 38 | } |
36 | #else | 39 | #else |
37 | static inline int device_is_not_partition(struct device *dev) | 40 | static inline int device_is_not_partition(struct device *dev) |
38 | { | 41 | { |
39 | return 1; | 42 | return 1; |
40 | } | 43 | } |
41 | #endif | 44 | #endif |
42 | 45 | ||
43 | /** | 46 | /** |
44 | * dev_driver_string - Return a device's driver name, if at all possible | 47 | * dev_driver_string - Return a device's driver name, if at all possible |
45 | * @dev: struct device to get the name of | 48 | * @dev: struct device to get the name of |
46 | * | 49 | * |
47 | * Will return the device's driver's name if it is bound to a device. If | 50 | * Will return the device's driver's name if it is bound to a device. If |
48 | * the device is not bound to a device, it will return the name of the bus | 51 | * the device is not bound to a device, it will return the name of the bus |
49 | * it is attached to. If it is not attached to a bus either, an empty | 52 | * it is attached to. If it is not attached to a bus either, an empty |
50 | * string will be returned. | 53 | * string will be returned. |
51 | */ | 54 | */ |
52 | const char *dev_driver_string(struct device *dev) | 55 | const char *dev_driver_string(struct device *dev) |
53 | { | 56 | { |
54 | return dev->driver ? dev->driver->name : | 57 | return dev->driver ? dev->driver->name : |
55 | (dev->bus ? dev->bus->name : | 58 | (dev->bus ? dev->bus->name : |
56 | (dev->class ? dev->class->name : "")); | 59 | (dev->class ? dev->class->name : "")); |
57 | } | 60 | } |
58 | EXPORT_SYMBOL(dev_driver_string); | 61 | EXPORT_SYMBOL(dev_driver_string); |
59 | 62 | ||
60 | #define to_dev(obj) container_of(obj, struct device, kobj) | 63 | #define to_dev(obj) container_of(obj, struct device, kobj) |
61 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 64 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
62 | 65 | ||
63 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, | 66 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, |
64 | char *buf) | 67 | char *buf) |
65 | { | 68 | { |
66 | struct device_attribute *dev_attr = to_dev_attr(attr); | 69 | struct device_attribute *dev_attr = to_dev_attr(attr); |
67 | struct device *dev = to_dev(kobj); | 70 | struct device *dev = to_dev(kobj); |
68 | ssize_t ret = -EIO; | 71 | ssize_t ret = -EIO; |
69 | 72 | ||
70 | if (dev_attr->show) | 73 | if (dev_attr->show) |
71 | ret = dev_attr->show(dev, dev_attr, buf); | 74 | ret = dev_attr->show(dev, dev_attr, buf); |
72 | if (ret >= (ssize_t)PAGE_SIZE) { | 75 | if (ret >= (ssize_t)PAGE_SIZE) { |
73 | print_symbol("dev_attr_show: %s returned bad count\n", | 76 | print_symbol("dev_attr_show: %s returned bad count\n", |
74 | (unsigned long)dev_attr->show); | 77 | (unsigned long)dev_attr->show); |
75 | } | 78 | } |
76 | return ret; | 79 | return ret; |
77 | } | 80 | } |
78 | 81 | ||
79 | static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, | 82 | static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, |
80 | const char *buf, size_t count) | 83 | const char *buf, size_t count) |
81 | { | 84 | { |
82 | struct device_attribute *dev_attr = to_dev_attr(attr); | 85 | struct device_attribute *dev_attr = to_dev_attr(attr); |
83 | struct device *dev = to_dev(kobj); | 86 | struct device *dev = to_dev(kobj); |
84 | ssize_t ret = -EIO; | 87 | ssize_t ret = -EIO; |
85 | 88 | ||
86 | if (dev_attr->store) | 89 | if (dev_attr->store) |
87 | ret = dev_attr->store(dev, dev_attr, buf, count); | 90 | ret = dev_attr->store(dev, dev_attr, buf, count); |
88 | return ret; | 91 | return ret; |
89 | } | 92 | } |
90 | 93 | ||
91 | static struct sysfs_ops dev_sysfs_ops = { | 94 | static struct sysfs_ops dev_sysfs_ops = { |
92 | .show = dev_attr_show, | 95 | .show = dev_attr_show, |
93 | .store = dev_attr_store, | 96 | .store = dev_attr_store, |
94 | }; | 97 | }; |
95 | 98 | ||
96 | 99 | ||
97 | /** | 100 | /** |
98 | * device_release - free device structure. | 101 | * device_release - free device structure. |
99 | * @kobj: device's kobject. | 102 | * @kobj: device's kobject. |
100 | * | 103 | * |
101 | * This is called once the reference count for the object | 104 | * This is called once the reference count for the object |
102 | * reaches 0. We forward the call to the device's release | 105 | * reaches 0. We forward the call to the device's release |
103 | * method, which should handle actually freeing the structure. | 106 | * method, which should handle actually freeing the structure. |
104 | */ | 107 | */ |
105 | static void device_release(struct kobject *kobj) | 108 | static void device_release(struct kobject *kobj) |
106 | { | 109 | { |
107 | struct device *dev = to_dev(kobj); | 110 | struct device *dev = to_dev(kobj); |
108 | 111 | ||
109 | if (dev->release) | 112 | if (dev->release) |
110 | dev->release(dev); | 113 | dev->release(dev); |
111 | else if (dev->type && dev->type->release) | 114 | else if (dev->type && dev->type->release) |
112 | dev->type->release(dev); | 115 | dev->type->release(dev); |
113 | else if (dev->class && dev->class->dev_release) | 116 | else if (dev->class && dev->class->dev_release) |
114 | dev->class->dev_release(dev); | 117 | dev->class->dev_release(dev); |
115 | else { | 118 | else { |
116 | printk(KERN_ERR "Device '%s' does not have a release() " | 119 | printk(KERN_ERR "Device '%s' does not have a release() " |
117 | "function, it is broken and must be fixed.\n", | 120 | "function, it is broken and must be fixed.\n", |
118 | dev->bus_id); | 121 | dev->bus_id); |
119 | WARN_ON(1); | 122 | WARN_ON(1); |
120 | } | 123 | } |
121 | } | 124 | } |
122 | 125 | ||
123 | static struct kobj_type device_ktype = { | 126 | static struct kobj_type device_ktype = { |
124 | .release = device_release, | 127 | .release = device_release, |
125 | .sysfs_ops = &dev_sysfs_ops, | 128 | .sysfs_ops = &dev_sysfs_ops, |
126 | }; | 129 | }; |
127 | 130 | ||
128 | 131 | ||
129 | static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | 132 | static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) |
130 | { | 133 | { |
131 | struct kobj_type *ktype = get_ktype(kobj); | 134 | struct kobj_type *ktype = get_ktype(kobj); |
132 | 135 | ||
133 | if (ktype == &device_ktype) { | 136 | if (ktype == &device_ktype) { |
134 | struct device *dev = to_dev(kobj); | 137 | struct device *dev = to_dev(kobj); |
135 | if (dev->uevent_suppress) | 138 | if (dev->uevent_suppress) |
136 | return 0; | 139 | return 0; |
137 | if (dev->bus) | 140 | if (dev->bus) |
138 | return 1; | 141 | return 1; |
139 | if (dev->class) | 142 | if (dev->class) |
140 | return 1; | 143 | return 1; |
141 | } | 144 | } |
142 | return 0; | 145 | return 0; |
143 | } | 146 | } |
144 | 147 | ||
145 | static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) | 148 | static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) |
146 | { | 149 | { |
147 | struct device *dev = to_dev(kobj); | 150 | struct device *dev = to_dev(kobj); |
148 | 151 | ||
149 | if (dev->bus) | 152 | if (dev->bus) |
150 | return dev->bus->name; | 153 | return dev->bus->name; |
151 | if (dev->class) | 154 | if (dev->class) |
152 | return dev->class->name; | 155 | return dev->class->name; |
153 | return NULL; | 156 | return NULL; |
154 | } | 157 | } |
155 | 158 | ||
156 | static int dev_uevent(struct kset *kset, struct kobject *kobj, | 159 | static int dev_uevent(struct kset *kset, struct kobject *kobj, |
157 | struct kobj_uevent_env *env) | 160 | struct kobj_uevent_env *env) |
158 | { | 161 | { |
159 | struct device *dev = to_dev(kobj); | 162 | struct device *dev = to_dev(kobj); |
160 | int retval = 0; | 163 | int retval = 0; |
161 | 164 | ||
162 | /* add the major/minor if present */ | 165 | /* add the major/minor if present */ |
163 | if (MAJOR(dev->devt)) { | 166 | if (MAJOR(dev->devt)) { |
164 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); | 167 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); |
165 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); | 168 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); |
166 | } | 169 | } |
167 | 170 | ||
168 | if (dev->type && dev->type->name) | 171 | if (dev->type && dev->type->name) |
169 | add_uevent_var(env, "DEVTYPE=%s", dev->type->name); | 172 | add_uevent_var(env, "DEVTYPE=%s", dev->type->name); |
170 | 173 | ||
171 | if (dev->driver) | 174 | if (dev->driver) |
172 | add_uevent_var(env, "DRIVER=%s", dev->driver->name); | 175 | add_uevent_var(env, "DRIVER=%s", dev->driver->name); |
173 | 176 | ||
174 | #ifdef CONFIG_SYSFS_DEPRECATED | 177 | #ifdef CONFIG_SYSFS_DEPRECATED |
175 | if (dev->class) { | 178 | if (dev->class) { |
176 | struct device *parent = dev->parent; | 179 | struct device *parent = dev->parent; |
177 | 180 | ||
178 | /* find first bus device in parent chain */ | 181 | /* find first bus device in parent chain */ |
179 | while (parent && !parent->bus) | 182 | while (parent && !parent->bus) |
180 | parent = parent->parent; | 183 | parent = parent->parent; |
181 | if (parent && parent->bus) { | 184 | if (parent && parent->bus) { |
182 | const char *path; | 185 | const char *path; |
183 | 186 | ||
184 | path = kobject_get_path(&parent->kobj, GFP_KERNEL); | 187 | path = kobject_get_path(&parent->kobj, GFP_KERNEL); |
185 | if (path) { | 188 | if (path) { |
186 | add_uevent_var(env, "PHYSDEVPATH=%s", path); | 189 | add_uevent_var(env, "PHYSDEVPATH=%s", path); |
187 | kfree(path); | 190 | kfree(path); |
188 | } | 191 | } |
189 | 192 | ||
190 | add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name); | 193 | add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name); |
191 | 194 | ||
192 | if (parent->driver) | 195 | if (parent->driver) |
193 | add_uevent_var(env, "PHYSDEVDRIVER=%s", | 196 | add_uevent_var(env, "PHYSDEVDRIVER=%s", |
194 | parent->driver->name); | 197 | parent->driver->name); |
195 | } | 198 | } |
196 | } else if (dev->bus) { | 199 | } else if (dev->bus) { |
197 | add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); | 200 | add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); |
198 | 201 | ||
199 | if (dev->driver) | 202 | if (dev->driver) |
200 | add_uevent_var(env, "PHYSDEVDRIVER=%s", | 203 | add_uevent_var(env, "PHYSDEVDRIVER=%s", |
201 | dev->driver->name); | 204 | dev->driver->name); |
202 | } | 205 | } |
203 | #endif | 206 | #endif |
204 | 207 | ||
205 | /* have the bus specific function add its stuff */ | 208 | /* have the bus specific function add its stuff */ |
206 | if (dev->bus && dev->bus->uevent) { | 209 | if (dev->bus && dev->bus->uevent) { |
207 | retval = dev->bus->uevent(dev, env); | 210 | retval = dev->bus->uevent(dev, env); |
208 | if (retval) | 211 | if (retval) |
209 | pr_debug("device: '%s': %s: bus uevent() returned %d\n", | 212 | pr_debug("device: '%s': %s: bus uevent() returned %d\n", |
210 | dev->bus_id, __func__, retval); | 213 | dev->bus_id, __func__, retval); |
211 | } | 214 | } |
212 | 215 | ||
213 | /* have the class specific function add its stuff */ | 216 | /* have the class specific function add its stuff */ |
214 | if (dev->class && dev->class->dev_uevent) { | 217 | if (dev->class && dev->class->dev_uevent) { |
215 | retval = dev->class->dev_uevent(dev, env); | 218 | retval = dev->class->dev_uevent(dev, env); |
216 | if (retval) | 219 | if (retval) |
217 | pr_debug("device: '%s': %s: class uevent() " | 220 | pr_debug("device: '%s': %s: class uevent() " |
218 | "returned %d\n", dev->bus_id, | 221 | "returned %d\n", dev->bus_id, |
219 | __func__, retval); | 222 | __func__, retval); |
220 | } | 223 | } |
221 | 224 | ||
222 | /* have the device type specific fuction add its stuff */ | 225 | /* have the device type specific fuction add its stuff */ |
223 | if (dev->type && dev->type->uevent) { | 226 | if (dev->type && dev->type->uevent) { |
224 | retval = dev->type->uevent(dev, env); | 227 | retval = dev->type->uevent(dev, env); |
225 | if (retval) | 228 | if (retval) |
226 | pr_debug("device: '%s': %s: dev_type uevent() " | 229 | pr_debug("device: '%s': %s: dev_type uevent() " |
227 | "returned %d\n", dev->bus_id, | 230 | "returned %d\n", dev->bus_id, |
228 | __func__, retval); | 231 | __func__, retval); |
229 | } | 232 | } |
230 | 233 | ||
231 | return retval; | 234 | return retval; |
232 | } | 235 | } |
233 | 236 | ||
234 | static struct kset_uevent_ops device_uevent_ops = { | 237 | static struct kset_uevent_ops device_uevent_ops = { |
235 | .filter = dev_uevent_filter, | 238 | .filter = dev_uevent_filter, |
236 | .name = dev_uevent_name, | 239 | .name = dev_uevent_name, |
237 | .uevent = dev_uevent, | 240 | .uevent = dev_uevent, |
238 | }; | 241 | }; |
239 | 242 | ||
240 | static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, | 243 | static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, |
241 | char *buf) | 244 | char *buf) |
242 | { | 245 | { |
243 | struct kobject *top_kobj; | 246 | struct kobject *top_kobj; |
244 | struct kset *kset; | 247 | struct kset *kset; |
245 | struct kobj_uevent_env *env = NULL; | 248 | struct kobj_uevent_env *env = NULL; |
246 | int i; | 249 | int i; |
247 | size_t count = 0; | 250 | size_t count = 0; |
248 | int retval; | 251 | int retval; |
249 | 252 | ||
250 | /* search the kset, the device belongs to */ | 253 | /* search the kset, the device belongs to */ |
251 | top_kobj = &dev->kobj; | 254 | top_kobj = &dev->kobj; |
252 | while (!top_kobj->kset && top_kobj->parent) | 255 | while (!top_kobj->kset && top_kobj->parent) |
253 | top_kobj = top_kobj->parent; | 256 | top_kobj = top_kobj->parent; |
254 | if (!top_kobj->kset) | 257 | if (!top_kobj->kset) |
255 | goto out; | 258 | goto out; |
256 | 259 | ||
257 | kset = top_kobj->kset; | 260 | kset = top_kobj->kset; |
258 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) | 261 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) |
259 | goto out; | 262 | goto out; |
260 | 263 | ||
261 | /* respect filter */ | 264 | /* respect filter */ |
262 | if (kset->uevent_ops && kset->uevent_ops->filter) | 265 | if (kset->uevent_ops && kset->uevent_ops->filter) |
263 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) | 266 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) |
264 | goto out; | 267 | goto out; |
265 | 268 | ||
266 | env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); | 269 | env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); |
267 | if (!env) | 270 | if (!env) |
268 | return -ENOMEM; | 271 | return -ENOMEM; |
269 | 272 | ||
270 | /* let the kset specific function add its keys */ | 273 | /* let the kset specific function add its keys */ |
271 | retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); | 274 | retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); |
272 | if (retval) | 275 | if (retval) |
273 | goto out; | 276 | goto out; |
274 | 277 | ||
275 | /* copy keys to file */ | 278 | /* copy keys to file */ |
276 | for (i = 0; i < env->envp_idx; i++) | 279 | for (i = 0; i < env->envp_idx; i++) |
277 | count += sprintf(&buf[count], "%s\n", env->envp[i]); | 280 | count += sprintf(&buf[count], "%s\n", env->envp[i]); |
278 | out: | 281 | out: |
279 | kfree(env); | 282 | kfree(env); |
280 | return count; | 283 | return count; |
281 | } | 284 | } |
282 | 285 | ||
283 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | 286 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, |
284 | const char *buf, size_t count) | 287 | const char *buf, size_t count) |
285 | { | 288 | { |
286 | enum kobject_action action; | 289 | enum kobject_action action; |
287 | 290 | ||
288 | if (kobject_action_type(buf, count, &action) == 0) { | 291 | if (kobject_action_type(buf, count, &action) == 0) { |
289 | kobject_uevent(&dev->kobj, action); | 292 | kobject_uevent(&dev->kobj, action); |
290 | goto out; | 293 | goto out; |
291 | } | 294 | } |
292 | 295 | ||
293 | dev_err(dev, "uevent: unsupported action-string; this will " | 296 | dev_err(dev, "uevent: unsupported action-string; this will " |
294 | "be ignored in a future kernel version\n"); | 297 | "be ignored in a future kernel version\n"); |
295 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 298 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
296 | out: | 299 | out: |
297 | return count; | 300 | return count; |
298 | } | 301 | } |
299 | 302 | ||
300 | static struct device_attribute uevent_attr = | 303 | static struct device_attribute uevent_attr = |
301 | __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent); | 304 | __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent); |
302 | 305 | ||
303 | static int device_add_attributes(struct device *dev, | 306 | static int device_add_attributes(struct device *dev, |
304 | struct device_attribute *attrs) | 307 | struct device_attribute *attrs) |
305 | { | 308 | { |
306 | int error = 0; | 309 | int error = 0; |
307 | int i; | 310 | int i; |
308 | 311 | ||
309 | if (attrs) { | 312 | if (attrs) { |
310 | for (i = 0; attr_name(attrs[i]); i++) { | 313 | for (i = 0; attr_name(attrs[i]); i++) { |
311 | error = device_create_file(dev, &attrs[i]); | 314 | error = device_create_file(dev, &attrs[i]); |
312 | if (error) | 315 | if (error) |
313 | break; | 316 | break; |
314 | } | 317 | } |
315 | if (error) | 318 | if (error) |
316 | while (--i >= 0) | 319 | while (--i >= 0) |
317 | device_remove_file(dev, &attrs[i]); | 320 | device_remove_file(dev, &attrs[i]); |
318 | } | 321 | } |
319 | return error; | 322 | return error; |
320 | } | 323 | } |
321 | 324 | ||
322 | static void device_remove_attributes(struct device *dev, | 325 | static void device_remove_attributes(struct device *dev, |
323 | struct device_attribute *attrs) | 326 | struct device_attribute *attrs) |
324 | { | 327 | { |
325 | int i; | 328 | int i; |
326 | 329 | ||
327 | if (attrs) | 330 | if (attrs) |
328 | for (i = 0; attr_name(attrs[i]); i++) | 331 | for (i = 0; attr_name(attrs[i]); i++) |
329 | device_remove_file(dev, &attrs[i]); | 332 | device_remove_file(dev, &attrs[i]); |
330 | } | 333 | } |
331 | 334 | ||
332 | static int device_add_groups(struct device *dev, | 335 | static int device_add_groups(struct device *dev, |
333 | struct attribute_group **groups) | 336 | struct attribute_group **groups) |
334 | { | 337 | { |
335 | int error = 0; | 338 | int error = 0; |
336 | int i; | 339 | int i; |
337 | 340 | ||
338 | if (groups) { | 341 | if (groups) { |
339 | for (i = 0; groups[i]; i++) { | 342 | for (i = 0; groups[i]; i++) { |
340 | error = sysfs_create_group(&dev->kobj, groups[i]); | 343 | error = sysfs_create_group(&dev->kobj, groups[i]); |
341 | if (error) { | 344 | if (error) { |
342 | while (--i >= 0) | 345 | while (--i >= 0) |
343 | sysfs_remove_group(&dev->kobj, | 346 | sysfs_remove_group(&dev->kobj, |
344 | groups[i]); | 347 | groups[i]); |
345 | break; | 348 | break; |
346 | } | 349 | } |
347 | } | 350 | } |
348 | } | 351 | } |
349 | return error; | 352 | return error; |
350 | } | 353 | } |
351 | 354 | ||
352 | static void device_remove_groups(struct device *dev, | 355 | static void device_remove_groups(struct device *dev, |
353 | struct attribute_group **groups) | 356 | struct attribute_group **groups) |
354 | { | 357 | { |
355 | int i; | 358 | int i; |
356 | 359 | ||
357 | if (groups) | 360 | if (groups) |
358 | for (i = 0; groups[i]; i++) | 361 | for (i = 0; groups[i]; i++) |
359 | sysfs_remove_group(&dev->kobj, groups[i]); | 362 | sysfs_remove_group(&dev->kobj, groups[i]); |
360 | } | 363 | } |
361 | 364 | ||
362 | static int device_add_attrs(struct device *dev) | 365 | static int device_add_attrs(struct device *dev) |
363 | { | 366 | { |
364 | struct class *class = dev->class; | 367 | struct class *class = dev->class; |
365 | struct device_type *type = dev->type; | 368 | struct device_type *type = dev->type; |
366 | int error; | 369 | int error; |
367 | 370 | ||
368 | if (class) { | 371 | if (class) { |
369 | error = device_add_attributes(dev, class->dev_attrs); | 372 | error = device_add_attributes(dev, class->dev_attrs); |
370 | if (error) | 373 | if (error) |
371 | return error; | 374 | return error; |
372 | } | 375 | } |
373 | 376 | ||
374 | if (type) { | 377 | if (type) { |
375 | error = device_add_groups(dev, type->groups); | 378 | error = device_add_groups(dev, type->groups); |
376 | if (error) | 379 | if (error) |
377 | goto err_remove_class_attrs; | 380 | goto err_remove_class_attrs; |
378 | } | 381 | } |
379 | 382 | ||
380 | error = device_add_groups(dev, dev->groups); | 383 | error = device_add_groups(dev, dev->groups); |
381 | if (error) | 384 | if (error) |
382 | goto err_remove_type_groups; | 385 | goto err_remove_type_groups; |
383 | 386 | ||
384 | return 0; | 387 | return 0; |
385 | 388 | ||
386 | err_remove_type_groups: | 389 | err_remove_type_groups: |
387 | if (type) | 390 | if (type) |
388 | device_remove_groups(dev, type->groups); | 391 | device_remove_groups(dev, type->groups); |
389 | err_remove_class_attrs: | 392 | err_remove_class_attrs: |
390 | if (class) | 393 | if (class) |
391 | device_remove_attributes(dev, class->dev_attrs); | 394 | device_remove_attributes(dev, class->dev_attrs); |
392 | 395 | ||
393 | return error; | 396 | return error; |
394 | } | 397 | } |
395 | 398 | ||
396 | static void device_remove_attrs(struct device *dev) | 399 | static void device_remove_attrs(struct device *dev) |
397 | { | 400 | { |
398 | struct class *class = dev->class; | 401 | struct class *class = dev->class; |
399 | struct device_type *type = dev->type; | 402 | struct device_type *type = dev->type; |
400 | 403 | ||
401 | device_remove_groups(dev, dev->groups); | 404 | device_remove_groups(dev, dev->groups); |
402 | 405 | ||
403 | if (type) | 406 | if (type) |
404 | device_remove_groups(dev, type->groups); | 407 | device_remove_groups(dev, type->groups); |
405 | 408 | ||
406 | if (class) | 409 | if (class) |
407 | device_remove_attributes(dev, class->dev_attrs); | 410 | device_remove_attributes(dev, class->dev_attrs); |
408 | } | 411 | } |
409 | 412 | ||
410 | 413 | ||
411 | static ssize_t show_dev(struct device *dev, struct device_attribute *attr, | 414 | static ssize_t show_dev(struct device *dev, struct device_attribute *attr, |
412 | char *buf) | 415 | char *buf) |
413 | { | 416 | { |
414 | return print_dev_t(buf, dev->devt); | 417 | return print_dev_t(buf, dev->devt); |
415 | } | 418 | } |
416 | 419 | ||
417 | static struct device_attribute devt_attr = | 420 | static struct device_attribute devt_attr = |
418 | __ATTR(dev, S_IRUGO, show_dev, NULL); | 421 | __ATTR(dev, S_IRUGO, show_dev, NULL); |
419 | 422 | ||
420 | /* kset to create /sys/devices/ */ | 423 | /* kset to create /sys/devices/ */ |
421 | struct kset *devices_kset; | 424 | struct kset *devices_kset; |
422 | 425 | ||
423 | /** | 426 | /** |
424 | * device_create_file - create sysfs attribute file for device. | 427 | * device_create_file - create sysfs attribute file for device. |
425 | * @dev: device. | 428 | * @dev: device. |
426 | * @attr: device attribute descriptor. | 429 | * @attr: device attribute descriptor. |
427 | */ | 430 | */ |
428 | int device_create_file(struct device *dev, struct device_attribute *attr) | 431 | int device_create_file(struct device *dev, struct device_attribute *attr) |
429 | { | 432 | { |
430 | int error = 0; | 433 | int error = 0; |
431 | if (dev) | 434 | if (dev) |
432 | error = sysfs_create_file(&dev->kobj, &attr->attr); | 435 | error = sysfs_create_file(&dev->kobj, &attr->attr); |
433 | return error; | 436 | return error; |
434 | } | 437 | } |
435 | 438 | ||
436 | /** | 439 | /** |
437 | * device_remove_file - remove sysfs attribute file. | 440 | * device_remove_file - remove sysfs attribute file. |
438 | * @dev: device. | 441 | * @dev: device. |
439 | * @attr: device attribute descriptor. | 442 | * @attr: device attribute descriptor. |
440 | */ | 443 | */ |
441 | void device_remove_file(struct device *dev, struct device_attribute *attr) | 444 | void device_remove_file(struct device *dev, struct device_attribute *attr) |
442 | { | 445 | { |
443 | if (dev) | 446 | if (dev) |
444 | sysfs_remove_file(&dev->kobj, &attr->attr); | 447 | sysfs_remove_file(&dev->kobj, &attr->attr); |
445 | } | 448 | } |
446 | 449 | ||
447 | /** | 450 | /** |
448 | * device_create_bin_file - create sysfs binary attribute file for device. | 451 | * device_create_bin_file - create sysfs binary attribute file for device. |
449 | * @dev: device. | 452 | * @dev: device. |
450 | * @attr: device binary attribute descriptor. | 453 | * @attr: device binary attribute descriptor. |
451 | */ | 454 | */ |
452 | int device_create_bin_file(struct device *dev, struct bin_attribute *attr) | 455 | int device_create_bin_file(struct device *dev, struct bin_attribute *attr) |
453 | { | 456 | { |
454 | int error = -EINVAL; | 457 | int error = -EINVAL; |
455 | if (dev) | 458 | if (dev) |
456 | error = sysfs_create_bin_file(&dev->kobj, attr); | 459 | error = sysfs_create_bin_file(&dev->kobj, attr); |
457 | return error; | 460 | return error; |
458 | } | 461 | } |
459 | EXPORT_SYMBOL_GPL(device_create_bin_file); | 462 | EXPORT_SYMBOL_GPL(device_create_bin_file); |
460 | 463 | ||
461 | /** | 464 | /** |
462 | * device_remove_bin_file - remove sysfs binary attribute file | 465 | * device_remove_bin_file - remove sysfs binary attribute file |
463 | * @dev: device. | 466 | * @dev: device. |
464 | * @attr: device binary attribute descriptor. | 467 | * @attr: device binary attribute descriptor. |
465 | */ | 468 | */ |
466 | void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) | 469 | void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) |
467 | { | 470 | { |
468 | if (dev) | 471 | if (dev) |
469 | sysfs_remove_bin_file(&dev->kobj, attr); | 472 | sysfs_remove_bin_file(&dev->kobj, attr); |
470 | } | 473 | } |
471 | EXPORT_SYMBOL_GPL(device_remove_bin_file); | 474 | EXPORT_SYMBOL_GPL(device_remove_bin_file); |
472 | 475 | ||
473 | /** | 476 | /** |
474 | * device_schedule_callback_owner - helper to schedule a callback for a device | 477 | * device_schedule_callback_owner - helper to schedule a callback for a device |
475 | * @dev: device. | 478 | * @dev: device. |
476 | * @func: callback function to invoke later. | 479 | * @func: callback function to invoke later. |
477 | * @owner: module owning the callback routine | 480 | * @owner: module owning the callback routine |
478 | * | 481 | * |
479 | * Attribute methods must not unregister themselves or their parent device | 482 | * Attribute methods must not unregister themselves or their parent device |
480 | * (which would amount to the same thing). Attempts to do so will deadlock, | 483 | * (which would amount to the same thing). Attempts to do so will deadlock, |
481 | * since unregistration is mutually exclusive with driver callbacks. | 484 | * since unregistration is mutually exclusive with driver callbacks. |
482 | * | 485 | * |
483 | * Instead methods can call this routine, which will attempt to allocate | 486 | * Instead methods can call this routine, which will attempt to allocate |
484 | * and schedule a workqueue request to call back @func with @dev as its | 487 | * and schedule a workqueue request to call back @func with @dev as its |
485 | * argument in the workqueue's process context. @dev will be pinned until | 488 | * argument in the workqueue's process context. @dev will be pinned until |
486 | * @func returns. | 489 | * @func returns. |
487 | * | 490 | * |
488 | * This routine is usually called via the inline device_schedule_callback(), | 491 | * This routine is usually called via the inline device_schedule_callback(), |
489 | * which automatically sets @owner to THIS_MODULE. | 492 | * which automatically sets @owner to THIS_MODULE. |
490 | * | 493 | * |
491 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | 494 | * Returns 0 if the request was submitted, -ENOMEM if storage could not |
492 | * be allocated, -ENODEV if a reference to @owner isn't available. | 495 | * be allocated, -ENODEV if a reference to @owner isn't available. |
493 | * | 496 | * |
494 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an | 497 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an |
495 | * underlying sysfs routine (since it is intended for use by attribute | 498 | * underlying sysfs routine (since it is intended for use by attribute |
496 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. | 499 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. |
497 | */ | 500 | */ |
498 | int device_schedule_callback_owner(struct device *dev, | 501 | int device_schedule_callback_owner(struct device *dev, |
499 | void (*func)(struct device *), struct module *owner) | 502 | void (*func)(struct device *), struct module *owner) |
500 | { | 503 | { |
501 | return sysfs_schedule_callback(&dev->kobj, | 504 | return sysfs_schedule_callback(&dev->kobj, |
502 | (void (*)(void *)) func, dev, owner); | 505 | (void (*)(void *)) func, dev, owner); |
503 | } | 506 | } |
504 | EXPORT_SYMBOL_GPL(device_schedule_callback_owner); | 507 | EXPORT_SYMBOL_GPL(device_schedule_callback_owner); |
505 | 508 | ||
506 | static void klist_children_get(struct klist_node *n) | 509 | static void klist_children_get(struct klist_node *n) |
507 | { | 510 | { |
508 | struct device *dev = container_of(n, struct device, knode_parent); | 511 | struct device *dev = container_of(n, struct device, knode_parent); |
509 | 512 | ||
510 | get_device(dev); | 513 | get_device(dev); |
511 | } | 514 | } |
512 | 515 | ||
513 | static void klist_children_put(struct klist_node *n) | 516 | static void klist_children_put(struct klist_node *n) |
514 | { | 517 | { |
515 | struct device *dev = container_of(n, struct device, knode_parent); | 518 | struct device *dev = container_of(n, struct device, knode_parent); |
516 | 519 | ||
517 | put_device(dev); | 520 | put_device(dev); |
518 | } | 521 | } |
519 | 522 | ||
520 | /** | 523 | /** |
521 | * device_initialize - init device structure. | 524 | * device_initialize - init device structure. |
522 | * @dev: device. | 525 | * @dev: device. |
523 | * | 526 | * |
524 | * This prepares the device for use by other layers, | 527 | * This prepares the device for use by other layers, |
525 | * including adding it to the device hierarchy. | 528 | * including adding it to the device hierarchy. |
526 | * It is the first half of device_register(), if called by | 529 | * It is the first half of device_register(), if called by |
527 | * that, though it can also be called separately, so one | 530 | * that, though it can also be called separately, so one |
528 | * may use @dev's fields (e.g. the refcount). | 531 | * may use @dev's fields (e.g. the refcount). |
529 | */ | 532 | */ |
530 | void device_initialize(struct device *dev) | 533 | void device_initialize(struct device *dev) |
531 | { | 534 | { |
532 | dev->kobj.kset = devices_kset; | 535 | dev->kobj.kset = devices_kset; |
533 | kobject_init(&dev->kobj, &device_ktype); | 536 | kobject_init(&dev->kobj, &device_ktype); |
534 | klist_init(&dev->klist_children, klist_children_get, | 537 | klist_init(&dev->klist_children, klist_children_get, |
535 | klist_children_put); | 538 | klist_children_put); |
536 | INIT_LIST_HEAD(&dev->dma_pools); | 539 | INIT_LIST_HEAD(&dev->dma_pools); |
537 | INIT_LIST_HEAD(&dev->node); | 540 | INIT_LIST_HEAD(&dev->node); |
538 | init_MUTEX(&dev->sem); | 541 | init_MUTEX(&dev->sem); |
539 | spin_lock_init(&dev->devres_lock); | 542 | spin_lock_init(&dev->devres_lock); |
540 | INIT_LIST_HEAD(&dev->devres_head); | 543 | INIT_LIST_HEAD(&dev->devres_head); |
541 | device_init_wakeup(dev, 0); | 544 | device_init_wakeup(dev, 0); |
542 | set_dev_node(dev, -1); | 545 | set_dev_node(dev, -1); |
543 | } | 546 | } |
544 | 547 | ||
545 | #ifdef CONFIG_SYSFS_DEPRECATED | 548 | #ifdef CONFIG_SYSFS_DEPRECATED |
546 | static struct kobject *get_device_parent(struct device *dev, | 549 | static struct kobject *get_device_parent(struct device *dev, |
547 | struct device *parent) | 550 | struct device *parent) |
548 | { | 551 | { |
549 | /* class devices without a parent live in /sys/class/<classname>/ */ | 552 | /* class devices without a parent live in /sys/class/<classname>/ */ |
550 | if (dev->class && (!parent || parent->class != dev->class)) | 553 | if (dev->class && (!parent || parent->class != dev->class)) |
551 | return &dev->class->subsys.kobj; | 554 | return &dev->class->subsys.kobj; |
552 | /* all other devices keep their parent */ | 555 | /* all other devices keep their parent */ |
553 | else if (parent) | 556 | else if (parent) |
554 | return &parent->kobj; | 557 | return &parent->kobj; |
555 | 558 | ||
556 | return NULL; | 559 | return NULL; |
557 | } | 560 | } |
558 | 561 | ||
559 | static inline void cleanup_device_parent(struct device *dev) {} | 562 | static inline void cleanup_device_parent(struct device *dev) {} |
560 | static inline void cleanup_glue_dir(struct device *dev, | 563 | static inline void cleanup_glue_dir(struct device *dev, |
561 | struct kobject *glue_dir) {} | 564 | struct kobject *glue_dir) {} |
562 | #else | 565 | #else |
563 | static struct kobject *virtual_device_parent(struct device *dev) | 566 | static struct kobject *virtual_device_parent(struct device *dev) |
564 | { | 567 | { |
565 | static struct kobject *virtual_dir = NULL; | 568 | static struct kobject *virtual_dir = NULL; |
566 | 569 | ||
567 | if (!virtual_dir) | 570 | if (!virtual_dir) |
568 | virtual_dir = kobject_create_and_add("virtual", | 571 | virtual_dir = kobject_create_and_add("virtual", |
569 | &devices_kset->kobj); | 572 | &devices_kset->kobj); |
570 | 573 | ||
571 | return virtual_dir; | 574 | return virtual_dir; |
572 | } | 575 | } |
573 | 576 | ||
574 | static struct kobject *get_device_parent(struct device *dev, | 577 | static struct kobject *get_device_parent(struct device *dev, |
575 | struct device *parent) | 578 | struct device *parent) |
576 | { | 579 | { |
577 | int retval; | 580 | int retval; |
578 | 581 | ||
579 | if (dev->class) { | 582 | if (dev->class) { |
580 | struct kobject *kobj = NULL; | 583 | struct kobject *kobj = NULL; |
581 | struct kobject *parent_kobj; | 584 | struct kobject *parent_kobj; |
582 | struct kobject *k; | 585 | struct kobject *k; |
583 | 586 | ||
584 | /* | 587 | /* |
585 | * If we have no parent, we live in "virtual". | 588 | * If we have no parent, we live in "virtual". |
586 | * Class-devices with a non class-device as parent, live | 589 | * Class-devices with a non class-device as parent, live |
587 | * in a "glue" directory to prevent namespace collisions. | 590 | * in a "glue" directory to prevent namespace collisions. |
588 | */ | 591 | */ |
589 | if (parent == NULL) | 592 | if (parent == NULL) |
590 | parent_kobj = virtual_device_parent(dev); | 593 | parent_kobj = virtual_device_parent(dev); |
591 | else if (parent->class) | 594 | else if (parent->class) |
592 | return &parent->kobj; | 595 | return &parent->kobj; |
593 | else | 596 | else |
594 | parent_kobj = &parent->kobj; | 597 | parent_kobj = &parent->kobj; |
595 | 598 | ||
596 | /* find our class-directory at the parent and reference it */ | 599 | /* find our class-directory at the parent and reference it */ |
597 | spin_lock(&dev->class->class_dirs.list_lock); | 600 | spin_lock(&dev->class->class_dirs.list_lock); |
598 | list_for_each_entry(k, &dev->class->class_dirs.list, entry) | 601 | list_for_each_entry(k, &dev->class->class_dirs.list, entry) |
599 | if (k->parent == parent_kobj) { | 602 | if (k->parent == parent_kobj) { |
600 | kobj = kobject_get(k); | 603 | kobj = kobject_get(k); |
601 | break; | 604 | break; |
602 | } | 605 | } |
603 | spin_unlock(&dev->class->class_dirs.list_lock); | 606 | spin_unlock(&dev->class->class_dirs.list_lock); |
604 | if (kobj) | 607 | if (kobj) |
605 | return kobj; | 608 | return kobj; |
606 | 609 | ||
607 | /* or create a new class-directory at the parent device */ | 610 | /* or create a new class-directory at the parent device */ |
608 | k = kobject_create(); | 611 | k = kobject_create(); |
609 | if (!k) | 612 | if (!k) |
610 | return NULL; | 613 | return NULL; |
611 | k->kset = &dev->class->class_dirs; | 614 | k->kset = &dev->class->class_dirs; |
612 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); | 615 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); |
613 | if (retval < 0) { | 616 | if (retval < 0) { |
614 | kobject_put(k); | 617 | kobject_put(k); |
615 | return NULL; | 618 | return NULL; |
616 | } | 619 | } |
617 | /* do not emit an uevent for this simple "glue" directory */ | 620 | /* do not emit an uevent for this simple "glue" directory */ |
618 | return k; | 621 | return k; |
619 | } | 622 | } |
620 | 623 | ||
621 | if (parent) | 624 | if (parent) |
622 | return &parent->kobj; | 625 | return &parent->kobj; |
623 | return NULL; | 626 | return NULL; |
624 | } | 627 | } |
625 | 628 | ||
626 | static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) | 629 | static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) |
627 | { | 630 | { |
628 | /* see if we live in a "glue" directory */ | 631 | /* see if we live in a "glue" directory */ |
629 | if (!glue_dir || !dev->class || | 632 | if (!glue_dir || !dev->class || |
630 | glue_dir->kset != &dev->class->class_dirs) | 633 | glue_dir->kset != &dev->class->class_dirs) |
631 | return; | 634 | return; |
632 | 635 | ||
633 | kobject_put(glue_dir); | 636 | kobject_put(glue_dir); |
634 | } | 637 | } |
635 | 638 | ||
636 | static void cleanup_device_parent(struct device *dev) | 639 | static void cleanup_device_parent(struct device *dev) |
637 | { | 640 | { |
638 | cleanup_glue_dir(dev, dev->kobj.parent); | 641 | cleanup_glue_dir(dev, dev->kobj.parent); |
639 | } | 642 | } |
640 | #endif | 643 | #endif |
641 | 644 | ||
642 | static void setup_parent(struct device *dev, struct device *parent) | 645 | static void setup_parent(struct device *dev, struct device *parent) |
643 | { | 646 | { |
644 | struct kobject *kobj; | 647 | struct kobject *kobj; |
645 | kobj = get_device_parent(dev, parent); | 648 | kobj = get_device_parent(dev, parent); |
646 | if (kobj) | 649 | if (kobj) |
647 | dev->kobj.parent = kobj; | 650 | dev->kobj.parent = kobj; |
648 | } | 651 | } |
649 | 652 | ||
650 | static int device_add_class_symlinks(struct device *dev) | 653 | static int device_add_class_symlinks(struct device *dev) |
651 | { | 654 | { |
652 | int error; | 655 | int error; |
653 | 656 | ||
654 | if (!dev->class) | 657 | if (!dev->class) |
655 | return 0; | 658 | return 0; |
656 | 659 | ||
657 | error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, | 660 | error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, |
658 | "subsystem"); | 661 | "subsystem"); |
659 | if (error) | 662 | if (error) |
660 | goto out; | 663 | goto out; |
661 | 664 | ||
662 | #ifdef CONFIG_SYSFS_DEPRECATED | 665 | #ifdef CONFIG_SYSFS_DEPRECATED |
663 | /* stacked class devices need a symlink in the class directory */ | 666 | /* stacked class devices need a symlink in the class directory */ |
664 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 667 | if (dev->kobj.parent != &dev->class->subsys.kobj && |
665 | device_is_not_partition(dev)) { | 668 | device_is_not_partition(dev)) { |
666 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 669 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, |
667 | dev->bus_id); | 670 | dev->bus_id); |
668 | if (error) | 671 | if (error) |
669 | goto out_subsys; | 672 | goto out_subsys; |
670 | } | 673 | } |
671 | 674 | ||
672 | if (dev->parent && device_is_not_partition(dev)) { | 675 | if (dev->parent && device_is_not_partition(dev)) { |
673 | struct device *parent = dev->parent; | 676 | struct device *parent = dev->parent; |
674 | char *class_name; | 677 | char *class_name; |
675 | 678 | ||
676 | /* | 679 | /* |
677 | * stacked class devices have the 'device' link | 680 | * stacked class devices have the 'device' link |
678 | * pointing to the bus device instead of the parent | 681 | * pointing to the bus device instead of the parent |
679 | */ | 682 | */ |
680 | while (parent->class && !parent->bus && parent->parent) | 683 | while (parent->class && !parent->bus && parent->parent) |
681 | parent = parent->parent; | 684 | parent = parent->parent; |
682 | 685 | ||
683 | error = sysfs_create_link(&dev->kobj, | 686 | error = sysfs_create_link(&dev->kobj, |
684 | &parent->kobj, | 687 | &parent->kobj, |
685 | "device"); | 688 | "device"); |
686 | if (error) | 689 | if (error) |
687 | goto out_busid; | 690 | goto out_busid; |
688 | 691 | ||
689 | class_name = make_class_name(dev->class->name, | 692 | class_name = make_class_name(dev->class->name, |
690 | &dev->kobj); | 693 | &dev->kobj); |
691 | if (class_name) | 694 | if (class_name) |
692 | error = sysfs_create_link(&dev->parent->kobj, | 695 | error = sysfs_create_link(&dev->parent->kobj, |
693 | &dev->kobj, class_name); | 696 | &dev->kobj, class_name); |
694 | kfree(class_name); | 697 | kfree(class_name); |
695 | if (error) | 698 | if (error) |
696 | goto out_device; | 699 | goto out_device; |
697 | } | 700 | } |
698 | return 0; | 701 | return 0; |
699 | 702 | ||
700 | out_device: | 703 | out_device: |
701 | if (dev->parent && device_is_not_partition(dev)) | 704 | if (dev->parent && device_is_not_partition(dev)) |
702 | sysfs_remove_link(&dev->kobj, "device"); | 705 | sysfs_remove_link(&dev->kobj, "device"); |
703 | out_busid: | 706 | out_busid: |
704 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 707 | if (dev->kobj.parent != &dev->class->subsys.kobj && |
705 | device_is_not_partition(dev)) | 708 | device_is_not_partition(dev)) |
706 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 709 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); |
707 | #else | 710 | #else |
708 | /* link in the class directory pointing to the device */ | 711 | /* link in the class directory pointing to the device */ |
709 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 712 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, |
710 | dev->bus_id); | 713 | dev->bus_id); |
711 | if (error) | 714 | if (error) |
712 | goto out_subsys; | 715 | goto out_subsys; |
713 | 716 | ||
714 | if (dev->parent && device_is_not_partition(dev)) { | 717 | if (dev->parent && device_is_not_partition(dev)) { |
715 | error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, | 718 | error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, |
716 | "device"); | 719 | "device"); |
717 | if (error) | 720 | if (error) |
718 | goto out_busid; | 721 | goto out_busid; |
719 | } | 722 | } |
720 | return 0; | 723 | return 0; |
721 | 724 | ||
722 | out_busid: | 725 | out_busid: |
723 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 726 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); |
724 | #endif | 727 | #endif |
725 | 728 | ||
726 | out_subsys: | 729 | out_subsys: |
727 | sysfs_remove_link(&dev->kobj, "subsystem"); | 730 | sysfs_remove_link(&dev->kobj, "subsystem"); |
728 | out: | 731 | out: |
729 | return error; | 732 | return error; |
730 | } | 733 | } |
731 | 734 | ||
732 | static void device_remove_class_symlinks(struct device *dev) | 735 | static void device_remove_class_symlinks(struct device *dev) |
733 | { | 736 | { |
734 | if (!dev->class) | 737 | if (!dev->class) |
735 | return; | 738 | return; |
736 | 739 | ||
737 | #ifdef CONFIG_SYSFS_DEPRECATED | 740 | #ifdef CONFIG_SYSFS_DEPRECATED |
738 | if (dev->parent && device_is_not_partition(dev)) { | 741 | if (dev->parent && device_is_not_partition(dev)) { |
739 | char *class_name; | 742 | char *class_name; |
740 | 743 | ||
741 | class_name = make_class_name(dev->class->name, &dev->kobj); | 744 | class_name = make_class_name(dev->class->name, &dev->kobj); |
742 | if (class_name) { | 745 | if (class_name) { |
743 | sysfs_remove_link(&dev->parent->kobj, class_name); | 746 | sysfs_remove_link(&dev->parent->kobj, class_name); |
744 | kfree(class_name); | 747 | kfree(class_name); |
745 | } | 748 | } |
746 | sysfs_remove_link(&dev->kobj, "device"); | 749 | sysfs_remove_link(&dev->kobj, "device"); |
747 | } | 750 | } |
748 | 751 | ||
749 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 752 | if (dev->kobj.parent != &dev->class->subsys.kobj && |
750 | device_is_not_partition(dev)) | 753 | device_is_not_partition(dev)) |
751 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 754 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); |
752 | #else | 755 | #else |
753 | if (dev->parent && device_is_not_partition(dev)) | 756 | if (dev->parent && device_is_not_partition(dev)) |
754 | sysfs_remove_link(&dev->kobj, "device"); | 757 | sysfs_remove_link(&dev->kobj, "device"); |
755 | 758 | ||
756 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 759 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); |
757 | #endif | 760 | #endif |
758 | 761 | ||
759 | sysfs_remove_link(&dev->kobj, "subsystem"); | 762 | sysfs_remove_link(&dev->kobj, "subsystem"); |
760 | } | 763 | } |
761 | 764 | ||
762 | /** | 765 | /** |
763 | * dev_set_name - set a device name | 766 | * dev_set_name - set a device name |
764 | * @dev: device | 767 | * @dev: device |
765 | * @fmt: format string for the device's name | 768 | * @fmt: format string for the device's name |
766 | */ | 769 | */ |
767 | int dev_set_name(struct device *dev, const char *fmt, ...) | 770 | int dev_set_name(struct device *dev, const char *fmt, ...) |
768 | { | 771 | { |
769 | va_list vargs; | 772 | va_list vargs; |
770 | 773 | ||
771 | va_start(vargs, fmt); | 774 | va_start(vargs, fmt); |
772 | vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); | 775 | vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); |
773 | va_end(vargs); | 776 | va_end(vargs); |
774 | return 0; | 777 | return 0; |
775 | } | 778 | } |
776 | EXPORT_SYMBOL_GPL(dev_set_name); | 779 | EXPORT_SYMBOL_GPL(dev_set_name); |
777 | 780 | ||
778 | /** | 781 | /** |
782 | * device_to_dev_kobj - select a /sys/dev/ directory for the device | ||
783 | * @dev: device | ||
784 | * | ||
785 | * By default we select char/ for new entries. Setting class->dev_obj | ||
786 | * to NULL prevents an entry from being created. class->dev_kobj must | ||
787 | * be set (or cleared) before any devices are registered to the class | ||
788 | * otherwise device_create_sys_dev_entry() and | ||
789 | * device_remove_sys_dev_entry() will disagree about the the presence | ||
790 | * of the link. | ||
791 | */ | ||
792 | static struct kobject *device_to_dev_kobj(struct device *dev) | ||
793 | { | ||
794 | struct kobject *kobj; | ||
795 | |||
796 | if (dev->class) | ||
797 | kobj = dev->class->dev_kobj; | ||
798 | else | ||
799 | kobj = sysfs_dev_char_kobj; | ||
800 | |||
801 | return kobj; | ||
802 | } | ||
803 | |||
804 | static int device_create_sys_dev_entry(struct device *dev) | ||
805 | { | ||
806 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
807 | int error = 0; | ||
808 | char devt_str[15]; | ||
809 | |||
810 | if (kobj) { | ||
811 | format_dev_t(devt_str, dev->devt); | ||
812 | error = sysfs_create_link(kobj, &dev->kobj, devt_str); | ||
813 | } | ||
814 | |||
815 | return error; | ||
816 | } | ||
817 | |||
818 | static void device_remove_sys_dev_entry(struct device *dev) | ||
819 | { | ||
820 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
821 | char devt_str[15]; | ||
822 | |||
823 | if (kobj) { | ||
824 | format_dev_t(devt_str, dev->devt); | ||
825 | sysfs_remove_link(kobj, devt_str); | ||
826 | } | ||
827 | } | ||
828 | |||
829 | /** | ||
779 | * device_add - add device to device hierarchy. | 830 | * device_add - add device to device hierarchy. |
780 | * @dev: device. | 831 | * @dev: device. |
781 | * | 832 | * |
782 | * This is part 2 of device_register(), though may be called | 833 | * This is part 2 of device_register(), though may be called |
783 | * separately _iff_ device_initialize() has been called separately. | 834 | * separately _iff_ device_initialize() has been called separately. |
784 | * | 835 | * |
785 | * This adds it to the kobject hierarchy via kobject_add(), adds it | 836 | * This adds it to the kobject hierarchy via kobject_add(), adds it |
786 | * to the global and sibling lists for the device, then | 837 | * to the global and sibling lists for the device, then |
787 | * adds it to the other relevant subsystems of the driver model. | 838 | * adds it to the other relevant subsystems of the driver model. |
788 | */ | 839 | */ |
789 | int device_add(struct device *dev) | 840 | int device_add(struct device *dev) |
790 | { | 841 | { |
791 | struct device *parent = NULL; | 842 | struct device *parent = NULL; |
792 | struct class_interface *class_intf; | 843 | struct class_interface *class_intf; |
793 | int error; | 844 | int error; |
794 | 845 | ||
795 | dev = get_device(dev); | 846 | dev = get_device(dev); |
796 | if (!dev || !strlen(dev->bus_id)) { | 847 | if (!dev || !strlen(dev->bus_id)) { |
797 | error = -EINVAL; | 848 | error = -EINVAL; |
798 | goto Done; | 849 | goto Done; |
799 | } | 850 | } |
800 | 851 | ||
801 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); | 852 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); |
802 | 853 | ||
803 | parent = get_device(dev->parent); | 854 | parent = get_device(dev->parent); |
804 | setup_parent(dev, parent); | 855 | setup_parent(dev, parent); |
805 | 856 | ||
806 | /* use parent numa_node */ | 857 | /* use parent numa_node */ |
807 | if (parent) | 858 | if (parent) |
808 | set_dev_node(dev, dev_to_node(parent)); | 859 | set_dev_node(dev, dev_to_node(parent)); |
809 | 860 | ||
810 | /* first, register with generic layer. */ | 861 | /* first, register with generic layer. */ |
811 | error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id); | 862 | error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id); |
812 | if (error) | 863 | if (error) |
813 | goto Error; | 864 | goto Error; |
814 | 865 | ||
815 | /* notify platform of device entry */ | 866 | /* notify platform of device entry */ |
816 | if (platform_notify) | 867 | if (platform_notify) |
817 | platform_notify(dev); | 868 | platform_notify(dev); |
818 | 869 | ||
819 | /* notify clients of device entry (new way) */ | 870 | /* notify clients of device entry (new way) */ |
820 | if (dev->bus) | 871 | if (dev->bus) |
821 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 872 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
822 | BUS_NOTIFY_ADD_DEVICE, dev); | 873 | BUS_NOTIFY_ADD_DEVICE, dev); |
823 | 874 | ||
824 | error = device_create_file(dev, &uevent_attr); | 875 | error = device_create_file(dev, &uevent_attr); |
825 | if (error) | 876 | if (error) |
826 | goto attrError; | 877 | goto attrError; |
827 | 878 | ||
828 | if (MAJOR(dev->devt)) { | 879 | if (MAJOR(dev->devt)) { |
829 | error = device_create_file(dev, &devt_attr); | 880 | error = device_create_file(dev, &devt_attr); |
830 | if (error) | 881 | if (error) |
831 | goto ueventattrError; | 882 | goto ueventattrError; |
883 | |||
884 | error = device_create_sys_dev_entry(dev); | ||
885 | if (error) | ||
886 | goto devtattrError; | ||
832 | } | 887 | } |
833 | 888 | ||
834 | error = device_add_class_symlinks(dev); | 889 | error = device_add_class_symlinks(dev); |
835 | if (error) | 890 | if (error) |
836 | goto SymlinkError; | 891 | goto SymlinkError; |
837 | error = device_add_attrs(dev); | 892 | error = device_add_attrs(dev); |
838 | if (error) | 893 | if (error) |
839 | goto AttrsError; | 894 | goto AttrsError; |
840 | error = bus_add_device(dev); | 895 | error = bus_add_device(dev); |
841 | if (error) | 896 | if (error) |
842 | goto BusError; | 897 | goto BusError; |
843 | error = device_pm_add(dev); | 898 | error = device_pm_add(dev); |
844 | if (error) | 899 | if (error) |
845 | goto PMError; | 900 | goto PMError; |
846 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 901 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
847 | bus_attach_device(dev); | 902 | bus_attach_device(dev); |
848 | if (parent) | 903 | if (parent) |
849 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 904 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
850 | 905 | ||
851 | if (dev->class) { | 906 | if (dev->class) { |
852 | down(&dev->class->sem); | 907 | down(&dev->class->sem); |
853 | /* tie the class to the device */ | 908 | /* tie the class to the device */ |
854 | list_add_tail(&dev->node, &dev->class->devices); | 909 | list_add_tail(&dev->node, &dev->class->devices); |
855 | 910 | ||
856 | /* notify any interfaces that the device is here */ | 911 | /* notify any interfaces that the device is here */ |
857 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 912 | list_for_each_entry(class_intf, &dev->class->interfaces, node) |
858 | if (class_intf->add_dev) | 913 | if (class_intf->add_dev) |
859 | class_intf->add_dev(dev, class_intf); | 914 | class_intf->add_dev(dev, class_intf); |
860 | up(&dev->class->sem); | 915 | up(&dev->class->sem); |
861 | } | 916 | } |
862 | Done: | 917 | Done: |
863 | put_device(dev); | 918 | put_device(dev); |
864 | return error; | 919 | return error; |
865 | PMError: | 920 | PMError: |
866 | bus_remove_device(dev); | 921 | bus_remove_device(dev); |
867 | BusError: | 922 | BusError: |
868 | if (dev->bus) | 923 | if (dev->bus) |
869 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 924 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
870 | BUS_NOTIFY_DEL_DEVICE, dev); | 925 | BUS_NOTIFY_DEL_DEVICE, dev); |
871 | device_remove_attrs(dev); | 926 | device_remove_attrs(dev); |
872 | AttrsError: | 927 | AttrsError: |
873 | device_remove_class_symlinks(dev); | 928 | device_remove_class_symlinks(dev); |
874 | SymlinkError: | 929 | SymlinkError: |
875 | if (MAJOR(dev->devt)) | 930 | if (MAJOR(dev->devt)) |
931 | device_remove_sys_dev_entry(dev); | ||
932 | devtattrError: | ||
933 | if (MAJOR(dev->devt)) | ||
876 | device_remove_file(dev, &devt_attr); | 934 | device_remove_file(dev, &devt_attr); |
877 | ueventattrError: | 935 | ueventattrError: |
878 | device_remove_file(dev, &uevent_attr); | 936 | device_remove_file(dev, &uevent_attr); |
879 | attrError: | 937 | attrError: |
880 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 938 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
881 | kobject_del(&dev->kobj); | 939 | kobject_del(&dev->kobj); |
882 | Error: | 940 | Error: |
883 | cleanup_device_parent(dev); | 941 | cleanup_device_parent(dev); |
884 | if (parent) | 942 | if (parent) |
885 | put_device(parent); | 943 | put_device(parent); |
886 | goto Done; | 944 | goto Done; |
887 | } | 945 | } |
888 | 946 | ||
889 | /** | 947 | /** |
890 | * device_register - register a device with the system. | 948 | * device_register - register a device with the system. |
891 | * @dev: pointer to the device structure | 949 | * @dev: pointer to the device structure |
892 | * | 950 | * |
893 | * This happens in two clean steps - initialize the device | 951 | * This happens in two clean steps - initialize the device |
894 | * and add it to the system. The two steps can be called | 952 | * and add it to the system. The two steps can be called |
895 | * separately, but this is the easiest and most common. | 953 | * separately, but this is the easiest and most common. |
896 | * I.e. you should only call the two helpers separately if | 954 | * I.e. you should only call the two helpers separately if |
897 | * have a clearly defined need to use and refcount the device | 955 | * have a clearly defined need to use and refcount the device |
898 | * before it is added to the hierarchy. | 956 | * before it is added to the hierarchy. |
899 | */ | 957 | */ |
900 | int device_register(struct device *dev) | 958 | int device_register(struct device *dev) |
901 | { | 959 | { |
902 | device_initialize(dev); | 960 | device_initialize(dev); |
903 | return device_add(dev); | 961 | return device_add(dev); |
904 | } | 962 | } |
905 | 963 | ||
906 | /** | 964 | /** |
907 | * get_device - increment reference count for device. | 965 | * get_device - increment reference count for device. |
908 | * @dev: device. | 966 | * @dev: device. |
909 | * | 967 | * |
910 | * This simply forwards the call to kobject_get(), though | 968 | * This simply forwards the call to kobject_get(), though |
911 | * we do take care to provide for the case that we get a NULL | 969 | * we do take care to provide for the case that we get a NULL |
912 | * pointer passed in. | 970 | * pointer passed in. |
913 | */ | 971 | */ |
914 | struct device *get_device(struct device *dev) | 972 | struct device *get_device(struct device *dev) |
915 | { | 973 | { |
916 | return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; | 974 | return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; |
917 | } | 975 | } |
918 | 976 | ||
919 | /** | 977 | /** |
920 | * put_device - decrement reference count. | 978 | * put_device - decrement reference count. |
921 | * @dev: device in question. | 979 | * @dev: device in question. |
922 | */ | 980 | */ |
923 | void put_device(struct device *dev) | 981 | void put_device(struct device *dev) |
924 | { | 982 | { |
925 | /* might_sleep(); */ | 983 | /* might_sleep(); */ |
926 | if (dev) | 984 | if (dev) |
927 | kobject_put(&dev->kobj); | 985 | kobject_put(&dev->kobj); |
928 | } | 986 | } |
929 | 987 | ||
930 | /** | 988 | /** |
931 | * device_del - delete device from system. | 989 | * device_del - delete device from system. |
932 | * @dev: device. | 990 | * @dev: device. |
933 | * | 991 | * |
934 | * This is the first part of the device unregistration | 992 | * This is the first part of the device unregistration |
935 | * sequence. This removes the device from the lists we control | 993 | * sequence. This removes the device from the lists we control |
936 | * from here, has it removed from the other driver model | 994 | * from here, has it removed from the other driver model |
937 | * subsystems it was added to in device_add(), and removes it | 995 | * subsystems it was added to in device_add(), and removes it |
938 | * from the kobject hierarchy. | 996 | * from the kobject hierarchy. |
939 | * | 997 | * |
940 | * NOTE: this should be called manually _iff_ device_add() was | 998 | * NOTE: this should be called manually _iff_ device_add() was |
941 | * also called manually. | 999 | * also called manually. |
942 | */ | 1000 | */ |
943 | void device_del(struct device *dev) | 1001 | void device_del(struct device *dev) |
944 | { | 1002 | { |
945 | struct device *parent = dev->parent; | 1003 | struct device *parent = dev->parent; |
946 | struct class_interface *class_intf; | 1004 | struct class_interface *class_intf; |
947 | 1005 | ||
948 | device_pm_remove(dev); | 1006 | device_pm_remove(dev); |
949 | if (parent) | 1007 | if (parent) |
950 | klist_del(&dev->knode_parent); | 1008 | klist_del(&dev->knode_parent); |
951 | if (MAJOR(dev->devt)) | 1009 | if (MAJOR(dev->devt)) { |
1010 | device_remove_sys_dev_entry(dev); | ||
952 | device_remove_file(dev, &devt_attr); | 1011 | device_remove_file(dev, &devt_attr); |
1012 | } | ||
953 | if (dev->class) { | 1013 | if (dev->class) { |
954 | device_remove_class_symlinks(dev); | 1014 | device_remove_class_symlinks(dev); |
955 | 1015 | ||
956 | down(&dev->class->sem); | 1016 | down(&dev->class->sem); |
957 | /* notify any interfaces that the device is now gone */ | 1017 | /* notify any interfaces that the device is now gone */ |
958 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 1018 | list_for_each_entry(class_intf, &dev->class->interfaces, node) |
959 | if (class_intf->remove_dev) | 1019 | if (class_intf->remove_dev) |
960 | class_intf->remove_dev(dev, class_intf); | 1020 | class_intf->remove_dev(dev, class_intf); |
961 | /* remove the device from the class list */ | 1021 | /* remove the device from the class list */ |
962 | list_del_init(&dev->node); | 1022 | list_del_init(&dev->node); |
963 | up(&dev->class->sem); | 1023 | up(&dev->class->sem); |
964 | } | 1024 | } |
965 | device_remove_file(dev, &uevent_attr); | 1025 | device_remove_file(dev, &uevent_attr); |
966 | device_remove_attrs(dev); | 1026 | device_remove_attrs(dev); |
967 | bus_remove_device(dev); | 1027 | bus_remove_device(dev); |
968 | 1028 | ||
969 | /* | 1029 | /* |
970 | * Some platform devices are driven without driver attached | 1030 | * Some platform devices are driven without driver attached |
971 | * and managed resources may have been acquired. Make sure | 1031 | * and managed resources may have been acquired. Make sure |
972 | * all resources are released. | 1032 | * all resources are released. |
973 | */ | 1033 | */ |
974 | devres_release_all(dev); | 1034 | devres_release_all(dev); |
975 | 1035 | ||
976 | /* Notify the platform of the removal, in case they | 1036 | /* Notify the platform of the removal, in case they |
977 | * need to do anything... | 1037 | * need to do anything... |
978 | */ | 1038 | */ |
979 | if (platform_notify_remove) | 1039 | if (platform_notify_remove) |
980 | platform_notify_remove(dev); | 1040 | platform_notify_remove(dev); |
981 | if (dev->bus) | 1041 | if (dev->bus) |
982 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 1042 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
983 | BUS_NOTIFY_DEL_DEVICE, dev); | 1043 | BUS_NOTIFY_DEL_DEVICE, dev); |
984 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 1044 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
985 | cleanup_device_parent(dev); | 1045 | cleanup_device_parent(dev); |
986 | kobject_del(&dev->kobj); | 1046 | kobject_del(&dev->kobj); |
987 | put_device(parent); | 1047 | put_device(parent); |
988 | } | 1048 | } |
989 | 1049 | ||
990 | /** | 1050 | /** |
991 | * device_unregister - unregister device from system. | 1051 | * device_unregister - unregister device from system. |
992 | * @dev: device going away. | 1052 | * @dev: device going away. |
993 | * | 1053 | * |
994 | * We do this in two parts, like we do device_register(). First, | 1054 | * We do this in two parts, like we do device_register(). First, |
995 | * we remove it from all the subsystems with device_del(), then | 1055 | * we remove it from all the subsystems with device_del(), then |
996 | * we decrement the reference count via put_device(). If that | 1056 | * we decrement the reference count via put_device(). If that |
997 | * is the final reference count, the device will be cleaned up | 1057 | * is the final reference count, the device will be cleaned up |
998 | * via device_release() above. Otherwise, the structure will | 1058 | * via device_release() above. Otherwise, the structure will |
999 | * stick around until the final reference to the device is dropped. | 1059 | * stick around until the final reference to the device is dropped. |
1000 | */ | 1060 | */ |
1001 | void device_unregister(struct device *dev) | 1061 | void device_unregister(struct device *dev) |
1002 | { | 1062 | { |
1003 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); | 1063 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); |
1004 | device_del(dev); | 1064 | device_del(dev); |
1005 | put_device(dev); | 1065 | put_device(dev); |
1006 | } | 1066 | } |
1007 | 1067 | ||
1008 | static struct device *next_device(struct klist_iter *i) | 1068 | static struct device *next_device(struct klist_iter *i) |
1009 | { | 1069 | { |
1010 | struct klist_node *n = klist_next(i); | 1070 | struct klist_node *n = klist_next(i); |
1011 | return n ? container_of(n, struct device, knode_parent) : NULL; | 1071 | return n ? container_of(n, struct device, knode_parent) : NULL; |
1012 | } | 1072 | } |
1013 | 1073 | ||
1014 | /** | 1074 | /** |
1015 | * device_for_each_child - device child iterator. | 1075 | * device_for_each_child - device child iterator. |
1016 | * @parent: parent struct device. | 1076 | * @parent: parent struct device. |
1017 | * @data: data for the callback. | 1077 | * @data: data for the callback. |
1018 | * @fn: function to be called for each device. | 1078 | * @fn: function to be called for each device. |
1019 | * | 1079 | * |
1020 | * Iterate over @parent's child devices, and call @fn for each, | 1080 | * Iterate over @parent's child devices, and call @fn for each, |
1021 | * passing it @data. | 1081 | * passing it @data. |
1022 | * | 1082 | * |
1023 | * We check the return of @fn each time. If it returns anything | 1083 | * We check the return of @fn each time. If it returns anything |
1024 | * other than 0, we break out and return that value. | 1084 | * other than 0, we break out and return that value. |
1025 | */ | 1085 | */ |
1026 | int device_for_each_child(struct device *parent, void *data, | 1086 | int device_for_each_child(struct device *parent, void *data, |
1027 | int (*fn)(struct device *dev, void *data)) | 1087 | int (*fn)(struct device *dev, void *data)) |
1028 | { | 1088 | { |
1029 | struct klist_iter i; | 1089 | struct klist_iter i; |
1030 | struct device *child; | 1090 | struct device *child; |
1031 | int error = 0; | 1091 | int error = 0; |
1032 | 1092 | ||
1033 | klist_iter_init(&parent->klist_children, &i); | 1093 | klist_iter_init(&parent->klist_children, &i); |
1034 | while ((child = next_device(&i)) && !error) | 1094 | while ((child = next_device(&i)) && !error) |
1035 | error = fn(child, data); | 1095 | error = fn(child, data); |
1036 | klist_iter_exit(&i); | 1096 | klist_iter_exit(&i); |
1037 | return error; | 1097 | return error; |
1038 | } | 1098 | } |
1039 | 1099 | ||
1040 | /** | 1100 | /** |
1041 | * device_find_child - device iterator for locating a particular device. | 1101 | * device_find_child - device iterator for locating a particular device. |
1042 | * @parent: parent struct device | 1102 | * @parent: parent struct device |
1043 | * @data: Data to pass to match function | 1103 | * @data: Data to pass to match function |
1044 | * @match: Callback function to check device | 1104 | * @match: Callback function to check device |
1045 | * | 1105 | * |
1046 | * This is similar to the device_for_each_child() function above, but it | 1106 | * This is similar to the device_for_each_child() function above, but it |
1047 | * returns a reference to a device that is 'found' for later use, as | 1107 | * returns a reference to a device that is 'found' for later use, as |
1048 | * determined by the @match callback. | 1108 | * determined by the @match callback. |
1049 | * | 1109 | * |
1050 | * The callback should return 0 if the device doesn't match and non-zero | 1110 | * The callback should return 0 if the device doesn't match and non-zero |
1051 | * if it does. If the callback returns non-zero and a reference to the | 1111 | * if it does. If the callback returns non-zero and a reference to the |
1052 | * current device can be obtained, this function will return to the caller | 1112 | * current device can be obtained, this function will return to the caller |
1053 | * and not iterate over any more devices. | 1113 | * and not iterate over any more devices. |
1054 | */ | 1114 | */ |
1055 | struct device *device_find_child(struct device *parent, void *data, | 1115 | struct device *device_find_child(struct device *parent, void *data, |
1056 | int (*match)(struct device *dev, void *data)) | 1116 | int (*match)(struct device *dev, void *data)) |
1057 | { | 1117 | { |
1058 | struct klist_iter i; | 1118 | struct klist_iter i; |
1059 | struct device *child; | 1119 | struct device *child; |
1060 | 1120 | ||
1061 | if (!parent) | 1121 | if (!parent) |
1062 | return NULL; | 1122 | return NULL; |
1063 | 1123 | ||
1064 | klist_iter_init(&parent->klist_children, &i); | 1124 | klist_iter_init(&parent->klist_children, &i); |
1065 | while ((child = next_device(&i))) | 1125 | while ((child = next_device(&i))) |
1066 | if (match(child, data) && get_device(child)) | 1126 | if (match(child, data) && get_device(child)) |
1067 | break; | 1127 | break; |
1068 | klist_iter_exit(&i); | 1128 | klist_iter_exit(&i); |
1069 | return child; | 1129 | return child; |
1070 | } | 1130 | } |
1071 | 1131 | ||
1072 | int __init devices_init(void) | 1132 | int __init devices_init(void) |
1073 | { | 1133 | { |
1074 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); | 1134 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); |
1075 | if (!devices_kset) | 1135 | if (!devices_kset) |
1076 | return -ENOMEM; | 1136 | return -ENOMEM; |
1137 | dev_kobj = kobject_create_and_add("dev", NULL); | ||
1138 | if (!dev_kobj) | ||
1139 | goto dev_kobj_err; | ||
1140 | sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); | ||
1141 | if (!sysfs_dev_block_kobj) | ||
1142 | goto block_kobj_err; | ||
1143 | sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); | ||
1144 | if (!sysfs_dev_char_kobj) | ||
1145 | goto char_kobj_err; | ||
1146 | |||
1077 | return 0; | 1147 | return 0; |
1148 | |||
1149 | char_kobj_err: | ||
1150 | kobject_put(sysfs_dev_block_kobj); | ||
1151 | block_kobj_err: | ||
1152 | kobject_put(dev_kobj); | ||
1153 | dev_kobj_err: | ||
1154 | kset_unregister(devices_kset); | ||
1155 | return -ENOMEM; | ||
1078 | } | 1156 | } |
1079 | 1157 | ||
1080 | EXPORT_SYMBOL_GPL(device_for_each_child); | 1158 | EXPORT_SYMBOL_GPL(device_for_each_child); |
1081 | EXPORT_SYMBOL_GPL(device_find_child); | 1159 | EXPORT_SYMBOL_GPL(device_find_child); |
1082 | 1160 | ||
1083 | EXPORT_SYMBOL_GPL(device_initialize); | 1161 | EXPORT_SYMBOL_GPL(device_initialize); |
1084 | EXPORT_SYMBOL_GPL(device_add); | 1162 | EXPORT_SYMBOL_GPL(device_add); |
1085 | EXPORT_SYMBOL_GPL(device_register); | 1163 | EXPORT_SYMBOL_GPL(device_register); |
1086 | 1164 | ||
1087 | EXPORT_SYMBOL_GPL(device_del); | 1165 | EXPORT_SYMBOL_GPL(device_del); |
1088 | EXPORT_SYMBOL_GPL(device_unregister); | 1166 | EXPORT_SYMBOL_GPL(device_unregister); |
1089 | EXPORT_SYMBOL_GPL(get_device); | 1167 | EXPORT_SYMBOL_GPL(get_device); |
1090 | EXPORT_SYMBOL_GPL(put_device); | 1168 | EXPORT_SYMBOL_GPL(put_device); |
1091 | 1169 | ||
1092 | EXPORT_SYMBOL_GPL(device_create_file); | 1170 | EXPORT_SYMBOL_GPL(device_create_file); |
1093 | EXPORT_SYMBOL_GPL(device_remove_file); | 1171 | EXPORT_SYMBOL_GPL(device_remove_file); |
1094 | 1172 | ||
1095 | 1173 | ||
1096 | static void device_create_release(struct device *dev) | 1174 | static void device_create_release(struct device *dev) |
1097 | { | 1175 | { |
1098 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); | 1176 | pr_debug("device: '%s': %s\n", dev->bus_id, __func__); |
1099 | kfree(dev); | 1177 | kfree(dev); |
1100 | } | 1178 | } |
1101 | 1179 | ||
1102 | /** | 1180 | /** |
1103 | * device_create_vargs - creates a device and registers it with sysfs | 1181 | * device_create_vargs - creates a device and registers it with sysfs |
1104 | * @class: pointer to the struct class that this device should be registered to | 1182 | * @class: pointer to the struct class that this device should be registered to |
1105 | * @parent: pointer to the parent struct device of this new device, if any | 1183 | * @parent: pointer to the parent struct device of this new device, if any |
1106 | * @devt: the dev_t for the char device to be added | 1184 | * @devt: the dev_t for the char device to be added |
1107 | * @drvdata: the data to be added to the device for callbacks | 1185 | * @drvdata: the data to be added to the device for callbacks |
1108 | * @fmt: string for the device's name | 1186 | * @fmt: string for the device's name |
1109 | * @args: va_list for the device's name | 1187 | * @args: va_list for the device's name |
1110 | * | 1188 | * |
1111 | * This function can be used by char device classes. A struct device | 1189 | * This function can be used by char device classes. A struct device |
1112 | * will be created in sysfs, registered to the specified class. | 1190 | * will be created in sysfs, registered to the specified class. |
1113 | * | 1191 | * |
1114 | * A "dev" file will be created, showing the dev_t for the device, if | 1192 | * A "dev" file will be created, showing the dev_t for the device, if |
1115 | * the dev_t is not 0,0. | 1193 | * the dev_t is not 0,0. |
1116 | * If a pointer to a parent struct device is passed in, the newly created | 1194 | * If a pointer to a parent struct device is passed in, the newly created |
1117 | * struct device will be a child of that device in sysfs. | 1195 | * struct device will be a child of that device in sysfs. |
1118 | * The pointer to the struct device will be returned from the call. | 1196 | * The pointer to the struct device will be returned from the call. |
1119 | * Any further sysfs files that might be required can be created using this | 1197 | * Any further sysfs files that might be required can be created using this |
1120 | * pointer. | 1198 | * pointer. |
1121 | * | 1199 | * |
1122 | * Note: the struct class passed to this function must have previously | 1200 | * Note: the struct class passed to this function must have previously |
1123 | * been created with a call to class_create(). | 1201 | * been created with a call to class_create(). |
1124 | */ | 1202 | */ |
1125 | struct device *device_create_vargs(struct class *class, struct device *parent, | 1203 | struct device *device_create_vargs(struct class *class, struct device *parent, |
1126 | dev_t devt, void *drvdata, const char *fmt, | 1204 | dev_t devt, void *drvdata, const char *fmt, |
1127 | va_list args) | 1205 | va_list args) |
1128 | { | 1206 | { |
1129 | struct device *dev = NULL; | 1207 | struct device *dev = NULL; |
1130 | int retval = -ENODEV; | 1208 | int retval = -ENODEV; |
1131 | 1209 | ||
1132 | if (class == NULL || IS_ERR(class)) | 1210 | if (class == NULL || IS_ERR(class)) |
1133 | goto error; | 1211 | goto error; |
1134 | 1212 | ||
1135 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1213 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1136 | if (!dev) { | 1214 | if (!dev) { |
1137 | retval = -ENOMEM; | 1215 | retval = -ENOMEM; |
1138 | goto error; | 1216 | goto error; |
1139 | } | 1217 | } |
1140 | 1218 | ||
1141 | dev->devt = devt; | 1219 | dev->devt = devt; |
1142 | dev->class = class; | 1220 | dev->class = class; |
1143 | dev->parent = parent; | 1221 | dev->parent = parent; |
1144 | dev->release = device_create_release; | 1222 | dev->release = device_create_release; |
1145 | dev_set_drvdata(dev, drvdata); | 1223 | dev_set_drvdata(dev, drvdata); |
1146 | 1224 | ||
1147 | vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); | 1225 | vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); |
1148 | retval = device_register(dev); | 1226 | retval = device_register(dev); |
1149 | if (retval) | 1227 | if (retval) |
1150 | goto error; | 1228 | goto error; |
1151 | 1229 | ||
1152 | return dev; | 1230 | return dev; |
1153 | 1231 | ||
1154 | error: | 1232 | error: |
1155 | kfree(dev); | 1233 | kfree(dev); |
1156 | return ERR_PTR(retval); | 1234 | return ERR_PTR(retval); |
1157 | } | 1235 | } |
1158 | EXPORT_SYMBOL_GPL(device_create_vargs); | 1236 | EXPORT_SYMBOL_GPL(device_create_vargs); |
1159 | 1237 | ||
1160 | /** | 1238 | /** |
1161 | * device_create_drvdata - creates a device and registers it with sysfs | 1239 | * device_create_drvdata - creates a device and registers it with sysfs |
1162 | * @class: pointer to the struct class that this device should be registered to | 1240 | * @class: pointer to the struct class that this device should be registered to |
1163 | * @parent: pointer to the parent struct device of this new device, if any | 1241 | * @parent: pointer to the parent struct device of this new device, if any |
1164 | * @devt: the dev_t for the char device to be added | 1242 | * @devt: the dev_t for the char device to be added |
1165 | * @drvdata: the data to be added to the device for callbacks | 1243 | * @drvdata: the data to be added to the device for callbacks |
1166 | * @fmt: string for the device's name | 1244 | * @fmt: string for the device's name |
1167 | * | 1245 | * |
1168 | * This function can be used by char device classes. A struct device | 1246 | * This function can be used by char device classes. A struct device |
1169 | * will be created in sysfs, registered to the specified class. | 1247 | * will be created in sysfs, registered to the specified class. |
1170 | * | 1248 | * |
1171 | * A "dev" file will be created, showing the dev_t for the device, if | 1249 | * A "dev" file will be created, showing the dev_t for the device, if |
1172 | * the dev_t is not 0,0. | 1250 | * the dev_t is not 0,0. |
1173 | * If a pointer to a parent struct device is passed in, the newly created | 1251 | * If a pointer to a parent struct device is passed in, the newly created |
1174 | * struct device will be a child of that device in sysfs. | 1252 | * struct device will be a child of that device in sysfs. |
1175 | * The pointer to the struct device will be returned from the call. | 1253 | * The pointer to the struct device will be returned from the call. |
1176 | * Any further sysfs files that might be required can be created using this | 1254 | * Any further sysfs files that might be required can be created using this |
1177 | * pointer. | 1255 | * pointer. |
1178 | * | 1256 | * |
1179 | * Note: the struct class passed to this function must have previously | 1257 | * Note: the struct class passed to this function must have previously |
1180 | * been created with a call to class_create(). | 1258 | * been created with a call to class_create(). |
1181 | */ | 1259 | */ |
1182 | struct device *device_create_drvdata(struct class *class, | 1260 | struct device *device_create_drvdata(struct class *class, |
1183 | struct device *parent, | 1261 | struct device *parent, |
1184 | dev_t devt, | 1262 | dev_t devt, |
1185 | void *drvdata, | 1263 | void *drvdata, |
1186 | const char *fmt, ...) | 1264 | const char *fmt, ...) |
1187 | { | 1265 | { |
1188 | va_list vargs; | 1266 | va_list vargs; |
1189 | struct device *dev; | 1267 | struct device *dev; |
1190 | 1268 | ||
1191 | va_start(vargs, fmt); | 1269 | va_start(vargs, fmt); |
1192 | dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); | 1270 | dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); |
1193 | va_end(vargs); | 1271 | va_end(vargs); |
1194 | return dev; | 1272 | return dev; |
1195 | } | 1273 | } |
1196 | EXPORT_SYMBOL_GPL(device_create_drvdata); | 1274 | EXPORT_SYMBOL_GPL(device_create_drvdata); |
1197 | 1275 | ||
1198 | /** | 1276 | /** |
1199 | * device_create - creates a device and registers it with sysfs | 1277 | * device_create - creates a device and registers it with sysfs |
1200 | * @class: pointer to the struct class that this device should be registered to | 1278 | * @class: pointer to the struct class that this device should be registered to |
1201 | * @parent: pointer to the parent struct device of this new device, if any | 1279 | * @parent: pointer to the parent struct device of this new device, if any |
1202 | * @devt: the dev_t for the char device to be added | 1280 | * @devt: the dev_t for the char device to be added |
1203 | * @fmt: string for the device's name | 1281 | * @fmt: string for the device's name |
1204 | * | 1282 | * |
1205 | * This function can be used by char device classes. A struct device | 1283 | * This function can be used by char device classes. A struct device |
1206 | * will be created in sysfs, registered to the specified class. | 1284 | * will be created in sysfs, registered to the specified class. |
1207 | * | 1285 | * |
1208 | * A "dev" file will be created, showing the dev_t for the device, if | 1286 | * A "dev" file will be created, showing the dev_t for the device, if |
1209 | * the dev_t is not 0,0. | 1287 | * the dev_t is not 0,0. |
1210 | * If a pointer to a parent struct device is passed in, the newly created | 1288 | * If a pointer to a parent struct device is passed in, the newly created |
1211 | * struct device will be a child of that device in sysfs. | 1289 | * struct device will be a child of that device in sysfs. |
1212 | * The pointer to the struct device will be returned from the call. | 1290 | * The pointer to the struct device will be returned from the call. |
1213 | * Any further sysfs files that might be required can be created using this | 1291 | * Any further sysfs files that might be required can be created using this |
1214 | * pointer. | 1292 | * pointer. |
1215 | * | 1293 | * |
1216 | * Note: the struct class passed to this function must have previously | 1294 | * Note: the struct class passed to this function must have previously |
1217 | * been created with a call to class_create(). | 1295 | * been created with a call to class_create(). |
1218 | */ | 1296 | */ |
1219 | struct device *device_create(struct class *class, struct device *parent, | 1297 | struct device *device_create(struct class *class, struct device *parent, |
1220 | dev_t devt, const char *fmt, ...) | 1298 | dev_t devt, const char *fmt, ...) |
1221 | { | 1299 | { |
1222 | va_list vargs; | 1300 | va_list vargs; |
1223 | struct device *dev; | 1301 | struct device *dev; |
1224 | 1302 | ||
1225 | va_start(vargs, fmt); | 1303 | va_start(vargs, fmt); |
1226 | dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs); | 1304 | dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs); |
1227 | va_end(vargs); | 1305 | va_end(vargs); |
1228 | return dev; | 1306 | return dev; |
1229 | } | 1307 | } |
1230 | EXPORT_SYMBOL_GPL(device_create); | 1308 | EXPORT_SYMBOL_GPL(device_create); |
1231 | 1309 | ||
1232 | static int __match_devt(struct device *dev, void *data) | 1310 | static int __match_devt(struct device *dev, void *data) |
1233 | { | 1311 | { |
1234 | dev_t *devt = data; | 1312 | dev_t *devt = data; |
1235 | 1313 | ||
1236 | return dev->devt == *devt; | 1314 | return dev->devt == *devt; |
1237 | } | 1315 | } |
1238 | 1316 | ||
1239 | /** | 1317 | /** |
1240 | * device_destroy - removes a device that was created with device_create() | 1318 | * device_destroy - removes a device that was created with device_create() |
1241 | * @class: pointer to the struct class that this device was registered with | 1319 | * @class: pointer to the struct class that this device was registered with |
1242 | * @devt: the dev_t of the device that was previously registered | 1320 | * @devt: the dev_t of the device that was previously registered |
1243 | * | 1321 | * |
1244 | * This call unregisters and cleans up a device that was created with a | 1322 | * This call unregisters and cleans up a device that was created with a |
1245 | * call to device_create(). | 1323 | * call to device_create(). |
1246 | */ | 1324 | */ |
1247 | void device_destroy(struct class *class, dev_t devt) | 1325 | void device_destroy(struct class *class, dev_t devt) |
1248 | { | 1326 | { |
1249 | struct device *dev; | 1327 | struct device *dev; |
1250 | 1328 | ||
1251 | dev = class_find_device(class, &devt, __match_devt); | 1329 | dev = class_find_device(class, &devt, __match_devt); |
1252 | if (dev) { | 1330 | if (dev) { |
1253 | put_device(dev); | 1331 | put_device(dev); |
1254 | device_unregister(dev); | 1332 | device_unregister(dev); |
1255 | } | 1333 | } |
1256 | } | 1334 | } |
1257 | EXPORT_SYMBOL_GPL(device_destroy); | 1335 | EXPORT_SYMBOL_GPL(device_destroy); |
1258 | 1336 | ||
1259 | /** | 1337 | /** |
1260 | * device_rename - renames a device | 1338 | * device_rename - renames a device |
1261 | * @dev: the pointer to the struct device to be renamed | 1339 | * @dev: the pointer to the struct device to be renamed |
1262 | * @new_name: the new name of the device | 1340 | * @new_name: the new name of the device |
1263 | */ | 1341 | */ |
1264 | int device_rename(struct device *dev, char *new_name) | 1342 | int device_rename(struct device *dev, char *new_name) |
1265 | { | 1343 | { |
1266 | char *old_class_name = NULL; | 1344 | char *old_class_name = NULL; |
1267 | char *new_class_name = NULL; | 1345 | char *new_class_name = NULL; |
1268 | char *old_device_name = NULL; | 1346 | char *old_device_name = NULL; |
1269 | int error; | 1347 | int error; |
1270 | 1348 | ||
1271 | dev = get_device(dev); | 1349 | dev = get_device(dev); |
1272 | if (!dev) | 1350 | if (!dev) |
1273 | return -EINVAL; | 1351 | return -EINVAL; |
1274 | 1352 | ||
1275 | pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id, | 1353 | pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id, |
1276 | __func__, new_name); | 1354 | __func__, new_name); |
1277 | 1355 | ||
1278 | #ifdef CONFIG_SYSFS_DEPRECATED | 1356 | #ifdef CONFIG_SYSFS_DEPRECATED |
1279 | if ((dev->class) && (dev->parent)) | 1357 | if ((dev->class) && (dev->parent)) |
1280 | old_class_name = make_class_name(dev->class->name, &dev->kobj); | 1358 | old_class_name = make_class_name(dev->class->name, &dev->kobj); |
1281 | #endif | 1359 | #endif |
1282 | 1360 | ||
1283 | old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); | 1361 | old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); |
1284 | if (!old_device_name) { | 1362 | if (!old_device_name) { |
1285 | error = -ENOMEM; | 1363 | error = -ENOMEM; |
1286 | goto out; | 1364 | goto out; |
1287 | } | 1365 | } |
1288 | strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); | 1366 | strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); |
1289 | strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); | 1367 | strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); |
1290 | 1368 | ||
1291 | error = kobject_rename(&dev->kobj, new_name); | 1369 | error = kobject_rename(&dev->kobj, new_name); |
1292 | if (error) { | 1370 | if (error) { |
1293 | strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); | 1371 | strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); |
1294 | goto out; | 1372 | goto out; |
1295 | } | 1373 | } |
1296 | 1374 | ||
1297 | #ifdef CONFIG_SYSFS_DEPRECATED | 1375 | #ifdef CONFIG_SYSFS_DEPRECATED |
1298 | if (old_class_name) { | 1376 | if (old_class_name) { |
1299 | new_class_name = make_class_name(dev->class->name, &dev->kobj); | 1377 | new_class_name = make_class_name(dev->class->name, &dev->kobj); |
1300 | if (new_class_name) { | 1378 | if (new_class_name) { |
1301 | error = sysfs_create_link(&dev->parent->kobj, | 1379 | error = sysfs_create_link(&dev->parent->kobj, |
1302 | &dev->kobj, new_class_name); | 1380 | &dev->kobj, new_class_name); |
1303 | if (error) | 1381 | if (error) |
1304 | goto out; | 1382 | goto out; |
1305 | sysfs_remove_link(&dev->parent->kobj, old_class_name); | 1383 | sysfs_remove_link(&dev->parent->kobj, old_class_name); |
1306 | } | 1384 | } |
1307 | } | 1385 | } |
1308 | #else | 1386 | #else |
1309 | if (dev->class) { | 1387 | if (dev->class) { |
1310 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 1388 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, |
1311 | dev->bus_id); | 1389 | dev->bus_id); |
1312 | if (error) | 1390 | if (error) |
1313 | goto out; | 1391 | goto out; |
1314 | sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); | 1392 | sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); |
1315 | } | 1393 | } |
1316 | #endif | 1394 | #endif |
1317 | 1395 | ||
1318 | out: | 1396 | out: |
1319 | put_device(dev); | 1397 | put_device(dev); |
1320 | 1398 | ||
1321 | kfree(new_class_name); | 1399 | kfree(new_class_name); |
1322 | kfree(old_class_name); | 1400 | kfree(old_class_name); |
1323 | kfree(old_device_name); | 1401 | kfree(old_device_name); |
1324 | 1402 | ||
1325 | return error; | 1403 | return error; |
1326 | } | 1404 | } |
1327 | EXPORT_SYMBOL_GPL(device_rename); | 1405 | EXPORT_SYMBOL_GPL(device_rename); |
1328 | 1406 | ||
1329 | static int device_move_class_links(struct device *dev, | 1407 | static int device_move_class_links(struct device *dev, |
1330 | struct device *old_parent, | 1408 | struct device *old_parent, |
1331 | struct device *new_parent) | 1409 | struct device *new_parent) |
1332 | { | 1410 | { |
1333 | int error = 0; | 1411 | int error = 0; |
1334 | #ifdef CONFIG_SYSFS_DEPRECATED | 1412 | #ifdef CONFIG_SYSFS_DEPRECATED |
1335 | char *class_name; | 1413 | char *class_name; |
1336 | 1414 | ||
1337 | class_name = make_class_name(dev->class->name, &dev->kobj); | 1415 | class_name = make_class_name(dev->class->name, &dev->kobj); |
1338 | if (!class_name) { | 1416 | if (!class_name) { |
1339 | error = -ENOMEM; | 1417 | error = -ENOMEM; |
1340 | goto out; | 1418 | goto out; |
1341 | } | 1419 | } |
1342 | if (old_parent) { | 1420 | if (old_parent) { |
1343 | sysfs_remove_link(&dev->kobj, "device"); | 1421 | sysfs_remove_link(&dev->kobj, "device"); |
1344 | sysfs_remove_link(&old_parent->kobj, class_name); | 1422 | sysfs_remove_link(&old_parent->kobj, class_name); |
1345 | } | 1423 | } |
1346 | if (new_parent) { | 1424 | if (new_parent) { |
1347 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, | 1425 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, |
1348 | "device"); | 1426 | "device"); |
1349 | if (error) | 1427 | if (error) |
1350 | goto out; | 1428 | goto out; |
1351 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, | 1429 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, |
1352 | class_name); | 1430 | class_name); |
1353 | if (error) | 1431 | if (error) |
1354 | sysfs_remove_link(&dev->kobj, "device"); | 1432 | sysfs_remove_link(&dev->kobj, "device"); |
1355 | } else | 1433 | } else |
1356 | error = 0; | 1434 | error = 0; |
1357 | out: | 1435 | out: |
1358 | kfree(class_name); | 1436 | kfree(class_name); |
1359 | return error; | 1437 | return error; |
1360 | #else | 1438 | #else |
1361 | if (old_parent) | 1439 | if (old_parent) |
1362 | sysfs_remove_link(&dev->kobj, "device"); | 1440 | sysfs_remove_link(&dev->kobj, "device"); |
1363 | if (new_parent) | 1441 | if (new_parent) |
1364 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, | 1442 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, |
1365 | "device"); | 1443 | "device"); |
1366 | return error; | 1444 | return error; |
1367 | #endif | 1445 | #endif |
1368 | } | 1446 | } |
1369 | 1447 | ||
1370 | /** | 1448 | /** |
1371 | * device_move - moves a device to a new parent | 1449 | * device_move - moves a device to a new parent |
1372 | * @dev: the pointer to the struct device to be moved | 1450 | * @dev: the pointer to the struct device to be moved |
1373 | * @new_parent: the new parent of the device (can by NULL) | 1451 | * @new_parent: the new parent of the device (can by NULL) |
1374 | */ | 1452 | */ |
1375 | int device_move(struct device *dev, struct device *new_parent) | 1453 | int device_move(struct device *dev, struct device *new_parent) |
1376 | { | 1454 | { |
1377 | int error; | 1455 | int error; |
1378 | struct device *old_parent; | 1456 | struct device *old_parent; |
1379 | struct kobject *new_parent_kobj; | 1457 | struct kobject *new_parent_kobj; |
1380 | 1458 | ||
1381 | dev = get_device(dev); | 1459 | dev = get_device(dev); |
1382 | if (!dev) | 1460 | if (!dev) |
1383 | return -EINVAL; | 1461 | return -EINVAL; |
1384 | 1462 | ||
1385 | new_parent = get_device(new_parent); | 1463 | new_parent = get_device(new_parent); |
1386 | new_parent_kobj = get_device_parent(dev, new_parent); | 1464 | new_parent_kobj = get_device_parent(dev, new_parent); |
1387 | 1465 | ||
1388 | pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id, | 1466 | pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id, |
1389 | __func__, new_parent ? new_parent->bus_id : "<NULL>"); | 1467 | __func__, new_parent ? new_parent->bus_id : "<NULL>"); |
1390 | error = kobject_move(&dev->kobj, new_parent_kobj); | 1468 | error = kobject_move(&dev->kobj, new_parent_kobj); |
1391 | if (error) { | 1469 | if (error) { |
1392 | cleanup_glue_dir(dev, new_parent_kobj); | 1470 | cleanup_glue_dir(dev, new_parent_kobj); |
1393 | put_device(new_parent); | 1471 | put_device(new_parent); |
1394 | goto out; | 1472 | goto out; |
1395 | } | 1473 | } |
1396 | old_parent = dev->parent; | 1474 | old_parent = dev->parent; |
1397 | dev->parent = new_parent; | 1475 | dev->parent = new_parent; |
1398 | if (old_parent) | 1476 | if (old_parent) |
1399 | klist_remove(&dev->knode_parent); | 1477 | klist_remove(&dev->knode_parent); |
1400 | if (new_parent) { | 1478 | if (new_parent) { |
1401 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | 1479 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); |
1402 | set_dev_node(dev, dev_to_node(new_parent)); | 1480 | set_dev_node(dev, dev_to_node(new_parent)); |
1403 | } | 1481 | } |
1404 | 1482 | ||
1405 | if (!dev->class) | 1483 | if (!dev->class) |
1406 | goto out_put; | 1484 | goto out_put; |
1407 | error = device_move_class_links(dev, old_parent, new_parent); | 1485 | error = device_move_class_links(dev, old_parent, new_parent); |
1408 | if (error) { | 1486 | if (error) { |
1409 | /* We ignore errors on cleanup since we're hosed anyway... */ | 1487 | /* We ignore errors on cleanup since we're hosed anyway... */ |
1410 | device_move_class_links(dev, new_parent, old_parent); | 1488 | device_move_class_links(dev, new_parent, old_parent); |
1411 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { | 1489 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { |
1412 | if (new_parent) | 1490 | if (new_parent) |
1413 | klist_remove(&dev->knode_parent); | 1491 | klist_remove(&dev->knode_parent); |
1414 | dev->parent = old_parent; | 1492 | dev->parent = old_parent; |
1415 | if (old_parent) { | 1493 | if (old_parent) { |
1416 | klist_add_tail(&dev->knode_parent, | 1494 | klist_add_tail(&dev->knode_parent, |
1417 | &old_parent->klist_children); | 1495 | &old_parent->klist_children); |
1418 | set_dev_node(dev, dev_to_node(old_parent)); | 1496 | set_dev_node(dev, dev_to_node(old_parent)); |
1419 | } | 1497 | } |
1420 | } | 1498 | } |
1421 | cleanup_glue_dir(dev, new_parent_kobj); | 1499 | cleanup_glue_dir(dev, new_parent_kobj); |
1422 | put_device(new_parent); | 1500 | put_device(new_parent); |
1423 | goto out; | 1501 | goto out; |
1424 | } | 1502 | } |
1425 | out_put: | 1503 | out_put: |
1426 | put_device(old_parent); | 1504 | put_device(old_parent); |
1427 | out: | 1505 | out: |
1428 | put_device(dev); | 1506 | put_device(dev); |
1429 | return error; | 1507 | return error; |
1430 | } | 1508 | } |
1431 | EXPORT_SYMBOL_GPL(device_move); | 1509 | EXPORT_SYMBOL_GPL(device_move); |
1432 | 1510 | ||
1433 | /** | 1511 | /** |
1434 | * device_shutdown - call ->shutdown() on each device to shutdown. | 1512 | * device_shutdown - call ->shutdown() on each device to shutdown. |
1435 | */ | 1513 | */ |
1436 | void device_shutdown(void) | 1514 | void device_shutdown(void) |
1437 | { | 1515 | { |
1438 | struct device *dev, *devn; | 1516 | struct device *dev, *devn; |
1439 | 1517 | ||
1440 | list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list, | 1518 | list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list, |
1441 | kobj.entry) { | 1519 | kobj.entry) { |
1442 | if (dev->bus && dev->bus->shutdown) { | 1520 | if (dev->bus && dev->bus->shutdown) { |
1443 | dev_dbg(dev, "shutdown\n"); | 1521 | dev_dbg(dev, "shutdown\n"); |
1444 | dev->bus->shutdown(dev); | 1522 | dev->bus->shutdown(dev); |
1445 | } else if (dev->driver && dev->driver->shutdown) { | 1523 | } else if (dev->driver && dev->driver->shutdown) { |
1446 | dev_dbg(dev, "shutdown\n"); | 1524 | dev_dbg(dev, "shutdown\n"); |
1447 | dev->driver->shutdown(dev); | 1525 | dev->driver->shutdown(dev); |
1448 | } | 1526 | } |
1449 | } | 1527 | } |
1528 | kobject_put(sysfs_dev_char_kobj); | ||
1529 | kobject_put(sysfs_dev_block_kobj); | ||
1530 | kobject_put(dev_kobj); | ||
1450 | } | 1531 | } |
1451 | 1532 |
drivers/usb/core/devio.c
1 | /*****************************************************************************/ | 1 | /*****************************************************************************/ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * devio.c -- User space communication with USB devices. | 4 | * devio.c -- User space communication with USB devices. |
5 | * | 5 | * |
6 | * Copyright (C) 1999-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) | 6 | * Copyright (C) 1999-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | 21 | * |
22 | * This file implements the usbfs/x/y files, where | 22 | * This file implements the usbfs/x/y files, where |
23 | * x is the bus number and y the device number. | 23 | * x is the bus number and y the device number. |
24 | * | 24 | * |
25 | * It allows user space programs/"drivers" to communicate directly | 25 | * It allows user space programs/"drivers" to communicate directly |
26 | * with USB devices without intervening kernel driver. | 26 | * with USB devices without intervening kernel driver. |
27 | * | 27 | * |
28 | * Revision history | 28 | * Revision history |
29 | * 22.12.1999 0.1 Initial release (split from proc_usb.c) | 29 | * 22.12.1999 0.1 Initial release (split from proc_usb.c) |
30 | * 04.01.2000 0.2 Turned into its own filesystem | 30 | * 04.01.2000 0.2 Turned into its own filesystem |
31 | * 30.09.2005 0.3 Fix user-triggerable oops in async URB delivery | 31 | * 30.09.2005 0.3 Fix user-triggerable oops in async URB delivery |
32 | * (CAN-2005-3055) | 32 | * (CAN-2005-3055) |
33 | */ | 33 | */ |
34 | 34 | ||
35 | /*****************************************************************************/ | 35 | /*****************************************************************************/ |
36 | 36 | ||
37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/smp_lock.h> | 40 | #include <linux/smp_lock.h> |
41 | #include <linux/signal.h> | 41 | #include <linux/signal.h> |
42 | #include <linux/poll.h> | 42 | #include <linux/poll.h> |
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
45 | #include <linux/usbdevice_fs.h> | 45 | #include <linux/usbdevice_fs.h> |
46 | #include <linux/cdev.h> | 46 | #include <linux/cdev.h> |
47 | #include <linux/notifier.h> | 47 | #include <linux/notifier.h> |
48 | #include <linux/security.h> | 48 | #include <linux/security.h> |
49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
50 | #include <asm/byteorder.h> | 50 | #include <asm/byteorder.h> |
51 | #include <linux/moduleparam.h> | 51 | #include <linux/moduleparam.h> |
52 | 52 | ||
53 | #include "hcd.h" /* for usbcore internals */ | 53 | #include "hcd.h" /* for usbcore internals */ |
54 | #include "usb.h" | 54 | #include "usb.h" |
55 | 55 | ||
56 | #define USB_MAXBUS 64 | 56 | #define USB_MAXBUS 64 |
57 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 57 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
58 | 58 | ||
59 | /* Mutual exclusion for removal, open, and release */ | 59 | /* Mutual exclusion for removal, open, and release */ |
60 | DEFINE_MUTEX(usbfs_mutex); | 60 | DEFINE_MUTEX(usbfs_mutex); |
61 | 61 | ||
62 | struct dev_state { | 62 | struct dev_state { |
63 | struct list_head list; /* state list */ | 63 | struct list_head list; /* state list */ |
64 | struct usb_device *dev; | 64 | struct usb_device *dev; |
65 | struct file *file; | 65 | struct file *file; |
66 | spinlock_t lock; /* protects the async urb lists */ | 66 | spinlock_t lock; /* protects the async urb lists */ |
67 | struct list_head async_pending; | 67 | struct list_head async_pending; |
68 | struct list_head async_completed; | 68 | struct list_head async_completed; |
69 | wait_queue_head_t wait; /* wake up if a request completed */ | 69 | wait_queue_head_t wait; /* wake up if a request completed */ |
70 | unsigned int discsignr; | 70 | unsigned int discsignr; |
71 | struct pid *disc_pid; | 71 | struct pid *disc_pid; |
72 | uid_t disc_uid, disc_euid; | 72 | uid_t disc_uid, disc_euid; |
73 | void __user *disccontext; | 73 | void __user *disccontext; |
74 | unsigned long ifclaimed; | 74 | unsigned long ifclaimed; |
75 | u32 secid; | 75 | u32 secid; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | struct async { | 78 | struct async { |
79 | struct list_head asynclist; | 79 | struct list_head asynclist; |
80 | struct dev_state *ps; | 80 | struct dev_state *ps; |
81 | struct pid *pid; | 81 | struct pid *pid; |
82 | uid_t uid, euid; | 82 | uid_t uid, euid; |
83 | unsigned int signr; | 83 | unsigned int signr; |
84 | unsigned int ifnum; | 84 | unsigned int ifnum; |
85 | void __user *userbuffer; | 85 | void __user *userbuffer; |
86 | void __user *userurb; | 86 | void __user *userurb; |
87 | struct urb *urb; | 87 | struct urb *urb; |
88 | int status; | 88 | int status; |
89 | u32 secid; | 89 | u32 secid; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static int usbfs_snoop; | 92 | static int usbfs_snoop; |
93 | module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR); | 93 | module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR); |
94 | MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); | 94 | MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); |
95 | 95 | ||
96 | #define snoop(dev, format, arg...) \ | 96 | #define snoop(dev, format, arg...) \ |
97 | do { \ | 97 | do { \ |
98 | if (usbfs_snoop) \ | 98 | if (usbfs_snoop) \ |
99 | dev_info(dev , format , ## arg); \ | 99 | dev_info(dev , format , ## arg); \ |
100 | } while (0) | 100 | } while (0) |
101 | 101 | ||
102 | #define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) | 102 | #define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) |
103 | 103 | ||
104 | 104 | ||
105 | #define MAX_USBFS_BUFFER_SIZE 16384 | 105 | #define MAX_USBFS_BUFFER_SIZE 16384 |
106 | 106 | ||
107 | static inline int connected(struct dev_state *ps) | 107 | static inline int connected(struct dev_state *ps) |
108 | { | 108 | { |
109 | return (!list_empty(&ps->list) && | 109 | return (!list_empty(&ps->list) && |
110 | ps->dev->state != USB_STATE_NOTATTACHED); | 110 | ps->dev->state != USB_STATE_NOTATTACHED); |
111 | } | 111 | } |
112 | 112 | ||
113 | static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) | 113 | static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) |
114 | { | 114 | { |
115 | loff_t ret; | 115 | loff_t ret; |
116 | 116 | ||
117 | lock_kernel(); | 117 | lock_kernel(); |
118 | 118 | ||
119 | switch (orig) { | 119 | switch (orig) { |
120 | case 0: | 120 | case 0: |
121 | file->f_pos = offset; | 121 | file->f_pos = offset; |
122 | ret = file->f_pos; | 122 | ret = file->f_pos; |
123 | break; | 123 | break; |
124 | case 1: | 124 | case 1: |
125 | file->f_pos += offset; | 125 | file->f_pos += offset; |
126 | ret = file->f_pos; | 126 | ret = file->f_pos; |
127 | break; | 127 | break; |
128 | case 2: | 128 | case 2: |
129 | default: | 129 | default: |
130 | ret = -EINVAL; | 130 | ret = -EINVAL; |
131 | } | 131 | } |
132 | 132 | ||
133 | unlock_kernel(); | 133 | unlock_kernel(); |
134 | return ret; | 134 | return ret; |
135 | } | 135 | } |
136 | 136 | ||
137 | static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, | 137 | static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, |
138 | loff_t *ppos) | 138 | loff_t *ppos) |
139 | { | 139 | { |
140 | struct dev_state *ps = file->private_data; | 140 | struct dev_state *ps = file->private_data; |
141 | struct usb_device *dev = ps->dev; | 141 | struct usb_device *dev = ps->dev; |
142 | ssize_t ret = 0; | 142 | ssize_t ret = 0; |
143 | unsigned len; | 143 | unsigned len; |
144 | loff_t pos; | 144 | loff_t pos; |
145 | int i; | 145 | int i; |
146 | 146 | ||
147 | pos = *ppos; | 147 | pos = *ppos; |
148 | usb_lock_device(dev); | 148 | usb_lock_device(dev); |
149 | if (!connected(ps)) { | 149 | if (!connected(ps)) { |
150 | ret = -ENODEV; | 150 | ret = -ENODEV; |
151 | goto err; | 151 | goto err; |
152 | } else if (pos < 0) { | 152 | } else if (pos < 0) { |
153 | ret = -EINVAL; | 153 | ret = -EINVAL; |
154 | goto err; | 154 | goto err; |
155 | } | 155 | } |
156 | 156 | ||
157 | if (pos < sizeof(struct usb_device_descriptor)) { | 157 | if (pos < sizeof(struct usb_device_descriptor)) { |
158 | /* 18 bytes - fits on the stack */ | 158 | /* 18 bytes - fits on the stack */ |
159 | struct usb_device_descriptor temp_desc; | 159 | struct usb_device_descriptor temp_desc; |
160 | 160 | ||
161 | memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); | 161 | memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); |
162 | le16_to_cpus(&temp_desc.bcdUSB); | 162 | le16_to_cpus(&temp_desc.bcdUSB); |
163 | le16_to_cpus(&temp_desc.idVendor); | 163 | le16_to_cpus(&temp_desc.idVendor); |
164 | le16_to_cpus(&temp_desc.idProduct); | 164 | le16_to_cpus(&temp_desc.idProduct); |
165 | le16_to_cpus(&temp_desc.bcdDevice); | 165 | le16_to_cpus(&temp_desc.bcdDevice); |
166 | 166 | ||
167 | len = sizeof(struct usb_device_descriptor) - pos; | 167 | len = sizeof(struct usb_device_descriptor) - pos; |
168 | if (len > nbytes) | 168 | if (len > nbytes) |
169 | len = nbytes; | 169 | len = nbytes; |
170 | if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) { | 170 | if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) { |
171 | ret = -EFAULT; | 171 | ret = -EFAULT; |
172 | goto err; | 172 | goto err; |
173 | } | 173 | } |
174 | 174 | ||
175 | *ppos += len; | 175 | *ppos += len; |
176 | buf += len; | 176 | buf += len; |
177 | nbytes -= len; | 177 | nbytes -= len; |
178 | ret += len; | 178 | ret += len; |
179 | } | 179 | } |
180 | 180 | ||
181 | pos = sizeof(struct usb_device_descriptor); | 181 | pos = sizeof(struct usb_device_descriptor); |
182 | for (i = 0; nbytes && i < dev->descriptor.bNumConfigurations; i++) { | 182 | for (i = 0; nbytes && i < dev->descriptor.bNumConfigurations; i++) { |
183 | struct usb_config_descriptor *config = | 183 | struct usb_config_descriptor *config = |
184 | (struct usb_config_descriptor *)dev->rawdescriptors[i]; | 184 | (struct usb_config_descriptor *)dev->rawdescriptors[i]; |
185 | unsigned int length = le16_to_cpu(config->wTotalLength); | 185 | unsigned int length = le16_to_cpu(config->wTotalLength); |
186 | 186 | ||
187 | if (*ppos < pos + length) { | 187 | if (*ppos < pos + length) { |
188 | 188 | ||
189 | /* The descriptor may claim to be longer than it | 189 | /* The descriptor may claim to be longer than it |
190 | * really is. Here is the actual allocated length. */ | 190 | * really is. Here is the actual allocated length. */ |
191 | unsigned alloclen = | 191 | unsigned alloclen = |
192 | le16_to_cpu(dev->config[i].desc.wTotalLength); | 192 | le16_to_cpu(dev->config[i].desc.wTotalLength); |
193 | 193 | ||
194 | len = length - (*ppos - pos); | 194 | len = length - (*ppos - pos); |
195 | if (len > nbytes) | 195 | if (len > nbytes) |
196 | len = nbytes; | 196 | len = nbytes; |
197 | 197 | ||
198 | /* Simply don't write (skip over) unallocated parts */ | 198 | /* Simply don't write (skip over) unallocated parts */ |
199 | if (alloclen > (*ppos - pos)) { | 199 | if (alloclen > (*ppos - pos)) { |
200 | alloclen -= (*ppos - pos); | 200 | alloclen -= (*ppos - pos); |
201 | if (copy_to_user(buf, | 201 | if (copy_to_user(buf, |
202 | dev->rawdescriptors[i] + (*ppos - pos), | 202 | dev->rawdescriptors[i] + (*ppos - pos), |
203 | min(len, alloclen))) { | 203 | min(len, alloclen))) { |
204 | ret = -EFAULT; | 204 | ret = -EFAULT; |
205 | goto err; | 205 | goto err; |
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | *ppos += len; | 209 | *ppos += len; |
210 | buf += len; | 210 | buf += len; |
211 | nbytes -= len; | 211 | nbytes -= len; |
212 | ret += len; | 212 | ret += len; |
213 | } | 213 | } |
214 | 214 | ||
215 | pos += length; | 215 | pos += length; |
216 | } | 216 | } |
217 | 217 | ||
218 | err: | 218 | err: |
219 | usb_unlock_device(dev); | 219 | usb_unlock_device(dev); |
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * async list handling | 224 | * async list handling |
225 | */ | 225 | */ |
226 | 226 | ||
227 | static struct async *alloc_async(unsigned int numisoframes) | 227 | static struct async *alloc_async(unsigned int numisoframes) |
228 | { | 228 | { |
229 | struct async *as; | 229 | struct async *as; |
230 | 230 | ||
231 | as = kzalloc(sizeof(struct async), GFP_KERNEL); | 231 | as = kzalloc(sizeof(struct async), GFP_KERNEL); |
232 | if (!as) | 232 | if (!as) |
233 | return NULL; | 233 | return NULL; |
234 | as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL); | 234 | as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL); |
235 | if (!as->urb) { | 235 | if (!as->urb) { |
236 | kfree(as); | 236 | kfree(as); |
237 | return NULL; | 237 | return NULL; |
238 | } | 238 | } |
239 | return as; | 239 | return as; |
240 | } | 240 | } |
241 | 241 | ||
242 | static void free_async(struct async *as) | 242 | static void free_async(struct async *as) |
243 | { | 243 | { |
244 | put_pid(as->pid); | 244 | put_pid(as->pid); |
245 | kfree(as->urb->transfer_buffer); | 245 | kfree(as->urb->transfer_buffer); |
246 | kfree(as->urb->setup_packet); | 246 | kfree(as->urb->setup_packet); |
247 | usb_free_urb(as->urb); | 247 | usb_free_urb(as->urb); |
248 | kfree(as); | 248 | kfree(as); |
249 | } | 249 | } |
250 | 250 | ||
251 | static inline void async_newpending(struct async *as) | 251 | static inline void async_newpending(struct async *as) |
252 | { | 252 | { |
253 | struct dev_state *ps = as->ps; | 253 | struct dev_state *ps = as->ps; |
254 | unsigned long flags; | 254 | unsigned long flags; |
255 | 255 | ||
256 | spin_lock_irqsave(&ps->lock, flags); | 256 | spin_lock_irqsave(&ps->lock, flags); |
257 | list_add_tail(&as->asynclist, &ps->async_pending); | 257 | list_add_tail(&as->asynclist, &ps->async_pending); |
258 | spin_unlock_irqrestore(&ps->lock, flags); | 258 | spin_unlock_irqrestore(&ps->lock, flags); |
259 | } | 259 | } |
260 | 260 | ||
261 | static inline void async_removepending(struct async *as) | 261 | static inline void async_removepending(struct async *as) |
262 | { | 262 | { |
263 | struct dev_state *ps = as->ps; | 263 | struct dev_state *ps = as->ps; |
264 | unsigned long flags; | 264 | unsigned long flags; |
265 | 265 | ||
266 | spin_lock_irqsave(&ps->lock, flags); | 266 | spin_lock_irqsave(&ps->lock, flags); |
267 | list_del_init(&as->asynclist); | 267 | list_del_init(&as->asynclist); |
268 | spin_unlock_irqrestore(&ps->lock, flags); | 268 | spin_unlock_irqrestore(&ps->lock, flags); |
269 | } | 269 | } |
270 | 270 | ||
271 | static inline struct async *async_getcompleted(struct dev_state *ps) | 271 | static inline struct async *async_getcompleted(struct dev_state *ps) |
272 | { | 272 | { |
273 | unsigned long flags; | 273 | unsigned long flags; |
274 | struct async *as = NULL; | 274 | struct async *as = NULL; |
275 | 275 | ||
276 | spin_lock_irqsave(&ps->lock, flags); | 276 | spin_lock_irqsave(&ps->lock, flags); |
277 | if (!list_empty(&ps->async_completed)) { | 277 | if (!list_empty(&ps->async_completed)) { |
278 | as = list_entry(ps->async_completed.next, struct async, | 278 | as = list_entry(ps->async_completed.next, struct async, |
279 | asynclist); | 279 | asynclist); |
280 | list_del_init(&as->asynclist); | 280 | list_del_init(&as->asynclist); |
281 | } | 281 | } |
282 | spin_unlock_irqrestore(&ps->lock, flags); | 282 | spin_unlock_irqrestore(&ps->lock, flags); |
283 | return as; | 283 | return as; |
284 | } | 284 | } |
285 | 285 | ||
286 | static inline struct async *async_getpending(struct dev_state *ps, | 286 | static inline struct async *async_getpending(struct dev_state *ps, |
287 | void __user *userurb) | 287 | void __user *userurb) |
288 | { | 288 | { |
289 | unsigned long flags; | 289 | unsigned long flags; |
290 | struct async *as; | 290 | struct async *as; |
291 | 291 | ||
292 | spin_lock_irqsave(&ps->lock, flags); | 292 | spin_lock_irqsave(&ps->lock, flags); |
293 | list_for_each_entry(as, &ps->async_pending, asynclist) | 293 | list_for_each_entry(as, &ps->async_pending, asynclist) |
294 | if (as->userurb == userurb) { | 294 | if (as->userurb == userurb) { |
295 | list_del_init(&as->asynclist); | 295 | list_del_init(&as->asynclist); |
296 | spin_unlock_irqrestore(&ps->lock, flags); | 296 | spin_unlock_irqrestore(&ps->lock, flags); |
297 | return as; | 297 | return as; |
298 | } | 298 | } |
299 | spin_unlock_irqrestore(&ps->lock, flags); | 299 | spin_unlock_irqrestore(&ps->lock, flags); |
300 | return NULL; | 300 | return NULL; |
301 | } | 301 | } |
302 | 302 | ||
303 | static void snoop_urb(struct urb *urb, void __user *userurb) | 303 | static void snoop_urb(struct urb *urb, void __user *userurb) |
304 | { | 304 | { |
305 | int j; | 305 | int j; |
306 | unsigned char *data = urb->transfer_buffer; | 306 | unsigned char *data = urb->transfer_buffer; |
307 | 307 | ||
308 | if (!usbfs_snoop) | 308 | if (!usbfs_snoop) |
309 | return; | 309 | return; |
310 | 310 | ||
311 | dev_info(&urb->dev->dev, "direction=%s\n", | 311 | dev_info(&urb->dev->dev, "direction=%s\n", |
312 | usb_urb_dir_in(urb) ? "IN" : "OUT"); | 312 | usb_urb_dir_in(urb) ? "IN" : "OUT"); |
313 | dev_info(&urb->dev->dev, "userurb=%p\n", userurb); | 313 | dev_info(&urb->dev->dev, "userurb=%p\n", userurb); |
314 | dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", | 314 | dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", |
315 | urb->transfer_buffer_length); | 315 | urb->transfer_buffer_length); |
316 | dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); | 316 | dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); |
317 | dev_info(&urb->dev->dev, "data: "); | 317 | dev_info(&urb->dev->dev, "data: "); |
318 | for (j = 0; j < urb->transfer_buffer_length; ++j) | 318 | for (j = 0; j < urb->transfer_buffer_length; ++j) |
319 | printk("%02x ", data[j]); | 319 | printk("%02x ", data[j]); |
320 | printk("\n"); | 320 | printk("\n"); |
321 | } | 321 | } |
322 | 322 | ||
323 | static void async_completed(struct urb *urb) | 323 | static void async_completed(struct urb *urb) |
324 | { | 324 | { |
325 | struct async *as = urb->context; | 325 | struct async *as = urb->context; |
326 | struct dev_state *ps = as->ps; | 326 | struct dev_state *ps = as->ps; |
327 | struct siginfo sinfo; | 327 | struct siginfo sinfo; |
328 | 328 | ||
329 | spin_lock(&ps->lock); | 329 | spin_lock(&ps->lock); |
330 | list_move_tail(&as->asynclist, &ps->async_completed); | 330 | list_move_tail(&as->asynclist, &ps->async_completed); |
331 | spin_unlock(&ps->lock); | 331 | spin_unlock(&ps->lock); |
332 | as->status = urb->status; | 332 | as->status = urb->status; |
333 | if (as->signr) { | 333 | if (as->signr) { |
334 | sinfo.si_signo = as->signr; | 334 | sinfo.si_signo = as->signr; |
335 | sinfo.si_errno = as->status; | 335 | sinfo.si_errno = as->status; |
336 | sinfo.si_code = SI_ASYNCIO; | 336 | sinfo.si_code = SI_ASYNCIO; |
337 | sinfo.si_addr = as->userurb; | 337 | sinfo.si_addr = as->userurb; |
338 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, | 338 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, |
339 | as->euid, as->secid); | 339 | as->euid, as->secid); |
340 | } | 340 | } |
341 | snoop(&urb->dev->dev, "urb complete\n"); | 341 | snoop(&urb->dev->dev, "urb complete\n"); |
342 | snoop_urb(urb, as->userurb); | 342 | snoop_urb(urb, as->userurb); |
343 | wake_up(&ps->wait); | 343 | wake_up(&ps->wait); |
344 | } | 344 | } |
345 | 345 | ||
346 | static void destroy_async(struct dev_state *ps, struct list_head *list) | 346 | static void destroy_async(struct dev_state *ps, struct list_head *list) |
347 | { | 347 | { |
348 | struct async *as; | 348 | struct async *as; |
349 | unsigned long flags; | 349 | unsigned long flags; |
350 | 350 | ||
351 | spin_lock_irqsave(&ps->lock, flags); | 351 | spin_lock_irqsave(&ps->lock, flags); |
352 | while (!list_empty(list)) { | 352 | while (!list_empty(list)) { |
353 | as = list_entry(list->next, struct async, asynclist); | 353 | as = list_entry(list->next, struct async, asynclist); |
354 | list_del_init(&as->asynclist); | 354 | list_del_init(&as->asynclist); |
355 | 355 | ||
356 | /* drop the spinlock so the completion handler can run */ | 356 | /* drop the spinlock so the completion handler can run */ |
357 | spin_unlock_irqrestore(&ps->lock, flags); | 357 | spin_unlock_irqrestore(&ps->lock, flags); |
358 | usb_kill_urb(as->urb); | 358 | usb_kill_urb(as->urb); |
359 | spin_lock_irqsave(&ps->lock, flags); | 359 | spin_lock_irqsave(&ps->lock, flags); |
360 | } | 360 | } |
361 | spin_unlock_irqrestore(&ps->lock, flags); | 361 | spin_unlock_irqrestore(&ps->lock, flags); |
362 | as = async_getcompleted(ps); | 362 | as = async_getcompleted(ps); |
363 | while (as) { | 363 | while (as) { |
364 | free_async(as); | 364 | free_async(as); |
365 | as = async_getcompleted(ps); | 365 | as = async_getcompleted(ps); |
366 | } | 366 | } |
367 | } | 367 | } |
368 | 368 | ||
369 | static void destroy_async_on_interface(struct dev_state *ps, | 369 | static void destroy_async_on_interface(struct dev_state *ps, |
370 | unsigned int ifnum) | 370 | unsigned int ifnum) |
371 | { | 371 | { |
372 | struct list_head *p, *q, hitlist; | 372 | struct list_head *p, *q, hitlist; |
373 | unsigned long flags; | 373 | unsigned long flags; |
374 | 374 | ||
375 | INIT_LIST_HEAD(&hitlist); | 375 | INIT_LIST_HEAD(&hitlist); |
376 | spin_lock_irqsave(&ps->lock, flags); | 376 | spin_lock_irqsave(&ps->lock, flags); |
377 | list_for_each_safe(p, q, &ps->async_pending) | 377 | list_for_each_safe(p, q, &ps->async_pending) |
378 | if (ifnum == list_entry(p, struct async, asynclist)->ifnum) | 378 | if (ifnum == list_entry(p, struct async, asynclist)->ifnum) |
379 | list_move_tail(p, &hitlist); | 379 | list_move_tail(p, &hitlist); |
380 | spin_unlock_irqrestore(&ps->lock, flags); | 380 | spin_unlock_irqrestore(&ps->lock, flags); |
381 | destroy_async(ps, &hitlist); | 381 | destroy_async(ps, &hitlist); |
382 | } | 382 | } |
383 | 383 | ||
384 | static inline void destroy_all_async(struct dev_state *ps) | 384 | static inline void destroy_all_async(struct dev_state *ps) |
385 | { | 385 | { |
386 | destroy_async(ps, &ps->async_pending); | 386 | destroy_async(ps, &ps->async_pending); |
387 | } | 387 | } |
388 | 388 | ||
389 | /* | 389 | /* |
390 | * interface claims are made only at the request of user level code, | 390 | * interface claims are made only at the request of user level code, |
391 | * which can also release them (explicitly or by closing files). | 391 | * which can also release them (explicitly or by closing files). |
392 | * they're also undone when devices disconnect. | 392 | * they're also undone when devices disconnect. |
393 | */ | 393 | */ |
394 | 394 | ||
395 | static int driver_probe(struct usb_interface *intf, | 395 | static int driver_probe(struct usb_interface *intf, |
396 | const struct usb_device_id *id) | 396 | const struct usb_device_id *id) |
397 | { | 397 | { |
398 | return -ENODEV; | 398 | return -ENODEV; |
399 | } | 399 | } |
400 | 400 | ||
401 | static void driver_disconnect(struct usb_interface *intf) | 401 | static void driver_disconnect(struct usb_interface *intf) |
402 | { | 402 | { |
403 | struct dev_state *ps = usb_get_intfdata(intf); | 403 | struct dev_state *ps = usb_get_intfdata(intf); |
404 | unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber; | 404 | unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber; |
405 | 405 | ||
406 | if (!ps) | 406 | if (!ps) |
407 | return; | 407 | return; |
408 | 408 | ||
409 | /* NOTE: this relies on usbcore having canceled and completed | 409 | /* NOTE: this relies on usbcore having canceled and completed |
410 | * all pending I/O requests; 2.6 does that. | 410 | * all pending I/O requests; 2.6 does that. |
411 | */ | 411 | */ |
412 | 412 | ||
413 | if (likely(ifnum < 8*sizeof(ps->ifclaimed))) | 413 | if (likely(ifnum < 8*sizeof(ps->ifclaimed))) |
414 | clear_bit(ifnum, &ps->ifclaimed); | 414 | clear_bit(ifnum, &ps->ifclaimed); |
415 | else | 415 | else |
416 | warn("interface number %u out of range", ifnum); | 416 | warn("interface number %u out of range", ifnum); |
417 | 417 | ||
418 | usb_set_intfdata(intf, NULL); | 418 | usb_set_intfdata(intf, NULL); |
419 | 419 | ||
420 | /* force async requests to complete */ | 420 | /* force async requests to complete */ |
421 | destroy_async_on_interface(ps, ifnum); | 421 | destroy_async_on_interface(ps, ifnum); |
422 | } | 422 | } |
423 | 423 | ||
424 | /* The following routines are merely placeholders. There is no way | 424 | /* The following routines are merely placeholders. There is no way |
425 | * to inform a user task about suspend or resumes. | 425 | * to inform a user task about suspend or resumes. |
426 | */ | 426 | */ |
427 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) | 427 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) |
428 | { | 428 | { |
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
431 | 431 | ||
432 | static int driver_resume(struct usb_interface *intf) | 432 | static int driver_resume(struct usb_interface *intf) |
433 | { | 433 | { |
434 | return 0; | 434 | return 0; |
435 | } | 435 | } |
436 | 436 | ||
437 | struct usb_driver usbfs_driver = { | 437 | struct usb_driver usbfs_driver = { |
438 | .name = "usbfs", | 438 | .name = "usbfs", |
439 | .probe = driver_probe, | 439 | .probe = driver_probe, |
440 | .disconnect = driver_disconnect, | 440 | .disconnect = driver_disconnect, |
441 | .suspend = driver_suspend, | 441 | .suspend = driver_suspend, |
442 | .resume = driver_resume, | 442 | .resume = driver_resume, |
443 | }; | 443 | }; |
444 | 444 | ||
445 | static int claimintf(struct dev_state *ps, unsigned int ifnum) | 445 | static int claimintf(struct dev_state *ps, unsigned int ifnum) |
446 | { | 446 | { |
447 | struct usb_device *dev = ps->dev; | 447 | struct usb_device *dev = ps->dev; |
448 | struct usb_interface *intf; | 448 | struct usb_interface *intf; |
449 | int err; | 449 | int err; |
450 | 450 | ||
451 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | 451 | if (ifnum >= 8*sizeof(ps->ifclaimed)) |
452 | return -EINVAL; | 452 | return -EINVAL; |
453 | /* already claimed */ | 453 | /* already claimed */ |
454 | if (test_bit(ifnum, &ps->ifclaimed)) | 454 | if (test_bit(ifnum, &ps->ifclaimed)) |
455 | return 0; | 455 | return 0; |
456 | 456 | ||
457 | intf = usb_ifnum_to_if(dev, ifnum); | 457 | intf = usb_ifnum_to_if(dev, ifnum); |
458 | if (!intf) | 458 | if (!intf) |
459 | err = -ENOENT; | 459 | err = -ENOENT; |
460 | else | 460 | else |
461 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); | 461 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); |
462 | if (err == 0) | 462 | if (err == 0) |
463 | set_bit(ifnum, &ps->ifclaimed); | 463 | set_bit(ifnum, &ps->ifclaimed); |
464 | return err; | 464 | return err; |
465 | } | 465 | } |
466 | 466 | ||
467 | static int releaseintf(struct dev_state *ps, unsigned int ifnum) | 467 | static int releaseintf(struct dev_state *ps, unsigned int ifnum) |
468 | { | 468 | { |
469 | struct usb_device *dev; | 469 | struct usb_device *dev; |
470 | struct usb_interface *intf; | 470 | struct usb_interface *intf; |
471 | int err; | 471 | int err; |
472 | 472 | ||
473 | err = -EINVAL; | 473 | err = -EINVAL; |
474 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | 474 | if (ifnum >= 8*sizeof(ps->ifclaimed)) |
475 | return err; | 475 | return err; |
476 | dev = ps->dev; | 476 | dev = ps->dev; |
477 | intf = usb_ifnum_to_if(dev, ifnum); | 477 | intf = usb_ifnum_to_if(dev, ifnum); |
478 | if (!intf) | 478 | if (!intf) |
479 | err = -ENOENT; | 479 | err = -ENOENT; |
480 | else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { | 480 | else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { |
481 | usb_driver_release_interface(&usbfs_driver, intf); | 481 | usb_driver_release_interface(&usbfs_driver, intf); |
482 | err = 0; | 482 | err = 0; |
483 | } | 483 | } |
484 | return err; | 484 | return err; |
485 | } | 485 | } |
486 | 486 | ||
487 | static int checkintf(struct dev_state *ps, unsigned int ifnum) | 487 | static int checkintf(struct dev_state *ps, unsigned int ifnum) |
488 | { | 488 | { |
489 | if (ps->dev->state != USB_STATE_CONFIGURED) | 489 | if (ps->dev->state != USB_STATE_CONFIGURED) |
490 | return -EHOSTUNREACH; | 490 | return -EHOSTUNREACH; |
491 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | 491 | if (ifnum >= 8*sizeof(ps->ifclaimed)) |
492 | return -EINVAL; | 492 | return -EINVAL; |
493 | if (test_bit(ifnum, &ps->ifclaimed)) | 493 | if (test_bit(ifnum, &ps->ifclaimed)) |
494 | return 0; | 494 | return 0; |
495 | /* if not yet claimed, claim it for the driver */ | 495 | /* if not yet claimed, claim it for the driver */ |
496 | dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim " | 496 | dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim " |
497 | "interface %u before use\n", task_pid_nr(current), | 497 | "interface %u before use\n", task_pid_nr(current), |
498 | current->comm, ifnum); | 498 | current->comm, ifnum); |
499 | return claimintf(ps, ifnum); | 499 | return claimintf(ps, ifnum); |
500 | } | 500 | } |
501 | 501 | ||
502 | static int findintfep(struct usb_device *dev, unsigned int ep) | 502 | static int findintfep(struct usb_device *dev, unsigned int ep) |
503 | { | 503 | { |
504 | unsigned int i, j, e; | 504 | unsigned int i, j, e; |
505 | struct usb_interface *intf; | 505 | struct usb_interface *intf; |
506 | struct usb_host_interface *alts; | 506 | struct usb_host_interface *alts; |
507 | struct usb_endpoint_descriptor *endpt; | 507 | struct usb_endpoint_descriptor *endpt; |
508 | 508 | ||
509 | if (ep & ~(USB_DIR_IN|0xf)) | 509 | if (ep & ~(USB_DIR_IN|0xf)) |
510 | return -EINVAL; | 510 | return -EINVAL; |
511 | if (!dev->actconfig) | 511 | if (!dev->actconfig) |
512 | return -ESRCH; | 512 | return -ESRCH; |
513 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { | 513 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { |
514 | intf = dev->actconfig->interface[i]; | 514 | intf = dev->actconfig->interface[i]; |
515 | for (j = 0; j < intf->num_altsetting; j++) { | 515 | for (j = 0; j < intf->num_altsetting; j++) { |
516 | alts = &intf->altsetting[j]; | 516 | alts = &intf->altsetting[j]; |
517 | for (e = 0; e < alts->desc.bNumEndpoints; e++) { | 517 | for (e = 0; e < alts->desc.bNumEndpoints; e++) { |
518 | endpt = &alts->endpoint[e].desc; | 518 | endpt = &alts->endpoint[e].desc; |
519 | if (endpt->bEndpointAddress == ep) | 519 | if (endpt->bEndpointAddress == ep) |
520 | return alts->desc.bInterfaceNumber; | 520 | return alts->desc.bInterfaceNumber; |
521 | } | 521 | } |
522 | } | 522 | } |
523 | } | 523 | } |
524 | return -ENOENT; | 524 | return -ENOENT; |
525 | } | 525 | } |
526 | 526 | ||
527 | static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, | 527 | static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, |
528 | unsigned int index) | 528 | unsigned int index) |
529 | { | 529 | { |
530 | int ret = 0; | 530 | int ret = 0; |
531 | 531 | ||
532 | if (ps->dev->state != USB_STATE_ADDRESS | 532 | if (ps->dev->state != USB_STATE_ADDRESS |
533 | && ps->dev->state != USB_STATE_CONFIGURED) | 533 | && ps->dev->state != USB_STATE_CONFIGURED) |
534 | return -EHOSTUNREACH; | 534 | return -EHOSTUNREACH; |
535 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) | 535 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) |
536 | return 0; | 536 | return 0; |
537 | 537 | ||
538 | index &= 0xff; | 538 | index &= 0xff; |
539 | switch (requesttype & USB_RECIP_MASK) { | 539 | switch (requesttype & USB_RECIP_MASK) { |
540 | case USB_RECIP_ENDPOINT: | 540 | case USB_RECIP_ENDPOINT: |
541 | ret = findintfep(ps->dev, index); | 541 | ret = findintfep(ps->dev, index); |
542 | if (ret >= 0) | 542 | if (ret >= 0) |
543 | ret = checkintf(ps, ret); | 543 | ret = checkintf(ps, ret); |
544 | break; | 544 | break; |
545 | 545 | ||
546 | case USB_RECIP_INTERFACE: | 546 | case USB_RECIP_INTERFACE: |
547 | ret = checkintf(ps, index); | 547 | ret = checkintf(ps, index); |
548 | break; | 548 | break; |
549 | } | 549 | } |
550 | return ret; | 550 | return ret; |
551 | } | 551 | } |
552 | 552 | ||
553 | static int match_devt(struct device *dev, void *data) | 553 | static int match_devt(struct device *dev, void *data) |
554 | { | 554 | { |
555 | return dev->devt == (dev_t) (unsigned long) data; | 555 | return dev->devt == (dev_t) (unsigned long) data; |
556 | } | 556 | } |
557 | 557 | ||
558 | static struct usb_device *usbdev_lookup_by_devt(dev_t devt) | 558 | static struct usb_device *usbdev_lookup_by_devt(dev_t devt) |
559 | { | 559 | { |
560 | struct device *dev; | 560 | struct device *dev; |
561 | 561 | ||
562 | dev = bus_find_device(&usb_bus_type, NULL, | 562 | dev = bus_find_device(&usb_bus_type, NULL, |
563 | (void *) (unsigned long) devt, match_devt); | 563 | (void *) (unsigned long) devt, match_devt); |
564 | if (!dev) | 564 | if (!dev) |
565 | return NULL; | 565 | return NULL; |
566 | return container_of(dev, struct usb_device, dev); | 566 | return container_of(dev, struct usb_device, dev); |
567 | } | 567 | } |
568 | 568 | ||
569 | /* | 569 | /* |
570 | * file operations | 570 | * file operations |
571 | */ | 571 | */ |
572 | static int usbdev_open(struct inode *inode, struct file *file) | 572 | static int usbdev_open(struct inode *inode, struct file *file) |
573 | { | 573 | { |
574 | struct usb_device *dev = NULL; | 574 | struct usb_device *dev = NULL; |
575 | struct dev_state *ps; | 575 | struct dev_state *ps; |
576 | int ret; | 576 | int ret; |
577 | 577 | ||
578 | lock_kernel(); | 578 | lock_kernel(); |
579 | /* Protect against simultaneous removal or release */ | 579 | /* Protect against simultaneous removal or release */ |
580 | mutex_lock(&usbfs_mutex); | 580 | mutex_lock(&usbfs_mutex); |
581 | 581 | ||
582 | ret = -ENOMEM; | 582 | ret = -ENOMEM; |
583 | ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL); | 583 | ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL); |
584 | if (!ps) | 584 | if (!ps) |
585 | goto out; | 585 | goto out; |
586 | 586 | ||
587 | ret = -ENOENT; | 587 | ret = -ENOENT; |
588 | 588 | ||
589 | /* usbdev device-node */ | 589 | /* usbdev device-node */ |
590 | if (imajor(inode) == USB_DEVICE_MAJOR) | 590 | if (imajor(inode) == USB_DEVICE_MAJOR) |
591 | dev = usbdev_lookup_by_devt(inode->i_rdev); | 591 | dev = usbdev_lookup_by_devt(inode->i_rdev); |
592 | #ifdef CONFIG_USB_DEVICEFS | 592 | #ifdef CONFIG_USB_DEVICEFS |
593 | /* procfs file */ | 593 | /* procfs file */ |
594 | if (!dev) { | 594 | if (!dev) { |
595 | dev = inode->i_private; | 595 | dev = inode->i_private; |
596 | if (dev && dev->usbfs_dentry && | 596 | if (dev && dev->usbfs_dentry && |
597 | dev->usbfs_dentry->d_inode == inode) | 597 | dev->usbfs_dentry->d_inode == inode) |
598 | usb_get_dev(dev); | 598 | usb_get_dev(dev); |
599 | else | 599 | else |
600 | dev = NULL; | 600 | dev = NULL; |
601 | } | 601 | } |
602 | #endif | 602 | #endif |
603 | if (!dev || dev->state == USB_STATE_NOTATTACHED) | 603 | if (!dev || dev->state == USB_STATE_NOTATTACHED) |
604 | goto out; | 604 | goto out; |
605 | ret = usb_autoresume_device(dev); | 605 | ret = usb_autoresume_device(dev); |
606 | if (ret) | 606 | if (ret) |
607 | goto out; | 607 | goto out; |
608 | 608 | ||
609 | ret = 0; | 609 | ret = 0; |
610 | ps->dev = dev; | 610 | ps->dev = dev; |
611 | ps->file = file; | 611 | ps->file = file; |
612 | spin_lock_init(&ps->lock); | 612 | spin_lock_init(&ps->lock); |
613 | INIT_LIST_HEAD(&ps->list); | 613 | INIT_LIST_HEAD(&ps->list); |
614 | INIT_LIST_HEAD(&ps->async_pending); | 614 | INIT_LIST_HEAD(&ps->async_pending); |
615 | INIT_LIST_HEAD(&ps->async_completed); | 615 | INIT_LIST_HEAD(&ps->async_completed); |
616 | init_waitqueue_head(&ps->wait); | 616 | init_waitqueue_head(&ps->wait); |
617 | ps->discsignr = 0; | 617 | ps->discsignr = 0; |
618 | ps->disc_pid = get_pid(task_pid(current)); | 618 | ps->disc_pid = get_pid(task_pid(current)); |
619 | ps->disc_uid = current->uid; | 619 | ps->disc_uid = current->uid; |
620 | ps->disc_euid = current->euid; | 620 | ps->disc_euid = current->euid; |
621 | ps->disccontext = NULL; | 621 | ps->disccontext = NULL; |
622 | ps->ifclaimed = 0; | 622 | ps->ifclaimed = 0; |
623 | security_task_getsecid(current, &ps->secid); | 623 | security_task_getsecid(current, &ps->secid); |
624 | smp_wmb(); | 624 | smp_wmb(); |
625 | list_add_tail(&ps->list, &dev->filelist); | 625 | list_add_tail(&ps->list, &dev->filelist); |
626 | file->private_data = ps; | 626 | file->private_data = ps; |
627 | out: | 627 | out: |
628 | if (ret) { | 628 | if (ret) { |
629 | kfree(ps); | 629 | kfree(ps); |
630 | usb_put_dev(dev); | 630 | usb_put_dev(dev); |
631 | } | 631 | } |
632 | mutex_unlock(&usbfs_mutex); | 632 | mutex_unlock(&usbfs_mutex); |
633 | unlock_kernel(); | 633 | unlock_kernel(); |
634 | return ret; | 634 | return ret; |
635 | } | 635 | } |
636 | 636 | ||
637 | static int usbdev_release(struct inode *inode, struct file *file) | 637 | static int usbdev_release(struct inode *inode, struct file *file) |
638 | { | 638 | { |
639 | struct dev_state *ps = file->private_data; | 639 | struct dev_state *ps = file->private_data; |
640 | struct usb_device *dev = ps->dev; | 640 | struct usb_device *dev = ps->dev; |
641 | unsigned int ifnum; | 641 | unsigned int ifnum; |
642 | 642 | ||
643 | usb_lock_device(dev); | 643 | usb_lock_device(dev); |
644 | 644 | ||
645 | /* Protect against simultaneous open */ | 645 | /* Protect against simultaneous open */ |
646 | mutex_lock(&usbfs_mutex); | 646 | mutex_lock(&usbfs_mutex); |
647 | list_del_init(&ps->list); | 647 | list_del_init(&ps->list); |
648 | mutex_unlock(&usbfs_mutex); | 648 | mutex_unlock(&usbfs_mutex); |
649 | 649 | ||
650 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); | 650 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
651 | ifnum++) { | 651 | ifnum++) { |
652 | if (test_bit(ifnum, &ps->ifclaimed)) | 652 | if (test_bit(ifnum, &ps->ifclaimed)) |
653 | releaseintf(ps, ifnum); | 653 | releaseintf(ps, ifnum); |
654 | } | 654 | } |
655 | destroy_all_async(ps); | 655 | destroy_all_async(ps); |
656 | usb_autosuspend_device(dev); | 656 | usb_autosuspend_device(dev); |
657 | usb_unlock_device(dev); | 657 | usb_unlock_device(dev); |
658 | usb_put_dev(dev); | 658 | usb_put_dev(dev); |
659 | put_pid(ps->disc_pid); | 659 | put_pid(ps->disc_pid); |
660 | kfree(ps); | 660 | kfree(ps); |
661 | return 0; | 661 | return 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | static int proc_control(struct dev_state *ps, void __user *arg) | 664 | static int proc_control(struct dev_state *ps, void __user *arg) |
665 | { | 665 | { |
666 | struct usb_device *dev = ps->dev; | 666 | struct usb_device *dev = ps->dev; |
667 | struct usbdevfs_ctrltransfer ctrl; | 667 | struct usbdevfs_ctrltransfer ctrl; |
668 | unsigned int tmo; | 668 | unsigned int tmo; |
669 | unsigned char *tbuf; | 669 | unsigned char *tbuf; |
670 | unsigned wLength; | 670 | unsigned wLength; |
671 | int i, j, ret; | 671 | int i, j, ret; |
672 | 672 | ||
673 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 673 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
674 | return -EFAULT; | 674 | return -EFAULT; |
675 | ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex); | 675 | ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex); |
676 | if (ret) | 676 | if (ret) |
677 | return ret; | 677 | return ret; |
678 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ | 678 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ |
679 | if (wLength > PAGE_SIZE) | 679 | if (wLength > PAGE_SIZE) |
680 | return -EINVAL; | 680 | return -EINVAL; |
681 | tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); | 681 | tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); |
682 | if (!tbuf) | 682 | if (!tbuf) |
683 | return -ENOMEM; | 683 | return -ENOMEM; |
684 | tmo = ctrl.timeout; | 684 | tmo = ctrl.timeout; |
685 | if (ctrl.bRequestType & 0x80) { | 685 | if (ctrl.bRequestType & 0x80) { |
686 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, | 686 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, |
687 | ctrl.wLength)) { | 687 | ctrl.wLength)) { |
688 | free_page((unsigned long)tbuf); | 688 | free_page((unsigned long)tbuf); |
689 | return -EINVAL; | 689 | return -EINVAL; |
690 | } | 690 | } |
691 | snoop(&dev->dev, "control read: bRequest=%02x " | 691 | snoop(&dev->dev, "control read: bRequest=%02x " |
692 | "bRrequestType=%02x wValue=%04x " | 692 | "bRrequestType=%02x wValue=%04x " |
693 | "wIndex=%04x wLength=%04x\n", | 693 | "wIndex=%04x wLength=%04x\n", |
694 | ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, | 694 | ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, |
695 | ctrl.wIndex, ctrl.wLength); | 695 | ctrl.wIndex, ctrl.wLength); |
696 | 696 | ||
697 | usb_unlock_device(dev); | 697 | usb_unlock_device(dev); |
698 | i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, | 698 | i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, |
699 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, | 699 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, |
700 | tbuf, ctrl.wLength, tmo); | 700 | tbuf, ctrl.wLength, tmo); |
701 | usb_lock_device(dev); | 701 | usb_lock_device(dev); |
702 | if ((i > 0) && ctrl.wLength) { | 702 | if ((i > 0) && ctrl.wLength) { |
703 | if (usbfs_snoop) { | 703 | if (usbfs_snoop) { |
704 | dev_info(&dev->dev, "control read: data "); | 704 | dev_info(&dev->dev, "control read: data "); |
705 | for (j = 0; j < i; ++j) | 705 | for (j = 0; j < i; ++j) |
706 | printk("%02x ", (u8)(tbuf)[j]); | 706 | printk("%02x ", (u8)(tbuf)[j]); |
707 | printk("\n"); | 707 | printk("\n"); |
708 | } | 708 | } |
709 | if (copy_to_user(ctrl.data, tbuf, i)) { | 709 | if (copy_to_user(ctrl.data, tbuf, i)) { |
710 | free_page((unsigned long)tbuf); | 710 | free_page((unsigned long)tbuf); |
711 | return -EFAULT; | 711 | return -EFAULT; |
712 | } | 712 | } |
713 | } | 713 | } |
714 | } else { | 714 | } else { |
715 | if (ctrl.wLength) { | 715 | if (ctrl.wLength) { |
716 | if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { | 716 | if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { |
717 | free_page((unsigned long)tbuf); | 717 | free_page((unsigned long)tbuf); |
718 | return -EFAULT; | 718 | return -EFAULT; |
719 | } | 719 | } |
720 | } | 720 | } |
721 | snoop(&dev->dev, "control write: bRequest=%02x " | 721 | snoop(&dev->dev, "control write: bRequest=%02x " |
722 | "bRrequestType=%02x wValue=%04x " | 722 | "bRrequestType=%02x wValue=%04x " |
723 | "wIndex=%04x wLength=%04x\n", | 723 | "wIndex=%04x wLength=%04x\n", |
724 | ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, | 724 | ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, |
725 | ctrl.wIndex, ctrl.wLength); | 725 | ctrl.wIndex, ctrl.wLength); |
726 | if (usbfs_snoop) { | 726 | if (usbfs_snoop) { |
727 | dev_info(&dev->dev, "control write: data: "); | 727 | dev_info(&dev->dev, "control write: data: "); |
728 | for (j = 0; j < ctrl.wLength; ++j) | 728 | for (j = 0; j < ctrl.wLength; ++j) |
729 | printk("%02x ", (unsigned char)(tbuf)[j]); | 729 | printk("%02x ", (unsigned char)(tbuf)[j]); |
730 | printk("\n"); | 730 | printk("\n"); |
731 | } | 731 | } |
732 | usb_unlock_device(dev); | 732 | usb_unlock_device(dev); |
733 | i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, | 733 | i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, |
734 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, | 734 | ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, |
735 | tbuf, ctrl.wLength, tmo); | 735 | tbuf, ctrl.wLength, tmo); |
736 | usb_lock_device(dev); | 736 | usb_lock_device(dev); |
737 | } | 737 | } |
738 | free_page((unsigned long)tbuf); | 738 | free_page((unsigned long)tbuf); |
739 | if (i < 0 && i != -EPIPE) { | 739 | if (i < 0 && i != -EPIPE) { |
740 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " | 740 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " |
741 | "failed cmd %s rqt %u rq %u len %u ret %d\n", | 741 | "failed cmd %s rqt %u rq %u len %u ret %d\n", |
742 | current->comm, ctrl.bRequestType, ctrl.bRequest, | 742 | current->comm, ctrl.bRequestType, ctrl.bRequest, |
743 | ctrl.wLength, i); | 743 | ctrl.wLength, i); |
744 | } | 744 | } |
745 | return i; | 745 | return i; |
746 | } | 746 | } |
747 | 747 | ||
748 | static int proc_bulk(struct dev_state *ps, void __user *arg) | 748 | static int proc_bulk(struct dev_state *ps, void __user *arg) |
749 | { | 749 | { |
750 | struct usb_device *dev = ps->dev; | 750 | struct usb_device *dev = ps->dev; |
751 | struct usbdevfs_bulktransfer bulk; | 751 | struct usbdevfs_bulktransfer bulk; |
752 | unsigned int tmo, len1, pipe; | 752 | unsigned int tmo, len1, pipe; |
753 | int len2; | 753 | int len2; |
754 | unsigned char *tbuf; | 754 | unsigned char *tbuf; |
755 | int i, j, ret; | 755 | int i, j, ret; |
756 | 756 | ||
757 | if (copy_from_user(&bulk, arg, sizeof(bulk))) | 757 | if (copy_from_user(&bulk, arg, sizeof(bulk))) |
758 | return -EFAULT; | 758 | return -EFAULT; |
759 | ret = findintfep(ps->dev, bulk.ep); | 759 | ret = findintfep(ps->dev, bulk.ep); |
760 | if (ret < 0) | 760 | if (ret < 0) |
761 | return ret; | 761 | return ret; |
762 | ret = checkintf(ps, ret); | 762 | ret = checkintf(ps, ret); |
763 | if (ret) | 763 | if (ret) |
764 | return ret; | 764 | return ret; |
765 | if (bulk.ep & USB_DIR_IN) | 765 | if (bulk.ep & USB_DIR_IN) |
766 | pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); | 766 | pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); |
767 | else | 767 | else |
768 | pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); | 768 | pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); |
769 | if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) | 769 | if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) |
770 | return -EINVAL; | 770 | return -EINVAL; |
771 | len1 = bulk.len; | 771 | len1 = bulk.len; |
772 | if (len1 > MAX_USBFS_BUFFER_SIZE) | 772 | if (len1 > MAX_USBFS_BUFFER_SIZE) |
773 | return -EINVAL; | 773 | return -EINVAL; |
774 | if (!(tbuf = kmalloc(len1, GFP_KERNEL))) | 774 | if (!(tbuf = kmalloc(len1, GFP_KERNEL))) |
775 | return -ENOMEM; | 775 | return -ENOMEM; |
776 | tmo = bulk.timeout; | 776 | tmo = bulk.timeout; |
777 | if (bulk.ep & 0x80) { | 777 | if (bulk.ep & 0x80) { |
778 | if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { | 778 | if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { |
779 | kfree(tbuf); | 779 | kfree(tbuf); |
780 | return -EINVAL; | 780 | return -EINVAL; |
781 | } | 781 | } |
782 | snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n", | 782 | snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n", |
783 | bulk.len, bulk.timeout); | 783 | bulk.len, bulk.timeout); |
784 | usb_unlock_device(dev); | 784 | usb_unlock_device(dev); |
785 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); | 785 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); |
786 | usb_lock_device(dev); | 786 | usb_lock_device(dev); |
787 | if (!i && len2) { | 787 | if (!i && len2) { |
788 | if (usbfs_snoop) { | 788 | if (usbfs_snoop) { |
789 | dev_info(&dev->dev, "bulk read: data "); | 789 | dev_info(&dev->dev, "bulk read: data "); |
790 | for (j = 0; j < len2; ++j) | 790 | for (j = 0; j < len2; ++j) |
791 | printk("%02x ", (u8)(tbuf)[j]); | 791 | printk("%02x ", (u8)(tbuf)[j]); |
792 | printk("\n"); | 792 | printk("\n"); |
793 | } | 793 | } |
794 | if (copy_to_user(bulk.data, tbuf, len2)) { | 794 | if (copy_to_user(bulk.data, tbuf, len2)) { |
795 | kfree(tbuf); | 795 | kfree(tbuf); |
796 | return -EFAULT; | 796 | return -EFAULT; |
797 | } | 797 | } |
798 | } | 798 | } |
799 | } else { | 799 | } else { |
800 | if (len1) { | 800 | if (len1) { |
801 | if (copy_from_user(tbuf, bulk.data, len1)) { | 801 | if (copy_from_user(tbuf, bulk.data, len1)) { |
802 | kfree(tbuf); | 802 | kfree(tbuf); |
803 | return -EFAULT; | 803 | return -EFAULT; |
804 | } | 804 | } |
805 | } | 805 | } |
806 | snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n", | 806 | snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n", |
807 | bulk.len, bulk.timeout); | 807 | bulk.len, bulk.timeout); |
808 | if (usbfs_snoop) { | 808 | if (usbfs_snoop) { |
809 | dev_info(&dev->dev, "bulk write: data: "); | 809 | dev_info(&dev->dev, "bulk write: data: "); |
810 | for (j = 0; j < len1; ++j) | 810 | for (j = 0; j < len1; ++j) |
811 | printk("%02x ", (unsigned char)(tbuf)[j]); | 811 | printk("%02x ", (unsigned char)(tbuf)[j]); |
812 | printk("\n"); | 812 | printk("\n"); |
813 | } | 813 | } |
814 | usb_unlock_device(dev); | 814 | usb_unlock_device(dev); |
815 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); | 815 | i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); |
816 | usb_lock_device(dev); | 816 | usb_lock_device(dev); |
817 | } | 817 | } |
818 | kfree(tbuf); | 818 | kfree(tbuf); |
819 | if (i < 0) | 819 | if (i < 0) |
820 | return i; | 820 | return i; |
821 | return len2; | 821 | return len2; |
822 | } | 822 | } |
823 | 823 | ||
824 | static int proc_resetep(struct dev_state *ps, void __user *arg) | 824 | static int proc_resetep(struct dev_state *ps, void __user *arg) |
825 | { | 825 | { |
826 | unsigned int ep; | 826 | unsigned int ep; |
827 | int ret; | 827 | int ret; |
828 | 828 | ||
829 | if (get_user(ep, (unsigned int __user *)arg)) | 829 | if (get_user(ep, (unsigned int __user *)arg)) |
830 | return -EFAULT; | 830 | return -EFAULT; |
831 | ret = findintfep(ps->dev, ep); | 831 | ret = findintfep(ps->dev, ep); |
832 | if (ret < 0) | 832 | if (ret < 0) |
833 | return ret; | 833 | return ret; |
834 | ret = checkintf(ps, ret); | 834 | ret = checkintf(ps, ret); |
835 | if (ret) | 835 | if (ret) |
836 | return ret; | 836 | return ret; |
837 | usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0); | 837 | usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0); |
838 | return 0; | 838 | return 0; |
839 | } | 839 | } |
840 | 840 | ||
841 | static int proc_clearhalt(struct dev_state *ps, void __user *arg) | 841 | static int proc_clearhalt(struct dev_state *ps, void __user *arg) |
842 | { | 842 | { |
843 | unsigned int ep; | 843 | unsigned int ep; |
844 | int pipe; | 844 | int pipe; |
845 | int ret; | 845 | int ret; |
846 | 846 | ||
847 | if (get_user(ep, (unsigned int __user *)arg)) | 847 | if (get_user(ep, (unsigned int __user *)arg)) |
848 | return -EFAULT; | 848 | return -EFAULT; |
849 | ret = findintfep(ps->dev, ep); | 849 | ret = findintfep(ps->dev, ep); |
850 | if (ret < 0) | 850 | if (ret < 0) |
851 | return ret; | 851 | return ret; |
852 | ret = checkintf(ps, ret); | 852 | ret = checkintf(ps, ret); |
853 | if (ret) | 853 | if (ret) |
854 | return ret; | 854 | return ret; |
855 | if (ep & USB_DIR_IN) | 855 | if (ep & USB_DIR_IN) |
856 | pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f); | 856 | pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f); |
857 | else | 857 | else |
858 | pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f); | 858 | pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f); |
859 | 859 | ||
860 | return usb_clear_halt(ps->dev, pipe); | 860 | return usb_clear_halt(ps->dev, pipe); |
861 | } | 861 | } |
862 | 862 | ||
863 | static int proc_getdriver(struct dev_state *ps, void __user *arg) | 863 | static int proc_getdriver(struct dev_state *ps, void __user *arg) |
864 | { | 864 | { |
865 | struct usbdevfs_getdriver gd; | 865 | struct usbdevfs_getdriver gd; |
866 | struct usb_interface *intf; | 866 | struct usb_interface *intf; |
867 | int ret; | 867 | int ret; |
868 | 868 | ||
869 | if (copy_from_user(&gd, arg, sizeof(gd))) | 869 | if (copy_from_user(&gd, arg, sizeof(gd))) |
870 | return -EFAULT; | 870 | return -EFAULT; |
871 | intf = usb_ifnum_to_if(ps->dev, gd.interface); | 871 | intf = usb_ifnum_to_if(ps->dev, gd.interface); |
872 | if (!intf || !intf->dev.driver) | 872 | if (!intf || !intf->dev.driver) |
873 | ret = -ENODATA; | 873 | ret = -ENODATA; |
874 | else { | 874 | else { |
875 | strncpy(gd.driver, intf->dev.driver->name, | 875 | strncpy(gd.driver, intf->dev.driver->name, |
876 | sizeof(gd.driver)); | 876 | sizeof(gd.driver)); |
877 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); | 877 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); |
878 | } | 878 | } |
879 | return ret; | 879 | return ret; |
880 | } | 880 | } |
881 | 881 | ||
882 | static int proc_connectinfo(struct dev_state *ps, void __user *arg) | 882 | static int proc_connectinfo(struct dev_state *ps, void __user *arg) |
883 | { | 883 | { |
884 | struct usbdevfs_connectinfo ci; | 884 | struct usbdevfs_connectinfo ci; |
885 | 885 | ||
886 | ci.devnum = ps->dev->devnum; | 886 | ci.devnum = ps->dev->devnum; |
887 | ci.slow = ps->dev->speed == USB_SPEED_LOW; | 887 | ci.slow = ps->dev->speed == USB_SPEED_LOW; |
888 | if (copy_to_user(arg, &ci, sizeof(ci))) | 888 | if (copy_to_user(arg, &ci, sizeof(ci))) |
889 | return -EFAULT; | 889 | return -EFAULT; |
890 | return 0; | 890 | return 0; |
891 | } | 891 | } |
892 | 892 | ||
893 | static int proc_resetdevice(struct dev_state *ps) | 893 | static int proc_resetdevice(struct dev_state *ps) |
894 | { | 894 | { |
895 | return usb_reset_device(ps->dev); | 895 | return usb_reset_device(ps->dev); |
896 | } | 896 | } |
897 | 897 | ||
898 | static int proc_setintf(struct dev_state *ps, void __user *arg) | 898 | static int proc_setintf(struct dev_state *ps, void __user *arg) |
899 | { | 899 | { |
900 | struct usbdevfs_setinterface setintf; | 900 | struct usbdevfs_setinterface setintf; |
901 | int ret; | 901 | int ret; |
902 | 902 | ||
903 | if (copy_from_user(&setintf, arg, sizeof(setintf))) | 903 | if (copy_from_user(&setintf, arg, sizeof(setintf))) |
904 | return -EFAULT; | 904 | return -EFAULT; |
905 | if ((ret = checkintf(ps, setintf.interface))) | 905 | if ((ret = checkintf(ps, setintf.interface))) |
906 | return ret; | 906 | return ret; |
907 | return usb_set_interface(ps->dev, setintf.interface, | 907 | return usb_set_interface(ps->dev, setintf.interface, |
908 | setintf.altsetting); | 908 | setintf.altsetting); |
909 | } | 909 | } |
910 | 910 | ||
911 | static int proc_setconfig(struct dev_state *ps, void __user *arg) | 911 | static int proc_setconfig(struct dev_state *ps, void __user *arg) |
912 | { | 912 | { |
913 | int u; | 913 | int u; |
914 | int status = 0; | 914 | int status = 0; |
915 | struct usb_host_config *actconfig; | 915 | struct usb_host_config *actconfig; |
916 | 916 | ||
917 | if (get_user(u, (int __user *)arg)) | 917 | if (get_user(u, (int __user *)arg)) |
918 | return -EFAULT; | 918 | return -EFAULT; |
919 | 919 | ||
920 | actconfig = ps->dev->actconfig; | 920 | actconfig = ps->dev->actconfig; |
921 | 921 | ||
922 | /* Don't touch the device if any interfaces are claimed. | 922 | /* Don't touch the device if any interfaces are claimed. |
923 | * It could interfere with other drivers' operations, and if | 923 | * It could interfere with other drivers' operations, and if |
924 | * an interface is claimed by usbfs it could easily deadlock. | 924 | * an interface is claimed by usbfs it could easily deadlock. |
925 | */ | 925 | */ |
926 | if (actconfig) { | 926 | if (actconfig) { |
927 | int i; | 927 | int i; |
928 | 928 | ||
929 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { | 929 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { |
930 | if (usb_interface_claimed(actconfig->interface[i])) { | 930 | if (usb_interface_claimed(actconfig->interface[i])) { |
931 | dev_warn(&ps->dev->dev, | 931 | dev_warn(&ps->dev->dev, |
932 | "usbfs: interface %d claimed by %s " | 932 | "usbfs: interface %d claimed by %s " |
933 | "while '%s' sets config #%d\n", | 933 | "while '%s' sets config #%d\n", |
934 | actconfig->interface[i] | 934 | actconfig->interface[i] |
935 | ->cur_altsetting | 935 | ->cur_altsetting |
936 | ->desc.bInterfaceNumber, | 936 | ->desc.bInterfaceNumber, |
937 | actconfig->interface[i] | 937 | actconfig->interface[i] |
938 | ->dev.driver->name, | 938 | ->dev.driver->name, |
939 | current->comm, u); | 939 | current->comm, u); |
940 | status = -EBUSY; | 940 | status = -EBUSY; |
941 | break; | 941 | break; |
942 | } | 942 | } |
943 | } | 943 | } |
944 | } | 944 | } |
945 | 945 | ||
946 | /* SET_CONFIGURATION is often abused as a "cheap" driver reset, | 946 | /* SET_CONFIGURATION is often abused as a "cheap" driver reset, |
947 | * so avoid usb_set_configuration()'s kick to sysfs | 947 | * so avoid usb_set_configuration()'s kick to sysfs |
948 | */ | 948 | */ |
949 | if (status == 0) { | 949 | if (status == 0) { |
950 | if (actconfig && actconfig->desc.bConfigurationValue == u) | 950 | if (actconfig && actconfig->desc.bConfigurationValue == u) |
951 | status = usb_reset_configuration(ps->dev); | 951 | status = usb_reset_configuration(ps->dev); |
952 | else | 952 | else |
953 | status = usb_set_configuration(ps->dev, u); | 953 | status = usb_set_configuration(ps->dev, u); |
954 | } | 954 | } |
955 | 955 | ||
956 | return status; | 956 | return status; |
957 | } | 957 | } |
958 | 958 | ||
959 | static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | 959 | static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, |
960 | struct usbdevfs_iso_packet_desc __user *iso_frame_desc, | 960 | struct usbdevfs_iso_packet_desc __user *iso_frame_desc, |
961 | void __user *arg) | 961 | void __user *arg) |
962 | { | 962 | { |
963 | struct usbdevfs_iso_packet_desc *isopkt = NULL; | 963 | struct usbdevfs_iso_packet_desc *isopkt = NULL; |
964 | struct usb_host_endpoint *ep; | 964 | struct usb_host_endpoint *ep; |
965 | struct async *as; | 965 | struct async *as; |
966 | struct usb_ctrlrequest *dr = NULL; | 966 | struct usb_ctrlrequest *dr = NULL; |
967 | unsigned int u, totlen, isofrmlen; | 967 | unsigned int u, totlen, isofrmlen; |
968 | int ret, ifnum = -1; | 968 | int ret, ifnum = -1; |
969 | int is_in; | 969 | int is_in; |
970 | 970 | ||
971 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | | 971 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | |
972 | USBDEVFS_URB_SHORT_NOT_OK | | 972 | USBDEVFS_URB_SHORT_NOT_OK | |
973 | USBDEVFS_URB_NO_FSBR | | 973 | USBDEVFS_URB_NO_FSBR | |
974 | USBDEVFS_URB_ZERO_PACKET | | 974 | USBDEVFS_URB_ZERO_PACKET | |
975 | USBDEVFS_URB_NO_INTERRUPT)) | 975 | USBDEVFS_URB_NO_INTERRUPT)) |
976 | return -EINVAL; | 976 | return -EINVAL; |
977 | if (!uurb->buffer) | 977 | if (!uurb->buffer) |
978 | return -EINVAL; | 978 | return -EINVAL; |
979 | if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || | 979 | if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || |
980 | uurb->signr > SIGRTMAX)) | 980 | uurb->signr > SIGRTMAX)) |
981 | return -EINVAL; | 981 | return -EINVAL; |
982 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && | 982 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && |
983 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { | 983 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { |
984 | ifnum = findintfep(ps->dev, uurb->endpoint); | 984 | ifnum = findintfep(ps->dev, uurb->endpoint); |
985 | if (ifnum < 0) | 985 | if (ifnum < 0) |
986 | return ifnum; | 986 | return ifnum; |
987 | ret = checkintf(ps, ifnum); | 987 | ret = checkintf(ps, ifnum); |
988 | if (ret) | 988 | if (ret) |
989 | return ret; | 989 | return ret; |
990 | } | 990 | } |
991 | if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) { | 991 | if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) { |
992 | is_in = 1; | 992 | is_in = 1; |
993 | ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; | 993 | ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; |
994 | } else { | 994 | } else { |
995 | is_in = 0; | 995 | is_in = 0; |
996 | ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; | 996 | ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; |
997 | } | 997 | } |
998 | if (!ep) | 998 | if (!ep) |
999 | return -ENOENT; | 999 | return -ENOENT; |
1000 | switch(uurb->type) { | 1000 | switch(uurb->type) { |
1001 | case USBDEVFS_URB_TYPE_CONTROL: | 1001 | case USBDEVFS_URB_TYPE_CONTROL: |
1002 | if (!usb_endpoint_xfer_control(&ep->desc)) | 1002 | if (!usb_endpoint_xfer_control(&ep->desc)) |
1003 | return -EINVAL; | 1003 | return -EINVAL; |
1004 | /* min 8 byte setup packet, | 1004 | /* min 8 byte setup packet, |
1005 | * max 8 byte setup plus an arbitrary data stage */ | 1005 | * max 8 byte setup plus an arbitrary data stage */ |
1006 | if (uurb->buffer_length < 8 || | 1006 | if (uurb->buffer_length < 8 || |
1007 | uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) | 1007 | uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) |
1008 | return -EINVAL; | 1008 | return -EINVAL; |
1009 | dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); | 1009 | dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); |
1010 | if (!dr) | 1010 | if (!dr) |
1011 | return -ENOMEM; | 1011 | return -ENOMEM; |
1012 | if (copy_from_user(dr, uurb->buffer, 8)) { | 1012 | if (copy_from_user(dr, uurb->buffer, 8)) { |
1013 | kfree(dr); | 1013 | kfree(dr); |
1014 | return -EFAULT; | 1014 | return -EFAULT; |
1015 | } | 1015 | } |
1016 | if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { | 1016 | if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { |
1017 | kfree(dr); | 1017 | kfree(dr); |
1018 | return -EINVAL; | 1018 | return -EINVAL; |
1019 | } | 1019 | } |
1020 | ret = check_ctrlrecip(ps, dr->bRequestType, | 1020 | ret = check_ctrlrecip(ps, dr->bRequestType, |
1021 | le16_to_cpup(&dr->wIndex)); | 1021 | le16_to_cpup(&dr->wIndex)); |
1022 | if (ret) { | 1022 | if (ret) { |
1023 | kfree(dr); | 1023 | kfree(dr); |
1024 | return ret; | 1024 | return ret; |
1025 | } | 1025 | } |
1026 | uurb->number_of_packets = 0; | 1026 | uurb->number_of_packets = 0; |
1027 | uurb->buffer_length = le16_to_cpup(&dr->wLength); | 1027 | uurb->buffer_length = le16_to_cpup(&dr->wLength); |
1028 | uurb->buffer += 8; | 1028 | uurb->buffer += 8; |
1029 | if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { | 1029 | if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { |
1030 | is_in = 1; | 1030 | is_in = 1; |
1031 | uurb->endpoint |= USB_DIR_IN; | 1031 | uurb->endpoint |= USB_DIR_IN; |
1032 | } else { | 1032 | } else { |
1033 | is_in = 0; | 1033 | is_in = 0; |
1034 | uurb->endpoint &= ~USB_DIR_IN; | 1034 | uurb->endpoint &= ~USB_DIR_IN; |
1035 | } | 1035 | } |
1036 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | 1036 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1037 | uurb->buffer, uurb->buffer_length)) { | 1037 | uurb->buffer, uurb->buffer_length)) { |
1038 | kfree(dr); | 1038 | kfree(dr); |
1039 | return -EFAULT; | 1039 | return -EFAULT; |
1040 | } | 1040 | } |
1041 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " | 1041 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " |
1042 | "bRrequestType=%02x wValue=%04x " | 1042 | "bRrequestType=%02x wValue=%04x " |
1043 | "wIndex=%04x wLength=%04x\n", | 1043 | "wIndex=%04x wLength=%04x\n", |
1044 | dr->bRequest, dr->bRequestType, | 1044 | dr->bRequest, dr->bRequestType, |
1045 | __le16_to_cpup(&dr->wValue), | 1045 | __le16_to_cpup(&dr->wValue), |
1046 | __le16_to_cpup(&dr->wIndex), | 1046 | __le16_to_cpup(&dr->wIndex), |
1047 | __le16_to_cpup(&dr->wLength)); | 1047 | __le16_to_cpup(&dr->wLength)); |
1048 | break; | 1048 | break; |
1049 | 1049 | ||
1050 | case USBDEVFS_URB_TYPE_BULK: | 1050 | case USBDEVFS_URB_TYPE_BULK: |
1051 | switch (usb_endpoint_type(&ep->desc)) { | 1051 | switch (usb_endpoint_type(&ep->desc)) { |
1052 | case USB_ENDPOINT_XFER_CONTROL: | 1052 | case USB_ENDPOINT_XFER_CONTROL: |
1053 | case USB_ENDPOINT_XFER_ISOC: | 1053 | case USB_ENDPOINT_XFER_ISOC: |
1054 | return -EINVAL; | 1054 | return -EINVAL; |
1055 | /* allow single-shot interrupt transfers, at bogus rates */ | 1055 | /* allow single-shot interrupt transfers, at bogus rates */ |
1056 | } | 1056 | } |
1057 | uurb->number_of_packets = 0; | 1057 | uurb->number_of_packets = 0; |
1058 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1058 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
1059 | return -EINVAL; | 1059 | return -EINVAL; |
1060 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | 1060 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1061 | uurb->buffer, uurb->buffer_length)) | 1061 | uurb->buffer, uurb->buffer_length)) |
1062 | return -EFAULT; | 1062 | return -EFAULT; |
1063 | snoop(&ps->dev->dev, "bulk urb\n"); | 1063 | snoop(&ps->dev->dev, "bulk urb\n"); |
1064 | break; | 1064 | break; |
1065 | 1065 | ||
1066 | case USBDEVFS_URB_TYPE_ISO: | 1066 | case USBDEVFS_URB_TYPE_ISO: |
1067 | /* arbitrary limit */ | 1067 | /* arbitrary limit */ |
1068 | if (uurb->number_of_packets < 1 || | 1068 | if (uurb->number_of_packets < 1 || |
1069 | uurb->number_of_packets > 128) | 1069 | uurb->number_of_packets > 128) |
1070 | return -EINVAL; | 1070 | return -EINVAL; |
1071 | if (!usb_endpoint_xfer_isoc(&ep->desc)) | 1071 | if (!usb_endpoint_xfer_isoc(&ep->desc)) |
1072 | return -EINVAL; | 1072 | return -EINVAL; |
1073 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * | 1073 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * |
1074 | uurb->number_of_packets; | 1074 | uurb->number_of_packets; |
1075 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) | 1075 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) |
1076 | return -ENOMEM; | 1076 | return -ENOMEM; |
1077 | if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { | 1077 | if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { |
1078 | kfree(isopkt); | 1078 | kfree(isopkt); |
1079 | return -EFAULT; | 1079 | return -EFAULT; |
1080 | } | 1080 | } |
1081 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { | 1081 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { |
1082 | /* arbitrary limit, | 1082 | /* arbitrary limit, |
1083 | * sufficient for USB 2.0 high-bandwidth iso */ | 1083 | * sufficient for USB 2.0 high-bandwidth iso */ |
1084 | if (isopkt[u].length > 8192) { | 1084 | if (isopkt[u].length > 8192) { |
1085 | kfree(isopkt); | 1085 | kfree(isopkt); |
1086 | return -EINVAL; | 1086 | return -EINVAL; |
1087 | } | 1087 | } |
1088 | totlen += isopkt[u].length; | 1088 | totlen += isopkt[u].length; |
1089 | } | 1089 | } |
1090 | if (totlen > 32768) { | 1090 | if (totlen > 32768) { |
1091 | kfree(isopkt); | 1091 | kfree(isopkt); |
1092 | return -EINVAL; | 1092 | return -EINVAL; |
1093 | } | 1093 | } |
1094 | uurb->buffer_length = totlen; | 1094 | uurb->buffer_length = totlen; |
1095 | snoop(&ps->dev->dev, "iso urb\n"); | 1095 | snoop(&ps->dev->dev, "iso urb\n"); |
1096 | break; | 1096 | break; |
1097 | 1097 | ||
1098 | case USBDEVFS_URB_TYPE_INTERRUPT: | 1098 | case USBDEVFS_URB_TYPE_INTERRUPT: |
1099 | uurb->number_of_packets = 0; | 1099 | uurb->number_of_packets = 0; |
1100 | if (!usb_endpoint_xfer_int(&ep->desc)) | 1100 | if (!usb_endpoint_xfer_int(&ep->desc)) |
1101 | return -EINVAL; | 1101 | return -EINVAL; |
1102 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1102 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
1103 | return -EINVAL; | 1103 | return -EINVAL; |
1104 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | 1104 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1105 | uurb->buffer, uurb->buffer_length)) | 1105 | uurb->buffer, uurb->buffer_length)) |
1106 | return -EFAULT; | 1106 | return -EFAULT; |
1107 | snoop(&ps->dev->dev, "interrupt urb\n"); | 1107 | snoop(&ps->dev->dev, "interrupt urb\n"); |
1108 | break; | 1108 | break; |
1109 | 1109 | ||
1110 | default: | 1110 | default: |
1111 | return -EINVAL; | 1111 | return -EINVAL; |
1112 | } | 1112 | } |
1113 | as = alloc_async(uurb->number_of_packets); | 1113 | as = alloc_async(uurb->number_of_packets); |
1114 | if (!as) { | 1114 | if (!as) { |
1115 | kfree(isopkt); | 1115 | kfree(isopkt); |
1116 | kfree(dr); | 1116 | kfree(dr); |
1117 | return -ENOMEM; | 1117 | return -ENOMEM; |
1118 | } | 1118 | } |
1119 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); | 1119 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); |
1120 | if (!as->urb->transfer_buffer) { | 1120 | if (!as->urb->transfer_buffer) { |
1121 | kfree(isopkt); | 1121 | kfree(isopkt); |
1122 | kfree(dr); | 1122 | kfree(dr); |
1123 | free_async(as); | 1123 | free_async(as); |
1124 | return -ENOMEM; | 1124 | return -ENOMEM; |
1125 | } | 1125 | } |
1126 | as->urb->dev = ps->dev; | 1126 | as->urb->dev = ps->dev; |
1127 | as->urb->pipe = (uurb->type << 30) | | 1127 | as->urb->pipe = (uurb->type << 30) | |
1128 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | | 1128 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | |
1129 | (uurb->endpoint & USB_DIR_IN); | 1129 | (uurb->endpoint & USB_DIR_IN); |
1130 | 1130 | ||
1131 | /* This tedious sequence is necessary because the URB_* flags | 1131 | /* This tedious sequence is necessary because the URB_* flags |
1132 | * are internal to the kernel and subject to change, whereas | 1132 | * are internal to the kernel and subject to change, whereas |
1133 | * the USBDEVFS_URB_* flags are a user API and must not be changed. | 1133 | * the USBDEVFS_URB_* flags are a user API and must not be changed. |
1134 | */ | 1134 | */ |
1135 | u = (is_in ? URB_DIR_IN : URB_DIR_OUT); | 1135 | u = (is_in ? URB_DIR_IN : URB_DIR_OUT); |
1136 | if (uurb->flags & USBDEVFS_URB_ISO_ASAP) | 1136 | if (uurb->flags & USBDEVFS_URB_ISO_ASAP) |
1137 | u |= URB_ISO_ASAP; | 1137 | u |= URB_ISO_ASAP; |
1138 | if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) | 1138 | if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) |
1139 | u |= URB_SHORT_NOT_OK; | 1139 | u |= URB_SHORT_NOT_OK; |
1140 | if (uurb->flags & USBDEVFS_URB_NO_FSBR) | 1140 | if (uurb->flags & USBDEVFS_URB_NO_FSBR) |
1141 | u |= URB_NO_FSBR; | 1141 | u |= URB_NO_FSBR; |
1142 | if (uurb->flags & USBDEVFS_URB_ZERO_PACKET) | 1142 | if (uurb->flags & USBDEVFS_URB_ZERO_PACKET) |
1143 | u |= URB_ZERO_PACKET; | 1143 | u |= URB_ZERO_PACKET; |
1144 | if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT) | 1144 | if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT) |
1145 | u |= URB_NO_INTERRUPT; | 1145 | u |= URB_NO_INTERRUPT; |
1146 | as->urb->transfer_flags = u; | 1146 | as->urb->transfer_flags = u; |
1147 | 1147 | ||
1148 | as->urb->transfer_buffer_length = uurb->buffer_length; | 1148 | as->urb->transfer_buffer_length = uurb->buffer_length; |
1149 | as->urb->setup_packet = (unsigned char *)dr; | 1149 | as->urb->setup_packet = (unsigned char *)dr; |
1150 | as->urb->start_frame = uurb->start_frame; | 1150 | as->urb->start_frame = uurb->start_frame; |
1151 | as->urb->number_of_packets = uurb->number_of_packets; | 1151 | as->urb->number_of_packets = uurb->number_of_packets; |
1152 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || | 1152 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || |
1153 | ps->dev->speed == USB_SPEED_HIGH) | 1153 | ps->dev->speed == USB_SPEED_HIGH) |
1154 | as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); | 1154 | as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); |
1155 | else | 1155 | else |
1156 | as->urb->interval = ep->desc.bInterval; | 1156 | as->urb->interval = ep->desc.bInterval; |
1157 | as->urb->context = as; | 1157 | as->urb->context = as; |
1158 | as->urb->complete = async_completed; | 1158 | as->urb->complete = async_completed; |
1159 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { | 1159 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { |
1160 | as->urb->iso_frame_desc[u].offset = totlen; | 1160 | as->urb->iso_frame_desc[u].offset = totlen; |
1161 | as->urb->iso_frame_desc[u].length = isopkt[u].length; | 1161 | as->urb->iso_frame_desc[u].length = isopkt[u].length; |
1162 | totlen += isopkt[u].length; | 1162 | totlen += isopkt[u].length; |
1163 | } | 1163 | } |
1164 | kfree(isopkt); | 1164 | kfree(isopkt); |
1165 | as->ps = ps; | 1165 | as->ps = ps; |
1166 | as->userurb = arg; | 1166 | as->userurb = arg; |
1167 | if (uurb->endpoint & USB_DIR_IN) | 1167 | if (uurb->endpoint & USB_DIR_IN) |
1168 | as->userbuffer = uurb->buffer; | 1168 | as->userbuffer = uurb->buffer; |
1169 | else | 1169 | else |
1170 | as->userbuffer = NULL; | 1170 | as->userbuffer = NULL; |
1171 | as->signr = uurb->signr; | 1171 | as->signr = uurb->signr; |
1172 | as->ifnum = ifnum; | 1172 | as->ifnum = ifnum; |
1173 | as->pid = get_pid(task_pid(current)); | 1173 | as->pid = get_pid(task_pid(current)); |
1174 | as->uid = current->uid; | 1174 | as->uid = current->uid; |
1175 | as->euid = current->euid; | 1175 | as->euid = current->euid; |
1176 | security_task_getsecid(current, &as->secid); | 1176 | security_task_getsecid(current, &as->secid); |
1177 | if (!is_in) { | 1177 | if (!is_in) { |
1178 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | 1178 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
1179 | as->urb->transfer_buffer_length)) { | 1179 | as->urb->transfer_buffer_length)) { |
1180 | free_async(as); | 1180 | free_async(as); |
1181 | return -EFAULT; | 1181 | return -EFAULT; |
1182 | } | 1182 | } |
1183 | } | 1183 | } |
1184 | snoop_urb(as->urb, as->userurb); | 1184 | snoop_urb(as->urb, as->userurb); |
1185 | async_newpending(as); | 1185 | async_newpending(as); |
1186 | if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { | 1186 | if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { |
1187 | dev_printk(KERN_DEBUG, &ps->dev->dev, | 1187 | dev_printk(KERN_DEBUG, &ps->dev->dev, |
1188 | "usbfs: usb_submit_urb returned %d\n", ret); | 1188 | "usbfs: usb_submit_urb returned %d\n", ret); |
1189 | async_removepending(as); | 1189 | async_removepending(as); |
1190 | free_async(as); | 1190 | free_async(as); |
1191 | return ret; | 1191 | return ret; |
1192 | } | 1192 | } |
1193 | return 0; | 1193 | return 0; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | static int proc_submiturb(struct dev_state *ps, void __user *arg) | 1196 | static int proc_submiturb(struct dev_state *ps, void __user *arg) |
1197 | { | 1197 | { |
1198 | struct usbdevfs_urb uurb; | 1198 | struct usbdevfs_urb uurb; |
1199 | 1199 | ||
1200 | if (copy_from_user(&uurb, arg, sizeof(uurb))) | 1200 | if (copy_from_user(&uurb, arg, sizeof(uurb))) |
1201 | return -EFAULT; | 1201 | return -EFAULT; |
1202 | 1202 | ||
1203 | return proc_do_submiturb(ps, &uurb, | 1203 | return proc_do_submiturb(ps, &uurb, |
1204 | (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), | 1204 | (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), |
1205 | arg); | 1205 | arg); |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | static int proc_unlinkurb(struct dev_state *ps, void __user *arg) | 1208 | static int proc_unlinkurb(struct dev_state *ps, void __user *arg) |
1209 | { | 1209 | { |
1210 | struct async *as; | 1210 | struct async *as; |
1211 | 1211 | ||
1212 | as = async_getpending(ps, arg); | 1212 | as = async_getpending(ps, arg); |
1213 | if (!as) | 1213 | if (!as) |
1214 | return -EINVAL; | 1214 | return -EINVAL; |
1215 | usb_kill_urb(as->urb); | 1215 | usb_kill_urb(as->urb); |
1216 | return 0; | 1216 | return 0; |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | static int processcompl(struct async *as, void __user * __user *arg) | 1219 | static int processcompl(struct async *as, void __user * __user *arg) |
1220 | { | 1220 | { |
1221 | struct urb *urb = as->urb; | 1221 | struct urb *urb = as->urb; |
1222 | struct usbdevfs_urb __user *userurb = as->userurb; | 1222 | struct usbdevfs_urb __user *userurb = as->userurb; |
1223 | void __user *addr = as->userurb; | 1223 | void __user *addr = as->userurb; |
1224 | unsigned int i; | 1224 | unsigned int i; |
1225 | 1225 | ||
1226 | if (as->userbuffer) | 1226 | if (as->userbuffer) |
1227 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, | 1227 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, |
1228 | urb->transfer_buffer_length)) | 1228 | urb->transfer_buffer_length)) |
1229 | return -EFAULT; | 1229 | return -EFAULT; |
1230 | if (put_user(as->status, &userurb->status)) | 1230 | if (put_user(as->status, &userurb->status)) |
1231 | return -EFAULT; | 1231 | return -EFAULT; |
1232 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1232 | if (put_user(urb->actual_length, &userurb->actual_length)) |
1233 | return -EFAULT; | 1233 | return -EFAULT; |
1234 | if (put_user(urb->error_count, &userurb->error_count)) | 1234 | if (put_user(urb->error_count, &userurb->error_count)) |
1235 | return -EFAULT; | 1235 | return -EFAULT; |
1236 | 1236 | ||
1237 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { | 1237 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
1238 | for (i = 0; i < urb->number_of_packets; i++) { | 1238 | for (i = 0; i < urb->number_of_packets; i++) { |
1239 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1239 | if (put_user(urb->iso_frame_desc[i].actual_length, |
1240 | &userurb->iso_frame_desc[i].actual_length)) | 1240 | &userurb->iso_frame_desc[i].actual_length)) |
1241 | return -EFAULT; | 1241 | return -EFAULT; |
1242 | if (put_user(urb->iso_frame_desc[i].status, | 1242 | if (put_user(urb->iso_frame_desc[i].status, |
1243 | &userurb->iso_frame_desc[i].status)) | 1243 | &userurb->iso_frame_desc[i].status)) |
1244 | return -EFAULT; | 1244 | return -EFAULT; |
1245 | } | 1245 | } |
1246 | } | 1246 | } |
1247 | 1247 | ||
1248 | free_async(as); | 1248 | free_async(as); |
1249 | 1249 | ||
1250 | if (put_user(addr, (void __user * __user *)arg)) | 1250 | if (put_user(addr, (void __user * __user *)arg)) |
1251 | return -EFAULT; | 1251 | return -EFAULT; |
1252 | return 0; | 1252 | return 0; |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | static struct async *reap_as(struct dev_state *ps) | 1255 | static struct async *reap_as(struct dev_state *ps) |
1256 | { | 1256 | { |
1257 | DECLARE_WAITQUEUE(wait, current); | 1257 | DECLARE_WAITQUEUE(wait, current); |
1258 | struct async *as = NULL; | 1258 | struct async *as = NULL; |
1259 | struct usb_device *dev = ps->dev; | 1259 | struct usb_device *dev = ps->dev; |
1260 | 1260 | ||
1261 | add_wait_queue(&ps->wait, &wait); | 1261 | add_wait_queue(&ps->wait, &wait); |
1262 | for (;;) { | 1262 | for (;;) { |
1263 | __set_current_state(TASK_INTERRUPTIBLE); | 1263 | __set_current_state(TASK_INTERRUPTIBLE); |
1264 | as = async_getcompleted(ps); | 1264 | as = async_getcompleted(ps); |
1265 | if (as) | 1265 | if (as) |
1266 | break; | 1266 | break; |
1267 | if (signal_pending(current)) | 1267 | if (signal_pending(current)) |
1268 | break; | 1268 | break; |
1269 | usb_unlock_device(dev); | 1269 | usb_unlock_device(dev); |
1270 | schedule(); | 1270 | schedule(); |
1271 | usb_lock_device(dev); | 1271 | usb_lock_device(dev); |
1272 | } | 1272 | } |
1273 | remove_wait_queue(&ps->wait, &wait); | 1273 | remove_wait_queue(&ps->wait, &wait); |
1274 | set_current_state(TASK_RUNNING); | 1274 | set_current_state(TASK_RUNNING); |
1275 | return as; | 1275 | return as; |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | static int proc_reapurb(struct dev_state *ps, void __user *arg) | 1278 | static int proc_reapurb(struct dev_state *ps, void __user *arg) |
1279 | { | 1279 | { |
1280 | struct async *as = reap_as(ps); | 1280 | struct async *as = reap_as(ps); |
1281 | if (as) | 1281 | if (as) |
1282 | return processcompl(as, (void __user * __user *)arg); | 1282 | return processcompl(as, (void __user * __user *)arg); |
1283 | if (signal_pending(current)) | 1283 | if (signal_pending(current)) |
1284 | return -EINTR; | 1284 | return -EINTR; |
1285 | return -EIO; | 1285 | return -EIO; |
1286 | } | 1286 | } |
1287 | 1287 | ||
1288 | static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) | 1288 | static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) |
1289 | { | 1289 | { |
1290 | struct async *as; | 1290 | struct async *as; |
1291 | 1291 | ||
1292 | if (!(as = async_getcompleted(ps))) | 1292 | if (!(as = async_getcompleted(ps))) |
1293 | return -EAGAIN; | 1293 | return -EAGAIN; |
1294 | return processcompl(as, (void __user * __user *)arg); | 1294 | return processcompl(as, (void __user * __user *)arg); |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | #ifdef CONFIG_COMPAT | 1297 | #ifdef CONFIG_COMPAT |
1298 | 1298 | ||
1299 | static int get_urb32(struct usbdevfs_urb *kurb, | 1299 | static int get_urb32(struct usbdevfs_urb *kurb, |
1300 | struct usbdevfs_urb32 __user *uurb) | 1300 | struct usbdevfs_urb32 __user *uurb) |
1301 | { | 1301 | { |
1302 | __u32 uptr; | 1302 | __u32 uptr; |
1303 | if (get_user(kurb->type, &uurb->type) || | 1303 | if (get_user(kurb->type, &uurb->type) || |
1304 | __get_user(kurb->endpoint, &uurb->endpoint) || | 1304 | __get_user(kurb->endpoint, &uurb->endpoint) || |
1305 | __get_user(kurb->status, &uurb->status) || | 1305 | __get_user(kurb->status, &uurb->status) || |
1306 | __get_user(kurb->flags, &uurb->flags) || | 1306 | __get_user(kurb->flags, &uurb->flags) || |
1307 | __get_user(kurb->buffer_length, &uurb->buffer_length) || | 1307 | __get_user(kurb->buffer_length, &uurb->buffer_length) || |
1308 | __get_user(kurb->actual_length, &uurb->actual_length) || | 1308 | __get_user(kurb->actual_length, &uurb->actual_length) || |
1309 | __get_user(kurb->start_frame, &uurb->start_frame) || | 1309 | __get_user(kurb->start_frame, &uurb->start_frame) || |
1310 | __get_user(kurb->number_of_packets, &uurb->number_of_packets) || | 1310 | __get_user(kurb->number_of_packets, &uurb->number_of_packets) || |
1311 | __get_user(kurb->error_count, &uurb->error_count) || | 1311 | __get_user(kurb->error_count, &uurb->error_count) || |
1312 | __get_user(kurb->signr, &uurb->signr)) | 1312 | __get_user(kurb->signr, &uurb->signr)) |
1313 | return -EFAULT; | 1313 | return -EFAULT; |
1314 | 1314 | ||
1315 | if (__get_user(uptr, &uurb->buffer)) | 1315 | if (__get_user(uptr, &uurb->buffer)) |
1316 | return -EFAULT; | 1316 | return -EFAULT; |
1317 | kurb->buffer = compat_ptr(uptr); | 1317 | kurb->buffer = compat_ptr(uptr); |
1318 | if (__get_user(uptr, &uurb->buffer)) | 1318 | if (__get_user(uptr, &uurb->buffer)) |
1319 | return -EFAULT; | 1319 | return -EFAULT; |
1320 | kurb->usercontext = compat_ptr(uptr); | 1320 | kurb->usercontext = compat_ptr(uptr); |
1321 | 1321 | ||
1322 | return 0; | 1322 | return 0; |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) | 1325 | static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) |
1326 | { | 1326 | { |
1327 | struct usbdevfs_urb uurb; | 1327 | struct usbdevfs_urb uurb; |
1328 | 1328 | ||
1329 | if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg)) | 1329 | if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg)) |
1330 | return -EFAULT; | 1330 | return -EFAULT; |
1331 | 1331 | ||
1332 | return proc_do_submiturb(ps, &uurb, | 1332 | return proc_do_submiturb(ps, &uurb, |
1333 | ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, | 1333 | ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, |
1334 | arg); | 1334 | arg); |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | static int processcompl_compat(struct async *as, void __user * __user *arg) | 1337 | static int processcompl_compat(struct async *as, void __user * __user *arg) |
1338 | { | 1338 | { |
1339 | struct urb *urb = as->urb; | 1339 | struct urb *urb = as->urb; |
1340 | struct usbdevfs_urb32 __user *userurb = as->userurb; | 1340 | struct usbdevfs_urb32 __user *userurb = as->userurb; |
1341 | void __user *addr = as->userurb; | 1341 | void __user *addr = as->userurb; |
1342 | unsigned int i; | 1342 | unsigned int i; |
1343 | 1343 | ||
1344 | if (as->userbuffer) | 1344 | if (as->userbuffer) |
1345 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, | 1345 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, |
1346 | urb->transfer_buffer_length)) | 1346 | urb->transfer_buffer_length)) |
1347 | return -EFAULT; | 1347 | return -EFAULT; |
1348 | if (put_user(as->status, &userurb->status)) | 1348 | if (put_user(as->status, &userurb->status)) |
1349 | return -EFAULT; | 1349 | return -EFAULT; |
1350 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1350 | if (put_user(urb->actual_length, &userurb->actual_length)) |
1351 | return -EFAULT; | 1351 | return -EFAULT; |
1352 | if (put_user(urb->error_count, &userurb->error_count)) | 1352 | if (put_user(urb->error_count, &userurb->error_count)) |
1353 | return -EFAULT; | 1353 | return -EFAULT; |
1354 | 1354 | ||
1355 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { | 1355 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
1356 | for (i = 0; i < urb->number_of_packets; i++) { | 1356 | for (i = 0; i < urb->number_of_packets; i++) { |
1357 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1357 | if (put_user(urb->iso_frame_desc[i].actual_length, |
1358 | &userurb->iso_frame_desc[i].actual_length)) | 1358 | &userurb->iso_frame_desc[i].actual_length)) |
1359 | return -EFAULT; | 1359 | return -EFAULT; |
1360 | if (put_user(urb->iso_frame_desc[i].status, | 1360 | if (put_user(urb->iso_frame_desc[i].status, |
1361 | &userurb->iso_frame_desc[i].status)) | 1361 | &userurb->iso_frame_desc[i].status)) |
1362 | return -EFAULT; | 1362 | return -EFAULT; |
1363 | } | 1363 | } |
1364 | } | 1364 | } |
1365 | 1365 | ||
1366 | free_async(as); | 1366 | free_async(as); |
1367 | if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) | 1367 | if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) |
1368 | return -EFAULT; | 1368 | return -EFAULT; |
1369 | return 0; | 1369 | return 0; |
1370 | } | 1370 | } |
1371 | 1371 | ||
1372 | static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) | 1372 | static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) |
1373 | { | 1373 | { |
1374 | struct async *as = reap_as(ps); | 1374 | struct async *as = reap_as(ps); |
1375 | if (as) | 1375 | if (as) |
1376 | return processcompl_compat(as, (void __user * __user *)arg); | 1376 | return processcompl_compat(as, (void __user * __user *)arg); |
1377 | if (signal_pending(current)) | 1377 | if (signal_pending(current)) |
1378 | return -EINTR; | 1378 | return -EINTR; |
1379 | return -EIO; | 1379 | return -EIO; |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) | 1382 | static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) |
1383 | { | 1383 | { |
1384 | struct async *as; | 1384 | struct async *as; |
1385 | 1385 | ||
1386 | if (!(as = async_getcompleted(ps))) | 1386 | if (!(as = async_getcompleted(ps))) |
1387 | return -EAGAIN; | 1387 | return -EAGAIN; |
1388 | return processcompl_compat(as, (void __user * __user *)arg); | 1388 | return processcompl_compat(as, (void __user * __user *)arg); |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | #endif | 1391 | #endif |
1392 | 1392 | ||
1393 | static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) | 1393 | static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) |
1394 | { | 1394 | { |
1395 | struct usbdevfs_disconnectsignal ds; | 1395 | struct usbdevfs_disconnectsignal ds; |
1396 | 1396 | ||
1397 | if (copy_from_user(&ds, arg, sizeof(ds))) | 1397 | if (copy_from_user(&ds, arg, sizeof(ds))) |
1398 | return -EFAULT; | 1398 | return -EFAULT; |
1399 | if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX)) | 1399 | if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX)) |
1400 | return -EINVAL; | 1400 | return -EINVAL; |
1401 | ps->discsignr = ds.signr; | 1401 | ps->discsignr = ds.signr; |
1402 | ps->disccontext = ds.context; | 1402 | ps->disccontext = ds.context; |
1403 | return 0; | 1403 | return 0; |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static int proc_claiminterface(struct dev_state *ps, void __user *arg) | 1406 | static int proc_claiminterface(struct dev_state *ps, void __user *arg) |
1407 | { | 1407 | { |
1408 | unsigned int ifnum; | 1408 | unsigned int ifnum; |
1409 | 1409 | ||
1410 | if (get_user(ifnum, (unsigned int __user *)arg)) | 1410 | if (get_user(ifnum, (unsigned int __user *)arg)) |
1411 | return -EFAULT; | 1411 | return -EFAULT; |
1412 | return claimintf(ps, ifnum); | 1412 | return claimintf(ps, ifnum); |
1413 | } | 1413 | } |
1414 | 1414 | ||
1415 | static int proc_releaseinterface(struct dev_state *ps, void __user *arg) | 1415 | static int proc_releaseinterface(struct dev_state *ps, void __user *arg) |
1416 | { | 1416 | { |
1417 | unsigned int ifnum; | 1417 | unsigned int ifnum; |
1418 | int ret; | 1418 | int ret; |
1419 | 1419 | ||
1420 | if (get_user(ifnum, (unsigned int __user *)arg)) | 1420 | if (get_user(ifnum, (unsigned int __user *)arg)) |
1421 | return -EFAULT; | 1421 | return -EFAULT; |
1422 | if ((ret = releaseintf(ps, ifnum)) < 0) | 1422 | if ((ret = releaseintf(ps, ifnum)) < 0) |
1423 | return ret; | 1423 | return ret; |
1424 | destroy_async_on_interface (ps, ifnum); | 1424 | destroy_async_on_interface (ps, ifnum); |
1425 | return 0; | 1425 | return 0; |
1426 | } | 1426 | } |
1427 | 1427 | ||
1428 | static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | 1428 | static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) |
1429 | { | 1429 | { |
1430 | int size; | 1430 | int size; |
1431 | void *buf = NULL; | 1431 | void *buf = NULL; |
1432 | int retval = 0; | 1432 | int retval = 0; |
1433 | struct usb_interface *intf = NULL; | 1433 | struct usb_interface *intf = NULL; |
1434 | struct usb_driver *driver = NULL; | 1434 | struct usb_driver *driver = NULL; |
1435 | 1435 | ||
1436 | /* alloc buffer */ | 1436 | /* alloc buffer */ |
1437 | if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { | 1437 | if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { |
1438 | if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) | 1438 | if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) |
1439 | return -ENOMEM; | 1439 | return -ENOMEM; |
1440 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { | 1440 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { |
1441 | if (copy_from_user(buf, ctl->data, size)) { | 1441 | if (copy_from_user(buf, ctl->data, size)) { |
1442 | kfree(buf); | 1442 | kfree(buf); |
1443 | return -EFAULT; | 1443 | return -EFAULT; |
1444 | } | 1444 | } |
1445 | } else { | 1445 | } else { |
1446 | memset(buf, 0, size); | 1446 | memset(buf, 0, size); |
1447 | } | 1447 | } |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | if (!connected(ps)) { | 1450 | if (!connected(ps)) { |
1451 | kfree(buf); | 1451 | kfree(buf); |
1452 | return -ENODEV; | 1452 | return -ENODEV; |
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | if (ps->dev->state != USB_STATE_CONFIGURED) | 1455 | if (ps->dev->state != USB_STATE_CONFIGURED) |
1456 | retval = -EHOSTUNREACH; | 1456 | retval = -EHOSTUNREACH; |
1457 | else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) | 1457 | else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) |
1458 | retval = -EINVAL; | 1458 | retval = -EINVAL; |
1459 | else switch (ctl->ioctl_code) { | 1459 | else switch (ctl->ioctl_code) { |
1460 | 1460 | ||
1461 | /* disconnect kernel driver from interface */ | 1461 | /* disconnect kernel driver from interface */ |
1462 | case USBDEVFS_DISCONNECT: | 1462 | case USBDEVFS_DISCONNECT: |
1463 | if (intf->dev.driver) { | 1463 | if (intf->dev.driver) { |
1464 | driver = to_usb_driver(intf->dev.driver); | 1464 | driver = to_usb_driver(intf->dev.driver); |
1465 | dev_dbg(&intf->dev, "disconnect by usbfs\n"); | 1465 | dev_dbg(&intf->dev, "disconnect by usbfs\n"); |
1466 | usb_driver_release_interface(driver, intf); | 1466 | usb_driver_release_interface(driver, intf); |
1467 | } else | 1467 | } else |
1468 | retval = -ENODATA; | 1468 | retval = -ENODATA; |
1469 | break; | 1469 | break; |
1470 | 1470 | ||
1471 | /* let kernel drivers try to (re)bind to the interface */ | 1471 | /* let kernel drivers try to (re)bind to the interface */ |
1472 | case USBDEVFS_CONNECT: | 1472 | case USBDEVFS_CONNECT: |
1473 | if (!intf->dev.driver) | 1473 | if (!intf->dev.driver) |
1474 | retval = device_attach(&intf->dev); | 1474 | retval = device_attach(&intf->dev); |
1475 | else | 1475 | else |
1476 | retval = -EBUSY; | 1476 | retval = -EBUSY; |
1477 | break; | 1477 | break; |
1478 | 1478 | ||
1479 | /* talk directly to the interface's driver */ | 1479 | /* talk directly to the interface's driver */ |
1480 | default: | 1480 | default: |
1481 | if (intf->dev.driver) | 1481 | if (intf->dev.driver) |
1482 | driver = to_usb_driver(intf->dev.driver); | 1482 | driver = to_usb_driver(intf->dev.driver); |
1483 | if (driver == NULL || driver->ioctl == NULL) { | 1483 | if (driver == NULL || driver->ioctl == NULL) { |
1484 | retval = -ENOTTY; | 1484 | retval = -ENOTTY; |
1485 | } else { | 1485 | } else { |
1486 | retval = driver->ioctl(intf, ctl->ioctl_code, buf); | 1486 | retval = driver->ioctl(intf, ctl->ioctl_code, buf); |
1487 | if (retval == -ENOIOCTLCMD) | 1487 | if (retval == -ENOIOCTLCMD) |
1488 | retval = -ENOTTY; | 1488 | retval = -ENOTTY; |
1489 | } | 1489 | } |
1490 | } | 1490 | } |
1491 | 1491 | ||
1492 | /* cleanup and return */ | 1492 | /* cleanup and return */ |
1493 | if (retval >= 0 | 1493 | if (retval >= 0 |
1494 | && (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0 | 1494 | && (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0 |
1495 | && size > 0 | 1495 | && size > 0 |
1496 | && copy_to_user(ctl->data, buf, size) != 0) | 1496 | && copy_to_user(ctl->data, buf, size) != 0) |
1497 | retval = -EFAULT; | 1497 | retval = -EFAULT; |
1498 | 1498 | ||
1499 | kfree(buf); | 1499 | kfree(buf); |
1500 | return retval; | 1500 | return retval; |
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | static int proc_ioctl_default(struct dev_state *ps, void __user *arg) | 1503 | static int proc_ioctl_default(struct dev_state *ps, void __user *arg) |
1504 | { | 1504 | { |
1505 | struct usbdevfs_ioctl ctrl; | 1505 | struct usbdevfs_ioctl ctrl; |
1506 | 1506 | ||
1507 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 1507 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
1508 | return -EFAULT; | 1508 | return -EFAULT; |
1509 | return proc_ioctl(ps, &ctrl); | 1509 | return proc_ioctl(ps, &ctrl); |
1510 | } | 1510 | } |
1511 | 1511 | ||
1512 | #ifdef CONFIG_COMPAT | 1512 | #ifdef CONFIG_COMPAT |
1513 | static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) | 1513 | static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) |
1514 | { | 1514 | { |
1515 | struct usbdevfs_ioctl32 __user *uioc; | 1515 | struct usbdevfs_ioctl32 __user *uioc; |
1516 | struct usbdevfs_ioctl ctrl; | 1516 | struct usbdevfs_ioctl ctrl; |
1517 | u32 udata; | 1517 | u32 udata; |
1518 | 1518 | ||
1519 | uioc = compat_ptr((long)arg); | 1519 | uioc = compat_ptr((long)arg); |
1520 | if (get_user(ctrl.ifno, &uioc->ifno) || | 1520 | if (get_user(ctrl.ifno, &uioc->ifno) || |
1521 | get_user(ctrl.ioctl_code, &uioc->ioctl_code) || | 1521 | get_user(ctrl.ioctl_code, &uioc->ioctl_code) || |
1522 | __get_user(udata, &uioc->data)) | 1522 | __get_user(udata, &uioc->data)) |
1523 | return -EFAULT; | 1523 | return -EFAULT; |
1524 | ctrl.data = compat_ptr(udata); | 1524 | ctrl.data = compat_ptr(udata); |
1525 | 1525 | ||
1526 | return proc_ioctl(ps, &ctrl); | 1526 | return proc_ioctl(ps, &ctrl); |
1527 | } | 1527 | } |
1528 | #endif | 1528 | #endif |
1529 | 1529 | ||
1530 | /* | 1530 | /* |
1531 | * NOTE: All requests here that have interface numbers as parameters | 1531 | * NOTE: All requests here that have interface numbers as parameters |
1532 | * are assuming that somehow the configuration has been prevented from | 1532 | * are assuming that somehow the configuration has been prevented from |
1533 | * changing. But there's no mechanism to ensure that... | 1533 | * changing. But there's no mechanism to ensure that... |
1534 | */ | 1534 | */ |
1535 | static int usbdev_ioctl(struct inode *inode, struct file *file, | 1535 | static int usbdev_ioctl(struct inode *inode, struct file *file, |
1536 | unsigned int cmd, unsigned long arg) | 1536 | unsigned int cmd, unsigned long arg) |
1537 | { | 1537 | { |
1538 | struct dev_state *ps = file->private_data; | 1538 | struct dev_state *ps = file->private_data; |
1539 | struct usb_device *dev = ps->dev; | 1539 | struct usb_device *dev = ps->dev; |
1540 | void __user *p = (void __user *)arg; | 1540 | void __user *p = (void __user *)arg; |
1541 | int ret = -ENOTTY; | 1541 | int ret = -ENOTTY; |
1542 | 1542 | ||
1543 | if (!(file->f_mode & FMODE_WRITE)) | 1543 | if (!(file->f_mode & FMODE_WRITE)) |
1544 | return -EPERM; | 1544 | return -EPERM; |
1545 | usb_lock_device(dev); | 1545 | usb_lock_device(dev); |
1546 | if (!connected(ps)) { | 1546 | if (!connected(ps)) { |
1547 | usb_unlock_device(dev); | 1547 | usb_unlock_device(dev); |
1548 | return -ENODEV; | 1548 | return -ENODEV; |
1549 | } | 1549 | } |
1550 | 1550 | ||
1551 | switch (cmd) { | 1551 | switch (cmd) { |
1552 | case USBDEVFS_CONTROL: | 1552 | case USBDEVFS_CONTROL: |
1553 | snoop(&dev->dev, "%s: CONTROL\n", __func__); | 1553 | snoop(&dev->dev, "%s: CONTROL\n", __func__); |
1554 | ret = proc_control(ps, p); | 1554 | ret = proc_control(ps, p); |
1555 | if (ret >= 0) | 1555 | if (ret >= 0) |
1556 | inode->i_mtime = CURRENT_TIME; | 1556 | inode->i_mtime = CURRENT_TIME; |
1557 | break; | 1557 | break; |
1558 | 1558 | ||
1559 | case USBDEVFS_BULK: | 1559 | case USBDEVFS_BULK: |
1560 | snoop(&dev->dev, "%s: BULK\n", __func__); | 1560 | snoop(&dev->dev, "%s: BULK\n", __func__); |
1561 | ret = proc_bulk(ps, p); | 1561 | ret = proc_bulk(ps, p); |
1562 | if (ret >= 0) | 1562 | if (ret >= 0) |
1563 | inode->i_mtime = CURRENT_TIME; | 1563 | inode->i_mtime = CURRENT_TIME; |
1564 | break; | 1564 | break; |
1565 | 1565 | ||
1566 | case USBDEVFS_RESETEP: | 1566 | case USBDEVFS_RESETEP: |
1567 | snoop(&dev->dev, "%s: RESETEP\n", __func__); | 1567 | snoop(&dev->dev, "%s: RESETEP\n", __func__); |
1568 | ret = proc_resetep(ps, p); | 1568 | ret = proc_resetep(ps, p); |
1569 | if (ret >= 0) | 1569 | if (ret >= 0) |
1570 | inode->i_mtime = CURRENT_TIME; | 1570 | inode->i_mtime = CURRENT_TIME; |
1571 | break; | 1571 | break; |
1572 | 1572 | ||
1573 | case USBDEVFS_RESET: | 1573 | case USBDEVFS_RESET: |
1574 | snoop(&dev->dev, "%s: RESET\n", __func__); | 1574 | snoop(&dev->dev, "%s: RESET\n", __func__); |
1575 | ret = proc_resetdevice(ps); | 1575 | ret = proc_resetdevice(ps); |
1576 | break; | 1576 | break; |
1577 | 1577 | ||
1578 | case USBDEVFS_CLEAR_HALT: | 1578 | case USBDEVFS_CLEAR_HALT: |
1579 | snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__); | 1579 | snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__); |
1580 | ret = proc_clearhalt(ps, p); | 1580 | ret = proc_clearhalt(ps, p); |
1581 | if (ret >= 0) | 1581 | if (ret >= 0) |
1582 | inode->i_mtime = CURRENT_TIME; | 1582 | inode->i_mtime = CURRENT_TIME; |
1583 | break; | 1583 | break; |
1584 | 1584 | ||
1585 | case USBDEVFS_GETDRIVER: | 1585 | case USBDEVFS_GETDRIVER: |
1586 | snoop(&dev->dev, "%s: GETDRIVER\n", __func__); | 1586 | snoop(&dev->dev, "%s: GETDRIVER\n", __func__); |
1587 | ret = proc_getdriver(ps, p); | 1587 | ret = proc_getdriver(ps, p); |
1588 | break; | 1588 | break; |
1589 | 1589 | ||
1590 | case USBDEVFS_CONNECTINFO: | 1590 | case USBDEVFS_CONNECTINFO: |
1591 | snoop(&dev->dev, "%s: CONNECTINFO\n", __func__); | 1591 | snoop(&dev->dev, "%s: CONNECTINFO\n", __func__); |
1592 | ret = proc_connectinfo(ps, p); | 1592 | ret = proc_connectinfo(ps, p); |
1593 | break; | 1593 | break; |
1594 | 1594 | ||
1595 | case USBDEVFS_SETINTERFACE: | 1595 | case USBDEVFS_SETINTERFACE: |
1596 | snoop(&dev->dev, "%s: SETINTERFACE\n", __func__); | 1596 | snoop(&dev->dev, "%s: SETINTERFACE\n", __func__); |
1597 | ret = proc_setintf(ps, p); | 1597 | ret = proc_setintf(ps, p); |
1598 | break; | 1598 | break; |
1599 | 1599 | ||
1600 | case USBDEVFS_SETCONFIGURATION: | 1600 | case USBDEVFS_SETCONFIGURATION: |
1601 | snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__); | 1601 | snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__); |
1602 | ret = proc_setconfig(ps, p); | 1602 | ret = proc_setconfig(ps, p); |
1603 | break; | 1603 | break; |
1604 | 1604 | ||
1605 | case USBDEVFS_SUBMITURB: | 1605 | case USBDEVFS_SUBMITURB: |
1606 | snoop(&dev->dev, "%s: SUBMITURB\n", __func__); | 1606 | snoop(&dev->dev, "%s: SUBMITURB\n", __func__); |
1607 | ret = proc_submiturb(ps, p); | 1607 | ret = proc_submiturb(ps, p); |
1608 | if (ret >= 0) | 1608 | if (ret >= 0) |
1609 | inode->i_mtime = CURRENT_TIME; | 1609 | inode->i_mtime = CURRENT_TIME; |
1610 | break; | 1610 | break; |
1611 | 1611 | ||
1612 | #ifdef CONFIG_COMPAT | 1612 | #ifdef CONFIG_COMPAT |
1613 | 1613 | ||
1614 | case USBDEVFS_SUBMITURB32: | 1614 | case USBDEVFS_SUBMITURB32: |
1615 | snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); | 1615 | snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); |
1616 | ret = proc_submiturb_compat(ps, p); | 1616 | ret = proc_submiturb_compat(ps, p); |
1617 | if (ret >= 0) | 1617 | if (ret >= 0) |
1618 | inode->i_mtime = CURRENT_TIME; | 1618 | inode->i_mtime = CURRENT_TIME; |
1619 | break; | 1619 | break; |
1620 | 1620 | ||
1621 | case USBDEVFS_REAPURB32: | 1621 | case USBDEVFS_REAPURB32: |
1622 | snoop(&dev->dev, "%s: REAPURB32\n", __func__); | 1622 | snoop(&dev->dev, "%s: REAPURB32\n", __func__); |
1623 | ret = proc_reapurb_compat(ps, p); | 1623 | ret = proc_reapurb_compat(ps, p); |
1624 | break; | 1624 | break; |
1625 | 1625 | ||
1626 | case USBDEVFS_REAPURBNDELAY32: | 1626 | case USBDEVFS_REAPURBNDELAY32: |
1627 | snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__); | 1627 | snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__); |
1628 | ret = proc_reapurbnonblock_compat(ps, p); | 1628 | ret = proc_reapurbnonblock_compat(ps, p); |
1629 | break; | 1629 | break; |
1630 | 1630 | ||
1631 | case USBDEVFS_IOCTL32: | 1631 | case USBDEVFS_IOCTL32: |
1632 | snoop(&dev->dev, "%s: IOCTL\n", __func__); | 1632 | snoop(&dev->dev, "%s: IOCTL\n", __func__); |
1633 | ret = proc_ioctl_compat(ps, ptr_to_compat(p)); | 1633 | ret = proc_ioctl_compat(ps, ptr_to_compat(p)); |
1634 | break; | 1634 | break; |
1635 | #endif | 1635 | #endif |
1636 | 1636 | ||
1637 | case USBDEVFS_DISCARDURB: | 1637 | case USBDEVFS_DISCARDURB: |
1638 | snoop(&dev->dev, "%s: DISCARDURB\n", __func__); | 1638 | snoop(&dev->dev, "%s: DISCARDURB\n", __func__); |
1639 | ret = proc_unlinkurb(ps, p); | 1639 | ret = proc_unlinkurb(ps, p); |
1640 | break; | 1640 | break; |
1641 | 1641 | ||
1642 | case USBDEVFS_REAPURB: | 1642 | case USBDEVFS_REAPURB: |
1643 | snoop(&dev->dev, "%s: REAPURB\n", __func__); | 1643 | snoop(&dev->dev, "%s: REAPURB\n", __func__); |
1644 | ret = proc_reapurb(ps, p); | 1644 | ret = proc_reapurb(ps, p); |
1645 | break; | 1645 | break; |
1646 | 1646 | ||
1647 | case USBDEVFS_REAPURBNDELAY: | 1647 | case USBDEVFS_REAPURBNDELAY: |
1648 | snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__); | 1648 | snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__); |
1649 | ret = proc_reapurbnonblock(ps, p); | 1649 | ret = proc_reapurbnonblock(ps, p); |
1650 | break; | 1650 | break; |
1651 | 1651 | ||
1652 | case USBDEVFS_DISCSIGNAL: | 1652 | case USBDEVFS_DISCSIGNAL: |
1653 | snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__); | 1653 | snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__); |
1654 | ret = proc_disconnectsignal(ps, p); | 1654 | ret = proc_disconnectsignal(ps, p); |
1655 | break; | 1655 | break; |
1656 | 1656 | ||
1657 | case USBDEVFS_CLAIMINTERFACE: | 1657 | case USBDEVFS_CLAIMINTERFACE: |
1658 | snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__); | 1658 | snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__); |
1659 | ret = proc_claiminterface(ps, p); | 1659 | ret = proc_claiminterface(ps, p); |
1660 | break; | 1660 | break; |
1661 | 1661 | ||
1662 | case USBDEVFS_RELEASEINTERFACE: | 1662 | case USBDEVFS_RELEASEINTERFACE: |
1663 | snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__); | 1663 | snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__); |
1664 | ret = proc_releaseinterface(ps, p); | 1664 | ret = proc_releaseinterface(ps, p); |
1665 | break; | 1665 | break; |
1666 | 1666 | ||
1667 | case USBDEVFS_IOCTL: | 1667 | case USBDEVFS_IOCTL: |
1668 | snoop(&dev->dev, "%s: IOCTL\n", __func__); | 1668 | snoop(&dev->dev, "%s: IOCTL\n", __func__); |
1669 | ret = proc_ioctl_default(ps, p); | 1669 | ret = proc_ioctl_default(ps, p); |
1670 | break; | 1670 | break; |
1671 | } | 1671 | } |
1672 | usb_unlock_device(dev); | 1672 | usb_unlock_device(dev); |
1673 | if (ret >= 0) | 1673 | if (ret >= 0) |
1674 | inode->i_atime = CURRENT_TIME; | 1674 | inode->i_atime = CURRENT_TIME; |
1675 | return ret; | 1675 | return ret; |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | /* No kernel lock - fine */ | 1678 | /* No kernel lock - fine */ |
1679 | static unsigned int usbdev_poll(struct file *file, | 1679 | static unsigned int usbdev_poll(struct file *file, |
1680 | struct poll_table_struct *wait) | 1680 | struct poll_table_struct *wait) |
1681 | { | 1681 | { |
1682 | struct dev_state *ps = file->private_data; | 1682 | struct dev_state *ps = file->private_data; |
1683 | unsigned int mask = 0; | 1683 | unsigned int mask = 0; |
1684 | 1684 | ||
1685 | poll_wait(file, &ps->wait, wait); | 1685 | poll_wait(file, &ps->wait, wait); |
1686 | if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) | 1686 | if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) |
1687 | mask |= POLLOUT | POLLWRNORM; | 1687 | mask |= POLLOUT | POLLWRNORM; |
1688 | if (!connected(ps)) | 1688 | if (!connected(ps)) |
1689 | mask |= POLLERR | POLLHUP; | 1689 | mask |= POLLERR | POLLHUP; |
1690 | return mask; | 1690 | return mask; |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | const struct file_operations usbdev_file_operations = { | 1693 | const struct file_operations usbdev_file_operations = { |
1694 | .owner = THIS_MODULE, | 1694 | .owner = THIS_MODULE, |
1695 | .llseek = usbdev_lseek, | 1695 | .llseek = usbdev_lseek, |
1696 | .read = usbdev_read, | 1696 | .read = usbdev_read, |
1697 | .poll = usbdev_poll, | 1697 | .poll = usbdev_poll, |
1698 | .ioctl = usbdev_ioctl, | 1698 | .ioctl = usbdev_ioctl, |
1699 | .open = usbdev_open, | 1699 | .open = usbdev_open, |
1700 | .release = usbdev_release, | 1700 | .release = usbdev_release, |
1701 | }; | 1701 | }; |
1702 | 1702 | ||
1703 | void usb_fs_classdev_common_remove(struct usb_device *udev) | 1703 | void usb_fs_classdev_common_remove(struct usb_device *udev) |
1704 | { | 1704 | { |
1705 | struct dev_state *ps; | 1705 | struct dev_state *ps; |
1706 | struct siginfo sinfo; | 1706 | struct siginfo sinfo; |
1707 | 1707 | ||
1708 | while (!list_empty(&udev->filelist)) { | 1708 | while (!list_empty(&udev->filelist)) { |
1709 | ps = list_entry(udev->filelist.next, struct dev_state, list); | 1709 | ps = list_entry(udev->filelist.next, struct dev_state, list); |
1710 | destroy_all_async(ps); | 1710 | destroy_all_async(ps); |
1711 | wake_up_all(&ps->wait); | 1711 | wake_up_all(&ps->wait); |
1712 | list_del_init(&ps->list); | 1712 | list_del_init(&ps->list); |
1713 | if (ps->discsignr) { | 1713 | if (ps->discsignr) { |
1714 | sinfo.si_signo = ps->discsignr; | 1714 | sinfo.si_signo = ps->discsignr; |
1715 | sinfo.si_errno = EPIPE; | 1715 | sinfo.si_errno = EPIPE; |
1716 | sinfo.si_code = SI_ASYNCIO; | 1716 | sinfo.si_code = SI_ASYNCIO; |
1717 | sinfo.si_addr = ps->disccontext; | 1717 | sinfo.si_addr = ps->disccontext; |
1718 | kill_pid_info_as_uid(ps->discsignr, &sinfo, | 1718 | kill_pid_info_as_uid(ps->discsignr, &sinfo, |
1719 | ps->disc_pid, ps->disc_uid, | 1719 | ps->disc_pid, ps->disc_uid, |
1720 | ps->disc_euid, ps->secid); | 1720 | ps->disc_euid, ps->secid); |
1721 | } | 1721 | } |
1722 | } | 1722 | } |
1723 | } | 1723 | } |
1724 | 1724 | ||
1725 | #ifdef CONFIG_USB_DEVICE_CLASS | 1725 | #ifdef CONFIG_USB_DEVICE_CLASS |
1726 | static struct class *usb_classdev_class; | 1726 | static struct class *usb_classdev_class; |
1727 | 1727 | ||
1728 | static int usb_classdev_add(struct usb_device *dev) | 1728 | static int usb_classdev_add(struct usb_device *dev) |
1729 | { | 1729 | { |
1730 | struct device *cldev; | 1730 | struct device *cldev; |
1731 | 1731 | ||
1732 | cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, | 1732 | cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt, |
1733 | "usbdev%d.%d", dev->bus->busnum, | 1733 | "usbdev%d.%d", dev->bus->busnum, |
1734 | dev->devnum); | 1734 | dev->devnum); |
1735 | if (IS_ERR(cldev)) | 1735 | if (IS_ERR(cldev)) |
1736 | return PTR_ERR(cldev); | 1736 | return PTR_ERR(cldev); |
1737 | dev->usb_classdev = cldev; | 1737 | dev->usb_classdev = cldev; |
1738 | return 0; | 1738 | return 0; |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | static void usb_classdev_remove(struct usb_device *dev) | 1741 | static void usb_classdev_remove(struct usb_device *dev) |
1742 | { | 1742 | { |
1743 | if (dev->usb_classdev) | 1743 | if (dev->usb_classdev) |
1744 | device_unregister(dev->usb_classdev); | 1744 | device_unregister(dev->usb_classdev); |
1745 | usb_fs_classdev_common_remove(dev); | 1745 | usb_fs_classdev_common_remove(dev); |
1746 | } | 1746 | } |
1747 | 1747 | ||
1748 | static int usb_classdev_notify(struct notifier_block *self, | 1748 | static int usb_classdev_notify(struct notifier_block *self, |
1749 | unsigned long action, void *dev) | 1749 | unsigned long action, void *dev) |
1750 | { | 1750 | { |
1751 | switch (action) { | 1751 | switch (action) { |
1752 | case USB_DEVICE_ADD: | 1752 | case USB_DEVICE_ADD: |
1753 | if (usb_classdev_add(dev)) | 1753 | if (usb_classdev_add(dev)) |
1754 | return NOTIFY_BAD; | 1754 | return NOTIFY_BAD; |
1755 | break; | 1755 | break; |
1756 | case USB_DEVICE_REMOVE: | 1756 | case USB_DEVICE_REMOVE: |
1757 | usb_classdev_remove(dev); | 1757 | usb_classdev_remove(dev); |
1758 | break; | 1758 | break; |
1759 | } | 1759 | } |
1760 | return NOTIFY_OK; | 1760 | return NOTIFY_OK; |
1761 | } | 1761 | } |
1762 | 1762 | ||
1763 | static struct notifier_block usbdev_nb = { | 1763 | static struct notifier_block usbdev_nb = { |
1764 | .notifier_call = usb_classdev_notify, | 1764 | .notifier_call = usb_classdev_notify, |
1765 | }; | 1765 | }; |
1766 | #endif | 1766 | #endif |
1767 | 1767 | ||
1768 | static struct cdev usb_device_cdev; | 1768 | static struct cdev usb_device_cdev; |
1769 | 1769 | ||
1770 | int __init usb_devio_init(void) | 1770 | int __init usb_devio_init(void) |
1771 | { | 1771 | { |
1772 | int retval; | 1772 | int retval; |
1773 | 1773 | ||
1774 | retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX, | 1774 | retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX, |
1775 | "usb_device"); | 1775 | "usb_device"); |
1776 | if (retval) { | 1776 | if (retval) { |
1777 | err("unable to register minors for usb_device"); | 1777 | err("unable to register minors for usb_device"); |
1778 | goto out; | 1778 | goto out; |
1779 | } | 1779 | } |
1780 | cdev_init(&usb_device_cdev, &usbdev_file_operations); | 1780 | cdev_init(&usb_device_cdev, &usbdev_file_operations); |
1781 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); | 1781 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); |
1782 | if (retval) { | 1782 | if (retval) { |
1783 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); | 1783 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); |
1784 | goto error_cdev; | 1784 | goto error_cdev; |
1785 | } | 1785 | } |
1786 | #ifdef CONFIG_USB_DEVICE_CLASS | 1786 | #ifdef CONFIG_USB_DEVICE_CLASS |
1787 | usb_classdev_class = class_create(THIS_MODULE, "usb_device"); | 1787 | usb_classdev_class = class_create(THIS_MODULE, "usb_device"); |
1788 | if (IS_ERR(usb_classdev_class)) { | 1788 | if (IS_ERR(usb_classdev_class)) { |
1789 | err("unable to register usb_device class"); | 1789 | err("unable to register usb_device class"); |
1790 | retval = PTR_ERR(usb_classdev_class); | 1790 | retval = PTR_ERR(usb_classdev_class); |
1791 | cdev_del(&usb_device_cdev); | 1791 | cdev_del(&usb_device_cdev); |
1792 | usb_classdev_class = NULL; | 1792 | usb_classdev_class = NULL; |
1793 | goto out; | 1793 | goto out; |
1794 | } | 1794 | } |
1795 | /* devices of this class shadow the major:minor of their parent | ||
1796 | * device, so clear ->dev_kobj to prevent adding duplicate entries | ||
1797 | * to /sys/dev | ||
1798 | */ | ||
1799 | usb_classdev_class->dev_kobj = NULL; | ||
1795 | 1800 | ||
1796 | usb_register_notify(&usbdev_nb); | 1801 | usb_register_notify(&usbdev_nb); |
1797 | #endif | 1802 | #endif |
1798 | out: | 1803 | out: |
1799 | return retval; | 1804 | return retval; |
1800 | 1805 | ||
1801 | error_cdev: | 1806 | error_cdev: |
1802 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1807 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
1803 | goto out; | 1808 | goto out; |
1804 | } | 1809 | } |
1805 | 1810 | ||
1806 | void usb_devio_cleanup(void) | 1811 | void usb_devio_cleanup(void) |
1807 | { | 1812 | { |
1808 | #ifdef CONFIG_USB_DEVICE_CLASS | 1813 | #ifdef CONFIG_USB_DEVICE_CLASS |
1809 | usb_unregister_notify(&usbdev_nb); | 1814 | usb_unregister_notify(&usbdev_nb); |
1810 | class_destroy(usb_classdev_class); | 1815 | class_destroy(usb_classdev_class); |
1811 | #endif | 1816 | #endif |
1812 | cdev_del(&usb_device_cdev); | 1817 | cdev_del(&usb_device_cdev); |
1813 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1818 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
1814 | } | 1819 | } |
1815 | 1820 |
include/linux/device.h
1 | /* | 1 | /* |
2 | * device.h - generic, centralized driver model | 2 | * device.h - generic, centralized driver model |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org> | 4 | * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org> |
5 | * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de> | 5 | * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de> |
6 | * | 6 | * |
7 | * This file is released under the GPLv2 | 7 | * This file is released under the GPLv2 |
8 | * | 8 | * |
9 | * See Documentation/driver-model/ for more information. | 9 | * See Documentation/driver-model/ for more information. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef _DEVICE_H_ | 12 | #ifndef _DEVICE_H_ |
13 | #define _DEVICE_H_ | 13 | #define _DEVICE_H_ |
14 | 14 | ||
15 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
16 | #include <linux/kobject.h> | 16 | #include <linux/kobject.h> |
17 | #include <linux/klist.h> | 17 | #include <linux/klist.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/compiler.h> | 19 | #include <linux/compiler.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/semaphore.h> | 23 | #include <linux/semaphore.h> |
24 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
25 | #include <asm/device.h> | 25 | #include <asm/device.h> |
26 | 26 | ||
27 | #define DEVICE_NAME_SIZE 50 | 27 | #define DEVICE_NAME_SIZE 50 |
28 | /* DEVICE_NAME_HALF is really less than half to accommodate slop */ | 28 | /* DEVICE_NAME_HALF is really less than half to accommodate slop */ |
29 | #define DEVICE_NAME_HALF __stringify(20) | 29 | #define DEVICE_NAME_HALF __stringify(20) |
30 | #define DEVICE_ID_SIZE 32 | 30 | #define DEVICE_ID_SIZE 32 |
31 | #define BUS_ID_SIZE KOBJ_NAME_LEN | 31 | #define BUS_ID_SIZE KOBJ_NAME_LEN |
32 | 32 | ||
33 | 33 | ||
34 | struct device; | 34 | struct device; |
35 | struct device_driver; | 35 | struct device_driver; |
36 | struct driver_private; | 36 | struct driver_private; |
37 | struct class; | 37 | struct class; |
38 | struct bus_type; | 38 | struct bus_type; |
39 | struct bus_type_private; | 39 | struct bus_type_private; |
40 | 40 | ||
41 | struct bus_attribute { | 41 | struct bus_attribute { |
42 | struct attribute attr; | 42 | struct attribute attr; |
43 | ssize_t (*show)(struct bus_type *bus, char *buf); | 43 | ssize_t (*show)(struct bus_type *bus, char *buf); |
44 | ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count); | 44 | ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count); |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define BUS_ATTR(_name, _mode, _show, _store) \ | 47 | #define BUS_ATTR(_name, _mode, _show, _store) \ |
48 | struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) | 48 | struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) |
49 | 49 | ||
50 | extern int __must_check bus_create_file(struct bus_type *, | 50 | extern int __must_check bus_create_file(struct bus_type *, |
51 | struct bus_attribute *); | 51 | struct bus_attribute *); |
52 | extern void bus_remove_file(struct bus_type *, struct bus_attribute *); | 52 | extern void bus_remove_file(struct bus_type *, struct bus_attribute *); |
53 | 53 | ||
54 | struct bus_type { | 54 | struct bus_type { |
55 | const char *name; | 55 | const char *name; |
56 | struct bus_attribute *bus_attrs; | 56 | struct bus_attribute *bus_attrs; |
57 | struct device_attribute *dev_attrs; | 57 | struct device_attribute *dev_attrs; |
58 | struct driver_attribute *drv_attrs; | 58 | struct driver_attribute *drv_attrs; |
59 | 59 | ||
60 | int (*match)(struct device *dev, struct device_driver *drv); | 60 | int (*match)(struct device *dev, struct device_driver *drv); |
61 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); | 61 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); |
62 | int (*probe)(struct device *dev); | 62 | int (*probe)(struct device *dev); |
63 | int (*remove)(struct device *dev); | 63 | int (*remove)(struct device *dev); |
64 | void (*shutdown)(struct device *dev); | 64 | void (*shutdown)(struct device *dev); |
65 | 65 | ||
66 | int (*suspend)(struct device *dev, pm_message_t state); | 66 | int (*suspend)(struct device *dev, pm_message_t state); |
67 | int (*suspend_late)(struct device *dev, pm_message_t state); | 67 | int (*suspend_late)(struct device *dev, pm_message_t state); |
68 | int (*resume_early)(struct device *dev); | 68 | int (*resume_early)(struct device *dev); |
69 | int (*resume)(struct device *dev); | 69 | int (*resume)(struct device *dev); |
70 | 70 | ||
71 | struct pm_ext_ops *pm; | 71 | struct pm_ext_ops *pm; |
72 | 72 | ||
73 | struct bus_type_private *p; | 73 | struct bus_type_private *p; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | extern int __must_check bus_register(struct bus_type *bus); | 76 | extern int __must_check bus_register(struct bus_type *bus); |
77 | extern void bus_unregister(struct bus_type *bus); | 77 | extern void bus_unregister(struct bus_type *bus); |
78 | 78 | ||
79 | extern int __must_check bus_rescan_devices(struct bus_type *bus); | 79 | extern int __must_check bus_rescan_devices(struct bus_type *bus); |
80 | 80 | ||
81 | /* iterator helpers for buses */ | 81 | /* iterator helpers for buses */ |
82 | 82 | ||
83 | int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, | 83 | int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, |
84 | int (*fn)(struct device *dev, void *data)); | 84 | int (*fn)(struct device *dev, void *data)); |
85 | struct device *bus_find_device(struct bus_type *bus, struct device *start, | 85 | struct device *bus_find_device(struct bus_type *bus, struct device *start, |
86 | void *data, | 86 | void *data, |
87 | int (*match)(struct device *dev, void *data)); | 87 | int (*match)(struct device *dev, void *data)); |
88 | struct device *bus_find_device_by_name(struct bus_type *bus, | 88 | struct device *bus_find_device_by_name(struct bus_type *bus, |
89 | struct device *start, | 89 | struct device *start, |
90 | const char *name); | 90 | const char *name); |
91 | 91 | ||
92 | int __must_check bus_for_each_drv(struct bus_type *bus, | 92 | int __must_check bus_for_each_drv(struct bus_type *bus, |
93 | struct device_driver *start, void *data, | 93 | struct device_driver *start, void *data, |
94 | int (*fn)(struct device_driver *, void *)); | 94 | int (*fn)(struct device_driver *, void *)); |
95 | 95 | ||
96 | /* | 96 | /* |
97 | * Bus notifiers: Get notified of addition/removal of devices | 97 | * Bus notifiers: Get notified of addition/removal of devices |
98 | * and binding/unbinding of drivers to devices. | 98 | * and binding/unbinding of drivers to devices. |
99 | * In the long run, it should be a replacement for the platform | 99 | * In the long run, it should be a replacement for the platform |
100 | * notify hooks. | 100 | * notify hooks. |
101 | */ | 101 | */ |
102 | struct notifier_block; | 102 | struct notifier_block; |
103 | 103 | ||
104 | extern int bus_register_notifier(struct bus_type *bus, | 104 | extern int bus_register_notifier(struct bus_type *bus, |
105 | struct notifier_block *nb); | 105 | struct notifier_block *nb); |
106 | extern int bus_unregister_notifier(struct bus_type *bus, | 106 | extern int bus_unregister_notifier(struct bus_type *bus, |
107 | struct notifier_block *nb); | 107 | struct notifier_block *nb); |
108 | 108 | ||
109 | /* All 4 notifers below get called with the target struct device * | 109 | /* All 4 notifers below get called with the target struct device * |
110 | * as an argument. Note that those functions are likely to be called | 110 | * as an argument. Note that those functions are likely to be called |
111 | * with the device semaphore held in the core, so be careful. | 111 | * with the device semaphore held in the core, so be careful. |
112 | */ | 112 | */ |
113 | #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ | 113 | #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ |
114 | #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ | 114 | #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ |
115 | #define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ | 115 | #define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ |
116 | #define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be | 116 | #define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be |
117 | unbound */ | 117 | unbound */ |
118 | 118 | ||
119 | extern struct kset *bus_get_kset(struct bus_type *bus); | 119 | extern struct kset *bus_get_kset(struct bus_type *bus); |
120 | extern struct klist *bus_get_device_klist(struct bus_type *bus); | 120 | extern struct klist *bus_get_device_klist(struct bus_type *bus); |
121 | 121 | ||
122 | struct device_driver { | 122 | struct device_driver { |
123 | const char *name; | 123 | const char *name; |
124 | struct bus_type *bus; | 124 | struct bus_type *bus; |
125 | 125 | ||
126 | struct module *owner; | 126 | struct module *owner; |
127 | const char *mod_name; /* used for built-in modules */ | 127 | const char *mod_name; /* used for built-in modules */ |
128 | 128 | ||
129 | int (*probe) (struct device *dev); | 129 | int (*probe) (struct device *dev); |
130 | int (*remove) (struct device *dev); | 130 | int (*remove) (struct device *dev); |
131 | void (*shutdown) (struct device *dev); | 131 | void (*shutdown) (struct device *dev); |
132 | int (*suspend) (struct device *dev, pm_message_t state); | 132 | int (*suspend) (struct device *dev, pm_message_t state); |
133 | int (*resume) (struct device *dev); | 133 | int (*resume) (struct device *dev); |
134 | struct attribute_group **groups; | 134 | struct attribute_group **groups; |
135 | 135 | ||
136 | struct pm_ops *pm; | 136 | struct pm_ops *pm; |
137 | 137 | ||
138 | struct driver_private *p; | 138 | struct driver_private *p; |
139 | }; | 139 | }; |
140 | 140 | ||
141 | 141 | ||
142 | extern int __must_check driver_register(struct device_driver *drv); | 142 | extern int __must_check driver_register(struct device_driver *drv); |
143 | extern void driver_unregister(struct device_driver *drv); | 143 | extern void driver_unregister(struct device_driver *drv); |
144 | 144 | ||
145 | extern struct device_driver *get_driver(struct device_driver *drv); | 145 | extern struct device_driver *get_driver(struct device_driver *drv); |
146 | extern void put_driver(struct device_driver *drv); | 146 | extern void put_driver(struct device_driver *drv); |
147 | extern struct device_driver *driver_find(const char *name, | 147 | extern struct device_driver *driver_find(const char *name, |
148 | struct bus_type *bus); | 148 | struct bus_type *bus); |
149 | extern int driver_probe_done(void); | 149 | extern int driver_probe_done(void); |
150 | 150 | ||
151 | /* sysfs interface for exporting driver attributes */ | 151 | /* sysfs interface for exporting driver attributes */ |
152 | 152 | ||
153 | struct driver_attribute { | 153 | struct driver_attribute { |
154 | struct attribute attr; | 154 | struct attribute attr; |
155 | ssize_t (*show)(struct device_driver *driver, char *buf); | 155 | ssize_t (*show)(struct device_driver *driver, char *buf); |
156 | ssize_t (*store)(struct device_driver *driver, const char *buf, | 156 | ssize_t (*store)(struct device_driver *driver, const char *buf, |
157 | size_t count); | 157 | size_t count); |
158 | }; | 158 | }; |
159 | 159 | ||
160 | #define DRIVER_ATTR(_name, _mode, _show, _store) \ | 160 | #define DRIVER_ATTR(_name, _mode, _show, _store) \ |
161 | struct driver_attribute driver_attr_##_name = \ | 161 | struct driver_attribute driver_attr_##_name = \ |
162 | __ATTR(_name, _mode, _show, _store) | 162 | __ATTR(_name, _mode, _show, _store) |
163 | 163 | ||
164 | extern int __must_check driver_create_file(struct device_driver *driver, | 164 | extern int __must_check driver_create_file(struct device_driver *driver, |
165 | struct driver_attribute *attr); | 165 | struct driver_attribute *attr); |
166 | extern void driver_remove_file(struct device_driver *driver, | 166 | extern void driver_remove_file(struct device_driver *driver, |
167 | struct driver_attribute *attr); | 167 | struct driver_attribute *attr); |
168 | 168 | ||
169 | extern int __must_check driver_add_kobj(struct device_driver *drv, | 169 | extern int __must_check driver_add_kobj(struct device_driver *drv, |
170 | struct kobject *kobj, | 170 | struct kobject *kobj, |
171 | const char *fmt, ...); | 171 | const char *fmt, ...); |
172 | 172 | ||
173 | extern int __must_check driver_for_each_device(struct device_driver *drv, | 173 | extern int __must_check driver_for_each_device(struct device_driver *drv, |
174 | struct device *start, | 174 | struct device *start, |
175 | void *data, | 175 | void *data, |
176 | int (*fn)(struct device *dev, | 176 | int (*fn)(struct device *dev, |
177 | void *)); | 177 | void *)); |
178 | struct device *driver_find_device(struct device_driver *drv, | 178 | struct device *driver_find_device(struct device_driver *drv, |
179 | struct device *start, void *data, | 179 | struct device *start, void *data, |
180 | int (*match)(struct device *dev, void *data)); | 180 | int (*match)(struct device *dev, void *data)); |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * device classes | 183 | * device classes |
184 | */ | 184 | */ |
185 | struct class { | 185 | struct class { |
186 | const char *name; | 186 | const char *name; |
187 | struct module *owner; | 187 | struct module *owner; |
188 | 188 | ||
189 | struct kset subsys; | 189 | struct kset subsys; |
190 | struct list_head devices; | 190 | struct list_head devices; |
191 | struct list_head interfaces; | 191 | struct list_head interfaces; |
192 | struct kset class_dirs; | 192 | struct kset class_dirs; |
193 | struct semaphore sem; /* locks children, devices, interfaces */ | 193 | struct semaphore sem; /* locks children, devices, interfaces */ |
194 | struct class_attribute *class_attrs; | 194 | struct class_attribute *class_attrs; |
195 | struct device_attribute *dev_attrs; | 195 | struct device_attribute *dev_attrs; |
196 | struct kobject *dev_kobj; | ||
196 | 197 | ||
197 | int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); | 198 | int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); |
198 | 199 | ||
199 | void (*class_release)(struct class *class); | 200 | void (*class_release)(struct class *class); |
200 | void (*dev_release)(struct device *dev); | 201 | void (*dev_release)(struct device *dev); |
201 | 202 | ||
202 | int (*suspend)(struct device *dev, pm_message_t state); | 203 | int (*suspend)(struct device *dev, pm_message_t state); |
203 | int (*resume)(struct device *dev); | 204 | int (*resume)(struct device *dev); |
204 | 205 | ||
205 | struct pm_ops *pm; | 206 | struct pm_ops *pm; |
206 | }; | 207 | }; |
207 | 208 | ||
209 | extern struct kobject *sysfs_dev_block_kobj; | ||
210 | extern struct kobject *sysfs_dev_char_kobj; | ||
208 | extern int __must_check class_register(struct class *class); | 211 | extern int __must_check class_register(struct class *class); |
209 | extern void class_unregister(struct class *class); | 212 | extern void class_unregister(struct class *class); |
210 | extern int class_for_each_device(struct class *class, void *data, | 213 | extern int class_for_each_device(struct class *class, void *data, |
211 | int (*fn)(struct device *dev, void *data)); | 214 | int (*fn)(struct device *dev, void *data)); |
212 | extern struct device *class_find_device(struct class *class, void *data, | 215 | extern struct device *class_find_device(struct class *class, void *data, |
213 | int (*match)(struct device *, void *)); | 216 | int (*match)(struct device *, void *)); |
214 | 217 | ||
215 | struct class_attribute { | 218 | struct class_attribute { |
216 | struct attribute attr; | 219 | struct attribute attr; |
217 | ssize_t (*show)(struct class *class, char *buf); | 220 | ssize_t (*show)(struct class *class, char *buf); |
218 | ssize_t (*store)(struct class *class, const char *buf, size_t count); | 221 | ssize_t (*store)(struct class *class, const char *buf, size_t count); |
219 | }; | 222 | }; |
220 | 223 | ||
221 | #define CLASS_ATTR(_name, _mode, _show, _store) \ | 224 | #define CLASS_ATTR(_name, _mode, _show, _store) \ |
222 | struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store) | 225 | struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store) |
223 | 226 | ||
224 | extern int __must_check class_create_file(struct class *class, | 227 | extern int __must_check class_create_file(struct class *class, |
225 | const struct class_attribute *attr); | 228 | const struct class_attribute *attr); |
226 | extern void class_remove_file(struct class *class, | 229 | extern void class_remove_file(struct class *class, |
227 | const struct class_attribute *attr); | 230 | const struct class_attribute *attr); |
228 | 231 | ||
229 | struct class_interface { | 232 | struct class_interface { |
230 | struct list_head node; | 233 | struct list_head node; |
231 | struct class *class; | 234 | struct class *class; |
232 | 235 | ||
233 | int (*add_dev) (struct device *, struct class_interface *); | 236 | int (*add_dev) (struct device *, struct class_interface *); |
234 | void (*remove_dev) (struct device *, struct class_interface *); | 237 | void (*remove_dev) (struct device *, struct class_interface *); |
235 | }; | 238 | }; |
236 | 239 | ||
237 | extern int __must_check class_interface_register(struct class_interface *); | 240 | extern int __must_check class_interface_register(struct class_interface *); |
238 | extern void class_interface_unregister(struct class_interface *); | 241 | extern void class_interface_unregister(struct class_interface *); |
239 | 242 | ||
240 | extern struct class *class_create(struct module *owner, const char *name); | 243 | extern struct class *class_create(struct module *owner, const char *name); |
241 | extern void class_destroy(struct class *cls); | 244 | extern void class_destroy(struct class *cls); |
242 | 245 | ||
243 | /* | 246 | /* |
244 | * The type of device, "struct device" is embedded in. A class | 247 | * The type of device, "struct device" is embedded in. A class |
245 | * or bus can contain devices of different types | 248 | * or bus can contain devices of different types |
246 | * like "partitions" and "disks", "mouse" and "event". | 249 | * like "partitions" and "disks", "mouse" and "event". |
247 | * This identifies the device type and carries type-specific | 250 | * This identifies the device type and carries type-specific |
248 | * information, equivalent to the kobj_type of a kobject. | 251 | * information, equivalent to the kobj_type of a kobject. |
249 | * If "name" is specified, the uevent will contain it in | 252 | * If "name" is specified, the uevent will contain it in |
250 | * the DEVTYPE variable. | 253 | * the DEVTYPE variable. |
251 | */ | 254 | */ |
252 | struct device_type { | 255 | struct device_type { |
253 | const char *name; | 256 | const char *name; |
254 | struct attribute_group **groups; | 257 | struct attribute_group **groups; |
255 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); | 258 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); |
256 | void (*release)(struct device *dev); | 259 | void (*release)(struct device *dev); |
257 | 260 | ||
258 | int (*suspend)(struct device *dev, pm_message_t state); | 261 | int (*suspend)(struct device *dev, pm_message_t state); |
259 | int (*resume)(struct device *dev); | 262 | int (*resume)(struct device *dev); |
260 | 263 | ||
261 | struct pm_ops *pm; | 264 | struct pm_ops *pm; |
262 | }; | 265 | }; |
263 | 266 | ||
264 | /* interface for exporting device attributes */ | 267 | /* interface for exporting device attributes */ |
265 | struct device_attribute { | 268 | struct device_attribute { |
266 | struct attribute attr; | 269 | struct attribute attr; |
267 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, | 270 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, |
268 | char *buf); | 271 | char *buf); |
269 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 272 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, |
270 | const char *buf, size_t count); | 273 | const char *buf, size_t count); |
271 | }; | 274 | }; |
272 | 275 | ||
273 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ | 276 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ |
274 | struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) | 277 | struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) |
275 | 278 | ||
276 | extern int __must_check device_create_file(struct device *device, | 279 | extern int __must_check device_create_file(struct device *device, |
277 | struct device_attribute *entry); | 280 | struct device_attribute *entry); |
278 | extern void device_remove_file(struct device *dev, | 281 | extern void device_remove_file(struct device *dev, |
279 | struct device_attribute *attr); | 282 | struct device_attribute *attr); |
280 | extern int __must_check device_create_bin_file(struct device *dev, | 283 | extern int __must_check device_create_bin_file(struct device *dev, |
281 | struct bin_attribute *attr); | 284 | struct bin_attribute *attr); |
282 | extern void device_remove_bin_file(struct device *dev, | 285 | extern void device_remove_bin_file(struct device *dev, |
283 | struct bin_attribute *attr); | 286 | struct bin_attribute *attr); |
284 | extern int device_schedule_callback_owner(struct device *dev, | 287 | extern int device_schedule_callback_owner(struct device *dev, |
285 | void (*func)(struct device *dev), struct module *owner); | 288 | void (*func)(struct device *dev), struct module *owner); |
286 | 289 | ||
287 | /* This is a macro to avoid include problems with THIS_MODULE */ | 290 | /* This is a macro to avoid include problems with THIS_MODULE */ |
288 | #define device_schedule_callback(dev, func) \ | 291 | #define device_schedule_callback(dev, func) \ |
289 | device_schedule_callback_owner(dev, func, THIS_MODULE) | 292 | device_schedule_callback_owner(dev, func, THIS_MODULE) |
290 | 293 | ||
291 | /* device resource management */ | 294 | /* device resource management */ |
292 | typedef void (*dr_release_t)(struct device *dev, void *res); | 295 | typedef void (*dr_release_t)(struct device *dev, void *res); |
293 | typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); | 296 | typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); |
294 | 297 | ||
295 | #ifdef CONFIG_DEBUG_DEVRES | 298 | #ifdef CONFIG_DEBUG_DEVRES |
296 | extern void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp, | 299 | extern void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp, |
297 | const char *name); | 300 | const char *name); |
298 | #define devres_alloc(release, size, gfp) \ | 301 | #define devres_alloc(release, size, gfp) \ |
299 | __devres_alloc(release, size, gfp, #release) | 302 | __devres_alloc(release, size, gfp, #release) |
300 | #else | 303 | #else |
301 | extern void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp); | 304 | extern void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp); |
302 | #endif | 305 | #endif |
303 | extern void devres_free(void *res); | 306 | extern void devres_free(void *res); |
304 | extern void devres_add(struct device *dev, void *res); | 307 | extern void devres_add(struct device *dev, void *res); |
305 | extern void *devres_find(struct device *dev, dr_release_t release, | 308 | extern void *devres_find(struct device *dev, dr_release_t release, |
306 | dr_match_t match, void *match_data); | 309 | dr_match_t match, void *match_data); |
307 | extern void *devres_get(struct device *dev, void *new_res, | 310 | extern void *devres_get(struct device *dev, void *new_res, |
308 | dr_match_t match, void *match_data); | 311 | dr_match_t match, void *match_data); |
309 | extern void *devres_remove(struct device *dev, dr_release_t release, | 312 | extern void *devres_remove(struct device *dev, dr_release_t release, |
310 | dr_match_t match, void *match_data); | 313 | dr_match_t match, void *match_data); |
311 | extern int devres_destroy(struct device *dev, dr_release_t release, | 314 | extern int devres_destroy(struct device *dev, dr_release_t release, |
312 | dr_match_t match, void *match_data); | 315 | dr_match_t match, void *match_data); |
313 | 316 | ||
314 | /* devres group */ | 317 | /* devres group */ |
315 | extern void * __must_check devres_open_group(struct device *dev, void *id, | 318 | extern void * __must_check devres_open_group(struct device *dev, void *id, |
316 | gfp_t gfp); | 319 | gfp_t gfp); |
317 | extern void devres_close_group(struct device *dev, void *id); | 320 | extern void devres_close_group(struct device *dev, void *id); |
318 | extern void devres_remove_group(struct device *dev, void *id); | 321 | extern void devres_remove_group(struct device *dev, void *id); |
319 | extern int devres_release_group(struct device *dev, void *id); | 322 | extern int devres_release_group(struct device *dev, void *id); |
320 | 323 | ||
321 | /* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */ | 324 | /* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */ |
322 | extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); | 325 | extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); |
323 | extern void devm_kfree(struct device *dev, void *p); | 326 | extern void devm_kfree(struct device *dev, void *p); |
324 | 327 | ||
325 | struct device_dma_parameters { | 328 | struct device_dma_parameters { |
326 | /* | 329 | /* |
327 | * a low level driver may set these to teach IOMMU code about | 330 | * a low level driver may set these to teach IOMMU code about |
328 | * sg limitations. | 331 | * sg limitations. |
329 | */ | 332 | */ |
330 | unsigned int max_segment_size; | 333 | unsigned int max_segment_size; |
331 | unsigned long segment_boundary_mask; | 334 | unsigned long segment_boundary_mask; |
332 | }; | 335 | }; |
333 | 336 | ||
334 | struct device { | 337 | struct device { |
335 | struct klist klist_children; | 338 | struct klist klist_children; |
336 | struct klist_node knode_parent; /* node in sibling list */ | 339 | struct klist_node knode_parent; /* node in sibling list */ |
337 | struct klist_node knode_driver; | 340 | struct klist_node knode_driver; |
338 | struct klist_node knode_bus; | 341 | struct klist_node knode_bus; |
339 | struct device *parent; | 342 | struct device *parent; |
340 | 343 | ||
341 | struct kobject kobj; | 344 | struct kobject kobj; |
342 | char bus_id[BUS_ID_SIZE]; /* position on parent bus */ | 345 | char bus_id[BUS_ID_SIZE]; /* position on parent bus */ |
343 | struct device_type *type; | 346 | struct device_type *type; |
344 | unsigned uevent_suppress:1; | 347 | unsigned uevent_suppress:1; |
345 | 348 | ||
346 | struct semaphore sem; /* semaphore to synchronize calls to | 349 | struct semaphore sem; /* semaphore to synchronize calls to |
347 | * its driver. | 350 | * its driver. |
348 | */ | 351 | */ |
349 | 352 | ||
350 | struct bus_type *bus; /* type of bus device is on */ | 353 | struct bus_type *bus; /* type of bus device is on */ |
351 | struct device_driver *driver; /* which driver has allocated this | 354 | struct device_driver *driver; /* which driver has allocated this |
352 | device */ | 355 | device */ |
353 | void *driver_data; /* data private to the driver */ | 356 | void *driver_data; /* data private to the driver */ |
354 | void *platform_data; /* Platform specific data, device | 357 | void *platform_data; /* Platform specific data, device |
355 | core doesn't touch it */ | 358 | core doesn't touch it */ |
356 | struct dev_pm_info power; | 359 | struct dev_pm_info power; |
357 | 360 | ||
358 | #ifdef CONFIG_NUMA | 361 | #ifdef CONFIG_NUMA |
359 | int numa_node; /* NUMA node this device is close to */ | 362 | int numa_node; /* NUMA node this device is close to */ |
360 | #endif | 363 | #endif |
361 | u64 *dma_mask; /* dma mask (if dma'able device) */ | 364 | u64 *dma_mask; /* dma mask (if dma'able device) */ |
362 | u64 coherent_dma_mask;/* Like dma_mask, but for | 365 | u64 coherent_dma_mask;/* Like dma_mask, but for |
363 | alloc_coherent mappings as | 366 | alloc_coherent mappings as |
364 | not all hardware supports | 367 | not all hardware supports |
365 | 64 bit addresses for consistent | 368 | 64 bit addresses for consistent |
366 | allocations such descriptors. */ | 369 | allocations such descriptors. */ |
367 | 370 | ||
368 | struct device_dma_parameters *dma_parms; | 371 | struct device_dma_parameters *dma_parms; |
369 | 372 | ||
370 | struct list_head dma_pools; /* dma pools (if dma'ble) */ | 373 | struct list_head dma_pools; /* dma pools (if dma'ble) */ |
371 | 374 | ||
372 | struct dma_coherent_mem *dma_mem; /* internal for coherent mem | 375 | struct dma_coherent_mem *dma_mem; /* internal for coherent mem |
373 | override */ | 376 | override */ |
374 | /* arch specific additions */ | 377 | /* arch specific additions */ |
375 | struct dev_archdata archdata; | 378 | struct dev_archdata archdata; |
376 | 379 | ||
377 | spinlock_t devres_lock; | 380 | spinlock_t devres_lock; |
378 | struct list_head devres_head; | 381 | struct list_head devres_head; |
379 | 382 | ||
380 | struct list_head node; | 383 | struct list_head node; |
381 | struct class *class; | 384 | struct class *class; |
382 | dev_t devt; /* dev_t, creates the sysfs "dev" */ | 385 | dev_t devt; /* dev_t, creates the sysfs "dev" */ |
383 | struct attribute_group **groups; /* optional groups */ | 386 | struct attribute_group **groups; /* optional groups */ |
384 | 387 | ||
385 | void (*release)(struct device *dev); | 388 | void (*release)(struct device *dev); |
386 | }; | 389 | }; |
387 | 390 | ||
388 | /* Get the wakeup routines, which depend on struct device */ | 391 | /* Get the wakeup routines, which depend on struct device */ |
389 | #include <linux/pm_wakeup.h> | 392 | #include <linux/pm_wakeup.h> |
390 | 393 | ||
391 | static inline const char *dev_name(struct device *dev) | 394 | static inline const char *dev_name(struct device *dev) |
392 | { | 395 | { |
393 | /* will be changed into kobject_name(&dev->kobj) in the near future */ | 396 | /* will be changed into kobject_name(&dev->kobj) in the near future */ |
394 | return dev->bus_id; | 397 | return dev->bus_id; |
395 | } | 398 | } |
396 | 399 | ||
397 | extern int dev_set_name(struct device *dev, const char *name, ...) | 400 | extern int dev_set_name(struct device *dev, const char *name, ...) |
398 | __attribute__((format(printf, 2, 3))); | 401 | __attribute__((format(printf, 2, 3))); |
399 | 402 | ||
400 | #ifdef CONFIG_NUMA | 403 | #ifdef CONFIG_NUMA |
401 | static inline int dev_to_node(struct device *dev) | 404 | static inline int dev_to_node(struct device *dev) |
402 | { | 405 | { |
403 | return dev->numa_node; | 406 | return dev->numa_node; |
404 | } | 407 | } |
405 | static inline void set_dev_node(struct device *dev, int node) | 408 | static inline void set_dev_node(struct device *dev, int node) |
406 | { | 409 | { |
407 | dev->numa_node = node; | 410 | dev->numa_node = node; |
408 | } | 411 | } |
409 | #else | 412 | #else |
410 | static inline int dev_to_node(struct device *dev) | 413 | static inline int dev_to_node(struct device *dev) |
411 | { | 414 | { |
412 | return -1; | 415 | return -1; |
413 | } | 416 | } |
414 | static inline void set_dev_node(struct device *dev, int node) | 417 | static inline void set_dev_node(struct device *dev, int node) |
415 | { | 418 | { |
416 | } | 419 | } |
417 | #endif | 420 | #endif |
418 | 421 | ||
419 | static inline void *dev_get_drvdata(struct device *dev) | 422 | static inline void *dev_get_drvdata(struct device *dev) |
420 | { | 423 | { |
421 | return dev->driver_data; | 424 | return dev->driver_data; |
422 | } | 425 | } |
423 | 426 | ||
424 | static inline void dev_set_drvdata(struct device *dev, void *data) | 427 | static inline void dev_set_drvdata(struct device *dev, void *data) |
425 | { | 428 | { |
426 | dev->driver_data = data; | 429 | dev->driver_data = data; |
427 | } | 430 | } |
428 | 431 | ||
429 | static inline int device_is_registered(struct device *dev) | 432 | static inline int device_is_registered(struct device *dev) |
430 | { | 433 | { |
431 | return dev->kobj.state_in_sysfs; | 434 | return dev->kobj.state_in_sysfs; |
432 | } | 435 | } |
433 | 436 | ||
434 | void driver_init(void); | 437 | void driver_init(void); |
435 | 438 | ||
436 | /* | 439 | /* |
437 | * High level routines for use by the bus drivers | 440 | * High level routines for use by the bus drivers |
438 | */ | 441 | */ |
439 | extern int __must_check device_register(struct device *dev); | 442 | extern int __must_check device_register(struct device *dev); |
440 | extern void device_unregister(struct device *dev); | 443 | extern void device_unregister(struct device *dev); |
441 | extern void device_initialize(struct device *dev); | 444 | extern void device_initialize(struct device *dev); |
442 | extern int __must_check device_add(struct device *dev); | 445 | extern int __must_check device_add(struct device *dev); |
443 | extern void device_del(struct device *dev); | 446 | extern void device_del(struct device *dev); |
444 | extern int device_for_each_child(struct device *dev, void *data, | 447 | extern int device_for_each_child(struct device *dev, void *data, |
445 | int (*fn)(struct device *dev, void *data)); | 448 | int (*fn)(struct device *dev, void *data)); |
446 | extern struct device *device_find_child(struct device *dev, void *data, | 449 | extern struct device *device_find_child(struct device *dev, void *data, |
447 | int (*match)(struct device *dev, void *data)); | 450 | int (*match)(struct device *dev, void *data)); |
448 | extern int device_rename(struct device *dev, char *new_name); | 451 | extern int device_rename(struct device *dev, char *new_name); |
449 | extern int device_move(struct device *dev, struct device *new_parent); | 452 | extern int device_move(struct device *dev, struct device *new_parent); |
450 | 453 | ||
451 | /* | 454 | /* |
452 | * Manual binding of a device to driver. See drivers/base/bus.c | 455 | * Manual binding of a device to driver. See drivers/base/bus.c |
453 | * for information on use. | 456 | * for information on use. |
454 | */ | 457 | */ |
455 | extern int __must_check device_bind_driver(struct device *dev); | 458 | extern int __must_check device_bind_driver(struct device *dev); |
456 | extern void device_release_driver(struct device *dev); | 459 | extern void device_release_driver(struct device *dev); |
457 | extern int __must_check device_attach(struct device *dev); | 460 | extern int __must_check device_attach(struct device *dev); |
458 | extern int __must_check driver_attach(struct device_driver *drv); | 461 | extern int __must_check driver_attach(struct device_driver *drv); |
459 | extern int __must_check device_reprobe(struct device *dev); | 462 | extern int __must_check device_reprobe(struct device *dev); |
460 | 463 | ||
461 | /* | 464 | /* |
462 | * Easy functions for dynamically creating devices on the fly | 465 | * Easy functions for dynamically creating devices on the fly |
463 | */ | 466 | */ |
464 | extern struct device *device_create_vargs(struct class *cls, | 467 | extern struct device *device_create_vargs(struct class *cls, |
465 | struct device *parent, | 468 | struct device *parent, |
466 | dev_t devt, | 469 | dev_t devt, |
467 | void *drvdata, | 470 | void *drvdata, |
468 | const char *fmt, | 471 | const char *fmt, |
469 | va_list vargs); | 472 | va_list vargs); |
470 | extern struct device *device_create(struct class *cls, struct device *parent, | 473 | extern struct device *device_create(struct class *cls, struct device *parent, |
471 | dev_t devt, const char *fmt, ...) | 474 | dev_t devt, const char *fmt, ...) |
472 | __attribute__((format(printf, 4, 5))); | 475 | __attribute__((format(printf, 4, 5))); |
473 | extern struct device *device_create_drvdata(struct class *cls, | 476 | extern struct device *device_create_drvdata(struct class *cls, |
474 | struct device *parent, | 477 | struct device *parent, |
475 | dev_t devt, | 478 | dev_t devt, |
476 | void *drvdata, | 479 | void *drvdata, |
477 | const char *fmt, ...) | 480 | const char *fmt, ...) |
478 | __attribute__((format(printf, 5, 6))); | 481 | __attribute__((format(printf, 5, 6))); |
479 | extern void device_destroy(struct class *cls, dev_t devt); | 482 | extern void device_destroy(struct class *cls, dev_t devt); |
480 | 483 | ||
481 | /* | 484 | /* |
482 | * Platform "fixup" functions - allow the platform to have their say | 485 | * Platform "fixup" functions - allow the platform to have their say |
483 | * about devices and actions that the general device layer doesn't | 486 | * about devices and actions that the general device layer doesn't |
484 | * know about. | 487 | * know about. |
485 | */ | 488 | */ |
486 | /* Notify platform of device discovery */ | 489 | /* Notify platform of device discovery */ |
487 | extern int (*platform_notify)(struct device *dev); | 490 | extern int (*platform_notify)(struct device *dev); |
488 | 491 | ||
489 | extern int (*platform_notify_remove)(struct device *dev); | 492 | extern int (*platform_notify_remove)(struct device *dev); |
490 | 493 | ||
491 | 494 | ||
492 | /** | 495 | /** |
493 | * get_device - atomically increment the reference count for the device. | 496 | * get_device - atomically increment the reference count for the device. |
494 | * | 497 | * |
495 | */ | 498 | */ |
496 | extern struct device *get_device(struct device *dev); | 499 | extern struct device *get_device(struct device *dev); |
497 | extern void put_device(struct device *dev); | 500 | extern void put_device(struct device *dev); |
498 | 501 | ||
499 | 502 | ||
500 | /* drivers/base/power/shutdown.c */ | 503 | /* drivers/base/power/shutdown.c */ |
501 | extern void device_shutdown(void); | 504 | extern void device_shutdown(void); |
502 | 505 | ||
503 | /* drivers/base/sys.c */ | 506 | /* drivers/base/sys.c */ |
504 | extern void sysdev_shutdown(void); | 507 | extern void sysdev_shutdown(void); |
505 | 508 | ||
506 | /* debugging and troubleshooting/diagnostic helpers. */ | 509 | /* debugging and troubleshooting/diagnostic helpers. */ |
507 | extern const char *dev_driver_string(struct device *dev); | 510 | extern const char *dev_driver_string(struct device *dev); |
508 | #define dev_printk(level, dev, format, arg...) \ | 511 | #define dev_printk(level, dev, format, arg...) \ |
509 | printk(level "%s %s: " format , dev_driver_string(dev) , \ | 512 | printk(level "%s %s: " format , dev_driver_string(dev) , \ |
510 | dev_name(dev) , ## arg) | 513 | dev_name(dev) , ## arg) |
511 | 514 | ||
512 | #define dev_emerg(dev, format, arg...) \ | 515 | #define dev_emerg(dev, format, arg...) \ |
513 | dev_printk(KERN_EMERG , dev , format , ## arg) | 516 | dev_printk(KERN_EMERG , dev , format , ## arg) |
514 | #define dev_alert(dev, format, arg...) \ | 517 | #define dev_alert(dev, format, arg...) \ |
515 | dev_printk(KERN_ALERT , dev , format , ## arg) | 518 | dev_printk(KERN_ALERT , dev , format , ## arg) |
516 | #define dev_crit(dev, format, arg...) \ | 519 | #define dev_crit(dev, format, arg...) \ |
517 | dev_printk(KERN_CRIT , dev , format , ## arg) | 520 | dev_printk(KERN_CRIT , dev , format , ## arg) |
518 | #define dev_err(dev, format, arg...) \ | 521 | #define dev_err(dev, format, arg...) \ |
519 | dev_printk(KERN_ERR , dev , format , ## arg) | 522 | dev_printk(KERN_ERR , dev , format , ## arg) |
520 | #define dev_warn(dev, format, arg...) \ | 523 | #define dev_warn(dev, format, arg...) \ |
521 | dev_printk(KERN_WARNING , dev , format , ## arg) | 524 | dev_printk(KERN_WARNING , dev , format , ## arg) |
522 | #define dev_notice(dev, format, arg...) \ | 525 | #define dev_notice(dev, format, arg...) \ |
523 | dev_printk(KERN_NOTICE , dev , format , ## arg) | 526 | dev_printk(KERN_NOTICE , dev , format , ## arg) |
524 | #define dev_info(dev, format, arg...) \ | 527 | #define dev_info(dev, format, arg...) \ |
525 | dev_printk(KERN_INFO , dev , format , ## arg) | 528 | dev_printk(KERN_INFO , dev , format , ## arg) |
526 | 529 | ||
527 | #ifdef DEBUG | 530 | #ifdef DEBUG |
528 | #define dev_dbg(dev, format, arg...) \ | 531 | #define dev_dbg(dev, format, arg...) \ |
529 | dev_printk(KERN_DEBUG , dev , format , ## arg) | 532 | dev_printk(KERN_DEBUG , dev , format , ## arg) |
530 | #else | 533 | #else |
531 | #define dev_dbg(dev, format, arg...) \ | 534 | #define dev_dbg(dev, format, arg...) \ |
532 | ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) | 535 | ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) |
533 | #endif | 536 | #endif |
534 | 537 | ||
535 | #ifdef VERBOSE_DEBUG | 538 | #ifdef VERBOSE_DEBUG |
536 | #define dev_vdbg dev_dbg | 539 | #define dev_vdbg dev_dbg |
537 | #else | 540 | #else |
538 | 541 | ||
539 | #define dev_vdbg(dev, format, arg...) \ | 542 | #define dev_vdbg(dev, format, arg...) \ |
540 | ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) | 543 | ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) |
541 | #endif | 544 | #endif |
542 | 545 | ||
543 | /* Create alias, so I can be autoloaded. */ | 546 | /* Create alias, so I can be autoloaded. */ |
544 | #define MODULE_ALIAS_CHARDEV(major,minor) \ | 547 | #define MODULE_ALIAS_CHARDEV(major,minor) \ |
545 | MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) | 548 | MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) |
546 | #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ | 549 | #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ |
547 | MODULE_ALIAS("char-major-" __stringify(major) "-*") | 550 | MODULE_ALIAS("char-major-" __stringify(major) "-*") |
548 | #endif /* _DEVICE_H_ */ | 551 | #endif /* _DEVICE_H_ */ |
549 | 552 |