aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorSteve Cameron <scameron@quandary.americas.cpqcorp.net>2007-10-17 02:27:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:55 -0400
commit1a614f505193fcfc1b298643268a5db5b48e297f (patch)
tree80413131fca8758fe31e0fb4d383f80f5e75834f /drivers/block
parent7fdfd4065c264bddd2d9277470a6a99d34e01bef (diff)
cciss: fix error reporting for SG_IO
This fixes a problem with the way cciss was filling out the "errors" field of the request structure upon completion of requests. Previously, it just put a 1 or a 0 in there and used the negation of this as the uptodate parameter to one of the functions in the block layer, being a block device. For the SG_IO ioctl, this was not sufficient, and we noticed that, for example, sg_turs from sg3_utils did not correctly detect problems due to cciss having set rq->errors incorrectly. Signed-off-by: Stephen M. Cameron <steve.cameron@hp.com> Acked-by: Mike Miller <mike.miller@hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 3fb7e8bc436d..5c269c00d6eb 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2365,30 +2365,55 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2365 start_io(h); 2365 start_io(h);
2366} 2366}
2367 2367
2368static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
2369 unsigned int msg_byte, unsigned int host_byte,
2370 unsigned int driver_byte)
2371{
2372 /* inverse of macros in scsi.h */
2373 return (scsi_status_byte & 0xff) |
2374 ((msg_byte & 0xff) << 8) |
2375 ((host_byte & 0xff) << 16) |
2376 ((driver_byte & 0xff) << 24);
2377}
2378
2368static inline int evaluate_target_status(CommandList_struct *cmd) 2379static inline int evaluate_target_status(CommandList_struct *cmd)
2369{ 2380{
2370 unsigned char sense_key; 2381 unsigned char sense_key;
2371 int error_count = 1; 2382 unsigned char status_byte, msg_byte, host_byte, driver_byte;
2383 int error_value;
2384
2385 /* If we get in here, it means we got "target status", that is, scsi status */
2386 status_byte = cmd->err_info->ScsiStatus;
2387 driver_byte = DRIVER_OK;
2388 msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */
2389
2390 if (blk_pc_request(cmd->rq))
2391 host_byte = DID_PASSTHROUGH;
2392 else
2393 host_byte = DID_OK;
2394
2395 error_value = make_status_bytes(status_byte, msg_byte,
2396 host_byte, driver_byte);
2372 2397
2373 if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */ 2398 if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) {
2374 if (!blk_pc_request(cmd->rq)) 2399 if (!blk_pc_request(cmd->rq))
2375 printk(KERN_WARNING "cciss: cmd %p " 2400 printk(KERN_WARNING "cciss: cmd %p "
2376 "has SCSI Status 0x%x\n", 2401 "has SCSI Status 0x%x\n",
2377 cmd, cmd->err_info->ScsiStatus); 2402 cmd, cmd->err_info->ScsiStatus);
2378 return error_count; 2403 return error_value;
2379 } 2404 }
2380 2405
2381 /* check the sense key */ 2406 /* check the sense key */
2382 sense_key = 0xf & cmd->err_info->SenseInfo[2]; 2407 sense_key = 0xf & cmd->err_info->SenseInfo[2];
2383 /* no status or recovered error */ 2408 /* no status or recovered error */
2384 if ((sense_key == 0x0) || (sense_key == 0x1)) 2409 if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
2385 error_count = 0; 2410 error_value = 0;
2386 2411
2387 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ 2412 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
2388 if (error_count != 0) 2413 if (error_value != 0)
2389 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" 2414 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
2390 " sense key = 0x%x\n", cmd, sense_key); 2415 " sense key = 0x%x\n", cmd, sense_key);
2391 return error_count; 2416 return error_value;
2392 } 2417 }
2393 2418
2394 /* SG_IO or similar, copy sense data back */ 2419 /* SG_IO or similar, copy sense data back */
@@ -2400,7 +2425,7 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
2400 } else 2425 } else
2401 cmd->rq->sense_len = 0; 2426 cmd->rq->sense_len = 0;
2402 2427
2403 return error_count; 2428 return error_value;
2404} 2429}
2405 2430
2406/* checks the status of the job and calls complete buffers to mark all 2431/* checks the status of the job and calls complete buffers to mark all
@@ -2416,7 +2441,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2416 rq->errors = 0; 2441 rq->errors = 0;
2417 2442
2418 if (timeout) 2443 if (timeout)
2419 rq->errors = 1; 2444 rq->errors = make_status_bytes(0, 0, 0, DRIVER_TIMEOUT);
2420 2445
2421 if (cmd->err_info->CommandStatus == 0) /* no error has occurred */ 2446 if (cmd->err_info->CommandStatus == 0) /* no error has occurred */
2422 goto after_error_processing; 2447 goto after_error_processing;
@@ -2442,32 +2467,44 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2442 case CMD_INVALID: 2467 case CMD_INVALID:
2443 printk(KERN_WARNING "cciss: cmd %p is " 2468 printk(KERN_WARNING "cciss: cmd %p is "
2444 "reported invalid\n", cmd); 2469 "reported invalid\n", cmd);
2445 rq->errors = 1; 2470 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2471 cmd->err_info->CommandStatus, DRIVER_OK,
2472 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2446 break; 2473 break;
2447 case CMD_PROTOCOL_ERR: 2474 case CMD_PROTOCOL_ERR:
2448 printk(KERN_WARNING "cciss: cmd %p has " 2475 printk(KERN_WARNING "cciss: cmd %p has "
2449 "protocol error \n", cmd); 2476 "protocol error \n", cmd);
2450 rq->errors = 1; 2477 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2478 cmd->err_info->CommandStatus, DRIVER_OK,
2479 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2451 break; 2480 break;
2452 case CMD_HARDWARE_ERR: 2481 case CMD_HARDWARE_ERR:
2453 printk(KERN_WARNING "cciss: cmd %p had " 2482 printk(KERN_WARNING "cciss: cmd %p had "
2454 " hardware error\n", cmd); 2483 " hardware error\n", cmd);
2455 rq->errors = 1; 2484 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2485 cmd->err_info->CommandStatus, DRIVER_OK,
2486 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2456 break; 2487 break;
2457 case CMD_CONNECTION_LOST: 2488 case CMD_CONNECTION_LOST:
2458 printk(KERN_WARNING "cciss: cmd %p had " 2489 printk(KERN_WARNING "cciss: cmd %p had "
2459 "connection lost\n", cmd); 2490 "connection lost\n", cmd);
2460 rq->errors = 1; 2491 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2492 cmd->err_info->CommandStatus, DRIVER_OK,
2493 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2461 break; 2494 break;
2462 case CMD_ABORTED: 2495 case CMD_ABORTED:
2463 printk(KERN_WARNING "cciss: cmd %p was " 2496 printk(KERN_WARNING "cciss: cmd %p was "
2464 "aborted\n", cmd); 2497 "aborted\n", cmd);
2465 rq->errors = 1; 2498 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2499 cmd->err_info->CommandStatus, DRIVER_OK,
2500 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
2466 break; 2501 break;
2467 case CMD_ABORT_FAILED: 2502 case CMD_ABORT_FAILED:
2468 printk(KERN_WARNING "cciss: cmd %p reports " 2503 printk(KERN_WARNING "cciss: cmd %p reports "
2469 "abort failed\n", cmd); 2504 "abort failed\n", cmd);
2470 rq->errors = 1; 2505 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2506 cmd->err_info->CommandStatus, DRIVER_OK,
2507 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2471 break; 2508 break;
2472 case CMD_UNSOLICITED_ABORT: 2509 case CMD_UNSOLICITED_ABORT:
2473 printk(KERN_WARNING "cciss%d: unsolicited " 2510 printk(KERN_WARNING "cciss%d: unsolicited "
@@ -2481,17 +2518,23 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2481 printk(KERN_WARNING 2518 printk(KERN_WARNING
2482 "cciss%d: %p retried too " 2519 "cciss%d: %p retried too "
2483 "many times\n", h->ctlr, cmd); 2520 "many times\n", h->ctlr, cmd);
2484 rq->errors = 1; 2521 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2522 cmd->err_info->CommandStatus, DRIVER_OK,
2523 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
2485 break; 2524 break;
2486 case CMD_TIMEOUT: 2525 case CMD_TIMEOUT:
2487 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); 2526 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
2488 rq->errors = 1; 2527 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2528 cmd->err_info->CommandStatus, DRIVER_OK,
2529 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2489 break; 2530 break;
2490 default: 2531 default:
2491 printk(KERN_WARNING "cciss: cmd %p returned " 2532 printk(KERN_WARNING "cciss: cmd %p returned "
2492 "unknown status %x\n", cmd, 2533 "unknown status %x\n", cmd,
2493 cmd->err_info->CommandStatus); 2534 cmd->err_info->CommandStatus);
2494 rq->errors = 1; 2535 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2536 cmd->err_info->CommandStatus, DRIVER_OK,
2537 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2495 } 2538 }
2496 2539
2497after_error_processing: 2540after_error_processing: