diff options
Diffstat (limited to 'drivers/message/i2o/device.c')
-rw-r--r-- | drivers/message/i2o/device.c | 272 |
1 files changed, 108 insertions, 164 deletions
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 21f16ba3ac38..d9879965eb50 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
@@ -45,10 +45,10 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, | |||
45 | writel(type, &msg->body[0]); | 45 | writel(type, &msg->body[0]); |
46 | 46 | ||
47 | return i2o_msg_post_wait(dev->iop, m, 60); | 47 | return i2o_msg_post_wait(dev->iop, m, 60); |
48 | }; | 48 | } |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * i2o_device_claim - claim a device for use by an OSM | 51 | * i2o_device_claim - claim a device for use by an OSM |
52 | * @dev: I2O device to claim | 52 | * @dev: I2O device to claim |
53 | * @drv: I2O driver which wants to claim the device | 53 | * @drv: I2O driver which wants to claim the device |
54 | * | 54 | * |
@@ -73,7 +73,7 @@ int i2o_device_claim(struct i2o_device *dev) | |||
73 | up(&dev->lock); | 73 | up(&dev->lock); |
74 | 74 | ||
75 | return rc; | 75 | return rc; |
76 | }; | 76 | } |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * i2o_device_claim_release - release a device that the OSM is using | 79 | * i2o_device_claim_release - release a device that the OSM is using |
@@ -119,7 +119,8 @@ int i2o_device_claim_release(struct i2o_device *dev) | |||
119 | up(&dev->lock); | 119 | up(&dev->lock); |
120 | 120 | ||
121 | return rc; | 121 | return rc; |
122 | }; | 122 | } |
123 | |||
123 | 124 | ||
124 | /** | 125 | /** |
125 | * i2o_device_release - release the memory for a I2O device | 126 | * i2o_device_release - release the memory for a I2O device |
@@ -135,39 +136,47 @@ static void i2o_device_release(struct device *dev) | |||
135 | pr_debug("i2o: device %s released\n", dev->bus_id); | 136 | pr_debug("i2o: device %s released\n", dev->bus_id); |
136 | 137 | ||
137 | kfree(i2o_dev); | 138 | kfree(i2o_dev); |
138 | }; | 139 | } |
140 | |||
139 | 141 | ||
140 | /** | 142 | /** |
141 | * i2o_device_class_release - Remove I2O device attributes | 143 | * i2o_device_class_show_class_id - Displays class id of I2O device |
142 | * @cd: I2O class device which is added to the I2O device class | 144 | * @cd: class device of which the class id should be displayed |
145 | * @buf: buffer into which the class id should be printed | ||
143 | * | 146 | * |
144 | * Removes attributes from the I2O device again. Also search each device | 147 | * Returns the number of bytes which are printed into the buffer. |
145 | * on the controller for I2O devices which refert to this device as parent | ||
146 | * or user and remove this links also. | ||
147 | */ | 148 | */ |
148 | static void i2o_device_class_release(struct class_device *cd) | 149 | static ssize_t i2o_device_show_class_id(struct device *dev, |
150 | struct device_attribute *attr, | ||
151 | char *buf) | ||
149 | { | 152 | { |
150 | struct i2o_device *i2o_dev, *tmp; | 153 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
151 | struct i2o_controller *c; | ||
152 | 154 | ||
153 | i2o_dev = to_i2o_device(cd->dev); | 155 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); |
154 | c = i2o_dev->iop; | 156 | return strlen(buf) + 1; |
157 | } | ||
155 | 158 | ||
156 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | 159 | /** |
157 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | 160 | * i2o_device_class_show_tid - Displays TID of I2O device |
161 | * @cd: class device of which the TID should be displayed | ||
162 | * @buf: buffer into which the class id should be printed | ||
163 | * | ||
164 | * Returns the number of bytes which are printed into the buffer. | ||
165 | */ | ||
166 | static ssize_t i2o_device_show_tid(struct device *dev, | ||
167 | struct device_attribute *attr, | ||
168 | char *buf) | ||
169 | { | ||
170 | struct i2o_device *i2o_dev = to_i2o_device(dev); | ||
158 | 171 | ||
159 | list_for_each_entry(tmp, &c->devices, list) { | 172 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); |
160 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 173 | return strlen(buf) + 1; |
161 | sysfs_remove_link(&tmp->device.kobj, "parent"); | 174 | } |
162 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
163 | sysfs_remove_link(&tmp->device.kobj, "user"); | ||
164 | } | ||
165 | }; | ||
166 | 175 | ||
167 | /* I2O device class */ | 176 | struct device_attribute i2o_device_attrs[] = { |
168 | static struct class i2o_device_class = { | 177 | __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), |
169 | .name = "i2o_device", | 178 | __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), |
170 | .release = i2o_device_class_release | 179 | __ATTR_NULL |
171 | }; | 180 | }; |
172 | 181 | ||
173 | /** | 182 | /** |
@@ -193,11 +202,69 @@ static struct i2o_device *i2o_device_alloc(void) | |||
193 | 202 | ||
194 | dev->device.bus = &i2o_bus_type; | 203 | dev->device.bus = &i2o_bus_type; |
195 | dev->device.release = &i2o_device_release; | 204 | dev->device.release = &i2o_device_release; |
196 | dev->classdev.class = &i2o_device_class; | ||
197 | dev->classdev.dev = &dev->device; | ||
198 | 205 | ||
199 | return dev; | 206 | return dev; |
200 | }; | 207 | } |
208 | |||
209 | /** | ||
210 | * i2o_setup_sysfs_links - Adds attributes to the I2O device | ||
211 | * @cd: I2O class device which is added to the I2O device class | ||
212 | * | ||
213 | * This function get called when a I2O device is added to the class. It | ||
214 | * creates the attributes for each device and creates user/parent symlink | ||
215 | * if necessary. | ||
216 | * | ||
217 | * Returns 0 on success or negative error code on failure. | ||
218 | */ | ||
219 | static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev) | ||
220 | { | ||
221 | struct i2o_controller *c = i2o_dev->iop; | ||
222 | struct i2o_device *tmp; | ||
223 | |||
224 | /* create user entries for this device */ | ||
225 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | ||
226 | if (tmp && tmp != i2o_dev) | ||
227 | sysfs_create_link(&i2o_dev->device.kobj, | ||
228 | &tmp->device.kobj, "user"); | ||
229 | |||
230 | /* create user entries refering to this device */ | ||
231 | list_for_each_entry(tmp, &c->devices, list) | ||
232 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid && | ||
233 | tmp != i2o_dev) | ||
234 | sysfs_create_link(&tmp->device.kobj, | ||
235 | &i2o_dev->device.kobj, "user"); | ||
236 | |||
237 | /* create parent entries for this device */ | ||
238 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | ||
239 | if (tmp && tmp != i2o_dev) | ||
240 | sysfs_create_link(&i2o_dev->device.kobj, | ||
241 | &tmp->device.kobj, "parent"); | ||
242 | |||
243 | /* create parent entries refering to this device */ | ||
244 | list_for_each_entry(tmp, &c->devices, list) | ||
245 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid && | ||
246 | tmp != i2o_dev) | ||
247 | sysfs_create_link(&tmp->device.kobj, | ||
248 | &i2o_dev->device.kobj, "parent"); | ||
249 | } | ||
250 | |||
251 | static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) | ||
252 | { | ||
253 | struct i2o_controller *c = i2o_dev->iop; | ||
254 | struct i2o_device *tmp; | ||
255 | |||
256 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | ||
257 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | ||
258 | |||
259 | list_for_each_entry(tmp, &c->devices, list) { | ||
260 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
261 | sysfs_remove_link(&tmp->device.kobj, "parent"); | ||
262 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
263 | sysfs_remove_link(&tmp->device.kobj, "user"); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | |||
201 | 268 | ||
202 | /** | 269 | /** |
203 | * i2o_device_add - allocate a new I2O device and add it to the IOP | 270 | * i2o_device_add - allocate a new I2O device and add it to the IOP |
@@ -222,28 +289,25 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
222 | } | 289 | } |
223 | 290 | ||
224 | dev->lct_data = *entry; | 291 | dev->lct_data = *entry; |
292 | dev->iop = c; | ||
225 | 293 | ||
226 | snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 294 | snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, |
227 | dev->lct_data.tid); | 295 | dev->lct_data.tid); |
228 | 296 | ||
229 | snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit, | ||
230 | dev->lct_data.tid); | ||
231 | |||
232 | dev->iop = c; | ||
233 | dev->device.parent = &c->device; | 297 | dev->device.parent = &c->device; |
234 | 298 | ||
235 | device_register(&dev->device); | 299 | device_register(&dev->device); |
236 | 300 | ||
237 | list_add_tail(&dev->list, &c->devices); | 301 | list_add_tail(&dev->list, &c->devices); |
238 | 302 | ||
239 | class_device_register(&dev->classdev); | 303 | i2o_setup_sysfs_links(dev); |
240 | 304 | ||
241 | i2o_driver_notify_device_add_all(dev); | 305 | i2o_driver_notify_device_add_all(dev); |
242 | 306 | ||
243 | pr_debug("i2o: device %s added\n", dev->device.bus_id); | 307 | pr_debug("i2o: device %s added\n", dev->device.bus_id); |
244 | 308 | ||
245 | return dev; | 309 | return dev; |
246 | }; | 310 | } |
247 | 311 | ||
248 | /** | 312 | /** |
249 | * i2o_device_remove - remove an I2O device from the I2O core | 313 | * i2o_device_remove - remove an I2O device from the I2O core |
@@ -256,10 +320,10 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
256 | void i2o_device_remove(struct i2o_device *i2o_dev) | 320 | void i2o_device_remove(struct i2o_device *i2o_dev) |
257 | { | 321 | { |
258 | i2o_driver_notify_device_remove_all(i2o_dev); | 322 | i2o_driver_notify_device_remove_all(i2o_dev); |
259 | class_device_unregister(&i2o_dev->classdev); | 323 | i2o_remove_sysfs_links(i2o_dev); |
260 | list_del(&i2o_dev->list); | 324 | list_del(&i2o_dev->list); |
261 | device_unregister(&i2o_dev->device); | 325 | device_unregister(&i2o_dev->device); |
262 | }; | 326 | } |
263 | 327 | ||
264 | /** | 328 | /** |
265 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices | 329 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices |
@@ -337,99 +401,8 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
337 | up(&c->lct_lock); | 401 | up(&c->lct_lock); |
338 | 402 | ||
339 | return 0; | 403 | return 0; |
340 | }; | 404 | } |
341 | |||
342 | /** | ||
343 | * i2o_device_class_show_class_id - Displays class id of I2O device | ||
344 | * @cd: class device of which the class id should be displayed | ||
345 | * @buf: buffer into which the class id should be printed | ||
346 | * | ||
347 | * Returns the number of bytes which are printed into the buffer. | ||
348 | */ | ||
349 | static ssize_t i2o_device_class_show_class_id(struct class_device *cd, | ||
350 | char *buf) | ||
351 | { | ||
352 | struct i2o_device *dev = to_i2o_device(cd->dev); | ||
353 | |||
354 | sprintf(buf, "0x%03x\n", dev->lct_data.class_id); | ||
355 | return strlen(buf) + 1; | ||
356 | }; | ||
357 | |||
358 | /** | ||
359 | * i2o_device_class_show_tid - Displays TID of I2O device | ||
360 | * @cd: class device of which the TID should be displayed | ||
361 | * @buf: buffer into which the class id should be printed | ||
362 | * | ||
363 | * Returns the number of bytes which are printed into the buffer. | ||
364 | */ | ||
365 | static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) | ||
366 | { | ||
367 | struct i2o_device *dev = to_i2o_device(cd->dev); | ||
368 | |||
369 | sprintf(buf, "0x%03x\n", dev->lct_data.tid); | ||
370 | return strlen(buf) + 1; | ||
371 | }; | ||
372 | |||
373 | /* I2O device class attributes */ | ||
374 | static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id, | ||
375 | NULL); | ||
376 | static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL); | ||
377 | |||
378 | /** | ||
379 | * i2o_device_class_add - Adds attributes to the I2O device | ||
380 | * @cd: I2O class device which is added to the I2O device class | ||
381 | * | ||
382 | * This function get called when a I2O device is added to the class. It | ||
383 | * creates the attributes for each device and creates user/parent symlink | ||
384 | * if necessary. | ||
385 | * | ||
386 | * Returns 0 on success or negative error code on failure. | ||
387 | */ | ||
388 | static int i2o_device_class_add(struct class_device *cd) | ||
389 | { | ||
390 | struct i2o_device *i2o_dev, *tmp; | ||
391 | struct i2o_controller *c; | ||
392 | |||
393 | i2o_dev = to_i2o_device(cd->dev); | ||
394 | c = i2o_dev->iop; | ||
395 | |||
396 | class_device_create_file(cd, &class_device_attr_class_id); | ||
397 | class_device_create_file(cd, &class_device_attr_tid); | ||
398 | |||
399 | /* create user entries for this device */ | ||
400 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | ||
401 | if (tmp && (tmp != i2o_dev)) | ||
402 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | ||
403 | "user"); | ||
404 | |||
405 | /* create user entries refering to this device */ | ||
406 | list_for_each_entry(tmp, &c->devices, list) | ||
407 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
408 | && (tmp != i2o_dev)) | ||
409 | sysfs_create_link(&tmp->device.kobj, | ||
410 | &i2o_dev->device.kobj, "user"); | ||
411 | |||
412 | /* create parent entries for this device */ | ||
413 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | ||
414 | if (tmp && (tmp != i2o_dev)) | ||
415 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | ||
416 | "parent"); | ||
417 | |||
418 | /* create parent entries refering to this device */ | ||
419 | list_for_each_entry(tmp, &c->devices, list) | ||
420 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
421 | && (tmp != i2o_dev)) | ||
422 | sysfs_create_link(&tmp->device.kobj, | ||
423 | &i2o_dev->device.kobj, "parent"); | ||
424 | |||
425 | return 0; | ||
426 | }; | ||
427 | 405 | ||
428 | /* I2O device class interface */ | ||
429 | static struct class_interface i2o_device_class_interface = { | ||
430 | .class = &i2o_device_class, | ||
431 | .add = i2o_device_class_add | ||
432 | }; | ||
433 | 406 | ||
434 | /* | 407 | /* |
435 | * Run time support routines | 408 | * Run time support routines |
@@ -553,11 +526,11 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | |||
553 | } | 526 | } |
554 | 527 | ||
555 | /* | 528 | /* |
556 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows | 529 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows |
557 | * if fieldcount == -1 return all fields | 530 | * if fieldcount == -1 return all fields |
558 | * ibuf and ibuflen are unused (use NULL, 0) | 531 | * ibuf and ibuflen are unused (use NULL, 0) |
559 | * else return specific fields | 532 | * else return specific fields |
560 | * ibuf contains fieldindexes | 533 | * ibuf contains fieldindexes |
561 | * | 534 | * |
562 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows | 535 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows |
563 | * if fieldcount == -1 return all fields | 536 | * if fieldcount == -1 return all fields |
@@ -602,35 +575,6 @@ int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, | |||
602 | return size; | 575 | return size; |
603 | } | 576 | } |
604 | 577 | ||
605 | /** | ||
606 | * i2o_device_init - Initialize I2O devices | ||
607 | * | ||
608 | * Registers the I2O device class. | ||
609 | * | ||
610 | * Returns 0 on success or negative error code on failure. | ||
611 | */ | ||
612 | int i2o_device_init(void) | ||
613 | { | ||
614 | int rc; | ||
615 | |||
616 | rc = class_register(&i2o_device_class); | ||
617 | if (rc) | ||
618 | return rc; | ||
619 | |||
620 | return class_interface_register(&i2o_device_class_interface); | ||
621 | }; | ||
622 | |||
623 | /** | ||
624 | * i2o_device_exit - I2O devices exit function | ||
625 | * | ||
626 | * Unregisters the I2O device class. | ||
627 | */ | ||
628 | void i2o_device_exit(void) | ||
629 | { | ||
630 | class_interface_register(&i2o_device_class_interface); | ||
631 | class_unregister(&i2o_device_class); | ||
632 | }; | ||
633 | |||
634 | EXPORT_SYMBOL(i2o_device_claim); | 578 | EXPORT_SYMBOL(i2o_device_claim); |
635 | EXPORT_SYMBOL(i2o_device_claim_release); | 579 | EXPORT_SYMBOL(i2o_device_claim_release); |
636 | EXPORT_SYMBOL(i2o_parm_field_get); | 580 | EXPORT_SYMBOL(i2o_parm_field_get); |