Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 25807
b: refs/heads/master
c: b4e93a7
h: refs/heads/master
i:
  25805: d574be7
  25803: 5e40360
  25799: a8beb8e
  25791: f951c8b
v: v3
  • Loading branch information
Matthew Wilcox authored and James Bottomley committed Apr 13, 2006
1 parent 23f27fc commit c789ec9
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c2349df918cdfd47dfe6afaaeed9f504b83255d0
refs/heads/master: b4e93a739ed1352664defd41d5e4f82afa29b928
84 changes: 22 additions & 62 deletions trunk/drivers/scsi/sym53c8xx_2/sym_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,25 +136,15 @@ static void sym2_setup_params(void)

static struct scsi_transport_template *sym2_transport_template = NULL;

/*
* Used by the eh thread to wait for command completion.
* It is allocated on the eh thread stack.
*/
struct sym_eh_wait {
struct completion done;
struct timer_list timer;
void (*old_done)(struct scsi_cmnd *);
int to_do;
int timed_out;
};

/*
* Driver private area in the SCSI command structure.
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
struct completion done;
void (*old_done)(struct scsi_cmnd *);
dma_addr_t data_mapping;
u_char data_mapped;
struct sym_eh_wait *eh_wait;
int to_do;
u_char data_mapped; /* corresponds to data_mapping above */
};

#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
Expand Down Expand Up @@ -713,55 +703,35 @@ static void sym53c8xx_timer(unsigned long npref)
#define SYM_EH_DO_WAIT 2

/*
* Our general completion handler.
* scsi_done() alias when error recovery is in progress.
*/
static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out)
static void sym_eh_done(struct scsi_cmnd *cmd)
{
struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait;
if (!ep)
return;

/* Try to avoid a race here (not 100% safe) */
if (!timed_out) {
ep->timed_out = 0;
if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer))
return;
}
struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));

/* Revert everything */
SYM_UCMD_PTR(cmd)->eh_wait = NULL;
cmd->scsi_done = ep->old_done;
cmd->scsi_done = ucmd->old_done;

/* Wake up the eh thread if it wants to sleep */
if (ep->to_do == SYM_EH_DO_WAIT)
complete(&ep->done);
if (ucmd->to_do == SYM_EH_DO_WAIT)
complete(&ucmd->done);
}

/*
* scsi_done() alias when error recovery is in progress.
*/
static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); }

/*
* Some timeout handler to avoid waiting too long.
*/
static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); }

/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
{
struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
struct Scsi_Host *host = cmd->device->host;
SYM_QUEHEAD *qp;
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
struct sym_eh_wait eh, *ep = &eh;

dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);

spin_lock_irq(cmd->device->host->host_lock);
spin_lock_irq(host->host_lock);
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
Expand All @@ -772,10 +742,9 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
}

if (to_do == SYM_EH_DO_WAIT) {
init_completion(&ep->done);
ep->old_done = cmd->scsi_done;
init_completion(&ucmd->done);
ucmd->old_done = cmd->scsi_done;
cmd->scsi_done = sym_eh_done;
SYM_UCMD_PTR(cmd)->eh_wait = ep;
}

/* Try to proceed the operation we have been asked for */
Expand All @@ -802,28 +771,19 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)

/* On error, restore everything and cross fingers :) */
if (sts) {
SYM_UCMD_PTR(cmd)->eh_wait = NULL;
cmd->scsi_done = ep->old_done;
cmd->scsi_done = ucmd->old_done;
to_do = SYM_EH_DO_IGNORE;
}

ep->to_do = to_do;
ucmd->to_do = to_do;
spin_unlock_irq(host->host_lock);

/* Wait for completion with locks released, as required by kernel */
if (to_do == SYM_EH_DO_WAIT) {
init_timer(&ep->timer);
ep->timer.expires = jiffies + (5*HZ);
ep->timer.function = sym_eh_timeout;
ep->timer.data = (u_long)cmd;
ep->timed_out = 1; /* Be pessimistic for once :) */
add_timer(&ep->timer);
spin_unlock_irq(np->s.host->host_lock);
wait_for_completion(&ep->done);
spin_lock_irq(np->s.host->host_lock);
if (ep->timed_out)
if (!wait_for_completion_timeout(&ucmd->done, 5*HZ)) {
ucmd->to_do = SYM_EH_DO_IGNORE;
sts = -2;
}
}
spin_unlock_irq(cmd->device->host->host_lock);
dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
return sts ? SCSI_FAILED : SCSI_SUCCESS;
Expand Down

0 comments on commit c789ec9

Please sign in to comment.