root/drivers/misc/enclosure.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. enclosure_find
  2. enclosure_for_each_device
  3. enclosure_register
  4. enclosure_unregister
  5. enclosure_link_name
  6. enclosure_remove_links
  7. enclosure_add_links
  8. enclosure_release
  9. enclosure_component_release
  10. enclosure_component_find_by_name
  11. enclosure_component_alloc
  12. enclosure_component_register
  13. enclosure_add_device
  14. enclosure_remove_device
  15. components_show
  16. id_show
  17. get_component_fault
  18. set_component_fault
  19. get_component_status
  20. set_component_status
  21. get_component_active
  22. set_component_active
  23. get_component_locate
  24. set_component_locate
  25. get_component_power_status
  26. set_component_power_status
  27. get_component_type
  28. get_component_slot
  29. enclosure_init
  30. enclosure_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Enclosure Services
   4  *
   5  * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
   6  *
   7 **-----------------------------------------------------------------------------
   8 **
   9 **
  10 **-----------------------------------------------------------------------------
  11 */
  12 #include <linux/device.h>
  13 #include <linux/enclosure.h>
  14 #include <linux/err.h>
  15 #include <linux/list.h>
  16 #include <linux/kernel.h>
  17 #include <linux/module.h>
  18 #include <linux/mutex.h>
  19 #include <linux/slab.h>
  20 
  21 static LIST_HEAD(container_list);
  22 static DEFINE_MUTEX(container_list_lock);
  23 static struct class enclosure_class;
  24 
  25 /**
  26  * enclosure_find - find an enclosure given a parent device
  27  * @dev:        the parent to match against
  28  * @start:      Optional enclosure device to start from (NULL if none)
  29  *
  30  * Looks through the list of registered enclosures to find all those
  31  * with @dev as a parent.  Returns NULL if no enclosure is
  32  * found. @start can be used as a starting point to obtain multiple
  33  * enclosures per parent (should begin with NULL and then be set to
  34  * each returned enclosure device). Obtains a reference to the
  35  * enclosure class device which must be released with device_put().
  36  * If @start is not NULL, a reference must be taken on it which is
  37  * released before returning (this allows a loop through all
  38  * enclosures to exit with only the reference on the enclosure of
  39  * interest held).  Note that the @dev may correspond to the actual
  40  * device housing the enclosure, in which case no iteration via @start
  41  * is required.
  42  */
  43 struct enclosure_device *enclosure_find(struct device *dev,
  44                                         struct enclosure_device *start)
  45 {
  46         struct enclosure_device *edev;
  47 
  48         mutex_lock(&container_list_lock);
  49         edev = list_prepare_entry(start, &container_list, node);
  50         if (start)
  51                 put_device(&start->edev);
  52 
  53         list_for_each_entry_continue(edev, &container_list, node) {
  54                 struct device *parent = edev->edev.parent;
  55                 /* parent might not be immediate, so iterate up to
  56                  * the root of the tree if necessary */
  57                 while (parent) {
  58                         if (parent == dev) {
  59                                 get_device(&edev->edev);
  60                                 mutex_unlock(&container_list_lock);
  61                                 return edev;
  62                         }
  63                         parent = parent->parent;
  64                 }
  65         }
  66         mutex_unlock(&container_list_lock);
  67 
  68         return NULL;
  69 }
  70 EXPORT_SYMBOL_GPL(enclosure_find);
  71 
  72 /**
  73  * enclosure_for_each_device - calls a function for each enclosure
  74  * @fn:         the function to call
  75  * @data:       the data to pass to each call
  76  *
  77  * Loops over all the enclosures calling the function.
  78  *
  79  * Note, this function uses a mutex which will be held across calls to
  80  * @fn, so it must have non atomic context, and @fn may (although it
  81  * should not) sleep or otherwise cause the mutex to be held for
  82  * indefinite periods
  83  */
  84 int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
  85                               void *data)
  86 {
  87         int error = 0;
  88         struct enclosure_device *edev;
  89 
  90         mutex_lock(&container_list_lock);
  91         list_for_each_entry(edev, &container_list, node) {
  92                 error = fn(edev, data);
  93                 if (error)
  94                         break;
  95         }
  96         mutex_unlock(&container_list_lock);
  97 
  98         return error;
  99 }
 100 EXPORT_SYMBOL_GPL(enclosure_for_each_device);
 101 
 102 /**
 103  * enclosure_register - register device as an enclosure
 104  *
 105  * @dev:        device containing the enclosure
 106  * @components: number of components in the enclosure
 107  *
 108  * This sets up the device for being an enclosure.  Note that @dev does
 109  * not have to be a dedicated enclosure device.  It may be some other type
 110  * of device that additionally responds to enclosure services
 111  */
 112 struct enclosure_device *
 113 enclosure_register(struct device *dev, const char *name, int components,
 114                    struct enclosure_component_callbacks *cb)
 115 {
 116         struct enclosure_device *edev =
 117                 kzalloc(struct_size(edev, component, components), GFP_KERNEL);
 118         int err, i;
 119 
 120         BUG_ON(!cb);
 121 
 122         if (!edev)
 123                 return ERR_PTR(-ENOMEM);
 124 
 125         edev->components = components;
 126 
 127         edev->edev.class = &enclosure_class;
 128         edev->edev.parent = get_device(dev);
 129         edev->cb = cb;
 130         dev_set_name(&edev->edev, "%s", name);
 131         err = device_register(&edev->edev);
 132         if (err)
 133                 goto err;
 134 
 135         for (i = 0; i < components; i++) {
 136                 edev->component[i].number = -1;
 137                 edev->component[i].slot = -1;
 138                 edev->component[i].power_status = -1;
 139         }
 140 
 141         mutex_lock(&container_list_lock);
 142         list_add_tail(&edev->node, &container_list);
 143         mutex_unlock(&container_list_lock);
 144 
 145         return edev;
 146 
 147  err:
 148         put_device(edev->edev.parent);
 149         kfree(edev);
 150         return ERR_PTR(err);
 151 }
 152 EXPORT_SYMBOL_GPL(enclosure_register);
 153 
 154 static struct enclosure_component_callbacks enclosure_null_callbacks;
 155 
 156 /**
 157  * enclosure_unregister - remove an enclosure
 158  *
 159  * @edev:       the registered enclosure to remove;
 160  */
 161 void enclosure_unregister(struct enclosure_device *edev)
 162 {
 163         int i;
 164 
 165         mutex_lock(&container_list_lock);
 166         list_del(&edev->node);
 167         mutex_unlock(&container_list_lock);
 168 
 169         for (i = 0; i < edev->components; i++)
 170                 if (edev->component[i].number != -1)
 171                         device_unregister(&edev->component[i].cdev);
 172 
 173         /* prevent any callbacks into service user */
 174         edev->cb = &enclosure_null_callbacks;
 175         device_unregister(&edev->edev);
 176 }
 177 EXPORT_SYMBOL_GPL(enclosure_unregister);
 178 
 179 #define ENCLOSURE_NAME_SIZE     64
 180 #define COMPONENT_NAME_SIZE     64
 181 
 182 static void enclosure_link_name(struct enclosure_component *cdev, char *name)
 183 {
 184         strcpy(name, "enclosure_device:");
 185         strcat(name, dev_name(&cdev->cdev));
 186 }
 187 
 188 static void enclosure_remove_links(struct enclosure_component *cdev)
 189 {
 190         char name[ENCLOSURE_NAME_SIZE];
 191 
 192         enclosure_link_name(cdev, name);
 193 
 194         /*
 195          * In odd circumstances, like multipath devices, something else may
 196          * already have removed the links, so check for this condition first.
 197          */
 198         if (cdev->dev->kobj.sd)
 199                 sysfs_remove_link(&cdev->dev->kobj, name);
 200 
 201         if (cdev->cdev.kobj.sd)
 202                 sysfs_remove_link(&cdev->cdev.kobj, "device");
 203 }
 204 
 205 static int enclosure_add_links(struct enclosure_component *cdev)
 206 {
 207         int error;
 208         char name[ENCLOSURE_NAME_SIZE];
 209 
 210         error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
 211         if (error)
 212                 return error;
 213 
 214         enclosure_link_name(cdev, name);
 215         error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
 216         if (error)
 217                 sysfs_remove_link(&cdev->cdev.kobj, "device");
 218 
 219         return error;
 220 }
 221 
 222 static void enclosure_release(struct device *cdev)
 223 {
 224         struct enclosure_device *edev = to_enclosure_device(cdev);
 225 
 226         put_device(cdev->parent);
 227         kfree(edev);
 228 }
 229 
 230 static void enclosure_component_release(struct device *dev)
 231 {
 232         struct enclosure_component *cdev = to_enclosure_component(dev);
 233 
 234         if (cdev->dev) {
 235                 enclosure_remove_links(cdev);
 236                 put_device(cdev->dev);
 237         }
 238         put_device(dev->parent);
 239 }
 240 
 241 static struct enclosure_component *
 242 enclosure_component_find_by_name(struct enclosure_device *edev,
 243                                 const char *name)
 244 {
 245         int i;
 246         const char *cname;
 247         struct enclosure_component *ecomp;
 248 
 249         if (!edev || !name || !name[0])
 250                 return NULL;
 251 
 252         for (i = 0; i < edev->components; i++) {
 253                 ecomp = &edev->component[i];
 254                 cname = dev_name(&ecomp->cdev);
 255                 if (ecomp->number != -1 &&
 256                     cname && cname[0] &&
 257                     !strcmp(cname, name))
 258                         return ecomp;
 259         }
 260 
 261         return NULL;
 262 }
 263 
 264 static const struct attribute_group *enclosure_component_groups[];
 265 
 266 /**
 267  * enclosure_component_alloc - prepare a new enclosure component
 268  * @edev:       the enclosure to add the component
 269  * @num:        the device number
 270  * @type:       the type of component being added
 271  * @name:       an optional name to appear in sysfs (leave NULL if none)
 272  *
 273  * The name is optional for enclosures that give their components a unique
 274  * name.  If not, leave the field NULL and a name will be assigned.
 275  *
 276  * Returns a pointer to the enclosure component or an error.
 277  */
 278 struct enclosure_component *
 279 enclosure_component_alloc(struct enclosure_device *edev,
 280                           unsigned int number,
 281                           enum enclosure_component_type type,
 282                           const char *name)
 283 {
 284         struct enclosure_component *ecomp;
 285         struct device *cdev;
 286         int i;
 287         char newname[COMPONENT_NAME_SIZE];
 288 
 289         if (number >= edev->components)
 290                 return ERR_PTR(-EINVAL);
 291 
 292         ecomp = &edev->component[number];
 293 
 294         if (ecomp->number != -1)
 295                 return ERR_PTR(-EINVAL);
 296 
 297         ecomp->type = type;
 298         ecomp->number = number;
 299         cdev = &ecomp->cdev;
 300         cdev->parent = get_device(&edev->edev);
 301 
 302         if (name && name[0]) {
 303                 /* Some hardware (e.g. enclosure in RX300 S6) has components
 304                  * with non unique names. Registering duplicates in sysfs
 305                  * will lead to warnings during bootup. So make the names
 306                  * unique by appending consecutive numbers -1, -2, ... */
 307                 i = 1;
 308                 snprintf(newname, COMPONENT_NAME_SIZE,
 309                          "%s", name);
 310                 while (enclosure_component_find_by_name(edev, newname))
 311                         snprintf(newname, COMPONENT_NAME_SIZE,
 312                                  "%s-%i", name, i++);
 313                 dev_set_name(cdev, "%s", newname);
 314         } else
 315                 dev_set_name(cdev, "%u", number);
 316 
 317         cdev->release = enclosure_component_release;
 318         cdev->groups = enclosure_component_groups;
 319 
 320         return ecomp;
 321 }
 322 EXPORT_SYMBOL_GPL(enclosure_component_alloc);
 323 
 324 /**
 325  * enclosure_component_register - publishes an initialized enclosure component
 326  * @ecomp:      component to add
 327  *
 328  * Returns 0 on successful registration, releases the component otherwise
 329  */
 330 int enclosure_component_register(struct enclosure_component *ecomp)
 331 {
 332         struct device *cdev;
 333         int err;
 334 
 335         cdev = &ecomp->cdev;
 336         err = device_register(cdev);
 337         if (err) {
 338                 ecomp->number = -1;
 339                 put_device(cdev);
 340                 return err;
 341         }
 342 
 343         return 0;
 344 }
 345 EXPORT_SYMBOL_GPL(enclosure_component_register);
 346 
 347 /**
 348  * enclosure_add_device - add a device as being part of an enclosure
 349  * @edev:       the enclosure device being added to.
 350  * @num:        the number of the component
 351  * @dev:        the device being added
 352  *
 353  * Declares a real device to reside in slot (or identifier) @num of an
 354  * enclosure.  This will cause the relevant sysfs links to appear.
 355  * This function may also be used to change a device associated with
 356  * an enclosure without having to call enclosure_remove_device() in
 357  * between.
 358  *
 359  * Returns zero on success or an error.
 360  */
 361 int enclosure_add_device(struct enclosure_device *edev, int component,
 362                          struct device *dev)
 363 {
 364         struct enclosure_component *cdev;
 365         int err;
 366 
 367         if (!edev || component >= edev->components)
 368                 return -EINVAL;
 369 
 370         cdev = &edev->component[component];
 371 
 372         if (cdev->dev == dev)
 373                 return -EEXIST;
 374 
 375         if (cdev->dev) {
 376                 enclosure_remove_links(cdev);
 377                 put_device(cdev->dev);
 378         }
 379         cdev->dev = get_device(dev);
 380         err = enclosure_add_links(cdev);
 381         if (err) {
 382                 put_device(cdev->dev);
 383                 cdev->dev = NULL;
 384         }
 385         return err;
 386 }
 387 EXPORT_SYMBOL_GPL(enclosure_add_device);
 388 
 389 /**
 390  * enclosure_remove_device - remove a device from an enclosure
 391  * @edev:       the enclosure device
 392  * @num:        the number of the component to remove
 393  *
 394  * Returns zero on success or an error.
 395  *
 396  */
 397 int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
 398 {
 399         struct enclosure_component *cdev;
 400         int i;
 401 
 402         if (!edev || !dev)
 403                 return -EINVAL;
 404 
 405         for (i = 0; i < edev->components; i++) {
 406                 cdev = &edev->component[i];
 407                 if (cdev->dev == dev) {
 408                         enclosure_remove_links(cdev);
 409                         put_device(dev);
 410                         cdev->dev = NULL;
 411                         return 0;
 412                 }
 413         }
 414         return -ENODEV;
 415 }
 416 EXPORT_SYMBOL_GPL(enclosure_remove_device);
 417 
 418 /*
 419  * sysfs pieces below
 420  */
 421 
 422 static ssize_t components_show(struct device *cdev,
 423                                struct device_attribute *attr, char *buf)
 424 {
 425         struct enclosure_device *edev = to_enclosure_device(cdev);
 426 
 427         return snprintf(buf, 40, "%d\n", edev->components);
 428 }
 429 static DEVICE_ATTR_RO(components);
 430 
 431 static ssize_t id_show(struct device *cdev,
 432                                  struct device_attribute *attr,
 433                                  char *buf)
 434 {
 435         struct enclosure_device *edev = to_enclosure_device(cdev);
 436 
 437         if (edev->cb->show_id)
 438                 return edev->cb->show_id(edev, buf);
 439         return -EINVAL;
 440 }
 441 static DEVICE_ATTR_RO(id);
 442 
 443 static struct attribute *enclosure_class_attrs[] = {
 444         &dev_attr_components.attr,
 445         &dev_attr_id.attr,
 446         NULL,
 447 };
 448 ATTRIBUTE_GROUPS(enclosure_class);
 449 
 450 static struct class enclosure_class = {
 451         .name                   = "enclosure",
 452         .owner                  = THIS_MODULE,
 453         .dev_release            = enclosure_release,
 454         .dev_groups             = enclosure_class_groups,
 455 };
 456 
 457 static const char *const enclosure_status[] = {
 458         [ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
 459         [ENCLOSURE_STATUS_OK] = "OK",
 460         [ENCLOSURE_STATUS_CRITICAL] = "critical",
 461         [ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
 462         [ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
 463         [ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
 464         [ENCLOSURE_STATUS_UNKNOWN] = "unknown",
 465         [ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
 466         [ENCLOSURE_STATUS_MAX] = NULL,
 467 };
 468 
 469 static const char *const enclosure_type[] = {
 470         [ENCLOSURE_COMPONENT_DEVICE] = "device",
 471         [ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
 472 };
 473 
 474 static ssize_t get_component_fault(struct device *cdev,
 475                                    struct device_attribute *attr, char *buf)
 476 {
 477         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 478         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 479 
 480         if (edev->cb->get_fault)
 481                 edev->cb->get_fault(edev, ecomp);
 482         return snprintf(buf, 40, "%d\n", ecomp->fault);
 483 }
 484 
 485 static ssize_t set_component_fault(struct device *cdev,
 486                                    struct device_attribute *attr,
 487                                    const char *buf, size_t count)
 488 {
 489         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 490         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 491         int val = simple_strtoul(buf, NULL, 0);
 492 
 493         if (edev->cb->set_fault)
 494                 edev->cb->set_fault(edev, ecomp, val);
 495         return count;
 496 }
 497 
 498 static ssize_t get_component_status(struct device *cdev,
 499                                     struct device_attribute *attr,char *buf)
 500 {
 501         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 502         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 503 
 504         if (edev->cb->get_status)
 505                 edev->cb->get_status(edev, ecomp);
 506         return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
 507 }
 508 
 509 static ssize_t set_component_status(struct device *cdev,
 510                                     struct device_attribute *attr,
 511                                     const char *buf, size_t count)
 512 {
 513         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 514         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 515         int i;
 516 
 517         for (i = 0; enclosure_status[i]; i++) {
 518                 if (strncmp(buf, enclosure_status[i],
 519                             strlen(enclosure_status[i])) == 0 &&
 520                     (buf[strlen(enclosure_status[i])] == '\n' ||
 521                      buf[strlen(enclosure_status[i])] == '\0'))
 522                         break;
 523         }
 524 
 525         if (enclosure_status[i] && edev->cb->set_status) {
 526                 edev->cb->set_status(edev, ecomp, i);
 527                 return count;
 528         } else
 529                 return -EINVAL;
 530 }
 531 
 532 static ssize_t get_component_active(struct device *cdev,
 533                                     struct device_attribute *attr, char *buf)
 534 {
 535         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 536         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 537 
 538         if (edev->cb->get_active)
 539                 edev->cb->get_active(edev, ecomp);
 540         return snprintf(buf, 40, "%d\n", ecomp->active);
 541 }
 542 
 543 static ssize_t set_component_active(struct device *cdev,
 544                                     struct device_attribute *attr,
 545                                     const char *buf, size_t count)
 546 {
 547         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 548         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 549         int val = simple_strtoul(buf, NULL, 0);
 550 
 551         if (edev->cb->set_active)
 552                 edev->cb->set_active(edev, ecomp, val);
 553         return count;
 554 }
 555 
 556 static ssize_t get_component_locate(struct device *cdev,
 557                                     struct device_attribute *attr, char *buf)
 558 {
 559         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 560         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 561 
 562         if (edev->cb->get_locate)
 563                 edev->cb->get_locate(edev, ecomp);
 564         return snprintf(buf, 40, "%d\n", ecomp->locate);
 565 }
 566 
 567 static ssize_t set_component_locate(struct device *cdev,
 568                                     struct device_attribute *attr,
 569                                     const char *buf, size_t count)
 570 {
 571         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 572         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 573         int val = simple_strtoul(buf, NULL, 0);
 574 
 575         if (edev->cb->set_locate)
 576                 edev->cb->set_locate(edev, ecomp, val);
 577         return count;
 578 }
 579 
 580 static ssize_t get_component_power_status(struct device *cdev,
 581                                           struct device_attribute *attr,
 582                                           char *buf)
 583 {
 584         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 585         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 586 
 587         if (edev->cb->get_power_status)
 588                 edev->cb->get_power_status(edev, ecomp);
 589 
 590         /* If still uninitialized, the callback failed or does not exist. */
 591         if (ecomp->power_status == -1)
 592                 return (edev->cb->get_power_status) ? -EIO : -ENOTTY;
 593 
 594         return snprintf(buf, 40, "%s\n", ecomp->power_status ? "on" : "off");
 595 }
 596 
 597 static ssize_t set_component_power_status(struct device *cdev,
 598                                           struct device_attribute *attr,
 599                                           const char *buf, size_t count)
 600 {
 601         struct enclosure_device *edev = to_enclosure_device(cdev->parent);
 602         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 603         int val;
 604 
 605         if (strncmp(buf, "on", 2) == 0 &&
 606             (buf[2] == '\n' || buf[2] == '\0'))
 607                 val = 1;
 608         else if (strncmp(buf, "off", 3) == 0 &&
 609             (buf[3] == '\n' || buf[3] == '\0'))
 610                 val = 0;
 611         else
 612                 return -EINVAL;
 613 
 614         if (edev->cb->set_power_status)
 615                 edev->cb->set_power_status(edev, ecomp, val);
 616         return count;
 617 }
 618 
 619 static ssize_t get_component_type(struct device *cdev,
 620                                   struct device_attribute *attr, char *buf)
 621 {
 622         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 623 
 624         return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]);
 625 }
 626 
 627 static ssize_t get_component_slot(struct device *cdev,
 628                                   struct device_attribute *attr, char *buf)
 629 {
 630         struct enclosure_component *ecomp = to_enclosure_component(cdev);
 631         int slot;
 632 
 633         /* if the enclosure does not override then use 'number' as a stand-in */
 634         if (ecomp->slot >= 0)
 635                 slot = ecomp->slot;
 636         else
 637                 slot = ecomp->number;
 638 
 639         return snprintf(buf, 40, "%d\n", slot);
 640 }
 641 
 642 static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
 643                     set_component_fault);
 644 static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
 645                    set_component_status);
 646 static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
 647                    set_component_active);
 648 static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
 649                    set_component_locate);
 650 static DEVICE_ATTR(power_status, S_IRUGO | S_IWUSR, get_component_power_status,
 651                    set_component_power_status);
 652 static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);
 653 static DEVICE_ATTR(slot, S_IRUGO, get_component_slot, NULL);
 654 
 655 static struct attribute *enclosure_component_attrs[] = {
 656         &dev_attr_fault.attr,
 657         &dev_attr_status.attr,
 658         &dev_attr_active.attr,
 659         &dev_attr_locate.attr,
 660         &dev_attr_power_status.attr,
 661         &dev_attr_type.attr,
 662         &dev_attr_slot.attr,
 663         NULL
 664 };
 665 ATTRIBUTE_GROUPS(enclosure_component);
 666 
 667 static int __init enclosure_init(void)
 668 {
 669         return class_register(&enclosure_class);
 670 }
 671 
 672 static void __exit enclosure_exit(void)
 673 {
 674         class_unregister(&enclosure_class);
 675 }
 676 
 677 module_init(enclosure_init);
 678 module_exit(enclosure_exit);
 679 
 680 MODULE_AUTHOR("James Bottomley");
 681 MODULE_DESCRIPTION("Enclosure Services");
 682 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */