summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2006-03-30 01:45:18 +0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-13 19:13:30 +0400
commitd637c4543fdc86cbef5805c679d24bb665172a7d (patch)
tree45ed36215b8e2623e75d02ab76ff2e50a3e937a0 /drivers/scsi
parent80286d478c2b0e07959e79cf34591a4061ff1797 (diff)
downloadlinux-d637c4543fdc86cbef5805c679d24bb665172a7d.tar.xz
[SCSI] sym2: Fix build when spinlock debugging is enabled
When spinlock debugging is turned on, a struct completion grows beyond the size allowed for the scsi_pointer. So move the struct completion back onto the stack. The additional memory barriers are to keep us from completing a random piece of kernel stack if the command happens to complete after the error handling has finished. Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 2c4e5f1e7a94..9c83b4d39a26 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -140,11 +140,11 @@ static struct scsi_transport_template *sym2_transport_template = NULL;
* 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;
- int to_do;
- u_char data_mapped; /* corresponds to data_mapping above */
+ dma_addr_t data_mapping;
+ unsigned char data_mapped;
+ unsigned char to_do; /* For error handling */
+ void (*old_done)(struct scsi_cmnd *); /* For error handling */
+ struct completion *eh_done; /* For error handling */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
@@ -713,7 +713,7 @@ static void sym_eh_done(struct scsi_cmnd *cmd)
cmd->scsi_done = ucmd->old_done;
if (ucmd->to_do == SYM_EH_DO_WAIT)
- complete(&ucmd->done);
+ complete(ucmd->eh_done);
}
/*
@@ -728,6 +728,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
SYM_QUEHEAD *qp;
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
+ struct completion eh_done;
dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
@@ -742,8 +743,10 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
}
if (to_do == SYM_EH_DO_WAIT) {
- init_completion(&ucmd->done);
+ init_completion(&eh_done);
ucmd->old_done = cmd->scsi_done;
+ ucmd->eh_done = &eh_done;
+ wmb();
cmd->scsi_done = sym_eh_done;
}
@@ -779,8 +782,9 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
spin_unlock_irq(host->host_lock);
if (to_do == SYM_EH_DO_WAIT) {
- if (!wait_for_completion_timeout(&ucmd->done, 5*HZ)) {
+ if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
ucmd->to_do = SYM_EH_DO_IGNORE;
+ wmb();
sts = -2;
}
}