scsi_dh_emc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. * Target driver for EMC CLARiiON AX/CX-series hardware.
  3. * Based on code from Lars Marowsky-Bree <lmb@suse.de>
  4. * and Ed Goggin <egoggin@emc.com>.
  5. *
  6. * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
  7. * Copyright (C) 2006 Mike Christie
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2, or (at your option)
  12. * any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; see the file COPYING. If not, write to
  21. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include <scsi/scsi.h>
  24. #include <scsi/scsi_eh.h>
  25. #include <scsi/scsi_dh.h>
  26. #include <scsi/scsi_device.h>
  27. #define CLARIION_NAME "emc_clariion"
  28. #define CLARIION_TRESPASS_PAGE 0x22
  29. #define CLARIION_BUFFER_SIZE 0x80
  30. #define CLARIION_TIMEOUT (60 * HZ)
  31. #define CLARIION_RETRIES 3
  32. #define CLARIION_UNBOUND_LU -1
  33. static unsigned char long_trespass[] = {
  34. 0, 0, 0, 0,
  35. CLARIION_TRESPASS_PAGE, /* Page code */
  36. 0x09, /* Page length - 2 */
  37. 0x81, /* Trespass code + Honor reservation bit */
  38. 0xff, 0xff, /* Trespass target */
  39. 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
  40. };
  41. static unsigned char long_trespass_hr[] = {
  42. 0, 0, 0, 0,
  43. CLARIION_TRESPASS_PAGE, /* Page code */
  44. 0x09, /* Page length - 2 */
  45. 0x01, /* Trespass code + Honor reservation bit */
  46. 0xff, 0xff, /* Trespass target */
  47. 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
  48. };
  49. static unsigned char short_trespass[] = {
  50. 0, 0, 0, 0,
  51. CLARIION_TRESPASS_PAGE, /* Page code */
  52. 0x02, /* Page length - 2 */
  53. 0x81, /* Trespass code + Honor reservation bit */
  54. 0xff, /* Trespass target */
  55. };
  56. static unsigned char short_trespass_hr[] = {
  57. 0, 0, 0, 0,
  58. CLARIION_TRESPASS_PAGE, /* Page code */
  59. 0x02, /* Page length - 2 */
  60. 0x01, /* Trespass code + Honor reservation bit */
  61. 0xff, /* Trespass target */
  62. };
  63. struct clariion_dh_data {
  64. /*
  65. * Use short trespass command (FC-series) or the long version
  66. * (default for AX/CX CLARiiON arrays).
  67. */
  68. unsigned short_trespass;
  69. /*
  70. * Whether or not (default) to honor SCSI reservations when
  71. * initiating a switch-over.
  72. */
  73. unsigned hr;
  74. /* I/O buffer for both MODE_SELECT and INQUIRY commands. */
  75. char buffer[CLARIION_BUFFER_SIZE];
  76. /*
  77. * SCSI sense buffer for commands -- assumes serial issuance
  78. * and completion sequence of all commands for same multipath.
  79. */
  80. unsigned char sense[SCSI_SENSE_BUFFERSIZE];
  81. /* which SP (A=0,B=1,UNBOUND=-1) is dflt SP for path's mapped dev */
  82. int default_sp;
  83. /* which SP (A=0,B=1,UNBOUND=-1) is active for path's mapped dev */
  84. int current_sp;
  85. };
  86. static inline struct clariion_dh_data
  87. *get_clariion_data(struct scsi_device *sdev)
  88. {
  89. struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
  90. BUG_ON(scsi_dh_data == NULL);
  91. return ((struct clariion_dh_data *) scsi_dh_data->buf);
  92. }
  93. /*
  94. * Parse MODE_SELECT cmd reply.
  95. */
  96. static int trespass_endio(struct scsi_device *sdev, int result)
  97. {
  98. int err = SCSI_DH_OK;
  99. struct scsi_sense_hdr sshdr;
  100. struct clariion_dh_data *csdev = get_clariion_data(sdev);
  101. char *sense = csdev->sense;
  102. if (status_byte(result) == CHECK_CONDITION &&
  103. scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
  104. sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, "
  105. "0x%2x, 0x%2x while sending CLARiiON trespass "
  106. "command.\n", sshdr.sense_key, sshdr.asc,
  107. sshdr.ascq);
  108. if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
  109. (sshdr.ascq == 0x00)) {
  110. /*
  111. * Array based copy in progress -- do not send
  112. * mode_select or copy will be aborted mid-stream.
  113. */
  114. sdev_printk(KERN_INFO, sdev, "Array Based Copy in "
  115. "progress while sending CLARiiON trespass "
  116. "command.\n");
  117. err = SCSI_DH_DEV_TEMP_BUSY;
  118. } else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
  119. (sshdr.ascq == 0x03)) {
  120. /*
  121. * LUN Not Ready - Manual Intervention Required
  122. * indicates in-progress ucode upgrade (NDU).
  123. */
  124. sdev_printk(KERN_INFO, sdev, "Detected in-progress "
  125. "ucode upgrade NDU operation while sending "
  126. "CLARiiON trespass command.\n");
  127. err = SCSI_DH_DEV_TEMP_BUSY;
  128. } else
  129. err = SCSI_DH_DEV_FAILED;
  130. } else if (result) {
  131. sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending "
  132. "CLARiiON trespass command.\n", result);
  133. err = SCSI_DH_IO;
  134. }
  135. return err;
  136. }
  137. static int parse_sp_info_reply(struct scsi_device *sdev, int result,
  138. int *default_sp, int *current_sp, int *new_current_sp)
  139. {
  140. int err = SCSI_DH_OK;
  141. struct clariion_dh_data *csdev = get_clariion_data(sdev);
  142. if (result == 0) {
  143. /* check for in-progress ucode upgrade (NDU) */
  144. if (csdev->buffer[48] != 0) {
  145. sdev_printk(KERN_NOTICE, sdev, "Detected in-progress "
  146. "ucode upgrade NDU operation while finding "
  147. "current active SP.");
  148. err = SCSI_DH_DEV_TEMP_BUSY;
  149. } else {
  150. *default_sp = csdev->buffer[5];
  151. if (csdev->buffer[4] == 2)
  152. /* SP for path is current */
  153. *current_sp = csdev->buffer[8];
  154. else {
  155. if (csdev->buffer[4] == 1)
  156. /* SP for this path is NOT current */
  157. if (csdev->buffer[8] == 0)
  158. *current_sp = 1;
  159. else
  160. *current_sp = 0;
  161. else
  162. /* unbound LU or LUNZ */
  163. *current_sp = CLARIION_UNBOUND_LU;
  164. }
  165. *new_current_sp = csdev->buffer[8];
  166. }
  167. } else {
  168. struct scsi_sense_hdr sshdr;
  169. err = SCSI_DH_IO;
  170. if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
  171. &sshdr))
  172. sdev_printk(KERN_ERR, sdev, "Found valid sense data "
  173. "0x%2x, 0x%2x, 0x%2x while finding current "
  174. "active SP.", sshdr.sense_key, sshdr.asc,
  175. sshdr.ascq);
  176. else
  177. sdev_printk(KERN_ERR, sdev, "Error 0x%x finding "
  178. "current active SP.", result);
  179. }
  180. return err;
  181. }
  182. static int sp_info_endio(struct scsi_device *sdev, int result,
  183. int mode_select_sent, int *done)
  184. {
  185. struct clariion_dh_data *csdev = get_clariion_data(sdev);
  186. int err_flags, default_sp, current_sp, new_current_sp;
  187. err_flags = parse_sp_info_reply(sdev, result, &default_sp,
  188. &current_sp, &new_current_sp);
  189. if (err_flags != SCSI_DH_OK)
  190. goto done;
  191. if (mode_select_sent) {
  192. csdev->default_sp = default_sp;
  193. csdev->current_sp = current_sp;
  194. } else {
  195. /*
  196. * Issue the actual module_selec request IFF either
  197. * (1) we do not know the identity of the current SP OR
  198. * (2) what we think we know is actually correct.
  199. */
  200. if ((current_sp != CLARIION_UNBOUND_LU) &&
  201. (new_current_sp != current_sp)) {
  202. csdev->default_sp = default_sp;
  203. csdev->current_sp = current_sp;
  204. sdev_printk(KERN_INFO, sdev, "Ignoring path group "
  205. "switch-over command for CLARiiON SP%s since "
  206. " mapped device is already initialized.",
  207. current_sp ? "B" : "A");
  208. if (done)
  209. *done = 1; /* as good as doing it */
  210. }
  211. }
  212. done:
  213. return err_flags;
  214. }
  215. /*
  216. * Get block request for REQ_BLOCK_PC command issued to path. Currently
  217. * limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
  218. *
  219. * Uses data and sense buffers in hardware handler context structure and
  220. * assumes serial servicing of commands, both issuance and completion.
  221. */
  222. static struct request *get_req(struct scsi_device *sdev, int cmd)
  223. {
  224. struct clariion_dh_data *csdev = get_clariion_data(sdev);
  225. struct request *rq;
  226. unsigned char *page22;
  227. int len = 0;
  228. rq = blk_get_request(sdev->request_queue,
  229. (cmd == MODE_SELECT) ? WRITE : READ, GFP_ATOMIC);
  230. if (!rq) {
  231. sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
  232. return NULL;
  233. }
  234. memset(&rq->cmd, 0, BLK_MAX_CDB);
  235. rq->cmd[0] = cmd;
  236. rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
  237. switch (cmd) {
  238. case MODE_SELECT:
  239. if (csdev->short_trespass) {
  240. page22 = csdev->hr ? short_trespass_hr : short_trespass;
  241. len = sizeof(short_trespass);
  242. } else {
  243. page22 = csdev->hr ? long_trespass_hr : long_trespass;
  244. len = sizeof(long_trespass);
  245. }
  246. /*
  247. * Can't DMA from kernel BSS -- must copy selected trespass
  248. * command mode page contents to context buffer which is
  249. * allocated by kmalloc.
  250. */
  251. BUG_ON((len > CLARIION_BUFFER_SIZE));
  252. memcpy(csdev->buffer, page22, len);
  253. rq->cmd_flags |= REQ_RW;
  254. rq->cmd[1] = 0x10;
  255. break;
  256. case INQUIRY:
  257. rq->cmd[1] = 0x1;
  258. rq->cmd[2] = 0xC0;
  259. len = CLARIION_BUFFER_SIZE;
  260. memset(csdev->buffer, 0, CLARIION_BUFFER_SIZE);
  261. break;
  262. default:
  263. BUG_ON(1);
  264. break;
  265. }
  266. rq->cmd[4] = len;
  267. rq->cmd_type = REQ_TYPE_BLOCK_PC;
  268. rq->cmd_flags |= REQ_FAILFAST;
  269. rq->timeout = CLARIION_TIMEOUT;
  270. rq->retries = CLARIION_RETRIES;
  271. rq->sense = csdev->sense;
  272. memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
  273. rq->sense_len = 0;
  274. if (blk_rq_map_kern(sdev->request_queue, rq, csdev->buffer,
  275. len, GFP_ATOMIC)) {
  276. __blk_put_request(rq->q, rq);
  277. return NULL;
  278. }
  279. return rq;
  280. }
  281. static int send_cmd(struct scsi_device *sdev, int cmd)
  282. {
  283. struct request *rq = get_req(sdev, cmd);
  284. if (!rq)
  285. return SCSI_DH_RES_TEMP_UNAVAIL;
  286. return blk_execute_rq(sdev->request_queue, NULL, rq, 1);
  287. }
  288. static int clariion_activate(struct scsi_device *sdev)
  289. {
  290. int result, done = 0;
  291. result = send_cmd(sdev, INQUIRY);
  292. result = sp_info_endio(sdev, result, 0, &done);
  293. if (result || done)
  294. goto done;
  295. result = send_cmd(sdev, MODE_SELECT);
  296. result = trespass_endio(sdev, result);
  297. if (result)
  298. goto done;
  299. result = send_cmd(sdev, INQUIRY);
  300. result = sp_info_endio(sdev, result, 1, NULL);
  301. done:
  302. return result;
  303. }
  304. static int clariion_check_sense(struct scsi_device *sdev,
  305. struct scsi_sense_hdr *sense_hdr)
  306. {
  307. switch (sense_hdr->sense_key) {
  308. case NOT_READY:
  309. if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x03)
  310. /*
  311. * LUN Not Ready - Manual Intervention Required
  312. * indicates this is a passive path.
  313. *
  314. * FIXME: However, if this is seen and EVPD C0
  315. * indicates that this is due to a NDU in
  316. * progress, we should set FAIL_PATH too.
  317. * This indicates we might have to do a SCSI
  318. * inquiry in the end_io path. Ugh.
  319. *
  320. * Can return FAILED only when we want the error
  321. * recovery process to kick in.
  322. */
  323. return SUCCESS;
  324. break;
  325. case ILLEGAL_REQUEST:
  326. if (sense_hdr->asc == 0x25 && sense_hdr->ascq == 0x01)
  327. /*
  328. * An array based copy is in progress. Do not
  329. * fail the path, do not bypass to another PG,
  330. * do not retry. Fail the IO immediately.
  331. * (Actually this is the same conclusion as in
  332. * the default handler, but lets make sure.)
  333. *
  334. * Can return FAILED only when we want the error
  335. * recovery process to kick in.
  336. */
  337. return SUCCESS;
  338. break;
  339. case UNIT_ATTENTION:
  340. if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
  341. /*
  342. * Unit Attention Code. This is the first IO
  343. * to the new path, so just retry.
  344. */
  345. return NEEDS_RETRY;
  346. break;
  347. }
  348. /* success just means we do not care what scsi-ml does */
  349. return SUCCESS;
  350. }
  351. static const struct {
  352. char *vendor;
  353. char *model;
  354. } clariion_dev_list[] = {
  355. {"DGC", "RAID"},
  356. {"DGC", "DISK"},
  357. {NULL, NULL},
  358. };
  359. static int clariion_bus_notify(struct notifier_block *, unsigned long, void *);
  360. static struct scsi_device_handler clariion_dh = {
  361. .name = CLARIION_NAME,
  362. .module = THIS_MODULE,
  363. .nb.notifier_call = clariion_bus_notify,
  364. .check_sense = clariion_check_sense,
  365. .activate = clariion_activate,
  366. };
  367. /*
  368. * TODO: need some interface so we can set trespass values
  369. */
  370. static int clariion_bus_notify(struct notifier_block *nb,
  371. unsigned long action, void *data)
  372. {
  373. struct device *dev = data;
  374. struct scsi_device *sdev;
  375. struct scsi_dh_data *scsi_dh_data;
  376. struct clariion_dh_data *h;
  377. int i, found = 0;
  378. unsigned long flags;
  379. if (!scsi_is_sdev_device(dev))
  380. return 0;
  381. sdev = to_scsi_device(dev);
  382. if (action == BUS_NOTIFY_ADD_DEVICE) {
  383. for (i = 0; clariion_dev_list[i].vendor; i++) {
  384. if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
  385. strlen(clariion_dev_list[i].vendor)) &&
  386. !strncmp(sdev->model, clariion_dev_list[i].model,
  387. strlen(clariion_dev_list[i].model))) {
  388. found = 1;
  389. break;
  390. }
  391. }
  392. if (!found)
  393. goto out;
  394. scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
  395. + sizeof(*h) , GFP_KERNEL);
  396. if (!scsi_dh_data) {
  397. sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
  398. CLARIION_NAME);
  399. goto out;
  400. }
  401. scsi_dh_data->scsi_dh = &clariion_dh;
  402. h = (struct clariion_dh_data *) scsi_dh_data->buf;
  403. h->default_sp = CLARIION_UNBOUND_LU;
  404. h->current_sp = CLARIION_UNBOUND_LU;
  405. spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
  406. sdev->scsi_dh_data = scsi_dh_data;
  407. spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
  408. sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME);
  409. try_module_get(THIS_MODULE);
  410. } else if (action == BUS_NOTIFY_DEL_DEVICE) {
  411. if (sdev->scsi_dh_data == NULL ||
  412. sdev->scsi_dh_data->scsi_dh != &clariion_dh)
  413. goto out;
  414. spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
  415. scsi_dh_data = sdev->scsi_dh_data;
  416. sdev->scsi_dh_data = NULL;
  417. spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
  418. sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n",
  419. CLARIION_NAME);
  420. kfree(scsi_dh_data);
  421. module_put(THIS_MODULE);
  422. }
  423. out:
  424. return 0;
  425. }
  426. static int __init clariion_init(void)
  427. {
  428. int r;
  429. r = scsi_register_device_handler(&clariion_dh);
  430. if (r != 0)
  431. printk(KERN_ERR "Failed to register scsi device handler.");
  432. return r;
  433. }
  434. static void __exit clariion_exit(void)
  435. {
  436. scsi_unregister_device_handler(&clariion_dh);
  437. }
  438. module_init(clariion_init);
  439. module_exit(clariion_exit);
  440. MODULE_DESCRIPTION("EMC CX/AX/FC-family driver");
  441. MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, Chandra Seetharaman <sekharan@us.ibm.com>");
  442. MODULE_LICENSE("GPL");