diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/enclosure.c | 100 |
1 files changed, 71 insertions, 29 deletions
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index fafb57fed761..0736cff9d97a 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c | |||
@@ -31,7 +31,6 @@ | |||
31 | static LIST_HEAD(container_list); | 31 | static LIST_HEAD(container_list); |
32 | static DEFINE_MUTEX(container_list_lock); | 32 | static DEFINE_MUTEX(container_list_lock); |
33 | static struct class enclosure_class; | 33 | static struct class enclosure_class; |
34 | static struct class enclosure_component_class; | ||
35 | 34 | ||
36 | /** | 35 | /** |
37 | * enclosure_find - find an enclosure given a device | 36 | * enclosure_find - find an enclosure given a device |
@@ -166,6 +165,40 @@ void enclosure_unregister(struct enclosure_device *edev) | |||
166 | } | 165 | } |
167 | EXPORT_SYMBOL_GPL(enclosure_unregister); | 166 | EXPORT_SYMBOL_GPL(enclosure_unregister); |
168 | 167 | ||
168 | #define ENCLOSURE_NAME_SIZE 64 | ||
169 | |||
170 | static void enclosure_link_name(struct enclosure_component *cdev, char *name) | ||
171 | { | ||
172 | strcpy(name, "enclosure_device:"); | ||
173 | strcat(name, cdev->cdev.bus_id); | ||
174 | } | ||
175 | |||
176 | static void enclosure_remove_links(struct enclosure_component *cdev) | ||
177 | { | ||
178 | char name[ENCLOSURE_NAME_SIZE]; | ||
179 | |||
180 | enclosure_link_name(cdev, name); | ||
181 | sysfs_remove_link(&cdev->dev->kobj, name); | ||
182 | sysfs_remove_link(&cdev->cdev.kobj, "device"); | ||
183 | } | ||
184 | |||
185 | static int enclosure_add_links(struct enclosure_component *cdev) | ||
186 | { | ||
187 | int error; | ||
188 | char name[ENCLOSURE_NAME_SIZE]; | ||
189 | |||
190 | error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device"); | ||
191 | if (error) | ||
192 | return error; | ||
193 | |||
194 | enclosure_link_name(cdev, name); | ||
195 | error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name); | ||
196 | if (error) | ||
197 | sysfs_remove_link(&cdev->cdev.kobj, "device"); | ||
198 | |||
199 | return error; | ||
200 | } | ||
201 | |||
169 | static void enclosure_release(struct device *cdev) | 202 | static void enclosure_release(struct device *cdev) |
170 | { | 203 | { |
171 | struct enclosure_device *edev = to_enclosure_device(cdev); | 204 | struct enclosure_device *edev = to_enclosure_device(cdev); |
@@ -178,10 +211,15 @@ static void enclosure_component_release(struct device *dev) | |||
178 | { | 211 | { |
179 | struct enclosure_component *cdev = to_enclosure_component(dev); | 212 | struct enclosure_component *cdev = to_enclosure_component(dev); |
180 | 213 | ||
181 | put_device(cdev->dev); | 214 | if (cdev->dev) { |
215 | enclosure_remove_links(cdev); | ||
216 | put_device(cdev->dev); | ||
217 | } | ||
182 | put_device(dev->parent); | 218 | put_device(dev->parent); |
183 | } | 219 | } |
184 | 220 | ||
221 | static struct attribute_group *enclosure_groups[]; | ||
222 | |||
185 | /** | 223 | /** |
186 | * enclosure_component_register - add a particular component to an enclosure | 224 | * enclosure_component_register - add a particular component to an enclosure |
187 | * @edev: the enclosure to add the component | 225 | * @edev: the enclosure to add the component |
@@ -217,12 +255,14 @@ enclosure_component_register(struct enclosure_device *edev, | |||
217 | ecomp->number = number; | 255 | ecomp->number = number; |
218 | cdev = &ecomp->cdev; | 256 | cdev = &ecomp->cdev; |
219 | cdev->parent = get_device(&edev->edev); | 257 | cdev->parent = get_device(&edev->edev); |
220 | cdev->class = &enclosure_component_class; | ||
221 | if (name) | 258 | if (name) |
222 | snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name); | 259 | snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name); |
223 | else | 260 | else |
224 | snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number); | 261 | snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number); |
225 | 262 | ||
263 | cdev->release = enclosure_component_release; | ||
264 | cdev->groups = enclosure_groups; | ||
265 | |||
226 | err = device_register(cdev); | 266 | err = device_register(cdev); |
227 | if (err) | 267 | if (err) |
228 | ERR_PTR(err); | 268 | ERR_PTR(err); |
@@ -255,10 +295,12 @@ int enclosure_add_device(struct enclosure_device *edev, int component, | |||
255 | 295 | ||
256 | cdev = &edev->component[component]; | 296 | cdev = &edev->component[component]; |
257 | 297 | ||
258 | device_del(&cdev->cdev); | 298 | if (cdev->dev) |
299 | enclosure_remove_links(cdev); | ||
300 | |||
259 | put_device(cdev->dev); | 301 | put_device(cdev->dev); |
260 | cdev->dev = get_device(dev); | 302 | cdev->dev = get_device(dev); |
261 | return device_add(&cdev->cdev); | 303 | return enclosure_add_links(cdev); |
262 | } | 304 | } |
263 | EXPORT_SYMBOL_GPL(enclosure_add_device); | 305 | EXPORT_SYMBOL_GPL(enclosure_add_device); |
264 | 306 | ||
@@ -442,24 +484,32 @@ static ssize_t get_component_type(struct device *cdev, | |||
442 | } | 484 | } |
443 | 485 | ||
444 | 486 | ||
445 | static struct device_attribute enclosure_component_attrs[] = { | 487 | static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault, |
446 | __ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault, | 488 | set_component_fault); |
447 | set_component_fault), | 489 | static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status, |
448 | __ATTR(status, S_IRUGO | S_IWUSR, get_component_status, | 490 | set_component_status); |
449 | set_component_status), | 491 | static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active, |
450 | __ATTR(active, S_IRUGO | S_IWUSR, get_component_active, | 492 | set_component_active); |
451 | set_component_active), | 493 | static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate, |
452 | __ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate, | 494 | set_component_locate); |
453 | set_component_locate), | 495 | static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL); |
454 | __ATTR(type, S_IRUGO, get_component_type, NULL), | 496 | |
455 | __ATTR_NULL | 497 | static struct attribute *enclosure_component_attrs[] = { |
498 | &dev_attr_fault.attr, | ||
499 | &dev_attr_status.attr, | ||
500 | &dev_attr_active.attr, | ||
501 | &dev_attr_locate.attr, | ||
502 | &dev_attr_type.attr, | ||
503 | NULL | ||
456 | }; | 504 | }; |
457 | 505 | ||
458 | static struct class enclosure_component_class = { | 506 | static struct attribute_group enclosure_group = { |
459 | .name = "enclosure_component", | 507 | .attrs = enclosure_component_attrs, |
460 | .owner = THIS_MODULE, | 508 | }; |
461 | .dev_attrs = enclosure_component_attrs, | 509 | |
462 | .dev_release = enclosure_component_release, | 510 | static struct attribute_group *enclosure_groups[] = { |
511 | &enclosure_group, | ||
512 | NULL | ||
463 | }; | 513 | }; |
464 | 514 | ||
465 | static int __init enclosure_init(void) | 515 | static int __init enclosure_init(void) |
@@ -469,20 +519,12 @@ static int __init enclosure_init(void) | |||
469 | err = class_register(&enclosure_class); | 519 | err = class_register(&enclosure_class); |
470 | if (err) | 520 | if (err) |
471 | return err; | 521 | return err; |
472 | err = class_register(&enclosure_component_class); | ||
473 | if (err) | ||
474 | goto err_out; | ||
475 | 522 | ||
476 | return 0; | 523 | return 0; |
477 | err_out: | ||
478 | class_unregister(&enclosure_class); | ||
479 | |||
480 | return err; | ||
481 | } | 524 | } |
482 | 525 | ||
483 | static void __exit enclosure_exit(void) | 526 | static void __exit enclosure_exit(void) |
484 | { | 527 | { |
485 | class_unregister(&enclosure_component_class); | ||
486 | class_unregister(&enclosure_class); | 528 | class_unregister(&enclosure_class); |
487 | } | 529 | } |
488 | 530 | ||