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