diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 135 |
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 | ||
2366 | static 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 | |||
2368 | static inline int evaluate_target_status(CommandList_struct *cmd) | 2377 | static 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 | ||
2497 | after_error_processing: | 2538 | after_error_processing: |