ses.c 17 KB

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