aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAaro Koskinen <Aaro.Koskinen@nokia.com>2009-01-15 10:13:36 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:57:57 -0400
commit49799fee82b4f78c45b1926be24e45b5cf667083 (patch)
tree5eca74c9d542b161ff5c91e44cd7a379d6a07ad3 /drivers/scsi
parent5ef074161b5bcd84acfe19f0ecd72b74765d8770 (diff)
[SCSI] sym53c8xx: Keep transfer negotiations valid
(The patch updated based on testing and comments from Tony Battersby.) Change the sym53c8xx_2 driver negotiation logic so that the driver will tolerate better device removals. Negotiation message(s) will be sent with every INQUIRY and REQUEST SENSE command, and whenever there is a change in goals or when the device reports check condition. The patch was made specifically to address the case where you hotswap the disk using remove-single-device/add-single-device commands through /proc/scsi/scsi. Without the patch the driver keeps using old transfer parameters even though the target is reset and reports check condition, so the data transfer of the very first INQUIRY will fail. Signed-off-by: Aaro Koskinen <Aaro.Koskinen@nokia.com> Tested-by: Tony Battersby <tonyb@cybernetics.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c35
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h1
2 files changed, 27 insertions, 9 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 98df1651404f..fe6359d4e1ef 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
1433 * Many devices implement PPR in a buggy way, so only use it if we 1433 * Many devices implement PPR in a buggy way, so only use it if we
1434 * really want to. 1434 * really want to.
1435 */ 1435 */
1436 if (goal->offset && 1436 if (goal->renego == NS_PPR || (goal->offset &&
1437 (goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) { 1437 (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) {
1438 nego = NS_PPR; 1438 nego = NS_PPR;
1439 } else if (spi_width(starget) != goal->width) { 1439 } else if (goal->renego == NS_WIDE || goal->width) {
1440 nego = NS_WIDE; 1440 nego = NS_WIDE;
1441 } else if (spi_period(starget) != goal->period || 1441 } else if (goal->renego == NS_SYNC || goal->offset) {
1442 spi_offset(starget) != goal->offset) {
1443 nego = NS_SYNC; 1442 nego = NS_SYNC;
1444 } else { 1443 } else {
1445 goal->check_nego = 0; 1444 goal->check_nego = 0;
@@ -2049,11 +2048,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
2049 struct sym_tcb *tp = &np->target[target]; 2048 struct sym_tcb *tp = &np->target[target];
2050 struct scsi_target *starget = tp->starget; 2049 struct scsi_target *starget = tp->starget;
2051 2050
2052 if (spi_width(starget) == wide)
2053 return;
2054
2055 sym_settrans(np, target, 0, 0, 0, wide, 0, 0); 2051 sym_settrans(np, target, 0, 0, 0, wide, 0, 0);
2056 2052
2053 if (wide)
2054 tp->tgoal.renego = NS_WIDE;
2055 else
2056 tp->tgoal.renego = 0;
2057 tp->tgoal.check_nego = 0;
2057 tp->tgoal.width = wide; 2058 tp->tgoal.width = wide;
2058 spi_offset(starget) = 0; 2059 spi_offset(starget) = 0;
2059 spi_period(starget) = 0; 2060 spi_period(starget) = 0;
@@ -2080,6 +2081,12 @@ sym_setsync(struct sym_hcb *np, int target,
2080 2081
2081 sym_settrans(np, target, 0, ofs, per, wide, div, fak); 2082 sym_settrans(np, target, 0, ofs, per, wide, div, fak);
2082 2083
2084 if (wide)
2085 tp->tgoal.renego = NS_WIDE;
2086 else if (ofs)
2087 tp->tgoal.renego = NS_SYNC;
2088 else
2089 tp->tgoal.renego = 0;
2083 spi_period(starget) = per; 2090 spi_period(starget) = per;
2084 spi_offset(starget) = ofs; 2091 spi_offset(starget) = ofs;
2085 spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0; 2092 spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0;
@@ -2106,6 +2113,10 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
2106 2113
2107 sym_settrans(np, target, opts, ofs, per, wide, div, fak); 2114 sym_settrans(np, target, opts, ofs, per, wide, div, fak);
2108 2115
2116 if (wide || ofs)
2117 tp->tgoal.renego = NS_PPR;
2118 else
2119 tp->tgoal.renego = 0;
2109 spi_width(starget) = tp->tgoal.width = wide; 2120 spi_width(starget) = tp->tgoal.width = wide;
2110 spi_period(starget) = tp->tgoal.period = per; 2121 spi_period(starget) = tp->tgoal.period = per;
2111 spi_offset(starget) = tp->tgoal.offset = ofs; 2122 spi_offset(starget) = tp->tgoal.offset = ofs;
@@ -3516,6 +3527,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
3516 spi_dt(starget) = 0; 3527 spi_dt(starget) = 0;
3517 spi_qas(starget) = 0; 3528 spi_qas(starget) = 0;
3518 tp->tgoal.check_nego = 1; 3529 tp->tgoal.check_nego = 1;
3530 tp->tgoal.renego = 0;
3519 } 3531 }
3520 3532
3521 /* 3533 /*
@@ -5135,9 +5147,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *
5135 /* 5147 /*
5136 * Build a negotiation message if needed. 5148 * Build a negotiation message if needed.
5137 * (nego_status is filled by sym_prepare_nego()) 5149 * (nego_status is filled by sym_prepare_nego())
5150 *
5151 * Always negotiate on INQUIRY and REQUEST SENSE.
5152 *
5138 */ 5153 */
5139 cp->nego_status = 0; 5154 cp->nego_status = 0;
5140 if (tp->tgoal.check_nego && !tp->nego_cp && lp) { 5155 if ((tp->tgoal.check_nego ||
5156 cmd->cmnd[0] == INQUIRY || cmd->cmnd[0] == REQUEST_SENSE) &&
5157 !tp->nego_cp && lp) {
5141 msglen += sym_prepare_nego(np, cp, msgptr + msglen); 5158 msglen += sym_prepare_nego(np, cp, msgptr + msglen);
5142 } 5159 }
5143 5160
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index ad078805e62b..233a3d0b2cef 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -354,6 +354,7 @@ struct sym_trans {
354 unsigned int dt:1; 354 unsigned int dt:1;
355 unsigned int qas:1; 355 unsigned int qas:1;
356 unsigned int check_nego:1; 356 unsigned int check_nego:1;
357 unsigned int renego:2;
357}; 358};
358 359
359/* 360/*