aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2007-07-29 15:27:06 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-08-04 10:14:24 -0400
commit45333ffa6ffd2f493fc3853481984b6e60b4fb93 (patch)
tree77be77784c92689593b3b56e92a070da64f84745 /drivers/scsi
parent66acdb0309507950376393f2fb1c8e7482fb4d52 (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.c55
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 {
552struct aha152x_scdata { 552struct 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);