diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2007-07-29 15:27:06 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-08-04 10:14:24 -0400 |
commit | 45333ffa6ffd2f493fc3853481984b6e60b4fb93 (patch) | |
tree | 77be77784c92689593b3b56e92a070da64f84745 /drivers/scsi | |
parent | 66acdb0309507950376393f2fb1c8e7482fb4d52 (diff) |
[SCSI] aha152x: Fix check_condition code-path
check_condition code-path was similar but more
complicated to Reset. It went like this:
1. extra space was allocated at aha152x_scdata for mirroring
scsi_cmnd members.
2. At aha152x_internal_queue() every not check_condition
(REQUEST_SENSE) command was copied to above members in
case of error.
3. At busfree_run() in the DONE_CS phase if a Status of
SAM_STAT_CHECK_CONDITION was detected. The command was
re-queued Internally using aha152x_internal_queue(,,check_condition,)
The old command members are over written with the
REQUEST_SENSE info.
4. At busfree_run() in the DONE_CS phase again. If it is a
check_condition command, info was restored from mirror
made at first call to aha152x_internal_queue() (see 2)
and the command is completed.
What I did is:
1. Allocate less space in aha152x_scdata only for the 16-byte
original command. (which is actually not needed by scsi-ml
anymore at this stage. But this is to much knowledge of scsi-ml)
2. If Status == SAM_STAT_CHECK_CONDITION, then like before
re-queue a REQUEST_SENSE command. But only now save original
command members. (Less of them)
3. In aha152x_internal_queue(), just like for Reset, use the
check_condition hint to set differently the working members.
execute the command.
4. At busfree_run() in the DONE_CS phase again. restore needed
members.
While at it. This patch fixes a BUG. Old code when sending
a REQUEST_SENSE for a failed command. Would than return with
cmd->resid == 0 which was the status of the REQUEST_SENSE.
The failing command resid was lost. And when would resid
be interesting if not on a failing command?
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/aha152x.c | 55 |
1 files changed, 27 insertions, 28 deletions
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index d7ca86f9d1f2..cf49ed584762 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c | |||
@@ -552,14 +552,11 @@ struct aha152x_hostdata { | |||
552 | struct aha152x_scdata { | 552 | struct aha152x_scdata { |
553 | Scsi_Cmnd *next; /* next sc in queue */ | 553 | Scsi_Cmnd *next; /* next sc in queue */ |
554 | struct completion *done;/* semaphore to block on */ | 554 | struct completion *done;/* semaphore to block on */ |
555 | unsigned char cmd_len; | 555 | unsigned char aha_orig_cmd_len; |
556 | unsigned char cmnd[MAX_COMMAND_SIZE]; | 556 | unsigned char aha_orig_cmnd[MAX_COMMAND_SIZE]; |
557 | unsigned short use_sg; | 557 | int aha_orig_resid; |
558 | unsigned request_bufflen; | ||
559 | void *request_buffer; | ||
560 | }; | 558 | }; |
561 | 559 | ||
562 | |||
563 | /* access macros for hostdata */ | 560 | /* access macros for hostdata */ |
564 | 561 | ||
565 | #define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata) | 562 | #define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata) |
@@ -997,20 +994,11 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, | |||
997 | return FAILED; | 994 | return FAILED; |
998 | } | 995 | } |
999 | } else { | 996 | } else { |
1000 | struct aha152x_scdata *sc; | ||
1001 | |||
1002 | SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); | 997 | SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); |
1003 | if(SCpnt->host_scribble==0) { | 998 | if(SCpnt->host_scribble==0) { |
1004 | printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); | 999 | printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); |
1005 | return FAILED; | 1000 | return FAILED; |
1006 | } | 1001 | } |
1007 | |||
1008 | sc = SCDATA(SCpnt); | ||
1009 | memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd)); | ||
1010 | sc->request_buffer = SCpnt->request_buffer; | ||
1011 | sc->request_bufflen = SCpnt->request_bufflen; | ||
1012 | sc->use_sg = SCpnt->use_sg; | ||
1013 | sc->cmd_len = SCpnt->cmd_len; | ||
1014 | } | 1002 | } |
1015 | 1003 | ||
1016 | SCNEXT(SCpnt) = NULL; | 1004 | SCNEXT(SCpnt) = NULL; |
@@ -1023,10 +1011,16 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, | |||
1023 | SCp.buffers_residual : left buffers in list | 1011 | SCp.buffers_residual : left buffers in list |
1024 | SCp.phase : current state of the command */ | 1012 | SCp.phase : current state of the command */ |
1025 | 1013 | ||
1026 | if(phase & resetting) { | 1014 | if (phase & (check_condition|resetting)) { |
1027 | SCpnt->SCp.ptr = NULL; | 1015 | if (phase & check_condition) { |
1028 | SCpnt->SCp.this_residual = 0; | 1016 | SCpnt->SCp.ptr = SCpnt->sense_buffer; |
1029 | SCpnt->resid = 0; | 1017 | SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); |
1018 | SCpnt->resid = sizeof(SCpnt->sense_buffer); | ||
1019 | } else { | ||
1020 | SCpnt->SCp.ptr = NULL; | ||
1021 | SCpnt->SCp.this_residual = 0; | ||
1022 | SCpnt->resid = 0; | ||
1023 | } | ||
1030 | SCpnt->SCp.buffer = NULL; | 1024 | SCpnt->SCp.buffer = NULL; |
1031 | SCpnt->SCp.buffers_residual = 0; | 1025 | SCpnt->SCp.buffers_residual = 0; |
1032 | } else { | 1026 | } else { |
@@ -1568,11 +1562,9 @@ static void busfree_run(struct Scsi_Host *shpnt) | |||
1568 | #endif | 1562 | #endif |
1569 | 1563 | ||
1570 | /* restore old command */ | 1564 | /* restore old command */ |
1571 | memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd)); | 1565 | memcpy(cmd->cmnd, sc->aha_orig_cmnd, sizeof(cmd->cmnd)); |
1572 | cmd->request_buffer = sc->request_buffer; | 1566 | cmd->cmd_len = sc->aha_orig_cmd_len; |
1573 | cmd->request_bufflen = sc->request_bufflen; | 1567 | cmd->resid = sc->aha_orig_resid; |
1574 | cmd->use_sg = sc->use_sg; | ||
1575 | cmd->cmd_len = sc->cmd_len; | ||
1576 | 1568 | ||
1577 | cmd->SCp.Status = SAM_STAT_CHECK_CONDITION; | 1569 | cmd->SCp.Status = SAM_STAT_CHECK_CONDITION; |
1578 | 1570 | ||
@@ -1588,12 +1580,22 @@ static void busfree_run(struct Scsi_Host *shpnt) | |||
1588 | #endif | 1580 | #endif |
1589 | 1581 | ||
1590 | if(!(DONE_SC->SCp.phase & not_issued)) { | 1582 | if(!(DONE_SC->SCp.phase & not_issued)) { |
1583 | struct aha152x_scdata *sc; | ||
1591 | Scsi_Cmnd *ptr = DONE_SC; | 1584 | Scsi_Cmnd *ptr = DONE_SC; |
1592 | DONE_SC=NULL; | 1585 | DONE_SC=NULL; |
1593 | #if 0 | 1586 | #if 0 |
1594 | DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr)); | 1587 | DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr)); |
1595 | #endif | 1588 | #endif |
1596 | 1589 | ||
1590 | /* save old command */ | ||
1591 | sc = SCDATA(ptr); | ||
1592 | /* It was allocated in aha152x_internal_queue? */ | ||
1593 | BUG_ON(!sc); | ||
1594 | memcpy(sc->aha_orig_cmnd, ptr->cmnd, | ||
1595 | sizeof(ptr->cmnd)); | ||
1596 | sc->aha_orig_cmd_len = ptr->cmd_len; | ||
1597 | sc->aha_orig_resid = ptr->resid; | ||
1598 | |||
1597 | ptr->cmnd[0] = REQUEST_SENSE; | 1599 | ptr->cmnd[0] = REQUEST_SENSE; |
1598 | ptr->cmnd[1] = 0; | 1600 | ptr->cmnd[1] = 0; |
1599 | ptr->cmnd[2] = 0; | 1601 | ptr->cmnd[2] = 0; |
@@ -1601,10 +1603,7 @@ static void busfree_run(struct Scsi_Host *shpnt) | |||
1601 | ptr->cmnd[4] = sizeof(ptr->sense_buffer); | 1603 | ptr->cmnd[4] = sizeof(ptr->sense_buffer); |
1602 | ptr->cmnd[5] = 0; | 1604 | ptr->cmnd[5] = 0; |
1603 | ptr->cmd_len = 6; | 1605 | ptr->cmd_len = 6; |
1604 | ptr->use_sg = 0; | 1606 | |
1605 | ptr->request_buffer = ptr->sense_buffer; | ||
1606 | ptr->request_bufflen = sizeof(ptr->sense_buffer); | ||
1607 | |||
1608 | DO_UNLOCK(flags); | 1607 | DO_UNLOCK(flags); |
1609 | aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done); | 1608 | aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done); |
1610 | DO_LOCK(flags); | 1609 | DO_LOCK(flags); |