[SCSI] sym2: Fix build when spinlock debugging is enabled
authorMatthew Wilcox <matthew@wil.cx>
Wed, 29 Mar 2006 21:45:18 +0000 (14:45 -0700)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Thu, 13 Apr 2006 15:13:30 +0000 (10:13 -0500)
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>
drivers/scsi/sym53c8xx_2/sym_glue.c

index 2c4e5f1..9c83b4d 100644 (file)
@@ -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;
                }
        }