0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/device.h>
0013 #include <linux/enclosure.h>
0014 #include <linux/err.h>
0015 #include <linux/list.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/mutex.h>
0019 #include <linux/slab.h>
0020
0021 static LIST_HEAD(container_list);
0022 static DEFINE_MUTEX(container_list_lock);
0023 static struct class enclosure_class;
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 struct enclosure_device *enclosure_find(struct device *dev,
0044 struct enclosure_device *start)
0045 {
0046 struct enclosure_device *edev;
0047
0048 mutex_lock(&container_list_lock);
0049 edev = list_prepare_entry(start, &container_list, node);
0050 if (start)
0051 put_device(&start->edev);
0052
0053 list_for_each_entry_continue(edev, &container_list, node) {
0054 struct device *parent = edev->edev.parent;
0055
0056
0057 while (parent) {
0058 if (parent == dev) {
0059 get_device(&edev->edev);
0060 mutex_unlock(&container_list_lock);
0061 return edev;
0062 }
0063 parent = parent->parent;
0064 }
0065 }
0066 mutex_unlock(&container_list_lock);
0067
0068 return NULL;
0069 }
0070 EXPORT_SYMBOL_GPL(enclosure_find);
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
0085 void *data)
0086 {
0087 int error = 0;
0088 struct enclosure_device *edev;
0089
0090 mutex_lock(&container_list_lock);
0091 list_for_each_entry(edev, &container_list, node) {
0092 error = fn(edev, data);
0093 if (error)
0094 break;
0095 }
0096 mutex_unlock(&container_list_lock);
0097
0098 return error;
0099 }
0100 EXPORT_SYMBOL_GPL(enclosure_for_each_device);
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 struct enclosure_device *
0115 enclosure_register(struct device *dev, const char *name, int components,
0116 struct enclosure_component_callbacks *cb)
0117 {
0118 struct enclosure_device *edev =
0119 kzalloc(struct_size(edev, component, components), GFP_KERNEL);
0120 int err, i;
0121
0122 BUG_ON(!cb);
0123
0124 if (!edev)
0125 return ERR_PTR(-ENOMEM);
0126
0127 edev->components = components;
0128
0129 edev->edev.class = &enclosure_class;
0130 edev->edev.parent = get_device(dev);
0131 edev->cb = cb;
0132 dev_set_name(&edev->edev, "%s", name);
0133 err = device_register(&edev->edev);
0134 if (err)
0135 goto err;
0136
0137 for (i = 0; i < components; i++) {
0138 edev->component[i].number = -1;
0139 edev->component[i].slot = -1;
0140 edev->component[i].power_status = -1;
0141 }
0142
0143 mutex_lock(&container_list_lock);
0144 list_add_tail(&edev->node, &container_list);
0145 mutex_unlock(&container_list_lock);
0146
0147 return edev;
0148
0149 err:
0150 put_device(edev->edev.parent);
0151 kfree(edev);
0152 return ERR_PTR(err);
0153 }
0154 EXPORT_SYMBOL_GPL(enclosure_register);
0155
0156 static struct enclosure_component_callbacks enclosure_null_callbacks;
0157
0158
0159
0160
0161
0162
0163 void enclosure_unregister(struct enclosure_device *edev)
0164 {
0165 int i;
0166
0167 mutex_lock(&container_list_lock);
0168 list_del(&edev->node);
0169 mutex_unlock(&container_list_lock);
0170
0171 for (i = 0; i < edev->components; i++)
0172 if (edev->component[i].number != -1)
0173 device_unregister(&edev->component[i].cdev);
0174
0175
0176 edev->cb = &enclosure_null_callbacks;
0177 device_unregister(&edev->edev);
0178 }
0179 EXPORT_SYMBOL_GPL(enclosure_unregister);
0180
0181 #define ENCLOSURE_NAME_SIZE 64
0182 #define COMPONENT_NAME_SIZE 64
0183
0184 static void enclosure_link_name(struct enclosure_component *cdev, char *name)
0185 {
0186 strcpy(name, "enclosure_device:");
0187 strcat(name, dev_name(&cdev->cdev));
0188 }
0189
0190 static void enclosure_remove_links(struct enclosure_component *cdev)
0191 {
0192 char name[ENCLOSURE_NAME_SIZE];
0193
0194 enclosure_link_name(cdev, name);
0195
0196
0197
0198
0199
0200 if (cdev->dev->kobj.sd)
0201 sysfs_remove_link(&cdev->dev->kobj, name);
0202
0203 if (cdev->cdev.kobj.sd)
0204 sysfs_remove_link(&cdev->cdev.kobj, "device");
0205 }
0206
0207 static int enclosure_add_links(struct enclosure_component *cdev)
0208 {
0209 int error;
0210 char name[ENCLOSURE_NAME_SIZE];
0211
0212 error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
0213 if (error)
0214 return error;
0215
0216 enclosure_link_name(cdev, name);
0217 error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
0218 if (error)
0219 sysfs_remove_link(&cdev->cdev.kobj, "device");
0220
0221 return error;
0222 }
0223
0224 static void enclosure_release(struct device *cdev)
0225 {
0226 struct enclosure_device *edev = to_enclosure_device(cdev);
0227
0228 put_device(cdev->parent);
0229 kfree(edev);
0230 }
0231
0232 static void enclosure_component_release(struct device *dev)
0233 {
0234 struct enclosure_component *cdev = to_enclosure_component(dev);
0235
0236 if (cdev->dev) {
0237 enclosure_remove_links(cdev);
0238 put_device(cdev->dev);
0239 }
0240 put_device(dev->parent);
0241 }
0242
0243 static struct enclosure_component *
0244 enclosure_component_find_by_name(struct enclosure_device *edev,
0245 const char *name)
0246 {
0247 int i;
0248 const char *cname;
0249 struct enclosure_component *ecomp;
0250
0251 if (!edev || !name || !name[0])
0252 return NULL;
0253
0254 for (i = 0; i < edev->components; i++) {
0255 ecomp = &edev->component[i];
0256 cname = dev_name(&ecomp->cdev);
0257 if (ecomp->number != -1 &&
0258 cname && cname[0] &&
0259 !strcmp(cname, name))
0260 return ecomp;
0261 }
0262
0263 return NULL;
0264 }
0265
0266 static const struct attribute_group *enclosure_component_groups[];
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 struct enclosure_component *
0281 enclosure_component_alloc(struct enclosure_device *edev,
0282 unsigned int number,
0283 enum enclosure_component_type type,
0284 const char *name)
0285 {
0286 struct enclosure_component *ecomp;
0287 struct device *cdev;
0288 int i;
0289 char newname[COMPONENT_NAME_SIZE];
0290
0291 if (number >= edev->components)
0292 return ERR_PTR(-EINVAL);
0293
0294 ecomp = &edev->component[number];
0295
0296 if (ecomp->number != -1)
0297 return ERR_PTR(-EINVAL);
0298
0299 ecomp->type = type;
0300 ecomp->number = number;
0301 cdev = &ecomp->cdev;
0302 cdev->parent = get_device(&edev->edev);
0303
0304 if (name && name[0]) {
0305
0306
0307
0308
0309 i = 1;
0310 snprintf(newname, COMPONENT_NAME_SIZE,
0311 "%s", name);
0312 while (enclosure_component_find_by_name(edev, newname))
0313 snprintf(newname, COMPONENT_NAME_SIZE,
0314 "%s-%i", name, i++);
0315 dev_set_name(cdev, "%s", newname);
0316 } else
0317 dev_set_name(cdev, "%u", number);
0318
0319 cdev->release = enclosure_component_release;
0320 cdev->groups = enclosure_component_groups;
0321
0322 return ecomp;
0323 }
0324 EXPORT_SYMBOL_GPL(enclosure_component_alloc);
0325
0326
0327
0328
0329
0330
0331
0332 int enclosure_component_register(struct enclosure_component *ecomp)
0333 {
0334 struct device *cdev;
0335 int err;
0336
0337 cdev = &ecomp->cdev;
0338 err = device_register(cdev);
0339 if (err) {
0340 ecomp->number = -1;
0341 put_device(cdev);
0342 return err;
0343 }
0344
0345 return 0;
0346 }
0347 EXPORT_SYMBOL_GPL(enclosure_component_register);
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363 int enclosure_add_device(struct enclosure_device *edev, int component,
0364 struct device *dev)
0365 {
0366 struct enclosure_component *cdev;
0367 int err;
0368
0369 if (!edev || component >= edev->components)
0370 return -EINVAL;
0371
0372 cdev = &edev->component[component];
0373
0374 if (cdev->dev == dev)
0375 return -EEXIST;
0376
0377 if (cdev->dev) {
0378 enclosure_remove_links(cdev);
0379 put_device(cdev->dev);
0380 }
0381 cdev->dev = get_device(dev);
0382 err = enclosure_add_links(cdev);
0383 if (err) {
0384 put_device(cdev->dev);
0385 cdev->dev = NULL;
0386 }
0387 return err;
0388 }
0389 EXPORT_SYMBOL_GPL(enclosure_add_device);
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399 int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
0400 {
0401 struct enclosure_component *cdev;
0402 int i;
0403
0404 if (!edev || !dev)
0405 return -EINVAL;
0406
0407 for (i = 0; i < edev->components; i++) {
0408 cdev = &edev->component[i];
0409 if (cdev->dev == dev) {
0410 enclosure_remove_links(cdev);
0411 put_device(dev);
0412 cdev->dev = NULL;
0413 return 0;
0414 }
0415 }
0416 return -ENODEV;
0417 }
0418 EXPORT_SYMBOL_GPL(enclosure_remove_device);
0419
0420
0421
0422
0423
0424 static ssize_t components_show(struct device *cdev,
0425 struct device_attribute *attr, char *buf)
0426 {
0427 struct enclosure_device *edev = to_enclosure_device(cdev);
0428
0429 return sysfs_emit(buf, "%d\n", edev->components);
0430 }
0431 static DEVICE_ATTR_RO(components);
0432
0433 static ssize_t id_show(struct device *cdev,
0434 struct device_attribute *attr,
0435 char *buf)
0436 {
0437 struct enclosure_device *edev = to_enclosure_device(cdev);
0438
0439 if (edev->cb->show_id)
0440 return edev->cb->show_id(edev, buf);
0441 return -EINVAL;
0442 }
0443 static DEVICE_ATTR_RO(id);
0444
0445 static struct attribute *enclosure_class_attrs[] = {
0446 &dev_attr_components.attr,
0447 &dev_attr_id.attr,
0448 NULL,
0449 };
0450 ATTRIBUTE_GROUPS(enclosure_class);
0451
0452 static struct class enclosure_class = {
0453 .name = "enclosure",
0454 .owner = THIS_MODULE,
0455 .dev_release = enclosure_release,
0456 .dev_groups = enclosure_class_groups,
0457 };
0458
0459 static const char *const enclosure_status[] = {
0460 [ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
0461 [ENCLOSURE_STATUS_OK] = "OK",
0462 [ENCLOSURE_STATUS_CRITICAL] = "critical",
0463 [ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
0464 [ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
0465 [ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
0466 [ENCLOSURE_STATUS_UNKNOWN] = "unknown",
0467 [ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
0468 [ENCLOSURE_STATUS_MAX] = NULL,
0469 };
0470
0471 static const char *const enclosure_type[] = {
0472 [ENCLOSURE_COMPONENT_DEVICE] = "device",
0473 [ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
0474 };
0475
0476 static ssize_t get_component_fault(struct device *cdev,
0477 struct device_attribute *attr, char *buf)
0478 {
0479 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0480 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0481
0482 if (edev->cb->get_fault)
0483 edev->cb->get_fault(edev, ecomp);
0484 return sysfs_emit(buf, "%d\n", ecomp->fault);
0485 }
0486
0487 static ssize_t set_component_fault(struct device *cdev,
0488 struct device_attribute *attr,
0489 const char *buf, size_t count)
0490 {
0491 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0492 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0493 int val = simple_strtoul(buf, NULL, 0);
0494
0495 if (edev->cb->set_fault)
0496 edev->cb->set_fault(edev, ecomp, val);
0497 return count;
0498 }
0499
0500 static ssize_t get_component_status(struct device *cdev,
0501 struct device_attribute *attr,char *buf)
0502 {
0503 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0504 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0505
0506 if (edev->cb->get_status)
0507 edev->cb->get_status(edev, ecomp);
0508 return sysfs_emit(buf, "%s\n", enclosure_status[ecomp->status]);
0509 }
0510
0511 static ssize_t set_component_status(struct device *cdev,
0512 struct device_attribute *attr,
0513 const char *buf, size_t count)
0514 {
0515 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0516 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0517 int i;
0518
0519 for (i = 0; enclosure_status[i]; i++) {
0520 if (strncmp(buf, enclosure_status[i],
0521 strlen(enclosure_status[i])) == 0 &&
0522 (buf[strlen(enclosure_status[i])] == '\n' ||
0523 buf[strlen(enclosure_status[i])] == '\0'))
0524 break;
0525 }
0526
0527 if (enclosure_status[i] && edev->cb->set_status) {
0528 edev->cb->set_status(edev, ecomp, i);
0529 return count;
0530 } else
0531 return -EINVAL;
0532 }
0533
0534 static ssize_t get_component_active(struct device *cdev,
0535 struct device_attribute *attr, char *buf)
0536 {
0537 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0538 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0539
0540 if (edev->cb->get_active)
0541 edev->cb->get_active(edev, ecomp);
0542 return sysfs_emit(buf, "%d\n", ecomp->active);
0543 }
0544
0545 static ssize_t set_component_active(struct device *cdev,
0546 struct device_attribute *attr,
0547 const char *buf, size_t count)
0548 {
0549 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0550 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0551 int val = simple_strtoul(buf, NULL, 0);
0552
0553 if (edev->cb->set_active)
0554 edev->cb->set_active(edev, ecomp, val);
0555 return count;
0556 }
0557
0558 static ssize_t get_component_locate(struct device *cdev,
0559 struct device_attribute *attr, char *buf)
0560 {
0561 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0562 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0563
0564 if (edev->cb->get_locate)
0565 edev->cb->get_locate(edev, ecomp);
0566 return sysfs_emit(buf, "%d\n", ecomp->locate);
0567 }
0568
0569 static ssize_t set_component_locate(struct device *cdev,
0570 struct device_attribute *attr,
0571 const char *buf, size_t count)
0572 {
0573 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0574 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0575 int val = simple_strtoul(buf, NULL, 0);
0576
0577 if (edev->cb->set_locate)
0578 edev->cb->set_locate(edev, ecomp, val);
0579 return count;
0580 }
0581
0582 static ssize_t get_component_power_status(struct device *cdev,
0583 struct device_attribute *attr,
0584 char *buf)
0585 {
0586 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0587 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0588
0589 if (edev->cb->get_power_status)
0590 edev->cb->get_power_status(edev, ecomp);
0591
0592
0593 if (ecomp->power_status == -1)
0594 return (edev->cb->get_power_status) ? -EIO : -ENOTTY;
0595
0596 return sysfs_emit(buf, "%s\n", ecomp->power_status ? "on" : "off");
0597 }
0598
0599 static ssize_t set_component_power_status(struct device *cdev,
0600 struct device_attribute *attr,
0601 const char *buf, size_t count)
0602 {
0603 struct enclosure_device *edev = to_enclosure_device(cdev->parent);
0604 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0605 int val;
0606
0607 if (strncmp(buf, "on", 2) == 0 &&
0608 (buf[2] == '\n' || buf[2] == '\0'))
0609 val = 1;
0610 else if (strncmp(buf, "off", 3) == 0 &&
0611 (buf[3] == '\n' || buf[3] == '\0'))
0612 val = 0;
0613 else
0614 return -EINVAL;
0615
0616 if (edev->cb->set_power_status)
0617 edev->cb->set_power_status(edev, ecomp, val);
0618 return count;
0619 }
0620
0621 static ssize_t get_component_type(struct device *cdev,
0622 struct device_attribute *attr, char *buf)
0623 {
0624 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0625
0626 return sysfs_emit(buf, "%s\n", enclosure_type[ecomp->type]);
0627 }
0628
0629 static ssize_t get_component_slot(struct device *cdev,
0630 struct device_attribute *attr, char *buf)
0631 {
0632 struct enclosure_component *ecomp = to_enclosure_component(cdev);
0633 int slot;
0634
0635
0636 if (ecomp->slot >= 0)
0637 slot = ecomp->slot;
0638 else
0639 slot = ecomp->number;
0640
0641 return sysfs_emit(buf, "%d\n", slot);
0642 }
0643
0644 static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
0645 set_component_fault);
0646 static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
0647 set_component_status);
0648 static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
0649 set_component_active);
0650 static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
0651 set_component_locate);
0652 static DEVICE_ATTR(power_status, S_IRUGO | S_IWUSR, get_component_power_status,
0653 set_component_power_status);
0654 static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);
0655 static DEVICE_ATTR(slot, S_IRUGO, get_component_slot, NULL);
0656
0657 static struct attribute *enclosure_component_attrs[] = {
0658 &dev_attr_fault.attr,
0659 &dev_attr_status.attr,
0660 &dev_attr_active.attr,
0661 &dev_attr_locate.attr,
0662 &dev_attr_power_status.attr,
0663 &dev_attr_type.attr,
0664 &dev_attr_slot.attr,
0665 NULL
0666 };
0667 ATTRIBUTE_GROUPS(enclosure_component);
0668
0669 static int __init enclosure_init(void)
0670 {
0671 return class_register(&enclosure_class);
0672 }
0673
0674 static void __exit enclosure_exit(void)
0675 {
0676 class_unregister(&enclosure_class);
0677 }
0678
0679 module_init(enclosure_init);
0680 module_exit(enclosure_exit);
0681
0682 MODULE_AUTHOR("James Bottomley");
0683 MODULE_DESCRIPTION("Enclosure Services");
0684 MODULE_LICENSE("GPL v2");