Skip to content

Commit 49799fe

Browse files
aakoskinJames Bottomley
authored andcommitted
[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 <[email protected]> Tested-by: Tony Battersby <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 5ef0741 commit 49799fe

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

drivers/scsi/sym53c8xx_2/sym_hipd.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
14331433
* Many devices implement PPR in a buggy way, so only use it if we
14341434
* really want to.
14351435
*/
1436-
if (goal->offset &&
1437-
(goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) {
1436+
if (goal->renego == NS_PPR || (goal->offset &&
1437+
(goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) {
14381438
nego = NS_PPR;
1439-
} else if (spi_width(starget) != goal->width) {
1439+
} else if (goal->renego == NS_WIDE || goal->width) {
14401440
nego = NS_WIDE;
1441-
} else if (spi_period(starget) != goal->period ||
1442-
spi_offset(starget) != goal->offset) {
1441+
} else if (goal->renego == NS_SYNC || goal->offset) {
14431442
nego = NS_SYNC;
14441443
} else {
14451444
goal->check_nego = 0;
@@ -2049,11 +2048,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
20492048
struct sym_tcb *tp = &np->target[target];
20502049
struct scsi_target *starget = tp->starget;
20512050

2052-
if (spi_width(starget) == wide)
2053-
return;
2054-
20552051
sym_settrans(np, target, 0, 0, 0, wide, 0, 0);
20562052

2053+
if (wide)
2054+
tp->tgoal.renego = NS_WIDE;
2055+
else
2056+
tp->tgoal.renego = 0;
2057+
tp->tgoal.check_nego = 0;
20572058
tp->tgoal.width = wide;
20582059
spi_offset(starget) = 0;
20592060
spi_period(starget) = 0;
@@ -2080,6 +2081,12 @@ sym_setsync(struct sym_hcb *np, int target,
20802081

20812082
sym_settrans(np, target, 0, ofs, per, wide, div, fak);
20822083

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;
20832090
spi_period(starget) = per;
20842091
spi_offset(starget) = ofs;
20852092
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,
21062113

21072114
sym_settrans(np, target, opts, ofs, per, wide, div, fak);
21082115

2116+
if (wide || ofs)
2117+
tp->tgoal.renego = NS_PPR;
2118+
else
2119+
tp->tgoal.renego = 0;
21092120
spi_width(starget) = tp->tgoal.width = wide;
21102121
spi_period(starget) = tp->tgoal.period = per;
21112122
spi_offset(starget) = tp->tgoal.offset = ofs;
@@ -3516,6 +3527,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
35163527
spi_dt(starget) = 0;
35173528
spi_qas(starget) = 0;
35183529
tp->tgoal.check_nego = 1;
3530+
tp->tgoal.renego = 0;
35193531
}
35203532

35213533
/*
@@ -5135,9 +5147,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *
51355147
/*
51365148
* Build a negotiation message if needed.
51375149
* (nego_status is filled by sym_prepare_nego())
5150+
*
5151+
* Always negotiate on INQUIRY and REQUEST SENSE.
5152+
*
51385153
*/
51395154
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) {
51415158
msglen += sym_prepare_nego(np, cp, msgptr + msglen);
51425159
}
51435160

drivers/scsi/sym53c8xx_2/sym_hipd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ struct sym_trans {
354354
unsigned int dt:1;
355355
unsigned int qas:1;
356356
unsigned int check_nego:1;
357+
unsigned int renego:2;
357358
};
358359

359360
/*

0 commit comments

Comments
 (0)