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 <linux/slab.h> 24 #include <linux/module.h> 25 #include <scsi/scsi.h> 26 #include <scsi/scsi_eh.h> 27 #include <scsi/scsi_dh.h> 28 #include <scsi/scsi_device.h> 29 30 #define CLARIION_NAME "emc" 31 32 #define CLARIION_TRESPASS_PAGE 0x22 33 #define CLARIION_BUFFER_SIZE 0xFC 34 #define CLARIION_TIMEOUT (60 * HZ) 35 #define CLARIION_RETRIES 3 36 #define CLARIION_UNBOUND_LU -1 37 #define CLARIION_SP_A 0 38 #define CLARIION_SP_B 1 39 40 /* Flags */ 41 #define CLARIION_SHORT_TRESPASS 1 42 #define CLARIION_HONOR_RESERVATIONS 2 43 44 /* LUN states */ 45 #define CLARIION_LUN_UNINITIALIZED -1 46 #define CLARIION_LUN_UNBOUND 0 47 #define CLARIION_LUN_BOUND 1 48 #define CLARIION_LUN_OWNED 2 49 50 static unsigned char long_trespass[] = { 51 0, 0, 0, 0, 0, 0, 0, 0, 52 CLARIION_TRESPASS_PAGE, /* Page code */ 53 0x09, /* Page length - 2 */ 54 0x01, /* Trespass code */ 55 0xff, 0xff, /* Trespass target */ 56 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */ 57 }; 58 59 static unsigned char short_trespass[] = { 60 0, 0, 0, 0, 61 CLARIION_TRESPASS_PAGE, /* Page code */ 62 0x02, /* Page length - 2 */ 63 0x01, /* Trespass code */ 64 0xff, /* Trespass target */ 65 }; 66 67 static const char * lun_state[] = 68 { 69 "not bound", 70 "bound", 71 "owned", 72 }; 73 74 struct clariion_dh_data { 75 /* 76 * Flags: 77 * CLARIION_SHORT_TRESPASS 78 * Use short trespass command (FC-series) or the long version 79 * (default for AX/CX CLARiiON arrays). 80 * 81 * CLARIION_HONOR_RESERVATIONS 82 * Whether or not (default) to honor SCSI reservations when 83 * initiating a switch-over. 84 */ 85 unsigned flags; 86 /* 87 * I/O buffer for both MODE_SELECT and INQUIRY commands. 88 */ 89 unsigned char buffer[CLARIION_BUFFER_SIZE]; 90 /* 91 * LUN state 92 */ 93 int lun_state; 94 /* 95 * SP Port number 96 */ 97 int port; 98 /* 99 * which SP (A=0,B=1,UNBOUND=-1) is the default SP for this 100 * path's mapped LUN 101 */ 102 int default_sp; 103 /* 104 * which SP (A=0,B=1,UNBOUND=-1) is the active SP for this 105 * path's mapped LUN 106 */ 107 int current_sp; 108 }; 109 110 /* 111 * Parse MODE_SELECT cmd reply. 112 */ 113 static int trespass_endio(struct scsi_device *sdev, 114 struct scsi_sense_hdr *sshdr) 115 { 116 int err = SCSI_DH_IO; 117 118 sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, " 119 "0x%2x, 0x%2x while sending CLARiiON trespass " 120 "command.\n", CLARIION_NAME, sshdr->sense_key, 121 sshdr->asc, sshdr->ascq); 122 123 if (sshdr->sense_key == 0x05 && sshdr->asc == 0x04 && 124 sshdr->ascq == 0x00) { 125 /* 126 * Array based copy in progress -- do not send 127 * mode_select or copy will be aborted mid-stream. 128 */ 129 sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in " 130 "progress while sending CLARiiON trespass " 131 "command.\n", CLARIION_NAME); 132 err = SCSI_DH_DEV_TEMP_BUSY; 133 } else if (sshdr->sense_key == 0x02 && sshdr->asc == 0x04 && 134 sshdr->ascq == 0x03) { 135 /* 136 * LUN Not Ready - Manual Intervention Required 137 * indicates in-progress ucode upgrade (NDU). 138 */ 139 sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress " 140 "ucode upgrade NDU operation while sending " 141 "CLARiiON trespass command.\n", CLARIION_NAME); 142 err = SCSI_DH_DEV_TEMP_BUSY; 143 } else 144 err = SCSI_DH_DEV_FAILED; 145 return err; 146 } 147 148 static int parse_sp_info_reply(struct scsi_device *sdev, 149 struct clariion_dh_data *csdev) 150 { 151 int err = SCSI_DH_OK; 152 153 /* check for in-progress ucode upgrade (NDU) */ 154 if (csdev->buffer[48] != 0) { 155 sdev_printk(KERN_NOTICE, sdev, "%s: Detected in-progress " 156 "ucode upgrade NDU operation while finding " 157 "current active SP.", CLARIION_NAME); 158 err = SCSI_DH_DEV_TEMP_BUSY; 159 goto out; 160 } 161 if (csdev->buffer[4] > 2) { 162 /* Invalid buffer format */ 163 sdev_printk(KERN_NOTICE, sdev, 164 "%s: invalid VPD page 0xC0 format\n", 165 CLARIION_NAME); 166 err = SCSI_DH_NOSYS; 167 goto out; 168 } 169 switch (csdev->buffer[28] & 0x0f) { 170 case 6: 171 sdev_printk(KERN_NOTICE, sdev, 172 "%s: ALUA failover mode detected\n", 173 CLARIION_NAME); 174 break; 175 case 4: 176 /* Linux failover */ 177 break; 178 default: 179 sdev_printk(KERN_WARNING, sdev, 180 "%s: Invalid failover mode %d\n", 181 CLARIION_NAME, csdev->buffer[28] & 0x0f); 182 err = SCSI_DH_NOSYS; 183 goto out; 184 } 185 186 csdev->default_sp = csdev->buffer[5]; 187 csdev->lun_state = csdev->buffer[4]; 188 csdev->current_sp = csdev->buffer[8]; 189 csdev->port = csdev->buffer[7]; 190 if (csdev->lun_state == CLARIION_LUN_OWNED) 191 sdev->access_state = SCSI_ACCESS_STATE_OPTIMAL; 192 else 193 sdev->access_state = SCSI_ACCESS_STATE_STANDBY; 194 if (csdev->default_sp == csdev->current_sp) 195 sdev->access_state |= SCSI_ACCESS_STATE_PREFERRED; 196 out: 197 return err; 198 } 199 200 #define emc_default_str "FC (Legacy)" 201 202 static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer) 203 { 204 unsigned char len = buffer[4] + 5; 205 char *sp_model = NULL; 206 unsigned char sp_len, serial_len; 207 208 if (len < 160) { 209 sdev_printk(KERN_WARNING, sdev, 210 "%s: Invalid information section length %d\n", 211 CLARIION_NAME, len); 212 /* Check for old FC arrays */ 213 if (!strncmp(buffer + 8, "DGC", 3)) { 214 /* Old FC array, not supporting extended information */ 215 sp_model = emc_default_str; 216 } 217 goto out; 218 } 219 220 /* 221 * Parse extended information for SP model number 222 */ 223 serial_len = buffer[160]; 224 if (serial_len == 0 || serial_len + 161 > len) { 225 sdev_printk(KERN_WARNING, sdev, 226 "%s: Invalid array serial number length %d\n", 227 CLARIION_NAME, serial_len); 228 goto out; 229 } 230 sp_len = buffer[99]; 231 if (sp_len == 0 || serial_len + sp_len + 161 > len) { 232 sdev_printk(KERN_WARNING, sdev, 233 "%s: Invalid model number length %d\n", 234 CLARIION_NAME, sp_len); 235 goto out; 236 } 237 sp_model = &buffer[serial_len + 161]; 238 /* Strip whitespace at the end */ 239 while (sp_len > 1 && sp_model[sp_len - 1] == ' ') 240 sp_len--; 241 242 sp_model[sp_len] = '\0'; 243 244 out: 245 return sp_model; 246 } 247 248 static int send_trespass_cmd(struct scsi_device *sdev, 249 struct clariion_dh_data *csdev) 250 { 251 unsigned char *page22; 252 unsigned char cdb[COMMAND_SIZE(MODE_SELECT)]; 253 int err, res = SCSI_DH_OK, len; 254 struct scsi_sense_hdr sshdr; 255 u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | 256 REQ_FAILFAST_DRIVER; 257 258 if (csdev->flags & CLARIION_SHORT_TRESPASS) { 259 page22 = short_trespass; 260 if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 261 /* Set Honor Reservations bit */ 262 page22[6] |= 0x80; 263 len = sizeof(short_trespass); 264 cdb[0] = MODE_SELECT; 265 cdb[1] = 0x10; 266 cdb[4] = len; 267 } else { 268 page22 = long_trespass; 269 if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 270 /* Set Honor Reservations bit */ 271 page22[10] |= 0x80; 272 len = sizeof(long_trespass); 273 cdb[0] = MODE_SELECT_10; 274 cdb[8] = len; 275 } 276 BUG_ON((len > CLARIION_BUFFER_SIZE)); 277 memcpy(csdev->buffer, page22, len); 278 279 err = scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE, 280 csdev->buffer, len, &sshdr, 281 CLARIION_TIMEOUT * HZ, CLARIION_RETRIES, 282 NULL, req_flags, 0); 283 if (err) { 284 if (scsi_sense_valid(&sshdr)) 285 res = trespass_endio(sdev, &sshdr); 286 else { 287 sdev_printk(KERN_INFO, sdev, 288 "%s: failed to send MODE SELECT: %x\n", 289 CLARIION_NAME, err); 290 res = SCSI_DH_IO; 291 } 292 } 293 294 return res; 295 } 296 297 static int clariion_check_sense(struct scsi_device *sdev, 298 struct scsi_sense_hdr *sense_hdr) 299 { 300 switch (sense_hdr->sense_key) { 301 case NOT_READY: 302 if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x03) 303 /* 304 * LUN Not Ready - Manual Intervention Required 305 * indicates this is a passive path. 306 * 307 * FIXME: However, if this is seen and EVPD C0 308 * indicates that this is due to a NDU in 309 * progress, we should set FAIL_PATH too. 310 * This indicates we might have to do a SCSI 311 * inquiry in the end_io path. Ugh. 312 * 313 * Can return FAILED only when we want the error 314 * recovery process to kick in. 315 */ 316 return SUCCESS; 317 break; 318 case ILLEGAL_REQUEST: 319 if (sense_hdr->asc == 0x25 && sense_hdr->ascq == 0x01) 320 /* 321 * An array based copy is in progress. Do not 322 * fail the path, do not bypass to another PG, 323 * do not retry. Fail the IO immediately. 324 * (Actually this is the same conclusion as in 325 * the default handler, but lets make sure.) 326 * 327 * Can return FAILED only when we want the error 328 * recovery process to kick in. 329 */ 330 return SUCCESS; 331 break; 332 case UNIT_ATTENTION: 333 if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) 334 /* 335 * Unit Attention Code. This is the first IO 336 * to the new path, so just retry. 337 */ 338 return ADD_TO_MLQUEUE; 339 break; 340 } 341 342 return SCSI_RETURN_NOT_HANDLED; 343 } 344 345 static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) 346 { 347 struct clariion_dh_data *h = sdev->handler_data; 348 int ret = BLKPREP_OK; 349 350 if (h->lun_state != CLARIION_LUN_OWNED) { 351 ret = BLKPREP_KILL; 352 req->rq_flags |= RQF_QUIET; 353 } 354 return ret; 355 356 } 357 358 static int clariion_std_inquiry(struct scsi_device *sdev, 359 struct clariion_dh_data *csdev) 360 { 361 int err; 362 char *sp_model; 363 364 sp_model = parse_sp_model(sdev, sdev->inquiry); 365 if (!sp_model) { 366 err = SCSI_DH_DEV_UNSUPP; 367 goto out; 368 } 369 370 /* 371 * FC Series arrays do not support long trespass 372 */ 373 if (!strlen(sp_model) || !strncmp(sp_model, "FC",2)) 374 csdev->flags |= CLARIION_SHORT_TRESPASS; 375 376 sdev_printk(KERN_INFO, sdev, 377 "%s: detected Clariion %s, flags %x\n", 378 CLARIION_NAME, sp_model, csdev->flags); 379 out: 380 return err; 381 } 382 383 static int clariion_send_inquiry(struct scsi_device *sdev, 384 struct clariion_dh_data *csdev) 385 { 386 int err = SCSI_DH_IO; 387 388 if (!scsi_get_vpd_page(sdev, 0xC0, csdev->buffer, 389 CLARIION_BUFFER_SIZE)) 390 err = parse_sp_info_reply(sdev, csdev); 391 392 return err; 393 } 394 395 static int clariion_activate(struct scsi_device *sdev, 396 activate_complete fn, void *data) 397 { 398 struct clariion_dh_data *csdev = sdev->handler_data; 399 int result; 400 401 result = clariion_send_inquiry(sdev, csdev); 402 if (result != SCSI_DH_OK) 403 goto done; 404 405 if (csdev->lun_state == CLARIION_LUN_OWNED) 406 goto done; 407 408 result = send_trespass_cmd(sdev, csdev); 409 if (result != SCSI_DH_OK) 410 goto done; 411 sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n", 412 CLARIION_NAME, 413 csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" ); 414 415 /* Update status */ 416 result = clariion_send_inquiry(sdev, csdev); 417 if (result != SCSI_DH_OK) 418 goto done; 419 420 done: 421 sdev_printk(KERN_INFO, sdev, 422 "%s: at SP %c Port %d (%s, default SP %c)\n", 423 CLARIION_NAME, csdev->current_sp + 'A', 424 csdev->port, lun_state[csdev->lun_state], 425 csdev->default_sp + 'A'); 426 427 if (fn) 428 fn(data, result); 429 return 0; 430 } 431 /* 432 * params - parameters in the following format 433 * "no_of_params\0param1\0param2\0param3\0...\0" 434 * for example, string for 2 parameters with value 10 and 21 435 * is specified as "2\010\021\0". 436 */ 437 static int clariion_set_params(struct scsi_device *sdev, const char *params) 438 { 439 struct clariion_dh_data *csdev = sdev->handler_data; 440 unsigned int hr = 0, st = 0, argc; 441 const char *p = params; 442 int result = SCSI_DH_OK; 443 444 if ((sscanf(params, "%u", &argc) != 1) || (argc != 2)) 445 return -EINVAL; 446 447 while (*p++) 448 ; 449 if ((sscanf(p, "%u", &st) != 1) || (st > 1)) 450 return -EINVAL; 451 452 while (*p++) 453 ; 454 if ((sscanf(p, "%u", &hr) != 1) || (hr > 1)) 455 return -EINVAL; 456 457 if (st) 458 csdev->flags |= CLARIION_SHORT_TRESPASS; 459 else 460 csdev->flags &= ~CLARIION_SHORT_TRESPASS; 461 462 if (hr) 463 csdev->flags |= CLARIION_HONOR_RESERVATIONS; 464 else 465 csdev->flags &= ~CLARIION_HONOR_RESERVATIONS; 466 467 /* 468 * If this path is owned, we have to send a trespass command 469 * with the new parameters. If not, simply return. Next trespass 470 * command would use the parameters. 471 */ 472 if (csdev->lun_state != CLARIION_LUN_OWNED) 473 goto done; 474 475 csdev->lun_state = CLARIION_LUN_UNINITIALIZED; 476 result = send_trespass_cmd(sdev, csdev); 477 if (result != SCSI_DH_OK) 478 goto done; 479 480 /* Update status */ 481 result = clariion_send_inquiry(sdev, csdev); 482 483 done: 484 return result; 485 } 486 487 static int clariion_bus_attach(struct scsi_device *sdev) 488 { 489 struct clariion_dh_data *h; 490 int err; 491 492 h = kzalloc(sizeof(*h) , GFP_KERNEL); 493 if (!h) 494 return -ENOMEM; 495 h->lun_state = CLARIION_LUN_UNINITIALIZED; 496 h->default_sp = CLARIION_UNBOUND_LU; 497 h->current_sp = CLARIION_UNBOUND_LU; 498 499 err = clariion_std_inquiry(sdev, h); 500 if (err != SCSI_DH_OK) 501 goto failed; 502 503 err = clariion_send_inquiry(sdev, h); 504 if (err != SCSI_DH_OK) 505 goto failed; 506 507 sdev_printk(KERN_INFO, sdev, 508 "%s: connected to SP %c Port %d (%s, default SP %c)\n", 509 CLARIION_NAME, h->current_sp + 'A', 510 h->port, lun_state[h->lun_state], 511 h->default_sp + 'A'); 512 513 sdev->handler_data = h; 514 return 0; 515 516 failed: 517 kfree(h); 518 return -EINVAL; 519 } 520 521 static void clariion_bus_detach(struct scsi_device *sdev) 522 { 523 kfree(sdev->handler_data); 524 sdev->handler_data = NULL; 525 } 526 527 static struct scsi_device_handler clariion_dh = { 528 .name = CLARIION_NAME, 529 .module = THIS_MODULE, 530 .attach = clariion_bus_attach, 531 .detach = clariion_bus_detach, 532 .check_sense = clariion_check_sense, 533 .activate = clariion_activate, 534 .prep_fn = clariion_prep_fn, 535 .set_params = clariion_set_params, 536 }; 537 538 static int __init clariion_init(void) 539 { 540 int r; 541 542 r = scsi_register_device_handler(&clariion_dh); 543 if (r != 0) 544 printk(KERN_ERR "%s: Failed to register scsi device handler.", 545 CLARIION_NAME); 546 return r; 547 } 548 549 static void __exit clariion_exit(void) 550 { 551 scsi_unregister_device_handler(&clariion_dh); 552 } 553 554 module_init(clariion_init); 555 module_exit(clariion_exit); 556 557 MODULE_DESCRIPTION("EMC CX/AX/FC-family driver"); 558 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, Chandra Seetharaman <sekharan@us.ibm.com>"); 559 MODULE_LICENSE("GPL"); 560