1 /* 2 * SCSI 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 24 #include <linux/slab.h> 25 #include <linux/module.h> 26 #include <linux/kernel.h> 27 #include <linux/enclosure.h> 28 29 #include <scsi/scsi.h> 30 #include <scsi/scsi_cmnd.h> 31 #include <scsi/scsi_dbg.h> 32 #include <scsi/scsi_device.h> 33 #include <scsi/scsi_driver.h> 34 #include <scsi/scsi_host.h> 35 36 struct ses_device { 37 unsigned char *page1; 38 unsigned char *page1_types; 39 unsigned char *page2; 40 unsigned char *page10; 41 short page1_len; 42 short page1_num_types; 43 short page2_len; 44 short page10_len; 45 }; 46 47 struct ses_component { 48 u64 addr; 49 unsigned char *desc; 50 }; 51 52 static int ses_probe(struct device *dev) 53 { 54 struct scsi_device *sdev = to_scsi_device(dev); 55 int err = -ENODEV; 56 57 if (sdev->type != TYPE_ENCLOSURE) 58 goto out; 59 60 err = 0; 61 sdev_printk(KERN_NOTICE, sdev, "Attached Enclosure device\n"); 62 63 out: 64 return err; 65 } 66 67 #define SES_TIMEOUT (30 * HZ) 68 #define SES_RETRIES 3 69 70 static int ses_recv_diag(struct scsi_device *sdev, int page_code, 71 void *buf, int bufflen) 72 { 73 unsigned char cmd[] = { 74 RECEIVE_DIAGNOSTIC, 75 1, /* Set PCV bit */ 76 page_code, 77 bufflen >> 8, 78 bufflen & 0xff, 79 0 80 }; 81 82 return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen, 83 NULL, SES_TIMEOUT, SES_RETRIES, NULL); 84 } 85 86 static int ses_send_diag(struct scsi_device *sdev, int page_code, 87 void *buf, int bufflen) 88 { 89 u32 result; 90 91 unsigned char cmd[] = { 92 SEND_DIAGNOSTIC, 93 0x10, /* Set PF bit */ 94 0, 95 bufflen >> 8, 96 bufflen & 0xff, 97 0 98 }; 99 100 result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen, 101 NULL, SES_TIMEOUT, SES_RETRIES, NULL); 102 if (result) 103 sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n", 104 result); 105 return result; 106 } 107 108 static int ses_set_page2_descriptor(struct enclosure_device *edev, 109 struct enclosure_component *ecomp, 110 unsigned char *desc) 111 { 112 int i, j, count = 0, descriptor = ecomp->number; 113 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 114 struct ses_device *ses_dev = edev->scratch; 115 unsigned char *type_ptr = ses_dev->page1_types; 116 unsigned char *desc_ptr = ses_dev->page2 + 8; 117 118 /* Clear everything */ 119 memset(desc_ptr, 0, ses_dev->page2_len - 8); 120 for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) { 121 for (j = 0; j < type_ptr[1]; j++) { 122 desc_ptr += 4; 123 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 124 type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE) 125 continue; 126 if (count++ == descriptor) { 127 memcpy(desc_ptr, desc, 4); 128 /* set select */ 129 desc_ptr[0] |= 0x80; 130 /* clear reserved, just in case */ 131 desc_ptr[0] &= 0xf0; 132 } 133 } 134 } 135 136 return ses_send_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); 137 } 138 139 static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev, 140 struct enclosure_component *ecomp) 141 { 142 int i, j, count = 0, descriptor = ecomp->number; 143 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 144 struct ses_device *ses_dev = edev->scratch; 145 unsigned char *type_ptr = ses_dev->page1_types; 146 unsigned char *desc_ptr = ses_dev->page2 + 8; 147 148 ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); 149 150 for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) { 151 for (j = 0; j < type_ptr[1]; j++) { 152 desc_ptr += 4; 153 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 154 type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE) 155 continue; 156 if (count++ == descriptor) 157 return desc_ptr; 158 } 159 } 160 return NULL; 161 } 162 163 /* For device slot and array device slot elements, byte 3 bit 6 164 * is "fault sensed" while byte 3 bit 5 is "fault reqstd". As this 165 * code stands these bits are shifted 4 positions right so in 166 * sysfs they will appear as bits 2 and 1 respectively. Strange. */ 167 static void ses_get_fault(struct enclosure_device *edev, 168 struct enclosure_component *ecomp) 169 { 170 unsigned char *desc; 171 172 desc = ses_get_page2_descriptor(edev, ecomp); 173 if (desc) 174 ecomp->fault = (desc[3] & 0x60) >> 4; 175 } 176 177 static int ses_set_fault(struct enclosure_device *edev, 178 struct enclosure_component *ecomp, 179 enum enclosure_component_setting val) 180 { 181 unsigned char desc[4] = {0 }; 182 183 switch (val) { 184 case ENCLOSURE_SETTING_DISABLED: 185 /* zero is disabled */ 186 break; 187 case ENCLOSURE_SETTING_ENABLED: 188 desc[3] = 0x20; 189 break; 190 default: 191 /* SES doesn't do the SGPIO blink settings */ 192 return -EINVAL; 193 } 194 195 return ses_set_page2_descriptor(edev, ecomp, desc); 196 } 197 198 static void ses_get_status(struct enclosure_device *edev, 199 struct enclosure_component *ecomp) 200 { 201 unsigned char *desc; 202 203 desc = ses_get_page2_descriptor(edev, ecomp); 204 if (desc) 205 ecomp->status = (desc[0] & 0x0f); 206 } 207 208 static void ses_get_locate(struct enclosure_device *edev, 209 struct enclosure_component *ecomp) 210 { 211 unsigned char *desc; 212 213 desc = ses_get_page2_descriptor(edev, ecomp); 214 if (desc) 215 ecomp->locate = (desc[2] & 0x02) ? 1 : 0; 216 } 217 218 static int ses_set_locate(struct enclosure_device *edev, 219 struct enclosure_component *ecomp, 220 enum enclosure_component_setting val) 221 { 222 unsigned char desc[4] = {0 }; 223 224 switch (val) { 225 case ENCLOSURE_SETTING_DISABLED: 226 /* zero is disabled */ 227 break; 228 case ENCLOSURE_SETTING_ENABLED: 229 desc[2] = 0x02; 230 break; 231 default: 232 /* SES doesn't do the SGPIO blink settings */ 233 return -EINVAL; 234 } 235 return ses_set_page2_descriptor(edev, ecomp, desc); 236 } 237 238 static int ses_set_active(struct enclosure_device *edev, 239 struct enclosure_component *ecomp, 240 enum enclosure_component_setting val) 241 { 242 unsigned char desc[4] = {0 }; 243 244 switch (val) { 245 case ENCLOSURE_SETTING_DISABLED: 246 /* zero is disabled */ 247 ecomp->active = 0; 248 break; 249 case ENCLOSURE_SETTING_ENABLED: 250 desc[2] = 0x80; 251 ecomp->active = 1; 252 break; 253 default: 254 /* SES doesn't do the SGPIO blink settings */ 255 return -EINVAL; 256 } 257 return ses_set_page2_descriptor(edev, ecomp, desc); 258 } 259 260 static struct enclosure_component_callbacks ses_enclosure_callbacks = { 261 .get_fault = ses_get_fault, 262 .set_fault = ses_set_fault, 263 .get_status = ses_get_status, 264 .get_locate = ses_get_locate, 265 .set_locate = ses_set_locate, 266 .set_active = ses_set_active, 267 }; 268 269 struct ses_host_edev { 270 struct Scsi_Host *shost; 271 struct enclosure_device *edev; 272 }; 273 274 #if 0 275 int ses_match_host(struct enclosure_device *edev, void *data) 276 { 277 struct ses_host_edev *sed = data; 278 struct scsi_device *sdev; 279 280 if (!scsi_is_sdev_device(edev->edev.parent)) 281 return 0; 282 283 sdev = to_scsi_device(edev->edev.parent); 284 285 if (sdev->host != sed->shost) 286 return 0; 287 288 sed->edev = edev; 289 return 1; 290 } 291 #endif /* 0 */ 292 293 static void ses_process_descriptor(struct enclosure_component *ecomp, 294 unsigned char *desc) 295 { 296 int eip = desc[0] & 0x10; 297 int invalid = desc[0] & 0x80; 298 enum scsi_protocol proto = desc[0] & 0x0f; 299 u64 addr = 0; 300 struct ses_component *scomp = ecomp->scratch; 301 unsigned char *d; 302 303 scomp->desc = desc; 304 305 if (invalid) 306 return; 307 308 switch (proto) { 309 case SCSI_PROTOCOL_SAS: 310 if (eip) 311 d = desc + 8; 312 else 313 d = desc + 4; 314 /* only take the phy0 addr */ 315 addr = (u64)d[12] << 56 | 316 (u64)d[13] << 48 | 317 (u64)d[14] << 40 | 318 (u64)d[15] << 32 | 319 (u64)d[16] << 24 | 320 (u64)d[17] << 16 | 321 (u64)d[18] << 8 | 322 (u64)d[19]; 323 break; 324 default: 325 /* FIXME: Need to add more protocols than just SAS */ 326 break; 327 } 328 scomp->addr = addr; 329 } 330 331 struct efd { 332 u64 addr; 333 struct device *dev; 334 }; 335 336 static int ses_enclosure_find_by_addr(struct enclosure_device *edev, 337 void *data) 338 { 339 struct efd *efd = data; 340 int i; 341 struct ses_component *scomp; 342 343 if (!edev->component[0].scratch) 344 return 0; 345 346 for (i = 0; i < edev->components; i++) { 347 scomp = edev->component[i].scratch; 348 if (scomp->addr != efd->addr) 349 continue; 350 351 enclosure_add_device(edev, i, efd->dev); 352 return 1; 353 } 354 return 0; 355 } 356 357 #define INIT_ALLOC_SIZE 32 358 359 static void ses_enclosure_data_process(struct enclosure_device *edev, 360 struct scsi_device *sdev, 361 int create) 362 { 363 u32 result; 364 unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL; 365 int i, j, page7_len, len, components; 366 struct ses_device *ses_dev = edev->scratch; 367 int types = ses_dev->page1_num_types; 368 unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 369 370 if (!hdr_buf) 371 goto simple_populate; 372 373 /* re-read page 10 */ 374 if (ses_dev->page10) 375 ses_recv_diag(sdev, 10, ses_dev->page10, ses_dev->page10_len); 376 /* Page 7 for the descriptors is optional */ 377 result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE); 378 if (result) 379 goto simple_populate; 380 381 page7_len = len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 382 /* add 1 for trailing '\0' we'll use */ 383 buf = kzalloc(len + 1, GFP_KERNEL); 384 if (!buf) 385 goto simple_populate; 386 result = ses_recv_diag(sdev, 7, buf, len); 387 if (result) { 388 simple_populate: 389 kfree(buf); 390 buf = NULL; 391 desc_ptr = NULL; 392 len = 0; 393 page7_len = 0; 394 } else { 395 desc_ptr = buf + 8; 396 len = (desc_ptr[2] << 8) + desc_ptr[3]; 397 /* skip past overall descriptor */ 398 desc_ptr += len + 4; 399 } 400 if (ses_dev->page10) 401 addl_desc_ptr = ses_dev->page10 + 8; 402 type_ptr = ses_dev->page1_types; 403 components = 0; 404 for (i = 0; i < types; i++, type_ptr += 4) { 405 for (j = 0; j < type_ptr[1]; j++) { 406 char *name = NULL; 407 struct enclosure_component *ecomp; 408 409 if (desc_ptr) { 410 if (desc_ptr >= buf + page7_len) { 411 desc_ptr = NULL; 412 } else { 413 len = (desc_ptr[2] << 8) + desc_ptr[3]; 414 desc_ptr += 4; 415 /* Add trailing zero - pushes into 416 * reserved space */ 417 desc_ptr[len] = '\0'; 418 name = desc_ptr; 419 } 420 } 421 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || 422 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) { 423 424 if (create) 425 ecomp = enclosure_component_register(edev, 426 components++, 427 type_ptr[0], 428 name); 429 else 430 ecomp = &edev->component[components++]; 431 432 if (!IS_ERR(ecomp) && addl_desc_ptr) 433 ses_process_descriptor(ecomp, 434 addl_desc_ptr); 435 } 436 if (desc_ptr) 437 desc_ptr += len; 438 439 if (addl_desc_ptr) 440 addl_desc_ptr += addl_desc_ptr[1] + 2; 441 442 } 443 } 444 kfree(buf); 445 kfree(hdr_buf); 446 } 447 448 static void ses_match_to_enclosure(struct enclosure_device *edev, 449 struct scsi_device *sdev) 450 { 451 unsigned char *buf; 452 unsigned char *desc; 453 unsigned int vpd_len; 454 struct efd efd = { 455 .addr = 0, 456 }; 457 458 buf = kmalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 459 if (!buf || scsi_get_vpd_page(sdev, 0x83, buf, INIT_ALLOC_SIZE)) 460 goto free; 461 462 ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0); 463 464 vpd_len = ((buf[2] << 8) | buf[3]) + 4; 465 kfree(buf); 466 buf = kmalloc(vpd_len, GFP_KERNEL); 467 if (!buf ||scsi_get_vpd_page(sdev, 0x83, buf, vpd_len)) 468 goto free; 469 470 desc = buf + 4; 471 while (desc < buf + vpd_len) { 472 enum scsi_protocol proto = desc[0] >> 4; 473 u8 code_set = desc[0] & 0x0f; 474 u8 piv = desc[1] & 0x80; 475 u8 assoc = (desc[1] & 0x30) >> 4; 476 u8 type = desc[1] & 0x0f; 477 u8 len = desc[3]; 478 479 if (piv && code_set == 1 && assoc == 1 480 && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8) 481 efd.addr = (u64)desc[4] << 56 | 482 (u64)desc[5] << 48 | 483 (u64)desc[6] << 40 | 484 (u64)desc[7] << 32 | 485 (u64)desc[8] << 24 | 486 (u64)desc[9] << 16 | 487 (u64)desc[10] << 8 | 488 (u64)desc[11]; 489 490 desc += len + 4; 491 } 492 if (!efd.addr) 493 goto free; 494 495 efd.dev = &sdev->sdev_gendev; 496 497 enclosure_for_each_device(ses_enclosure_find_by_addr, &efd); 498 free: 499 kfree(buf); 500 } 501 502 static int ses_intf_add(struct device *cdev, 503 struct class_interface *intf) 504 { 505 struct scsi_device *sdev = to_scsi_device(cdev->parent); 506 struct scsi_device *tmp_sdev; 507 unsigned char *buf = NULL, *hdr_buf, *type_ptr; 508 struct ses_device *ses_dev; 509 u32 result; 510 int i, types, len, components = 0; 511 int err = -ENOMEM; 512 int num_enclosures; 513 struct enclosure_device *edev; 514 struct ses_component *scomp = NULL; 515 516 if (!scsi_device_enclosure(sdev)) { 517 /* not an enclosure, but might be in one */ 518 struct enclosure_device *prev = NULL; 519 520 while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) { 521 ses_match_to_enclosure(edev, sdev); 522 prev = edev; 523 } 524 return -ENODEV; 525 } 526 527 /* TYPE_ENCLOSURE prints a message in probe */ 528 if (sdev->type != TYPE_ENCLOSURE) 529 sdev_printk(KERN_NOTICE, sdev, "Embedded Enclosure Device\n"); 530 531 ses_dev = kzalloc(sizeof(*ses_dev), GFP_KERNEL); 532 hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 533 if (!hdr_buf || !ses_dev) 534 goto err_init_free; 535 536 result = ses_recv_diag(sdev, 1, hdr_buf, INIT_ALLOC_SIZE); 537 if (result) 538 goto recv_failed; 539 540 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 541 buf = kzalloc(len, GFP_KERNEL); 542 if (!buf) 543 goto err_free; 544 545 result = ses_recv_diag(sdev, 1, buf, len); 546 if (result) 547 goto recv_failed; 548 549 types = 0; 550 551 /* we always have one main enclosure and the rest are referred 552 * to as secondary subenclosures */ 553 num_enclosures = buf[1] + 1; 554 555 /* begin at the enclosure descriptor */ 556 type_ptr = buf + 8; 557 /* skip all the enclosure descriptors */ 558 for (i = 0; i < num_enclosures && type_ptr < buf + len; i++) { 559 types += type_ptr[2]; 560 type_ptr += type_ptr[3] + 4; 561 } 562 563 ses_dev->page1_types = type_ptr; 564 ses_dev->page1_num_types = types; 565 566 for (i = 0; i < types && type_ptr < buf + len; i++, type_ptr += 4) { 567 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || 568 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) 569 components += type_ptr[1]; 570 } 571 ses_dev->page1 = buf; 572 ses_dev->page1_len = len; 573 buf = NULL; 574 575 result = ses_recv_diag(sdev, 2, hdr_buf, INIT_ALLOC_SIZE); 576 if (result) 577 goto recv_failed; 578 579 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 580 buf = kzalloc(len, GFP_KERNEL); 581 if (!buf) 582 goto err_free; 583 584 /* make sure getting page 2 actually works */ 585 result = ses_recv_diag(sdev, 2, buf, len); 586 if (result) 587 goto recv_failed; 588 ses_dev->page2 = buf; 589 ses_dev->page2_len = len; 590 buf = NULL; 591 592 /* The additional information page --- allows us 593 * to match up the devices */ 594 result = ses_recv_diag(sdev, 10, hdr_buf, INIT_ALLOC_SIZE); 595 if (!result) { 596 597 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 598 buf = kzalloc(len, GFP_KERNEL); 599 if (!buf) 600 goto err_free; 601 602 result = ses_recv_diag(sdev, 10, buf, len); 603 if (result) 604 goto recv_failed; 605 ses_dev->page10 = buf; 606 ses_dev->page10_len = len; 607 buf = NULL; 608 } 609 scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); 610 if (!scomp) 611 goto err_free; 612 613 edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev), 614 components, &ses_enclosure_callbacks); 615 if (IS_ERR(edev)) { 616 err = PTR_ERR(edev); 617 goto err_free; 618 } 619 620 kfree(hdr_buf); 621 622 edev->scratch = ses_dev; 623 for (i = 0; i < components; i++) 624 edev->component[i].scratch = scomp + i; 625 626 ses_enclosure_data_process(edev, sdev, 1); 627 628 /* see if there are any devices matching before 629 * we found the enclosure */ 630 shost_for_each_device(tmp_sdev, sdev->host) { 631 if (tmp_sdev->lun != 0 || scsi_device_enclosure(tmp_sdev)) 632 continue; 633 ses_match_to_enclosure(edev, tmp_sdev); 634 } 635 636 return 0; 637 638 recv_failed: 639 sdev_printk(KERN_ERR, sdev, "Failed to get diagnostic page 0x%x\n", 640 result); 641 err = -ENODEV; 642 err_free: 643 kfree(buf); 644 kfree(scomp); 645 kfree(ses_dev->page10); 646 kfree(ses_dev->page2); 647 kfree(ses_dev->page1); 648 err_init_free: 649 kfree(ses_dev); 650 kfree(hdr_buf); 651 sdev_printk(KERN_ERR, sdev, "Failed to bind enclosure %d\n", err); 652 return err; 653 } 654 655 static int ses_remove(struct device *dev) 656 { 657 return 0; 658 } 659 660 static void ses_intf_remove_component(struct scsi_device *sdev) 661 { 662 struct enclosure_device *edev, *prev = NULL; 663 664 while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) { 665 prev = edev; 666 if (!enclosure_remove_device(edev, &sdev->sdev_gendev)) 667 break; 668 } 669 if (edev) 670 put_device(&edev->edev); 671 } 672 673 static void ses_intf_remove_enclosure(struct scsi_device *sdev) 674 { 675 struct enclosure_device *edev; 676 struct ses_device *ses_dev; 677 678 /* exact match to this enclosure */ 679 edev = enclosure_find(&sdev->sdev_gendev, NULL); 680 if (!edev) 681 return; 682 683 ses_dev = edev->scratch; 684 edev->scratch = NULL; 685 686 kfree(ses_dev->page10); 687 kfree(ses_dev->page1); 688 kfree(ses_dev->page2); 689 kfree(ses_dev); 690 691 kfree(edev->component[0].scratch); 692 693 put_device(&edev->edev); 694 enclosure_unregister(edev); 695 } 696 697 static void ses_intf_remove(struct device *cdev, 698 struct class_interface *intf) 699 { 700 struct scsi_device *sdev = to_scsi_device(cdev->parent); 701 702 if (!scsi_device_enclosure(sdev)) 703 ses_intf_remove_component(sdev); 704 else 705 ses_intf_remove_enclosure(sdev); 706 } 707 708 static struct class_interface ses_interface = { 709 .add_dev = ses_intf_add, 710 .remove_dev = ses_intf_remove, 711 }; 712 713 static struct scsi_driver ses_template = { 714 .owner = THIS_MODULE, 715 .gendrv = { 716 .name = "ses", 717 .probe = ses_probe, 718 .remove = ses_remove, 719 }, 720 }; 721 722 static int __init ses_init(void) 723 { 724 int err; 725 726 err = scsi_register_interface(&ses_interface); 727 if (err) 728 return err; 729 730 err = scsi_register_driver(&ses_template.gendrv); 731 if (err) 732 goto out_unreg; 733 734 return 0; 735 736 out_unreg: 737 scsi_unregister_interface(&ses_interface); 738 return err; 739 } 740 741 static void __exit ses_exit(void) 742 { 743 scsi_unregister_driver(&ses_template.gendrv); 744 scsi_unregister_interface(&ses_interface); 745 } 746 747 module_init(ses_init); 748 module_exit(ses_exit); 749 750 MODULE_ALIAS_SCSI_DEVICE(TYPE_ENCLOSURE); 751 752 MODULE_AUTHOR("James Bottomley"); 753 MODULE_DESCRIPTION("SCSI Enclosure Services (ses) driver"); 754 MODULE_LICENSE("GPL v2"); 755