[SCSI] scsi_dh: Update EMC handler

This patch converts the EMC device handler to use a proper
state machine. We now also parse the extended INQUIRY
information to determine if long trespass commands are
supported. And we're now using the long trespass command
correctly. And finally there's now an check at init time
to refuse to attach to devices not supporting EMC-specific
VPD pages.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

authored by

Hannes Reinecke and committed by
James Bottomley
b6ff1b14 4c05ae52

+373 -175
+372 -175
drivers/scsi/device_handler/scsi_dh_emc.c
··· 25 25 #include <scsi/scsi_dh.h> 26 26 #include <scsi/scsi_device.h> 27 27 28 - #define CLARIION_NAME "emc_clariion" 28 + #define CLARIION_NAME "emc" 29 29 30 30 #define CLARIION_TRESPASS_PAGE 0x22 31 - #define CLARIION_BUFFER_SIZE 0x80 31 + #define CLARIION_BUFFER_SIZE 0xFC 32 32 #define CLARIION_TIMEOUT (60 * HZ) 33 33 #define CLARIION_RETRIES 3 34 34 #define CLARIION_UNBOUND_LU -1 35 + #define CLARIION_SP_A 0 36 + #define CLARIION_SP_B 1 37 + 38 + /* Flags */ 39 + #define CLARIION_SHORT_TRESPASS 1 40 + #define CLARIION_HONOR_RESERVATIONS 2 41 + 42 + /* LUN states */ 43 + #define CLARIION_LUN_UNINITIALIZED -1 44 + #define CLARIION_LUN_UNBOUND 0 45 + #define CLARIION_LUN_BOUND 1 46 + #define CLARIION_LUN_OWNED 2 35 47 36 48 static unsigned char long_trespass[] = { 37 - 0, 0, 0, 0, 49 + 0, 0, 0, 0, 0, 0, 0, 0, 38 50 CLARIION_TRESPASS_PAGE, /* Page code */ 39 51 0x09, /* Page length - 2 */ 40 - 0x81, /* Trespass code + Honor reservation bit */ 41 - 0xff, 0xff, /* Trespass target */ 42 - 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */ 43 - }; 44 - 45 - static unsigned char long_trespass_hr[] = { 46 - 0, 0, 0, 0, 47 - CLARIION_TRESPASS_PAGE, /* Page code */ 48 - 0x09, /* Page length - 2 */ 49 - 0x01, /* Trespass code + Honor reservation bit */ 52 + 0x01, /* Trespass code */ 50 53 0xff, 0xff, /* Trespass target */ 51 54 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */ 52 55 }; ··· 58 55 0, 0, 0, 0, 59 56 CLARIION_TRESPASS_PAGE, /* Page code */ 60 57 0x02, /* Page length - 2 */ 61 - 0x81, /* Trespass code + Honor reservation bit */ 58 + 0x01, /* Trespass code */ 62 59 0xff, /* Trespass target */ 63 60 }; 64 61 65 - static unsigned char short_trespass_hr[] = { 66 - 0, 0, 0, 0, 67 - CLARIION_TRESPASS_PAGE, /* Page code */ 68 - 0x02, /* Page length - 2 */ 69 - 0x01, /* Trespass code + Honor reservation bit */ 70 - 0xff, /* Trespass target */ 62 + static const char * lun_state[] = 63 + { 64 + "not bound", 65 + "bound", 66 + "owned", 71 67 }; 72 68 73 69 struct clariion_dh_data { 74 70 /* 71 + * Flags: 72 + * CLARIION_SHORT_TRESPASS 75 73 * Use short trespass command (FC-series) or the long version 76 74 * (default for AX/CX CLARiiON arrays). 77 - */ 78 - unsigned short_trespass; 79 - /* 75 + * 76 + * CLARIION_HONOR_RESERVATIONS 80 77 * Whether or not (default) to honor SCSI reservations when 81 78 * initiating a switch-over. 82 79 */ 83 - unsigned hr; 84 - /* I/O buffer for both MODE_SELECT and INQUIRY commands. */ 80 + unsigned flags; 81 + /* 82 + * I/O buffer for both MODE_SELECT and INQUIRY commands. 83 + */ 85 84 char buffer[CLARIION_BUFFER_SIZE]; 86 85 /* 87 86 * SCSI sense buffer for commands -- assumes serial issuance 88 87 * and completion sequence of all commands for same multipath. 89 88 */ 90 89 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 91 - /* which SP (A=0,B=1,UNBOUND=-1) is dflt SP for path's mapped dev */ 90 + unsigned int senselen; 91 + /* 92 + * LUN state 93 + */ 94 + int lun_state; 95 + /* 96 + * SP Port number 97 + */ 98 + int port; 99 + /* 100 + * which SP (A=0,B=1,UNBOUND=-1) is the default SP for this 101 + * path's mapped LUN 102 + */ 92 103 int default_sp; 93 - /* which SP (A=0,B=1,UNBOUND=-1) is active for path's mapped dev */ 104 + /* 105 + * which SP (A=0,B=1,UNBOUND=-1) is the active SP for this 106 + * path's mapped LUN 107 + */ 94 108 int current_sp; 95 109 }; 96 110 ··· 122 102 /* 123 103 * Parse MODE_SELECT cmd reply. 124 104 */ 125 - static int trespass_endio(struct scsi_device *sdev, int result) 105 + static int trespass_endio(struct scsi_device *sdev, char *sense) 126 106 { 127 - int err = SCSI_DH_OK; 107 + int err = SCSI_DH_IO; 128 108 struct scsi_sense_hdr sshdr; 129 - struct clariion_dh_data *csdev = get_clariion_data(sdev); 130 - char *sense = csdev->sense; 131 109 132 - if (status_byte(result) == CHECK_CONDITION && 133 - scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { 134 - sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, " 110 + if (!scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { 111 + sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, " 135 112 "0x%2x, 0x%2x while sending CLARiiON trespass " 136 - "command.\n", sshdr.sense_key, sshdr.asc, 137 - sshdr.ascq); 113 + "command.\n", CLARIION_NAME, sshdr.sense_key, 114 + sshdr.asc, sshdr.ascq); 138 115 139 116 if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) && 140 117 (sshdr.ascq == 0x00)) { ··· 139 122 * Array based copy in progress -- do not send 140 123 * mode_select or copy will be aborted mid-stream. 141 124 */ 142 - sdev_printk(KERN_INFO, sdev, "Array Based Copy in " 125 + sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in " 143 126 "progress while sending CLARiiON trespass " 144 - "command.\n"); 127 + "command.\n", CLARIION_NAME); 145 128 err = SCSI_DH_DEV_TEMP_BUSY; 146 129 } else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) && 147 130 (sshdr.ascq == 0x03)) { ··· 149 132 * LUN Not Ready - Manual Intervention Required 150 133 * indicates in-progress ucode upgrade (NDU). 151 134 */ 152 - sdev_printk(KERN_INFO, sdev, "Detected in-progress " 135 + sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress " 153 136 "ucode upgrade NDU operation while sending " 154 - "CLARiiON trespass command.\n"); 137 + "CLARiiON trespass command.\n", CLARIION_NAME); 155 138 err = SCSI_DH_DEV_TEMP_BUSY; 156 139 } else 157 140 err = SCSI_DH_DEV_FAILED; 158 - } else if (result) { 159 - sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending " 160 - "CLARiiON trespass command.\n", result); 161 - err = SCSI_DH_IO; 141 + } else { 142 + sdev_printk(KERN_INFO, sdev, 143 + "%s: failed to send MODE SELECT, no sense available\n", 144 + CLARIION_NAME); 162 145 } 163 - 164 146 return err; 165 147 } 166 148 167 - static int parse_sp_info_reply(struct scsi_device *sdev, int result, 168 - int *default_sp, int *current_sp, int *new_current_sp) 149 + static int parse_sp_info_reply(struct scsi_device *sdev, 150 + struct clariion_dh_data *csdev) 169 151 { 170 152 int err = SCSI_DH_OK; 171 - struct clariion_dh_data *csdev = get_clariion_data(sdev); 172 153 173 - if (result == 0) { 174 - /* check for in-progress ucode upgrade (NDU) */ 175 - if (csdev->buffer[48] != 0) { 176 - sdev_printk(KERN_NOTICE, sdev, "Detected in-progress " 177 - "ucode upgrade NDU operation while finding " 178 - "current active SP."); 179 - err = SCSI_DH_DEV_TEMP_BUSY; 180 - } else { 181 - *default_sp = csdev->buffer[5]; 182 - 183 - if (csdev->buffer[4] == 2) 184 - /* SP for path is current */ 185 - *current_sp = csdev->buffer[8]; 186 - else { 187 - if (csdev->buffer[4] == 1) 188 - /* SP for this path is NOT current */ 189 - if (csdev->buffer[8] == 0) 190 - *current_sp = 1; 191 - else 192 - *current_sp = 0; 193 - else 194 - /* unbound LU or LUNZ */ 195 - *current_sp = CLARIION_UNBOUND_LU; 196 - } 197 - *new_current_sp = csdev->buffer[8]; 198 - } 199 - } else { 200 - struct scsi_sense_hdr sshdr; 201 - 202 - err = SCSI_DH_IO; 203 - 204 - if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE, 205 - &sshdr)) 206 - sdev_printk(KERN_ERR, sdev, "Found valid sense data " 207 - "0x%2x, 0x%2x, 0x%2x while finding current " 208 - "active SP.", sshdr.sense_key, sshdr.asc, 209 - sshdr.ascq); 210 - else 211 - sdev_printk(KERN_ERR, sdev, "Error 0x%x finding " 212 - "current active SP.", result); 154 + /* check for in-progress ucode upgrade (NDU) */ 155 + if (csdev->buffer[48] != 0) { 156 + sdev_printk(KERN_NOTICE, sdev, "%s: Detected in-progress " 157 + "ucode upgrade NDU operation while finding " 158 + "current active SP.", CLARIION_NAME); 159 + err = SCSI_DH_DEV_TEMP_BUSY; 160 + goto out; 161 + } 162 + if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) { 163 + /* Invalid buffer format */ 164 + sdev_printk(KERN_NOTICE, sdev, 165 + "%s: invalid VPD page 0xC0 format\n", 166 + CLARIION_NAME); 167 + err = SCSI_DH_NOSYS; 168 + goto out; 169 + } 170 + switch (csdev->buffer[28] & 0x0f) { 171 + case 6: 172 + sdev_printk(KERN_NOTICE, sdev, 173 + "%s: ALUA failover mode detected\n", 174 + CLARIION_NAME); 175 + break; 176 + case 4: 177 + /* Linux failover */ 178 + break; 179 + default: 180 + sdev_printk(KERN_WARNING, sdev, 181 + "%s: Invalid failover mode %d\n", 182 + CLARIION_NAME, csdev->buffer[28] & 0x0f); 183 + err = SCSI_DH_NOSYS; 184 + goto out; 213 185 } 214 186 187 + csdev->default_sp = csdev->buffer[5]; 188 + csdev->lun_state = csdev->buffer[4]; 189 + csdev->current_sp = csdev->buffer[8]; 190 + csdev->port = csdev->buffer[7]; 191 + 192 + out: 215 193 return err; 216 194 } 217 195 218 - static int sp_info_endio(struct scsi_device *sdev, int result, 219 - int mode_select_sent, int *done) 196 + #define emc_default_str "FC (Legacy)" 197 + 198 + static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer) 220 199 { 221 - struct clariion_dh_data *csdev = get_clariion_data(sdev); 222 - int err_flags, default_sp, current_sp, new_current_sp; 200 + unsigned char len = buffer[4] + 5; 201 + char *sp_model = NULL; 202 + unsigned char sp_len, serial_len; 223 203 224 - err_flags = parse_sp_info_reply(sdev, result, &default_sp, 225 - &current_sp, &new_current_sp); 226 - 227 - if (err_flags != SCSI_DH_OK) 228 - goto done; 229 - 230 - if (mode_select_sent) { 231 - csdev->default_sp = default_sp; 232 - csdev->current_sp = current_sp; 233 - } else { 234 - /* 235 - * Issue the actual module_selec request IFF either 236 - * (1) we do not know the identity of the current SP OR 237 - * (2) what we think we know is actually correct. 238 - */ 239 - if ((current_sp != CLARIION_UNBOUND_LU) && 240 - (new_current_sp != current_sp)) { 241 - 242 - csdev->default_sp = default_sp; 243 - csdev->current_sp = current_sp; 244 - 245 - sdev_printk(KERN_INFO, sdev, "Ignoring path group " 246 - "switch-over command for CLARiiON SP%s since " 247 - " mapped device is already initialized.", 248 - current_sp ? "B" : "A"); 249 - if (done) 250 - *done = 1; /* as good as doing it */ 204 + if (len < 160) { 205 + sdev_printk(KERN_WARNING, sdev, 206 + "%s: Invalid information section length %d\n", 207 + CLARIION_NAME, len); 208 + /* Check for old FC arrays */ 209 + if (!strncmp(buffer + 8, "DGC", 3)) { 210 + /* Old FC array, not supporting extended information */ 211 + sp_model = emc_default_str; 251 212 } 213 + goto out; 252 214 } 253 - done: 254 - return err_flags; 215 + 216 + /* 217 + * Parse extended information for SP model number 218 + */ 219 + serial_len = buffer[160]; 220 + if (serial_len == 0 || serial_len + 161 > len) { 221 + sdev_printk(KERN_WARNING, sdev, 222 + "%s: Invalid array serial number length %d\n", 223 + CLARIION_NAME, serial_len); 224 + goto out; 225 + } 226 + sp_len = buffer[99]; 227 + if (sp_len == 0 || serial_len + sp_len + 161 > len) { 228 + sdev_printk(KERN_WARNING, sdev, 229 + "%s: Invalid model number length %d\n", 230 + CLARIION_NAME, sp_len); 231 + goto out; 232 + } 233 + sp_model = &buffer[serial_len + 161]; 234 + /* Strip whitespace at the end */ 235 + while (sp_len > 1 && sp_model[sp_len - 1] == ' ') 236 + sp_len--; 237 + 238 + sp_model[sp_len] = '\0'; 239 + 240 + out: 241 + return sp_model; 255 242 } 256 243 257 244 /* ··· 265 244 * Uses data and sense buffers in hardware handler context structure and 266 245 * assumes serial servicing of commands, both issuance and completion. 267 246 */ 268 - static struct request *get_req(struct scsi_device *sdev, int cmd) 247 + static struct request *get_req(struct scsi_device *sdev, int cmd, 248 + unsigned char *buffer) 269 249 { 270 - struct clariion_dh_data *csdev = get_clariion_data(sdev); 271 250 struct request *rq; 272 - unsigned char *page22; 273 251 int len = 0; 274 252 275 253 rq = blk_get_request(sdev->request_queue, 276 - (cmd == MODE_SELECT) ? WRITE : READ, GFP_ATOMIC); 254 + (cmd == MODE_SELECT) ? WRITE : READ, GFP_NOIO); 277 255 if (!rq) { 278 256 sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed"); 279 257 return NULL; 280 258 } 281 259 282 - memset(&rq->cmd, 0, BLK_MAX_CDB); 260 + memset(rq->cmd, 0, BLK_MAX_CDB); 261 + rq->cmd_len = COMMAND_SIZE(cmd); 283 262 rq->cmd[0] = cmd; 284 - rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); 285 263 286 264 switch (cmd) { 287 265 case MODE_SELECT: 288 - if (csdev->short_trespass) { 289 - page22 = csdev->hr ? short_trespass_hr : short_trespass; 290 - len = sizeof(short_trespass); 291 - } else { 292 - page22 = csdev->hr ? long_trespass_hr : long_trespass; 293 - len = sizeof(long_trespass); 294 - } 295 - /* 296 - * Can't DMA from kernel BSS -- must copy selected trespass 297 - * command mode page contents to context buffer which is 298 - * allocated by kmalloc. 299 - */ 300 - BUG_ON((len > CLARIION_BUFFER_SIZE)); 301 - memcpy(csdev->buffer, page22, len); 266 + len = sizeof(short_trespass); 267 + rq->cmd_flags |= REQ_RW; 268 + rq->cmd[1] = 0x10; 269 + break; 270 + case MODE_SELECT_10: 271 + len = sizeof(long_trespass); 302 272 rq->cmd_flags |= REQ_RW; 303 273 rq->cmd[1] = 0x10; 304 274 break; 305 275 case INQUIRY: 306 - rq->cmd[1] = 0x1; 307 - rq->cmd[2] = 0xC0; 308 276 len = CLARIION_BUFFER_SIZE; 309 - memset(csdev->buffer, 0, CLARIION_BUFFER_SIZE); 277 + memset(buffer, 0, len); 310 278 break; 311 279 default: 312 280 BUG_ON(1); ··· 308 298 rq->timeout = CLARIION_TIMEOUT; 309 299 rq->retries = CLARIION_RETRIES; 310 300 311 - rq->sense = csdev->sense; 312 - memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); 313 - rq->sense_len = 0; 314 - 315 - if (blk_rq_map_kern(sdev->request_queue, rq, csdev->buffer, 316 - len, GFP_ATOMIC)) { 317 - __blk_put_request(rq->q, rq); 301 + if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) { 302 + blk_put_request(rq); 318 303 return NULL; 319 304 } 320 305 321 306 return rq; 322 307 } 323 308 324 - static int send_cmd(struct scsi_device *sdev, int cmd) 309 + static int send_inquiry_cmd(struct scsi_device *sdev, int page, 310 + struct clariion_dh_data *csdev) 325 311 { 326 - struct request *rq = get_req(sdev, cmd); 312 + struct request *rq = get_req(sdev, INQUIRY, csdev->buffer); 313 + int err; 327 314 328 315 if (!rq) 329 316 return SCSI_DH_RES_TEMP_UNAVAIL; 330 317 331 - return blk_execute_rq(sdev->request_queue, NULL, rq, 1); 318 + rq->sense = csdev->sense; 319 + memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); 320 + rq->sense_len = csdev->senselen = 0; 321 + 322 + rq->cmd[0] = INQUIRY; 323 + if (page != 0) { 324 + rq->cmd[1] = 1; 325 + rq->cmd[2] = page; 326 + } 327 + err = blk_execute_rq(sdev->request_queue, NULL, rq, 1); 328 + if (err == -EIO) { 329 + sdev_printk(KERN_INFO, sdev, 330 + "%s: failed to send %s INQUIRY: %x\n", 331 + CLARIION_NAME, page?"EVPD":"standard", 332 + rq->errors); 333 + csdev->senselen = rq->sense_len; 334 + err = SCSI_DH_IO; 335 + } 336 + 337 + blk_put_request(rq); 338 + 339 + return err; 332 340 } 333 341 334 - static int clariion_activate(struct scsi_device *sdev) 342 + static int send_trespass_cmd(struct scsi_device *sdev, 343 + struct clariion_dh_data *csdev) 335 344 { 336 - int result, done = 0; 345 + struct request *rq; 346 + unsigned char *page22; 347 + int err, len, cmd; 337 348 338 - result = send_cmd(sdev, INQUIRY); 339 - result = sp_info_endio(sdev, result, 0, &done); 340 - if (result || done) 341 - goto done; 349 + if (csdev->flags & CLARIION_SHORT_TRESPASS) { 350 + page22 = short_trespass; 351 + if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 352 + /* Set Honor Reservations bit */ 353 + page22[6] |= 0x80; 354 + len = sizeof(short_trespass); 355 + cmd = MODE_SELECT; 356 + } else { 357 + page22 = long_trespass; 358 + if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) 359 + /* Set Honor Reservations bit */ 360 + page22[10] |= 0x80; 361 + len = sizeof(long_trespass); 362 + cmd = MODE_SELECT_10; 363 + } 364 + BUG_ON((len > CLARIION_BUFFER_SIZE)); 365 + memcpy(csdev->buffer, page22, len); 342 366 343 - result = send_cmd(sdev, MODE_SELECT); 344 - result = trespass_endio(sdev, result); 345 - if (result) 346 - goto done; 367 + rq = get_req(sdev, cmd, csdev->buffer); 368 + if (!rq) 369 + return SCSI_DH_RES_TEMP_UNAVAIL; 347 370 348 - result = send_cmd(sdev, INQUIRY); 349 - result = sp_info_endio(sdev, result, 1, NULL); 350 - done: 351 - return result; 371 + rq->sense = csdev->sense; 372 + memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); 373 + rq->sense_len = csdev->senselen = 0; 374 + 375 + err = blk_execute_rq(sdev->request_queue, NULL, rq, 1); 376 + if (err == -EIO) { 377 + if (rq->sense_len) { 378 + err = trespass_endio(sdev, csdev->sense); 379 + } else { 380 + sdev_printk(KERN_INFO, sdev, 381 + "%s: failed to send MODE SELECT: %x\n", 382 + CLARIION_NAME, rq->errors); 383 + } 384 + } 385 + 386 + blk_put_request(rq); 387 + 388 + return err; 352 389 } 353 390 354 391 static int clariion_check_sense(struct scsi_device *sdev, ··· 443 386 break; 444 387 } 445 388 446 - /* success just means we do not care what scsi-ml does */ 447 - return SUCCESS; 389 + return SCSI_RETURN_NOT_HANDLED; 390 + } 391 + 392 + static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) 393 + { 394 + struct clariion_dh_data *h = get_clariion_data(sdev); 395 + int ret = BLKPREP_OK; 396 + 397 + if (h->lun_state != CLARIION_LUN_OWNED) { 398 + ret = BLKPREP_KILL; 399 + req->cmd_flags |= REQ_QUIET; 400 + } 401 + return ret; 402 + 403 + } 404 + 405 + static int clariion_std_inquiry(struct scsi_device *sdev, 406 + struct clariion_dh_data *csdev) 407 + { 408 + int err; 409 + char *sp_model; 410 + 411 + err = send_inquiry_cmd(sdev, 0, csdev); 412 + if (err != SCSI_DH_OK && csdev->senselen) { 413 + struct scsi_sense_hdr sshdr; 414 + 415 + if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE, 416 + &sshdr)) { 417 + sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code " 418 + "%02x/%02x/%02x\n", CLARIION_NAME, 419 + sshdr.sense_key, sshdr.asc, sshdr.ascq); 420 + } 421 + err = SCSI_DH_IO; 422 + goto out; 423 + } 424 + 425 + sp_model = parse_sp_model(sdev, csdev->buffer); 426 + if (!sp_model) { 427 + err = SCSI_DH_DEV_UNSUPP; 428 + goto out; 429 + } 430 + 431 + /* 432 + * FC Series arrays do not support long trespass 433 + */ 434 + if (!strlen(sp_model) || !strncmp(sp_model, "FC",2)) 435 + csdev->flags |= CLARIION_SHORT_TRESPASS; 436 + 437 + sdev_printk(KERN_INFO, sdev, 438 + "%s: detected Clariion %s, flags %x\n", 439 + CLARIION_NAME, sp_model, csdev->flags); 440 + out: 441 + return err; 442 + } 443 + 444 + static int clariion_send_inquiry(struct scsi_device *sdev, 445 + struct clariion_dh_data *csdev) 446 + { 447 + int err, retry = CLARIION_RETRIES; 448 + 449 + retry: 450 + err = send_inquiry_cmd(sdev, 0xC0, csdev); 451 + if (err != SCSI_DH_OK && csdev->senselen) { 452 + struct scsi_sense_hdr sshdr; 453 + 454 + err = scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE, 455 + &sshdr); 456 + if (!err) 457 + return SCSI_DH_IO; 458 + 459 + err = clariion_check_sense(sdev, &sshdr); 460 + if (retry > 0 && err == NEEDS_RETRY) { 461 + retry--; 462 + goto retry; 463 + } 464 + sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code " 465 + "%02x/%02x/%02x\n", CLARIION_NAME, 466 + sshdr.sense_key, sshdr.asc, sshdr.ascq); 467 + err = SCSI_DH_IO; 468 + } else { 469 + err = parse_sp_info_reply(sdev, csdev); 470 + } 471 + return err; 472 + } 473 + 474 + static int clariion_activate(struct scsi_device *sdev) 475 + { 476 + struct clariion_dh_data *csdev = get_clariion_data(sdev); 477 + int result; 478 + 479 + result = clariion_send_inquiry(sdev, csdev); 480 + if (result != SCSI_DH_OK) 481 + goto done; 482 + 483 + if (csdev->lun_state == CLARIION_LUN_OWNED) 484 + goto done; 485 + 486 + result = send_trespass_cmd(sdev, csdev); 487 + if (result != SCSI_DH_OK) 488 + goto done; 489 + sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n", 490 + CLARIION_NAME, 491 + csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" ); 492 + 493 + /* Update status */ 494 + result = clariion_send_inquiry(sdev, csdev); 495 + if (result != SCSI_DH_OK) 496 + goto done; 497 + 498 + done: 499 + sdev_printk(KERN_INFO, sdev, 500 + "%s: at SP %c Port %d (%s, default SP %c)\n", 501 + CLARIION_NAME, csdev->current_sp + 'A', 502 + csdev->port, lun_state[csdev->lun_state], 503 + csdev->default_sp + 'A'); 504 + 505 + return result; 448 506 } 449 507 450 508 const struct scsi_dh_devlist clariion_dev_list[] = { 451 509 {"DGC", "RAID"}, 452 510 {"DGC", "DISK"}, 511 + {"DGC", "VRAID"}, 453 512 {NULL, NULL}, 454 513 }; 455 514 ··· 580 407 .detach = clariion_bus_detach, 581 408 .check_sense = clariion_check_sense, 582 409 .activate = clariion_activate, 410 + .prep_fn = clariion_prep_fn, 583 411 }; 584 412 585 413 /* ··· 591 417 struct scsi_dh_data *scsi_dh_data; 592 418 struct clariion_dh_data *h; 593 419 unsigned long flags; 420 + int err; 594 421 595 422 scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *) 596 423 + sizeof(*h) , GFP_KERNEL); 597 424 if (!scsi_dh_data) { 598 - sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n", 425 + sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", 599 426 CLARIION_NAME); 600 427 return -ENOMEM; 601 428 } 602 429 603 430 scsi_dh_data->scsi_dh = &clariion_dh; 604 431 h = (struct clariion_dh_data *) scsi_dh_data->buf; 432 + h->lun_state = CLARIION_LUN_UNINITIALIZED; 605 433 h->default_sp = CLARIION_UNBOUND_LU; 606 434 h->current_sp = CLARIION_UNBOUND_LU; 435 + 436 + err = clariion_std_inquiry(sdev, h); 437 + if (err != SCSI_DH_OK) 438 + goto failed; 439 + 440 + err = clariion_send_inquiry(sdev, h); 441 + if (err != SCSI_DH_OK) 442 + goto failed; 443 + 444 + if (!try_module_get(THIS_MODULE)) 445 + goto failed; 607 446 608 447 spin_lock_irqsave(sdev->request_queue->queue_lock, flags); 609 448 sdev->scsi_dh_data = scsi_dh_data; 610 449 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 611 450 612 - sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME); 613 - try_module_get(THIS_MODULE); 451 + sdev_printk(KERN_INFO, sdev, 452 + "%s: connected to SP %c Port %d (%s, default SP %c)\n", 453 + CLARIION_NAME, h->current_sp + 'A', 454 + h->port, lun_state[h->lun_state], 455 + h->default_sp + 'A'); 614 456 615 457 return 0; 458 + 459 + failed: 460 + kfree(scsi_dh_data); 461 + sdev_printk(KERN_ERR, sdev, "%s: not attached\n", 462 + CLARIION_NAME); 463 + return -EINVAL; 616 464 } 617 465 618 466 static void clariion_bus_detach(struct scsi_device *sdev) ··· 647 451 sdev->scsi_dh_data = NULL; 648 452 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); 649 453 650 - sdev_printk(KERN_NOTICE, sdev, "Detached %s.\n", 454 + sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", 651 455 CLARIION_NAME); 652 456 653 457 kfree(scsi_dh_data); ··· 660 464 661 465 r = scsi_register_device_handler(&clariion_dh); 662 466 if (r != 0) 663 - printk(KERN_ERR "Failed to register scsi device handler."); 467 + printk(KERN_ERR "%s: Failed to register scsi device handler.", 468 + CLARIION_NAME); 664 469 return r; 665 470 } 666 471
+1
include/scsi/scsi_dh.h
··· 32 32 */ 33 33 SCSI_DH_DEV_FAILED, /* generic device error */ 34 34 SCSI_DH_DEV_TEMP_BUSY, 35 + SCSI_DH_DEV_UNSUPP, /* device handler not supported */ 35 36 SCSI_DH_DEVICE_MAX, /* max device blkerr definition */ 36 37 37 38 /*