aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss_scsi.c
diff options
context:
space:
mode:
authormike.miller@hp.com <mike.miller@hp.com>2005-11-04 13:30:37 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-11-06 15:12:49 -0500
commit3da8b713da723e78a03f0404beedf3cc6f4f860b (patch)
treea09cc4308fcf0087aa607029bd71825b568d97e5 /drivers/block/cciss_scsi.c
parent13bf50d1f21b2f11452c4b8a82a91319791f8ba3 (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.c82
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... */
46static int sendcmd( 49static int sendcmd(
47 __u8 cmd, 50 __u8 cmd,
@@ -67,6 +70,8 @@ static int cciss_scsi_proc_info(
67 70
68static int cciss_scsi_queue_command (struct scsi_cmnd *cmd, 71static int cciss_scsi_queue_command (struct scsi_cmnd *cmd,
69 void (* done)(struct scsi_cmnd *)); 72 void (* done)(struct scsi_cmnd *));
73static int cciss_eh_device_reset_handler(struct scsi_cmnd *);
74static int cciss_eh_abort_handler(struct scsi_cmnd *);
70 75
71static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { 76static 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
251static int xmargin=8; 259static int xmargin=8;
252static int amargin=60; 260static 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
1470static 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
1501static 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 */