diff options
author | mike.miller@hp.com <mike.miller@hp.com> | 2005-11-04 13:30:37 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-11-06 15:12:49 -0500 |
commit | 3da8b713da723e78a03f0404beedf3cc6f4f860b (patch) | |
tree | a09cc4308fcf0087aa607029bd71825b568d97e5 /drivers/block/cciss_scsi.c | |
parent | 13bf50d1f21b2f11452c4b8a82a91319791f8ba3 (diff) |
[SCSI] cciss: scsi error handling
This patch adds SCSI error handling code to the SCSI portion
of the cciss driver.
Signed-off-by: Stephen M. Cameron <steve.cameron@hp.com>
Acked-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r-- | drivers/block/cciss_scsi.c | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index ec27976a57da..3226aa11c6ef 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -42,6 +42,9 @@ | |||
42 | 42 | ||
43 | #include "cciss_scsi.h" | 43 | #include "cciss_scsi.h" |
44 | 44 | ||
45 | #define CCISS_ABORT_MSG 0x00 | ||
46 | #define CCISS_RESET_MSG 0x01 | ||
47 | |||
45 | /* some prototypes... */ | 48 | /* some prototypes... */ |
46 | static int sendcmd( | 49 | static int sendcmd( |
47 | __u8 cmd, | 50 | __u8 cmd, |
@@ -67,6 +70,8 @@ static int cciss_scsi_proc_info( | |||
67 | 70 | ||
68 | static int cciss_scsi_queue_command (struct scsi_cmnd *cmd, | 71 | static int cciss_scsi_queue_command (struct scsi_cmnd *cmd, |
69 | void (* done)(struct scsi_cmnd *)); | 72 | void (* done)(struct scsi_cmnd *)); |
73 | static int cciss_eh_device_reset_handler(struct scsi_cmnd *); | ||
74 | static int cciss_eh_abort_handler(struct scsi_cmnd *); | ||
70 | 75 | ||
71 | static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { | 76 | static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { |
72 | { .name = "cciss0", .ndevices = 0 }, | 77 | { .name = "cciss0", .ndevices = 0 }, |
@@ -90,6 +95,9 @@ static struct scsi_host_template cciss_driver_template = { | |||
90 | .sg_tablesize = MAXSGENTRIES, | 95 | .sg_tablesize = MAXSGENTRIES, |
91 | .cmd_per_lun = 1, | 96 | .cmd_per_lun = 1, |
92 | .use_clustering = DISABLE_CLUSTERING, | 97 | .use_clustering = DISABLE_CLUSTERING, |
98 | /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */ | ||
99 | .eh_device_reset_handler= cciss_eh_device_reset_handler, | ||
100 | .eh_abort_handler = cciss_eh_abort_handler, | ||
93 | }; | 101 | }; |
94 | 102 | ||
95 | #pragma pack(1) | 103 | #pragma pack(1) |
@@ -247,7 +255,7 @@ scsi_cmd_stack_free(int ctlr) | |||
247 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ | 255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ |
248 | "Unknown" : scsi_device_types[n] | 256 | "Unknown" : scsi_device_types[n] |
249 | 257 | ||
250 | #if 0 | 258 | #if 1 |
251 | static int xmargin=8; | 259 | static int xmargin=8; |
252 | static int amargin=60; | 260 | static int amargin=60; |
253 | 261 | ||
@@ -1448,6 +1456,78 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) | |||
1448 | *pos += size; *len += size; | 1456 | *pos += size; *len += size; |
1449 | } | 1457 | } |
1450 | 1458 | ||
1459 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from | ||
1460 | * complaining. Doing a host- or bus-reset can't do anything good here. | ||
1461 | * Despite what it might say in scsi_error.c, there may well be commands | ||
1462 | * on the controller, as the cciss driver registers twice, once as a block | ||
1463 | * device for the logical drives, and once as a scsi device, for any tape | ||
1464 | * drives. So we know there are no commands out on the tape drives, but we | ||
1465 | * don't know there are no commands on the controller, and it is likely | ||
1466 | * that there probably are, as the cciss block device is most commonly used | ||
1467 | * as a boot device (embedded controller on HP/Compaq systems.) | ||
1468 | */ | ||
1469 | |||
1470 | static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | ||
1471 | { | ||
1472 | int rc; | ||
1473 | CommandList_struct *cmd_in_trouble; | ||
1474 | ctlr_info_t **c; | ||
1475 | int ctlr; | ||
1476 | |||
1477 | /* find the controller to which the command to be aborted was sent */ | ||
1478 | c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0]; | ||
1479 | if (c == NULL) /* paranoia */ | ||
1480 | return FAILED; | ||
1481 | ctlr = (*c)->ctlr; | ||
1482 | printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr); | ||
1483 | |||
1484 | /* find the command that's giving us trouble */ | ||
1485 | cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble; | ||
1486 | if (cmd_in_trouble == NULL) { /* paranoia */ | ||
1487 | return FAILED; | ||
1488 | } | ||
1489 | /* send a reset to the SCSI LUN which the command was sent to */ | ||
1490 | rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, | ||
1491 | (unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0], | ||
1492 | TYPE_MSG); | ||
1493 | /* sendcmd turned off interrputs on the board, turn 'em back on. */ | ||
1494 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
1495 | if (rc == 0) | ||
1496 | return SUCCESS; | ||
1497 | printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr); | ||
1498 | return FAILED; | ||
1499 | } | ||
1500 | |||
1501 | static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) | ||
1502 | { | ||
1503 | int rc; | ||
1504 | CommandList_struct *cmd_to_abort; | ||
1505 | ctlr_info_t **c; | ||
1506 | int ctlr; | ||
1507 | |||
1508 | /* find the controller to which the command to be aborted was sent */ | ||
1509 | c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0]; | ||
1510 | if (c == NULL) /* paranoia */ | ||
1511 | return FAILED; | ||
1512 | ctlr = (*c)->ctlr; | ||
1513 | printk(KERN_WARNING "cciss%d: aborting tardy SCSI cmd\n", ctlr); | ||
1514 | |||
1515 | /* find the command to be aborted */ | ||
1516 | cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble; | ||
1517 | if (cmd_to_abort == NULL) /* paranoia */ | ||
1518 | return FAILED; | ||
1519 | rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, | ||
1520 | 0, 2, 0, 0, | ||
1521 | (unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], | ||
1522 | TYPE_MSG); | ||
1523 | /* sendcmd turned off interrputs on the board, turn 'em back on. */ | ||
1524 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
1525 | if (rc == 0) | ||
1526 | return SUCCESS; | ||
1527 | return FAILED; | ||
1528 | |||
1529 | } | ||
1530 | |||
1451 | #else /* no CONFIG_CISS_SCSI_TAPE */ | 1531 | #else /* no CONFIG_CISS_SCSI_TAPE */ |
1452 | 1532 | ||
1453 | /* If no tape support, then these become defined out of existence */ | 1533 | /* If no tape support, then these become defined out of existence */ |