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