diff options
Diffstat (limited to 'drivers/message/i2o/device.c')
-rw-r--r-- | drivers/message/i2o/device.c | 255 |
1 files changed, 122 insertions, 133 deletions
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 21f16ba3ac38..551d582e2887 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,62 @@ 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 | } |
139 | 140 | ||
140 | /** | 141 | /** |
141 | * i2o_device_class_release - Remove I2O device attributes | 142 | * i2o_device_class_release - I2O class device release function |
142 | * @cd: I2O class device which is added to the I2O device class | 143 | * @cd: I2O class device which is added to the I2O device class |
143 | * | 144 | * |
144 | * Removes attributes from the I2O device again. Also search each device | 145 | * The function is just a stub - memory will be freed when |
145 | * on the controller for I2O devices which refert to this device as parent | 146 | * associated I2O device is released. |
146 | * or user and remove this links also. | ||
147 | */ | 147 | */ |
148 | static void i2o_device_class_release(struct class_device *cd) | 148 | static void i2o_device_class_release(struct class_device *cd) |
149 | { | 149 | { |
150 | struct i2o_device *i2o_dev, *tmp; | 150 | /* empty */ |
151 | struct i2o_controller *c; | 151 | } |
152 | 152 | ||
153 | i2o_dev = to_i2o_device(cd->dev); | 153 | /** |
154 | c = i2o_dev->iop; | 154 | * i2o_device_class_show_class_id - Displays class id of I2O device |
155 | * @cd: class device of which the class id should be displayed | ||
156 | * @buf: buffer into which the class id should be printed | ||
157 | * | ||
158 | * Returns the number of bytes which are printed into the buffer. | ||
159 | */ | ||
160 | static ssize_t i2o_device_class_show_class_id(struct class_device *cd, | ||
161 | char *buf) | ||
162 | { | ||
163 | struct i2o_device *dev = to_i2o_device(cd->dev); | ||
155 | 164 | ||
156 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | 165 | sprintf(buf, "0x%03x\n", dev->lct_data.class_id); |
157 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | 166 | return strlen(buf) + 1; |
167 | } | ||
158 | 168 | ||
159 | list_for_each_entry(tmp, &c->devices, list) { | 169 | /** |
160 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 170 | * i2o_device_class_show_tid - Displays TID of I2O device |
161 | sysfs_remove_link(&tmp->device.kobj, "parent"); | 171 | * @cd: class device of which the TID should be displayed |
162 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 172 | * @buf: buffer into which the class id should be printed |
163 | sysfs_remove_link(&tmp->device.kobj, "user"); | 173 | * |
164 | } | 174 | * Returns the number of bytes which are printed into the buffer. |
175 | */ | ||
176 | static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) | ||
177 | { | ||
178 | struct i2o_device *dev = to_i2o_device(cd->dev); | ||
179 | |||
180 | sprintf(buf, "0x%03x\n", dev->lct_data.tid); | ||
181 | return strlen(buf) + 1; | ||
182 | } | ||
183 | |||
184 | static struct class_device_attribute i2o_device_class_attrs[] = { | ||
185 | __ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id, NULL), | ||
186 | __ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL), | ||
187 | __ATTR_NULL | ||
165 | }; | 188 | }; |
166 | 189 | ||
167 | /* I2O device class */ | 190 | /* I2O device class */ |
168 | static struct class i2o_device_class = { | 191 | static struct class i2o_device_class = { |
169 | .name = "i2o_device", | 192 | .name = "i2o_device", |
170 | .release = i2o_device_class_release | 193 | .release = i2o_device_class_release, |
194 | .class_dev_attrs = i2o_device_class_attrs, | ||
171 | }; | 195 | }; |
172 | 196 | ||
173 | /** | 197 | /** |
@@ -197,7 +221,67 @@ static struct i2o_device *i2o_device_alloc(void) | |||
197 | dev->classdev.dev = &dev->device; | 221 | dev->classdev.dev = &dev->device; |
198 | 222 | ||
199 | return dev; | 223 | return dev; |
200 | }; | 224 | } |
225 | |||
226 | /** | ||
227 | * i2o_setup_sysfs_links - Adds attributes to the I2O device | ||
228 | * @cd: I2O class device which is added to the I2O device class | ||
229 | * | ||
230 | * This function get called when a I2O device is added to the class. It | ||
231 | * creates the attributes for each device and creates user/parent symlink | ||
232 | * if necessary. | ||
233 | * | ||
234 | * Returns 0 on success or negative error code on failure. | ||
235 | */ | ||
236 | static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev) | ||
237 | { | ||
238 | struct i2o_controller *c = i2o_dev->iop; | ||
239 | struct i2o_device *tmp; | ||
240 | |||
241 | /* create user entries for this device */ | ||
242 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | ||
243 | if (tmp && tmp != i2o_dev) | ||
244 | sysfs_create_link(&i2o_dev->device.kobj, | ||
245 | &tmp->device.kobj, "user"); | ||
246 | |||
247 | /* create user entries refering to this device */ | ||
248 | list_for_each_entry(tmp, &c->devices, list) | ||
249 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid && | ||
250 | tmp != i2o_dev) | ||
251 | sysfs_create_link(&tmp->device.kobj, | ||
252 | &i2o_dev->device.kobj, "user"); | ||
253 | |||
254 | /* create parent entries for this device */ | ||
255 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | ||
256 | if (tmp && tmp != i2o_dev) | ||
257 | sysfs_create_link(&i2o_dev->device.kobj, | ||
258 | &tmp->device.kobj, "parent"); | ||
259 | |||
260 | /* create parent entries refering to this device */ | ||
261 | list_for_each_entry(tmp, &c->devices, list) | ||
262 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid && | ||
263 | tmp != i2o_dev) | ||
264 | sysfs_create_link(&tmp->device.kobj, | ||
265 | &i2o_dev->device.kobj, "parent"); | ||
266 | } | ||
267 | |||
268 | static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) | ||
269 | { | ||
270 | struct i2o_controller *c = i2o_dev->iop; | ||
271 | struct i2o_device *tmp; | ||
272 | |||
273 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | ||
274 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | ||
275 | |||
276 | list_for_each_entry(tmp, &c->devices, list) { | ||
277 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
278 | sysfs_remove_link(&tmp->device.kobj, "parent"); | ||
279 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
280 | sysfs_remove_link(&tmp->device.kobj, "user"); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | |||
201 | 285 | ||
202 | /** | 286 | /** |
203 | * i2o_device_add - allocate a new I2O device and add it to the IOP | 287 | * i2o_device_add - allocate a new I2O device and add it to the IOP |
@@ -222,6 +306,7 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
222 | } | 306 | } |
223 | 307 | ||
224 | dev->lct_data = *entry; | 308 | dev->lct_data = *entry; |
309 | dev->iop = c; | ||
225 | 310 | ||
226 | snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 311 | snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, |
227 | dev->lct_data.tid); | 312 | dev->lct_data.tid); |
@@ -229,7 +314,6 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
229 | snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 314 | snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit, |
230 | dev->lct_data.tid); | 315 | dev->lct_data.tid); |
231 | 316 | ||
232 | dev->iop = c; | ||
233 | dev->device.parent = &c->device; | 317 | dev->device.parent = &c->device; |
234 | 318 | ||
235 | device_register(&dev->device); | 319 | device_register(&dev->device); |
@@ -238,12 +322,14 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
238 | 322 | ||
239 | class_device_register(&dev->classdev); | 323 | class_device_register(&dev->classdev); |
240 | 324 | ||
325 | i2o_setup_sysfs_links(dev); | ||
326 | |||
241 | i2o_driver_notify_device_add_all(dev); | 327 | i2o_driver_notify_device_add_all(dev); |
242 | 328 | ||
243 | pr_debug("i2o: device %s added\n", dev->device.bus_id); | 329 | pr_debug("i2o: device %s added\n", dev->device.bus_id); |
244 | 330 | ||
245 | return dev; | 331 | return dev; |
246 | }; | 332 | } |
247 | 333 | ||
248 | /** | 334 | /** |
249 | * i2o_device_remove - remove an I2O device from the I2O core | 335 | * i2o_device_remove - remove an I2O device from the I2O core |
@@ -256,10 +342,11 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
256 | void i2o_device_remove(struct i2o_device *i2o_dev) | 342 | void i2o_device_remove(struct i2o_device *i2o_dev) |
257 | { | 343 | { |
258 | i2o_driver_notify_device_remove_all(i2o_dev); | 344 | i2o_driver_notify_device_remove_all(i2o_dev); |
345 | i2o_remove_sysfs_links(i2o_dev); | ||
259 | class_device_unregister(&i2o_dev->classdev); | 346 | class_device_unregister(&i2o_dev->classdev); |
260 | list_del(&i2o_dev->list); | 347 | list_del(&i2o_dev->list); |
261 | device_unregister(&i2o_dev->device); | 348 | device_unregister(&i2o_dev->device); |
262 | }; | 349 | } |
263 | 350 | ||
264 | /** | 351 | /** |
265 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices | 352 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices |
@@ -337,99 +424,8 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
337 | up(&c->lct_lock); | 424 | up(&c->lct_lock); |
338 | 425 | ||
339 | return 0; | 426 | return 0; |
340 | }; | 427 | } |
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 | 428 | ||
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 | 429 | ||
434 | /* | 430 | /* |
435 | * Run time support routines | 431 | * Run time support routines |
@@ -553,11 +549,11 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | |||
553 | } | 549 | } |
554 | 550 | ||
555 | /* | 551 | /* |
556 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows | 552 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows |
557 | * if fieldcount == -1 return all fields | 553 | * if fieldcount == -1 return all fields |
558 | * ibuf and ibuflen are unused (use NULL, 0) | 554 | * ibuf and ibuflen are unused (use NULL, 0) |
559 | * else return specific fields | 555 | * else return specific fields |
560 | * ibuf contains fieldindexes | 556 | * ibuf contains fieldindexes |
561 | * | 557 | * |
562 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows | 558 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows |
563 | * if fieldcount == -1 return all fields | 559 | * if fieldcount == -1 return all fields |
@@ -611,14 +607,8 @@ int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, | |||
611 | */ | 607 | */ |
612 | int i2o_device_init(void) | 608 | int i2o_device_init(void) |
613 | { | 609 | { |
614 | int rc; | 610 | return class_register(&i2o_device_class); |
615 | 611 | } | |
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 | 612 | ||
623 | /** | 613 | /** |
624 | * i2o_device_exit - I2O devices exit function | 614 | * i2o_device_exit - I2O devices exit function |
@@ -627,9 +617,8 @@ int i2o_device_init(void) | |||
627 | */ | 617 | */ |
628 | void i2o_device_exit(void) | 618 | void i2o_device_exit(void) |
629 | { | 619 | { |
630 | class_interface_register(&i2o_device_class_interface); | ||
631 | class_unregister(&i2o_device_class); | 620 | class_unregister(&i2o_device_class); |
632 | }; | 621 | } |
633 | 622 | ||
634 | EXPORT_SYMBOL(i2o_device_claim); | 623 | EXPORT_SYMBOL(i2o_device_claim); |
635 | EXPORT_SYMBOL(i2o_device_claim_release); | 624 | EXPORT_SYMBOL(i2o_device_claim_release); |