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 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | 243 REQ_FAILFAST_DRIVER; 244 245 if (csdev->flags & CLARIION_SHORT_TRESPASS) { 246 page22 = short_trespass; 247 if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 248 /* Set Honor Reservations bit */ 249 page22[6] |= 0x80; 250 len = sizeof(short_trespass); 251 cdb[0] = MODE_SELECT; 252 cdb[1] = 0x10; 253 cdb[4] = len; 254 } else { 255 page22 = long_trespass; 256 if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 257 /* Set Honor Reservations bit */ 258 page22[10] |= 0x80; 259 len = sizeof(long_trespass); 260 cdb[0] = MODE_SELECT_10; 261 cdb[8] = len; 262 } 263 BUG_ON((len > CLARIION_BUFFER_SIZE)); 264 memcpy(csdev->buffer, page22, len); 265 266 err = scsi_execute(sdev, cdb, DMA_TO_DEVICE, csdev->buffer, len, NULL, 267 &sshdr, CLARIION_TIMEOUT * HZ, CLARIION_RETRIES, 268 req_flags, 0, NULL); 269 if (err) { 270 if (scsi_sense_valid(&sshdr)) 271 res = trespass_endio(sdev, &sshdr); 272 else { 273 sdev_printk(KERN_INFO, sdev, 274 "%s: failed to send MODE SELECT: %x\n", 275 CLARIION_NAME, err); 276 res = SCSI_DH_IO; 277 } 278 } 279 280 return res; 281 } 282 283 static enum scsi_disposition clariion_check_sense(struct scsi_device *sdev, 284 struct scsi_sense_hdr *sense_hdr) 285 { 286 switch (sense_hdr->sense_key) { 287 case NOT_READY: 288 if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x03) 289 /* 290 * LUN Not Ready - Manual Intervention Required 291 * indicates this is a passive path. 292 * 293 * FIXME: However, if this is seen and EVPD C0 294 * indicates that this is due to a NDU in 295 * progress, we should set FAIL_PATH too. 296 * This indicates we might have to do a SCSI 297 * inquiry in the end_io path. Ugh. 298 * 299 * Can return FAILED only when we want the error 300 * recovery process to kick in. 301 */ 302 return SUCCESS; 303 break; 304 case ILLEGAL_REQUEST: 305 if (sense_hdr->asc == 0x25 && sense_hdr->ascq == 0x01) 306 /* 307 * An array based copy is in progress. Do not 308 * fail the path, do not bypass to another PG, 309 * do not retry. Fail the IO immediately. 310 * (Actually this is the same conclusion as in 311 * the default handler, but lets make sure.) 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 UNIT_ATTENTION: 319 if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) 320 /* 321 * Unit Attention Code. This is the first IO 322 * to the new path, so just retry. 323 */ 324 return ADD_TO_MLQUEUE; 325 break; 326 } 327 328 return SCSI_RETURN_NOT_HANDLED; 329 } 330 331 static blk_status_t clariion_prep_fn(struct scsi_device *sdev, 332 struct request *req) 333 { 334 struct clariion_dh_data *h = sdev->handler_data; 335 336 if (h->lun_state != CLARIION_LUN_OWNED) { 337 req->rq_flags |= RQF_QUIET; 338 return BLK_STS_IOERR; 339 } 340 341 return BLK_STS_OK; 342 } 343 344 static int clariion_std_inquiry(struct scsi_device *sdev, 345 struct clariion_dh_data *csdev) 346 { 347 int err = SCSI_DH_OK; 348 char *sp_model; 349 350 sp_model = parse_sp_model(sdev, sdev->inquiry); 351 if (!sp_model) { 352 err = SCSI_DH_DEV_UNSUPP; 353 goto out; 354 } 355 356 /* 357 * FC Series arrays do not support long trespass 358 */ 359 if (!strlen(sp_model) || !strncmp(sp_model, "FC",2)) 360 csdev->flags |= CLARIION_SHORT_TRESPASS; 361 362 sdev_printk(KERN_INFO, sdev, 363 "%s: detected Clariion %s, flags %x\n", 364 CLARIION_NAME, sp_model, csdev->flags); 365 out: 366 return err; 367 } 368 369 static int clariion_send_inquiry(struct scsi_device *sdev, 370 struct clariion_dh_data *csdev) 371 { 372 int err = SCSI_DH_IO; 373 374 if (!scsi_get_vpd_page(sdev, 0xC0, csdev->buffer, 375 CLARIION_BUFFER_SIZE)) 376 err = parse_sp_info_reply(sdev, csdev); 377 378 return err; 379 } 380 381 static int clariion_activate(struct scsi_device *sdev, 382 activate_complete fn, void *data) 383 { 384 struct clariion_dh_data *csdev = sdev->handler_data; 385 int result; 386 387 result = clariion_send_inquiry(sdev, csdev); 388 if (result != SCSI_DH_OK) 389 goto done; 390 391 if (csdev->lun_state == CLARIION_LUN_OWNED) 392 goto done; 393 394 result = send_trespass_cmd(sdev, csdev); 395 if (result != SCSI_DH_OK) 396 goto done; 397 sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n", 398 CLARIION_NAME, 399 csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" ); 400 401 /* Update status */ 402 result = clariion_send_inquiry(sdev, csdev); 403 if (result != SCSI_DH_OK) 404 goto done; 405 406 done: 407 sdev_printk(KERN_INFO, sdev, 408 "%s: at SP %c Port %d (%s, default SP %c)\n", 409 CLARIION_NAME, csdev->current_sp + 'A', 410 csdev->port, lun_state[csdev->lun_state], 411 csdev->default_sp + 'A'); 412 413 if (fn) 414 fn(data, result); 415 return 0; 416 } 417 /* 418 * params - parameters in the following format 419 * "no_of_params\0param1\0param2\0param3\0...\0" 420 * for example, string for 2 parameters with value 10 and 21 421 * is specified as "2\010\021\0". 422 */ 423 static int clariion_set_params(struct scsi_device *sdev, const char *params) 424 { 425 struct clariion_dh_data *csdev = sdev->handler_data; 426 unsigned int hr = 0, st = 0, argc; 427 const char *p = params; 428 int result = SCSI_DH_OK; 429 430 if ((sscanf(params, "%u", &argc) != 1) || (argc != 2)) 431 return -EINVAL; 432 433 while (*p++) 434 ; 435 if ((sscanf(p, "%u", &st) != 1) || (st > 1)) 436 return -EINVAL; 437 438 while (*p++) 439 ; 440 if ((sscanf(p, "%u", &hr) != 1) || (hr > 1)) 441 return -EINVAL; 442 443 if (st) 444 csdev->flags |= CLARIION_SHORT_TRESPASS; 445 else 446 csdev->flags &= ~CLARIION_SHORT_TRESPASS; 447 448 if (hr) 449 csdev->flags |= CLARIION_HONOR_RESERVATIONS; 450 else 451 csdev->flags &= ~CLARIION_HONOR_RESERVATIONS; 452 453 /* 454 * If this path is owned, we have to send a trespass command 455 * with the new parameters. If not, simply return. Next trespass 456 * command would use the parameters. 457 */ 458 if (csdev->lun_state != CLARIION_LUN_OWNED) 459 goto done; 460 461 csdev->lun_state = CLARIION_LUN_UNINITIALIZED; 462 result = send_trespass_cmd(sdev, csdev); 463 if (result != SCSI_DH_OK) 464 goto done; 465 466 /* Update status */ 467 result = clariion_send_inquiry(sdev, csdev); 468 469 done: 470 return result; 471 } 472 473 static int clariion_bus_attach(struct scsi_device *sdev) 474 { 475 struct clariion_dh_data *h; 476 int err; 477 478 h = kzalloc(sizeof(*h) , GFP_KERNEL); 479 if (!h) 480 return SCSI_DH_NOMEM; 481 h->lun_state = CLARIION_LUN_UNINITIALIZED; 482 h->default_sp = CLARIION_UNBOUND_LU; 483 h->current_sp = CLARIION_UNBOUND_LU; 484 485 err = clariion_std_inquiry(sdev, h); 486 if (err != SCSI_DH_OK) 487 goto failed; 488 489 err = clariion_send_inquiry(sdev, h); 490 if (err != SCSI_DH_OK) 491 goto failed; 492 493 sdev_printk(KERN_INFO, sdev, 494 "%s: connected to SP %c Port %d (%s, default SP %c)\n", 495 CLARIION_NAME, h->current_sp + 'A', 496 h->port, lun_state[h->lun_state], 497 h->default_sp + 'A'); 498 499 sdev->handler_data = h; 500 return SCSI_DH_OK; 501 502 failed: 503 kfree(h); 504 return err; 505 } 506 507 static void clariion_bus_detach(struct scsi_device *sdev) 508 { 509 kfree(sdev->handler_data); 510 sdev->handler_data = NULL; 511 } 512 513 static struct scsi_device_handler clariion_dh = { 514 .name = CLARIION_NAME, 515 .module = THIS_MODULE, 516 .attach = clariion_bus_attach, 517 .detach = clariion_bus_detach, 518 .check_sense = clariion_check_sense, 519 .activate = clariion_activate, 520 .prep_fn = clariion_prep_fn, 521 .set_params = clariion_set_params, 522 }; 523 524 static int __init clariion_init(void) 525 { 526 int r; 527 528 r = scsi_register_device_handler(&clariion_dh); 529 if (r != 0) 530 printk(KERN_ERR "%s: Failed to register scsi device handler.", 531 CLARIION_NAME); 532 return r; 533 } 534 535 static void __exit clariion_exit(void) 536 { 537 scsi_unregister_device_handler(&clariion_dh); 538 } 539 540 module_init(clariion_init); 541 module_exit(clariion_exit); 542 543 MODULE_DESCRIPTION("EMC CX/AX/FC-family driver"); 544 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, Chandra Seetharaman <sekharan@us.ibm.com>"); 545 MODULE_LICENSE("GPL"); 546