aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c135
1 files changed, 88 insertions, 47 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index e330c26c5ad9..7c2cfde08f18 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1582,38 +1582,36 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
1582 * allows us to delete disk zero but keep the controller registered. 1582 * allows us to delete disk zero but keep the controller registered.
1583 */ 1583 */
1584 if (h->gendisk[0] != disk) { 1584 if (h->gendisk[0] != disk) {
1585 if (disk) { 1585 struct request_queue *q = disk->queue;
1586 struct request_queue *q = disk->queue; 1586 if (disk->flags & GENHD_FL_UP)
1587 if (disk->flags & GENHD_FL_UP) 1587 del_gendisk(disk);
1588 del_gendisk(disk); 1588 if (q) {
1589 if (q) { 1589 blk_cleanup_queue(q);
1590 blk_cleanup_queue(q); 1590 /* Set drv->queue to NULL so that we do not try
1591 /* Set drv->queue to NULL so that we do not try 1591 * to call blk_start_queue on this queue in the
1592 * to call blk_start_queue on this queue in the 1592 * interrupt handler
1593 * interrupt handler 1593 */
1594 */ 1594 drv->queue = NULL;
1595 drv->queue = NULL; 1595 }
1596 } 1596 /* If clear_all is set then we are deleting the logical
1597 /* If clear_all is set then we are deleting the logical 1597 * drive, not just refreshing its info. For drives
1598 * drive, not just refreshing its info. For drives 1598 * other than disk 0 we will call put_disk. We do not
1599 * other than disk 0 we will call put_disk. We do not 1599 * do this for disk 0 as we need it to be able to
1600 * do this for disk 0 as we need it to be able to 1600 * configure the controller.
1601 * configure the controller. 1601 */
1602 if (clear_all){
1603 /* This isn't pretty, but we need to find the
1604 * disk in our array and NULL our the pointer.
1605 * This is so that we will call alloc_disk if
1606 * this index is used again later.
1602 */ 1607 */
1603 if (clear_all){ 1608 for (i=0; i < CISS_MAX_LUN; i++){
1604 /* This isn't pretty, but we need to find the 1609 if(h->gendisk[i] == disk){
1605 * disk in our array and NULL our the pointer. 1610 h->gendisk[i] = NULL;
1606 * This is so that we will call alloc_disk if 1611 break;
1607 * this index is used again later.
1608 */
1609 for (i=0; i < CISS_MAX_LUN; i++){
1610 if(h->gendisk[i] == disk){
1611 h->gendisk[i] = NULL;
1612 break;
1613 }
1614 } 1612 }
1615 put_disk(disk);
1616 } 1613 }
1614 put_disk(disk);
1617 } 1615 }
1618 } else { 1616 } else {
1619 set_capacity(disk, 0); 1617 set_capacity(disk, 0);
@@ -2365,30 +2363,55 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2365 start_io(h); 2363 start_io(h);
2366} 2364}
2367 2365
2366static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
2367 unsigned int msg_byte, unsigned int host_byte,
2368 unsigned int driver_byte)
2369{
2370 /* inverse of macros in scsi.h */
2371 return (scsi_status_byte & 0xff) |
2372 ((msg_byte & 0xff) << 8) |
2373 ((host_byte & 0xff) << 16) |
2374 ((driver_byte & 0xff) << 24);
2375}
2376
2368static inline int evaluate_target_status(CommandList_struct *cmd) 2377static inline int evaluate_target_status(CommandList_struct *cmd)
2369{ 2378{
2370 unsigned char sense_key; 2379 unsigned char sense_key;
2371 int error_count = 1; 2380 unsigned char status_byte, msg_byte, host_byte, driver_byte;
2381 int error_value;
2382
2383 /* If we get in here, it means we got "target status", that is, scsi status */
2384 status_byte = cmd->err_info->ScsiStatus;
2385 driver_byte = DRIVER_OK;
2386 msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */
2387
2388 if (blk_pc_request(cmd->rq))
2389 host_byte = DID_PASSTHROUGH;
2390 else
2391 host_byte = DID_OK;
2392
2393 error_value = make_status_bytes(status_byte, msg_byte,
2394 host_byte, driver_byte);
2372 2395
2373 if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */ 2396 if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) {
2374 if (!blk_pc_request(cmd->rq)) 2397 if (!blk_pc_request(cmd->rq))
2375 printk(KERN_WARNING "cciss: cmd %p " 2398 printk(KERN_WARNING "cciss: cmd %p "
2376 "has SCSI Status 0x%x\n", 2399 "has SCSI Status 0x%x\n",
2377 cmd, cmd->err_info->ScsiStatus); 2400 cmd, cmd->err_info->ScsiStatus);
2378 return error_count; 2401 return error_value;
2379 } 2402 }
2380 2403
2381 /* check the sense key */ 2404 /* check the sense key */
2382 sense_key = 0xf & cmd->err_info->SenseInfo[2]; 2405 sense_key = 0xf & cmd->err_info->SenseInfo[2];
2383 /* no status or recovered error */ 2406 /* no status or recovered error */
2384 if ((sense_key == 0x0) || (sense_key == 0x1)) 2407 if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
2385 error_count = 0; 2408 error_value = 0;
2386 2409
2387 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ 2410 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
2388 if (error_count != 0) 2411 if (error_value != 0)
2389 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" 2412 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
2390 " sense key = 0x%x\n", cmd, sense_key); 2413 " sense key = 0x%x\n", cmd, sense_key);
2391 return error_count; 2414 return error_value;
2392 } 2415 }
2393 2416
2394 /* SG_IO or similar, copy sense data back */ 2417 /* SG_IO or similar, copy sense data back */
@@ -2400,7 +2423,7 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
2400 } else 2423 } else
2401 cmd->rq->sense_len = 0; 2424 cmd->rq->sense_len = 0;
2402 2425
2403 return error_count; 2426 return error_value;
2404} 2427}
2405 2428
2406/* checks the status of the job and calls complete buffers to mark all 2429/* checks the status of the job and calls complete buffers to mark all
@@ -2416,7 +2439,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2416 rq->errors = 0; 2439 rq->errors = 0;
2417 2440
2418 if (timeout) 2441 if (timeout)
2419 rq->errors = 1; 2442 rq->errors = make_status_bytes(0, 0, 0, DRIVER_TIMEOUT);
2420 2443
2421 if (cmd->err_info->CommandStatus == 0) /* no error has occurred */ 2444 if (cmd->err_info->CommandStatus == 0) /* no error has occurred */
2422 goto after_error_processing; 2445 goto after_error_processing;
@@ -2442,32 +2465,44 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2442 case CMD_INVALID: 2465 case CMD_INVALID:
2443 printk(KERN_WARNING "cciss: cmd %p is " 2466 printk(KERN_WARNING "cciss: cmd %p is "
2444 "reported invalid\n", cmd); 2467 "reported invalid\n", cmd);
2445 rq->errors = 1; 2468 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2469 cmd->err_info->CommandStatus, DRIVER_OK,
2470 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2446 break; 2471 break;
2447 case CMD_PROTOCOL_ERR: 2472 case CMD_PROTOCOL_ERR:
2448 printk(KERN_WARNING "cciss: cmd %p has " 2473 printk(KERN_WARNING "cciss: cmd %p has "
2449 "protocol error \n", cmd); 2474 "protocol error \n", cmd);
2450 rq->errors = 1; 2475 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2476 cmd->err_info->CommandStatus, DRIVER_OK,
2477 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2451 break; 2478 break;
2452 case CMD_HARDWARE_ERR: 2479 case CMD_HARDWARE_ERR:
2453 printk(KERN_WARNING "cciss: cmd %p had " 2480 printk(KERN_WARNING "cciss: cmd %p had "
2454 " hardware error\n", cmd); 2481 " hardware error\n", cmd);
2455 rq->errors = 1; 2482 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2483 cmd->err_info->CommandStatus, DRIVER_OK,
2484 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2456 break; 2485 break;
2457 case CMD_CONNECTION_LOST: 2486 case CMD_CONNECTION_LOST:
2458 printk(KERN_WARNING "cciss: cmd %p had " 2487 printk(KERN_WARNING "cciss: cmd %p had "
2459 "connection lost\n", cmd); 2488 "connection lost\n", cmd);
2460 rq->errors = 1; 2489 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2490 cmd->err_info->CommandStatus, DRIVER_OK,
2491 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2461 break; 2492 break;
2462 case CMD_ABORTED: 2493 case CMD_ABORTED:
2463 printk(KERN_WARNING "cciss: cmd %p was " 2494 printk(KERN_WARNING "cciss: cmd %p was "
2464 "aborted\n", cmd); 2495 "aborted\n", cmd);
2465 rq->errors = 1; 2496 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2497 cmd->err_info->CommandStatus, DRIVER_OK,
2498 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
2466 break; 2499 break;
2467 case CMD_ABORT_FAILED: 2500 case CMD_ABORT_FAILED:
2468 printk(KERN_WARNING "cciss: cmd %p reports " 2501 printk(KERN_WARNING "cciss: cmd %p reports "
2469 "abort failed\n", cmd); 2502 "abort failed\n", cmd);
2470 rq->errors = 1; 2503 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2504 cmd->err_info->CommandStatus, DRIVER_OK,
2505 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2471 break; 2506 break;
2472 case CMD_UNSOLICITED_ABORT: 2507 case CMD_UNSOLICITED_ABORT:
2473 printk(KERN_WARNING "cciss%d: unsolicited " 2508 printk(KERN_WARNING "cciss%d: unsolicited "
@@ -2481,17 +2516,23 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2481 printk(KERN_WARNING 2516 printk(KERN_WARNING
2482 "cciss%d: %p retried too " 2517 "cciss%d: %p retried too "
2483 "many times\n", h->ctlr, cmd); 2518 "many times\n", h->ctlr, cmd);
2484 rq->errors = 1; 2519 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2520 cmd->err_info->CommandStatus, DRIVER_OK,
2521 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT);
2485 break; 2522 break;
2486 case CMD_TIMEOUT: 2523 case CMD_TIMEOUT:
2487 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); 2524 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
2488 rq->errors = 1; 2525 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2526 cmd->err_info->CommandStatus, DRIVER_OK,
2527 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2489 break; 2528 break;
2490 default: 2529 default:
2491 printk(KERN_WARNING "cciss: cmd %p returned " 2530 printk(KERN_WARNING "cciss: cmd %p returned "
2492 "unknown status %x\n", cmd, 2531 "unknown status %x\n", cmd,
2493 cmd->err_info->CommandStatus); 2532 cmd->err_info->CommandStatus);
2494 rq->errors = 1; 2533 rq->errors = make_status_bytes(SAM_STAT_GOOD,
2534 cmd->err_info->CommandStatus, DRIVER_OK,
2535 blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR);
2495 } 2536 }
2496 2537
2497after_error_processing: 2538after_error_processing: