Skip to content

Commit

Permalink
[SCSI] sym53c8xx: Keep transfer negotiations valid
Browse files Browse the repository at this point in the history
(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>
  • Loading branch information
Aaro Koskinen authored and James Bottomley committed Mar 12, 2009
1 parent 5ef0741 commit 49799fe
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 deletions.
35 changes: 26 additions & 9 deletions drivers/scsi/sym53c8xx_2/sym_hipd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
* Many devices implement PPR in a buggy way, so only use it if we
* really want to.
*/
if (goal->offset &&
(goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) {
if (goal->renego == NS_PPR || (goal->offset &&
(goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) {
nego = NS_PPR;
} else if (spi_width(starget) != goal->width) {
} else if (goal->renego == NS_WIDE || goal->width) {
nego = NS_WIDE;
} else if (spi_period(starget) != goal->period ||
spi_offset(starget) != goal->offset) {
} else if (goal->renego == NS_SYNC || goal->offset) {
nego = NS_SYNC;
} else {
goal->check_nego = 0;
Expand Down Expand Up @@ -2049,11 +2048,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
struct sym_tcb *tp = &np->target[target];
struct scsi_target *starget = tp->starget;

if (spi_width(starget) == wide)
return;

sym_settrans(np, target, 0, 0, 0, wide, 0, 0);

if (wide)
tp->tgoal.renego = NS_WIDE;
else
tp->tgoal.renego = 0;
tp->tgoal.check_nego = 0;
tp->tgoal.width = wide;
spi_offset(starget) = 0;
spi_period(starget) = 0;
Expand All @@ -2080,6 +2081,12 @@ sym_setsync(struct sym_hcb *np, int target,

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

if (wide)
tp->tgoal.renego = NS_WIDE;
else if (ofs)
tp->tgoal.renego = NS_SYNC;
else
tp->tgoal.renego = 0;
spi_period(starget) = per;
spi_offset(starget) = ofs;
spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0;
Expand All @@ -2106,6 +2113,10 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,

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

if (wide || ofs)
tp->tgoal.renego = NS_PPR;
else
tp->tgoal.renego = 0;
spi_width(starget) = tp->tgoal.width = wide;
spi_period(starget) = tp->tgoal.period = per;
spi_offset(starget) = tp->tgoal.offset = ofs;
Expand Down Expand Up @@ -3516,6 +3527,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
spi_dt(starget) = 0;
spi_qas(starget) = 0;
tp->tgoal.check_nego = 1;
tp->tgoal.renego = 0;
}

/*
Expand Down Expand Up @@ -5135,9 +5147,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *
/*
* Build a negotiation message if needed.
* (nego_status is filled by sym_prepare_nego())
*
* Always negotiate on INQUIRY and REQUEST SENSE.
*
*/
cp->nego_status = 0;
if (tp->tgoal.check_nego && !tp->nego_cp && lp) {
if ((tp->tgoal.check_nego ||
cmd->cmnd[0] == INQUIRY || cmd->cmnd[0] == REQUEST_SENSE) &&
!tp->nego_cp && lp) {
msglen += sym_prepare_nego(np, cp, msgptr + msglen);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/sym53c8xx_2/sym_hipd.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ struct sym_trans {
unsigned int dt:1;
unsigned int qas:1;
unsigned int check_nego:1;
unsigned int renego:2;
};

/*
Expand Down

0 comments on commit 49799fe

Please sign in to comment.