All of lore.kernel.org
 help / color / mirror / Atom feed
* Full hostlock pushdown available
@ 2010-10-28 15:05 Andi Kleen
  2010-10-28 19:28 ` James Bottomley
  2010-10-31 12:22 ` Boaz Harrosh
  0 siblings, 2 replies; 26+ messages in thread
From: Andi Kleen @ 2010-10-28 15:05 UTC (permalink / raw)
  To: James.Bottomley, nab, linux-scsi


Here's the promised attempt to do a full host_lock pushdown. This
was done using coccinelle and some manual adjustments.

This is just a dumb pushdown of host lock and serial number into
the driver, no attempt to remove any locks yet.

Currently lightly tested, but compiles with allmodconfig on 32bit x86.

I made no attempt to automatically add maintainers to Cc.

I'm not posting the patches because they are numerous and boring,
but it's available in git.

This will likely bitrot quickly so if it's decided to do it this
way I would prefer if this was merged quickly.

Issues found:
- I found a clear deadlock in aha1740, not sure if that driver ever
worked since host_lock was introduced. Anyways I attempted to work
around it. But if it's really that unused it may be better to 
simply drop it.
- I'm not sure how to compile cciss_scsi, is it even used?

-Andi

The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:

  Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)

are available in the git repository at:

  ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock

Andi Kleen (87):
      SCSI: Remove hostlock for queuecommand
      SCSI: ibmmca: hostlock pushdown
      SCSI: ipr: hostlock pushdown
      SCSI: ultrastor: hostlock pushdown
      SCSI: aha1740: hostlock pushdown
      SCSI: ia64 simscsi: hostlock pushdown
      SCSI: sun3_NCR5380: pushdown of hostlock
      SCSI: staging/hv/storvsc_drv: pushdown of hostlock
      SCSI: s390/zfcp_scsi: hostlock pushdown
      SCSI: libiscsi: hostlock pushdown
      SCSI: libiscsi: remove hostlock drop
      SCSI: NCR5380: hostlock pushdown
      SCSI: libsas: hostlock pushdown
      SCSI: stex: hostlock pushdown
      SCSI: wd33c93: hostlock pushdown
      SCSI: aha152x: hostlock pushdown
      SCSI: microtek: hostlock pushdown
      SCSI: scsiglue: hostlock pushdown
      SCSI: uas: hostlock pushdown
      SCSI: i2o_scsi: hostlock pushdown
      SCSI: mptspi: hostlock pushdown
      SCSI: mptsas: hostlock pushdown
      SCSI: mptfc: hostlock pushdown
      SCSI: sbp2: hostlock pushdown
      SCSI: ib_srp: hostlock pushdown
      SCSI: mesh: hostlock pushdown
      SCSI: fd_mcs: hostlock pushdown
      SCSI: fnic_main: hostlock pushdown
      SCSI: gdth: hostlock pushdown
      SCSI: ppa: hostlock pushdown
      SCSI: qlogicpti: hostlock pushdown
      SCSI: 3w-sas: hostlock pushdown
      SCSI: 3w-9xxx: hostlock pushdown
      SCSI: fcoe: hostlock pushdown
      SCSI: ips: hostlock pushdown
      SCSI: sym_glue: hostlock pushdown
      SCSI: ql4_os: hostlock pushdown
      SCSI: mpt2sas_scsih: hostlock pushdown
      SCSI: fdomain: hostlock pushdown
      SCSI: initio: hostlock pushdown
      SCSI: in2000: hostlock pushdown
      SCSI: nsp32: hostlock pushdown
      SCSI: megaraid_sas: hostlock pushdown
      SCSI: megaraid_mbox: hostlock pushdown
      SCSI: BusLogic: hostlock pushdown
      SCSI: dpt_i2o: hostlock pushdown
      SCSI: 3w-xxxx: hostlock pushdown
      SCSI: atp870u: hostlock pushdown
      SCSI: qlogicfas: hostlock pushdown
      SCSI: qla1280: hostlock pushdown
      SCSI: dc395x: hostlock pushdown
      SCSI: linit: hostlock pushdown
      SCSI: ibmvfc: hostlock pushdown
      SCSI: ibmvscsi: hostlock pushdown
      SCSI: lpfc_scsi: hostlock pushdown
      SCSI: ps3rom: hostlock pushdown
      SCSI: pmcraid: hostlock pushdown
      SCSI: eata: hostlock pushdown
      SCSI: tmscsim: hostlock pushdown
      SCSI: imm: hostlock pushdown
      SCSI: wd7000: hostlock pushdown
      SCSI: sym53c416: hostlock pushdown
      SCSI: aic7xxx_old: hostlock pushdown
      SCSI: megaraid: hostlock pushdown
      SCSI: aha1542: hostlock pushdown
      SCSI: eata_pio: hostlock pushdown
      SCSI: esp_scsi: hostlock pushdown
      SCSI: a100u2w: hostlock pushdown
      SCSI: hpsa: hostlock pushdown
      SCSI: NCR53c406a: hostlock pushdown
      SCSI: mac53c94: hostlock pushdown
      SCSI: vmw_pvscsi: hostlock pushdown
      SCSI: 53c700: hostlock pushdown
      SCSI: u14-34f: hostlock pushdown
      SCSI: ncr53c8xx: hostlock pushdown
      SCSI: advansys: hostlock pushdown
      SCSI: hptiop: hostlock pushdown
      SCSI: arcmsr_hba: hostlock pushdown
      SCSI: aic79xx_osm: hostlock pushdown
      SCSI: aic7xxx_osm: hostlock pushdown
      SCSI: arm: hostlock pushdown
      SCSI: qla_os: hostlock pushdown
      SCSI: nsp_cs: hostlock pushdown
      SCSI: sym53c500_cs: hostlock pushdown
      SCSI: bfad_im: hostlock pushdown
      SCSI: cciss_scsi: hostlock pushdown
      SCSI: aha1740: Avoid instant deadlock

 arch/ia64/hp/sim/simscsi.c            |    7 +++++++
 drivers/block/cciss_scsi.c            |    6 ++++++
 drivers/firewire/sbp2.c               |    5 +++++
 drivers/infiniband/ulp/srp/ib_srp.c   |    6 ++++++
 drivers/message/fusion/mptfc.c        |    6 ++++++
 drivers/message/fusion/mptsas.c       |    8 +++++++-
 drivers/message/fusion/mptspi.c       |    5 +++++
 drivers/message/i2o/i2o_scsi.c        |    5 +++++
 drivers/s390/scsi/zfcp_scsi.c         |    8 ++++++++
 drivers/scsi/3w-9xxx.c                |    4 ++++
 drivers/scsi/3w-sas.c                 |    4 ++++
 drivers/scsi/3w-xxxx.c                |    4 ++++
 drivers/scsi/53c700.c                 |    6 ++++++
 drivers/scsi/BusLogic.c               |    5 +++++
 drivers/scsi/NCR5380.c                |    6 ++++++
 drivers/scsi/NCR53c406a.c             |    4 ++++
 drivers/scsi/a100u2w.c                |    9 ++++++++-
 drivers/scsi/aacraid/linit.c          |   10 ++++++++--
 drivers/scsi/advansys.c               |    4 ++++
 drivers/scsi/aha152x.c                |   10 +++++++++-
 drivers/scsi/aha1542.c                |   12 ++++++++++--
 drivers/scsi/aha1740.c                |   11 +++++++++++
 drivers/scsi/aic7xxx/aic79xx_osm.c    |    4 ++++
 drivers/scsi/aic7xxx/aic7xxx_osm.c    |    4 ++++
 drivers/scsi/aic7xxx_old.c            |    5 +++++
 drivers/scsi/arcmsr/arcmsr_hba.c      |   18 +++++++++++++++---
 drivers/scsi/arm/acornscsi.c          |    6 ++++++
 drivers/scsi/arm/fas216.c             |    8 ++++++++
 drivers/scsi/atp870u.c                |    8 ++++++++
 drivers/scsi/bfa/bfad_im.c            |   11 ++++++++++-
 drivers/scsi/dc395x.c                 |    6 ++++++
 drivers/scsi/dpt_i2o.c                |    9 +++++++++
 drivers/scsi/eata.c                   |    7 +++++++
 drivers/scsi/eata_pio.c               |    5 +++++
 drivers/scsi/esp_scsi.c               |    8 +++++++-
 drivers/scsi/fd_mcs.c                 |    4 ++++
 drivers/scsi/fdomain.c                |    4 ++++
 drivers/scsi/fnic/fnic_scsi.c         |    9 ++++++++-
 drivers/scsi/gdth.c                   |    4 ++++
 drivers/scsi/hpsa.c                   |    7 +++++++
 drivers/scsi/hptiop.c                 |    6 ++++++
 drivers/scsi/ibmmca.c                 |   12 ++++++++++++
 drivers/scsi/ibmvscsi/ibmvfc.c        |   12 ++++++++++--
 drivers/scsi/ibmvscsi/ibmvscsi.c      |    9 ++++++++-
 drivers/scsi/imm.c                    |    4 ++++
 drivers/scsi/in2000.c                 |    4 ++++
 drivers/scsi/initio.c                 |    8 +++++++-
 drivers/scsi/ipr.c                    |   17 ++++++++++++++---
 drivers/scsi/ips.c                    |   18 ++++++++++++++++--
 drivers/scsi/libfc/fc_fcp.c           |    5 +++++
 drivers/scsi/libiscsi.c               |   10 ++++++----
 drivers/scsi/libsas/sas_scsi_host.c   |    7 +++++--
 drivers/scsi/lpfc/lpfc_scsi.c         |    6 ++++++
 drivers/scsi/mac53c94.c               |    4 ++++
 drivers/scsi/megaraid.c               |    4 ++++
 drivers/scsi/megaraid/megaraid_mbox.c |    5 +++++
 drivers/scsi/megaraid/megaraid_sas.c  |   14 ++++++++++++--
 drivers/scsi/mesh.c                   |    4 ++++
 drivers/scsi/mpt2sas/mpt2sas_scsih.c  |   17 +++++++++++++++--
 drivers/scsi/ncr53c8xx.c              |    4 ++++
 drivers/scsi/nsp32.c                  |    8 ++++++++
 drivers/scsi/pcmcia/nsp_cs.c          |    6 ++++++
 drivers/scsi/pcmcia/sym53c500_cs.c    |    4 ++++
 drivers/scsi/pmcraid.c                |   11 ++++++++++-
 drivers/scsi/ppa.c                    |    4 ++++
 drivers/scsi/ps3rom.c                 |    4 ++++
 drivers/scsi/qla1280.c                |    4 ++++
 drivers/scsi/qla2xxx/qla_os.c         |    7 +++++++
 drivers/scsi/qla4xxx/ql4_os.c         |    7 +++++++
 drivers/scsi/qlogicfas408.c           |    4 ++++
 drivers/scsi/qlogicpti.c              |    5 +++++
 drivers/scsi/scsi.c                   |   15 +++------------
 drivers/scsi/stex.c                   |   20 ++++++++++++++++++--
 drivers/scsi/sun3_NCR5380.c           |    8 ++++++++
 drivers/scsi/sym53c416.c              |    4 ++++
 drivers/scsi/sym53c8xx_2/sym_glue.c   |   12 ++++++++++--
 drivers/scsi/tmscsim.c                |    5 +++++
 drivers/scsi/u14-34f.c                |    7 +++++++
 drivers/scsi/ultrastor.c              |    7 +++++++
 drivers/scsi/vmw_pvscsi.c             |    5 +++++
 drivers/scsi/wd33c93.c                |    6 +++++-
 drivers/scsi/wd7000.c                 |    4 ++++
 drivers/staging/hv/storvsc_drv.c      |    8 ++++++++
 drivers/usb/image/microtek.c          |    4 ++++
 drivers/usb/storage/scsiglue.c        |    6 ++++++
 drivers/usb/storage/uas.c             |    9 ++++++++-
 include/scsi/scsi_host.h              |    1 +
 87 files changed, 576 insertions(+), 51 deletions(-)

-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 15:05 Full hostlock pushdown available Andi Kleen
@ 2010-10-28 19:28 ` James Bottomley
  2010-10-28 19:32   ` Nicholas A. Bellinger
  2010-10-28 20:10   ` Andi Kleen
  2010-10-31 12:22 ` Boaz Harrosh
  1 sibling, 2 replies; 26+ messages in thread
From: James Bottomley @ 2010-10-28 19:28 UTC (permalink / raw)
  To: Andi Kleen; +Cc: nab, linux-scsi

On Thu, 2010-10-28 at 17:05 +0200, Andi Kleen wrote:
> Here's the promised attempt to do a full host_lock pushdown. This
> was done using coccinelle and some manual adjustments.
> 
> This is just a dumb pushdown of host lock and serial number into
> the driver, no attempt to remove any locks yet.
> 
> Currently lightly tested, but compiles with allmodconfig on 32bit x86.
> 
> I made no attempt to automatically add maintainers to Cc.
> 
> I'm not posting the patches because they are numerous and boring,
> but it's available in git.
> 
> This will likely bitrot quickly so if it's decided to do it this
> way I would prefer if this was merged quickly.

OK, so can you post an actual diff?  It obviously has to be done in one
commit rather than the 87 you have.

> Issues found:
> - I found a clear deadlock in aha1740, not sure if that driver ever
> worked since host_lock was introduced. Anyways I attempted to work
> around it. But if it's really that unused it may be better to 
> simply drop it.

I certainly don't have the hardware ... and I don't think we've had any
bug reports for a while

> - I'm not sure how to compile cciss_scsi, is it even used?

It's used for tape support in the cciss driver.  It's actually #included
into the cciss.c file (don't ask, I'll only start to cry) and is
conditioned on the CISS_SCSI_TAPE Kconfig variable.

James



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 19:28 ` James Bottomley
@ 2010-10-28 19:32   ` Nicholas A. Bellinger
  2010-11-01 14:06     ` Andi Kleen
  2010-10-28 20:10   ` Andi Kleen
  1 sibling, 1 reply; 26+ messages in thread
From: Nicholas A. Bellinger @ 2010-10-28 19:32 UTC (permalink / raw)
  To: James Bottomley; +Cc: Andi Kleen, linux-scsi

On Thu, 2010-10-28 at 14:28 -0500, James Bottomley wrote:
> On Thu, 2010-10-28 at 17:05 +0200, Andi Kleen wrote:
> > Here's the promised attempt to do a full host_lock pushdown. This
> > was done using coccinelle and some manual adjustments.
> > 
> > This is just a dumb pushdown of host lock and serial number into
> > the driver, no attempt to remove any locks yet.
> > 
> > Currently lightly tested, but compiles with allmodconfig on 32bit x86.
> > 
> > I made no attempt to automatically add maintainers to Cc.
> > 
> > I'm not posting the patches because they are numerous and boring,
> > but it's available in git.
> > 
> > This will likely bitrot quickly so if it's decided to do it this
> > way I would prefer if this was merged quickly.
> 
> OK, so can you post an actual diff?  It obviously has to be done in one
> commit rather than the 87 you have.
> 

So it appears this series will still need the atomic_add_return() usage
in scsi_cmd_get_serial() and drop host_lock usage from those LLDs that
we know can be converted to 'host_lock-less', yes..?

Following Chrisof's and David's comments for zfcp and srp host_lock push
down this morning, the latest v9 code has been pushed into:

git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-4.0.git host_lock-less-for-37-v9

+1 for ak for actually coding this up in coccinelle.  ;)

> > Issues found:
> > - I found a clear deadlock in aha1740, not sure if that driver ever
> > worked since host_lock was introduced. Anyways I attempted to work
> > around it. But if it's really that unused it may be better to 
> > simply drop it.
> 
> I certainly don't have the hardware ... and I don't think we've had any
> bug reports for a while
> 
> > - I'm not sure how to compile cciss_scsi, is it even used?
> 
> It's used for tape support in the cciss driver.  It's actually #included
> into the cciss.c file (don't ask, I'll only start to cry) and is
> conditioned on the CISS_SCSI_TAPE Kconfig variable.
> 

I just did a 'make drivers/block' to compile this code..

Thanks!

--nab


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 19:28 ` James Bottomley
  2010-10-28 19:32   ` Nicholas A. Bellinger
@ 2010-10-28 20:10   ` Andi Kleen
  2010-10-28 20:22     ` James Bottomley
  1 sibling, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2010-10-28 20:10 UTC (permalink / raw)
  To: James Bottomley; +Cc: Andi Kleen, nab, linux-scsi

On Thu, Oct 28, 2010 at 02:28:43PM -0500, James Bottomley wrote:
> On Thu, 2010-10-28 at 17:05 +0200, Andi Kleen wrote:
> > Here's the promised attempt to do a full host_lock pushdown. This
> > was done using coccinelle and some manual adjustments.
> > 
> > This is just a dumb pushdown of host lock and serial number into
> > the driver, no attempt to remove any locks yet.
> > 
> > Currently lightly tested, but compiles with allmodconfig on 32bit x86.
> > 
> > I made no attempt to automatically add maintainers to Cc.
> > 
> > I'm not posting the patches because they are numerous and boring,
> > but it's available in git.
> > 
> > This will likely bitrot quickly so if it's decided to do it this
> > way I would prefer if this was merged quickly.
> 
> OK, so can you post an actual diff?  It obviously has to be done in one
> commit rather than the 87 you have.

Why? I'm not sure a single commit is manageable. The multiple commits
are not atomic, but at least they should all compile and boot
and they minimze breakage.

Anyways full diff appended.

-Andi

SCSI: hostlock pushdown

Signed-off-by: Andi Kleen <ak@linux.intel.com>

diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index 3a078ad..ce32f2c 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -209,6 +209,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	size_t disk_size;
 	char *buf;
 	char localbuf[36];
+	unsigned long irqflags;
+
 #if DEBUG_SIMSCSI
 	register long sp asm ("sp");
 
@@ -217,6 +219,9 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 		       target_id, sc->cmnd[0], sc->serial_number, sp, done);
 #endif
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host);
+
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
 	if (target_id <= 15 && sc->device->lun == 0) {
@@ -323,6 +328,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN;
 
 	tasklet_schedule(&simscsi_tasklet);
+
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 575495f..0fb12f8 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1416,6 +1416,9 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 
 	// Get the ptr to our adapter structure (hba[i]) out of cmd->host.
 	// We violate cmd->host privacy here.  (Is there another way?)
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	h = (ctlr_info_t *) cmd->device->host->hostdata[0];
 
 	rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
@@ -1427,6 +1430,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		done(cmd);
 		/* we might want to think about registering controller itself
 		   as a processor device on the bus so sg binds to it. */
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1441,6 +1445,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		/* FIXME: next 3 lines are -> BAD! <- */
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1501,6 +1506,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 	cciss_scatter_gather(h, c, cmd);
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index bfae4b3..13f6f12 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1479,6 +1479,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	 * Bidirectional commands are not yet implemented, and unknown
 	 * transfer direction not handled.
 	 */
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
 		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
@@ -1489,6 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
 	if (orb == NULL) {
 		fw_notify("failed to alloc orb\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1531,6 +1535,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	retval = 0;
  out:
 	kref_put(&orb->base.kref, free_orb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return retval;
 }
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index cfc1d65..52c9d2e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1132,7 +1132,10 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	struct srp_cmd *cmd;
 	struct ib_device *dev;
 	int len;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 	if (target->state == SRP_TARGET_CONNECTING)
 		goto err;
 
@@ -1140,6 +1143,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
 		done(scmnd);
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1187,12 +1191,14 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 
 	list_move_tail(&req->list, &target->req_queue);
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return 0;
 
 err_unmap:
 	srp_unmap_data(scmnd, target, req);
 
 err:
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index e15220f..3f3705a 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -656,7 +656,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
@@ -667,6 +670,7 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(err)) {
 		SCpnt->result = err;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -675,9 +679,11 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(!ri)) {
 		SCpnt->result = DID_IMM_RETRY << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 83a5115..006ffa1 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1894,7 +1894,10 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	MPT_SCSI_HOST	*hd;
 	MPT_ADAPTER	*ioc;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
@@ -1904,12 +1907,15 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	hd = shost_priv(SCpnt->device->host);
 	ioc = hd->ioc;
 
-	if (ioc->sas_discovery_quiesce_io)
+	if (ioc->sas_discovery_quiesce_io) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (ioc->debug_level & MPT_DEBUG_SCSI)
 		scsi_print_command(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 0e28031..61d42b9 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -785,7 +785,10 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host);
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
 	MPT_ADAPTER *ioc = hd->ioc;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
@@ -796,12 +799,14 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 		mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (spi_dv_pending(scsi_target(SCpnt->device)))
 		ddvprintk(ioc, scsi_print_command(SCpnt));
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index ea6b219..21056dd 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -527,6 +527,9 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	/*
 	 *      Do the incoming paperwork
 	 */
+	unsigned long irqflags;
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	i2o_dev = SCpnt->device->hostdata;
 
 	SCpnt->scsi_done = done;
@@ -680,6 +683,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 
 	osm_debug("Issued %ld\n", SCpnt->serial_number);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 
       nomem:
@@ -687,6 +691,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	i2o_msg_nop(c, msg);
 
       exit:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return rc;
 };
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 50286d8..c28e5fe 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -83,6 +83,10 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
 	int    status, scsi_result, ret;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scpnt->device->host, scpnt);
 
 	/* reset the status for this request */
 	scpnt->result = 0;
@@ -94,6 +98,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		scpnt->result = scsi_result;
 		zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt);
 		scpnt->scsi_done(scpnt);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -104,6 +109,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		/* only LUN access denied, but port is good
 		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -115,10 +121,12 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
 		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	ret = zfcp_fsf_fcp_cmnd(scpnt);
+	spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	else if (unlikely(ret < 0))
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index fcf08b3..3ad0f51 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1769,7 +1769,10 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1809,6 +1812,7 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twa_scsi_queue() */
 
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 6a95d11..de5d845 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1505,7 +1505,10 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1533,6 +1536,7 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twl_scsi_queue() */
 
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index b112534..6812acc 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1953,7 +1953,10 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 	int request_id = 0;
 	int retval = 1;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags))
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -2020,6 +2023,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		done(SCpnt);
 		retval = 0;
 	}
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End tw_scsi_queue() */
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 89fc1c8..ac1a0e4 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1758,6 +1758,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	enum dma_data_direction direction;
 	struct NCR_700_command_slot *slot;
 
+	unsigned long irqflags;
+	spin_lock_irqsave(SCp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCp->device->host, SCp);
 	if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) {
 		/* We're over our allocation, this should never happen
 		 * since we report the max allocation to the mid layer */
@@ -1775,11 +1778,13 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	       || !blk_rq_tagged(SCp->request))) {
 		CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) {
 		CDEBUG(KERN_ERR, SCp, "has max tag depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
@@ -1901,6 +1906,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
 				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
+	spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index fc0b4b8..ab1ee41 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2824,6 +2824,9 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 	   Adapter for any errors, so they should not be executed explicitly unless
 	   the Sense Data is zero indicating that no error occurred.
 	 */
+	unsigned long irqflags;
+	spin_lock_irqsave(Command->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Command->device->host, Command);
 	if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
 		Command->result = DID_OK << 16;
 		CompletionRoutine(Command);
@@ -2844,6 +2847,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB == NULL) {
 			Command->result = DID_ERROR << 16;
 			CompletionRoutine(Command);
+			spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -2991,6 +2995,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB->Status == BusLogic_CCB_Completed)
 			BusLogic_ProcessCompletedCCBs(HostAdapter);
 	}
+	spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 5d2f148..f4bd889 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -957,6 +957,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance = cmd->device->host;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
 	switch (cmd->cmnd[0]) {
@@ -965,6 +969,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no);
 		cmd->result = (DID_ERROR << 16);
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1018,6 +1023,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	/* Run the coroutine if it isn't already running. */
 	/* Kick off command processing */
 	schedule_delayed_work(&hostdata->coroutine, 0);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 6961f78..b84bfe6 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -696,7 +696,10 @@ static void wait_intr(void)
 static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("NCR53c406a_queue called\n"));
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
 
@@ -723,6 +726,7 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(SELECT_NO_ATN, CMD_REG);
 
 	rtrc(1);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index dbbc601..1aa33f0 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -915,18 +915,25 @@ static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd
 {
 	struct orc_scb *scb;
 	struct orc_host *host;		/* Point to Host adapter control block */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	host = (struct orc_host *) cmd->device->host->hostdata;
 	cmd->scsi_done = done;
 	/* Get free SCSI control block  */
-	if ((scb = orc_alloc_scb(host)) == NULL)
+	if ((scb = orc_alloc_scb(host)) == NULL) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (inia100_build_scb(host, scb, cmd)) {
 		orc_release_scb(host, scb);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	orc_exec_scb(host, scb);	/* Start execute SCB            */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 29c0ed1..8679fa5 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -253,6 +253,9 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct Scsi_Host *host = cmd->device->host;
 	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	u32 count = 0;
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
 		struct fib * fib = &dev->fibs[count];
@@ -260,10 +263,13 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 		if (fib->hw_fib_va->header.XferState &&
 		    ((command = fib->callback_data)) &&
 		    (command == cmd) &&
-		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
-			return 0; /* Already owned by Adapter */
+		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) {
+		    	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+		    	return 0;
+		    } /* Already owned by Adapter */
 	}
 	cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return (aac_scsi_cmd(cmd) ? FAILED : 0);
 }
 
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0ec3da6..cb5e7c2 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9504,7 +9504,10 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
 	struct Scsi_Host *shost = scp->device->host;
 	int asc_res, result = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	ASC_STATS(shost, queuecommand);
 	scp->scsi_done = done;
 
@@ -9522,6 +9525,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 		break;
 	}
 
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return result;
 }
 
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 8eab858..055e953 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1058,6 +1058,12 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
  */
 static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
+	unsigned long irqflags;
+	int ret;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 #if 0
 	if(*SCpnt->cmnd == REQUEST_SENSE) {
 		SCpnt->result = 0;
@@ -1067,7 +1073,9 @@ static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	}
 #endif
 
-	return aha152x_internal_queue(SCpnt, NULL, 0, done);
+	ret = aha152x_internal_queue(SCpnt, NULL, 0, done);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+	return ret;
 }
 
 
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 4f785f2..f33b417 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -570,7 +570,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	int mbo;
 	struct mailbox *mb;
 	struct ccb *ccb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	DEB(int i);
 
 	mb = HOSTDATA(SCpnt->device->host)->mb;
@@ -593,6 +596,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 #endif
 		SCpnt->result = 0;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 #ifdef DEBUG
@@ -611,8 +615,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	for (i = 0; i < SCpnt->cmd_len; i++)
 		printk("%02x ", cmd[i]);
 	printk("\n");
-	if (*cmd == WRITE_10 || *cmd == WRITE_6)
-		return 0;	/* we are still testing, so *don't* write */
+	if (*cmd == WRITE_10 || *cmd == WRITE_6) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+		return 0;
+	}	/* we are still testing, so *don't* write */
 #endif
 	/* Use the outgoing mailboxes in a round-robin fashion, because this
 	   is how the host adapter will scan for them */
@@ -671,6 +677,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 		if (cptr == NULL) {
 			/* free the claimed mailbox slot */
 			HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL;
+			spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_HOST_BUSY;
 		}
 		scsi_for_each_sg(SCpnt, sg, sg_count, i) {
@@ -715,6 +722,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	} else
 		printk("aha1542_queuecommand: done can't be NULL\n");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 0107a4c..b973e15 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -331,6 +331,7 @@ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
+/* AK: Did this driver ever work? */
 static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
 	unchar direction;
@@ -341,14 +342,21 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 	dma_addr_t sg_dma;
 	struct aha1740_sg *sgptr;
 	int ecbno, nseg;
+	unsigned long irqflags;
 	DEB(int i);
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 	if(*cmd == REQUEST_SENSE) {
 		SCpnt->result = 0;
 		done(SCpnt); 
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+
 #ifdef DEBUG
 	if (*cmd == READ_10 || *cmd == WRITE_10)
 		i = xscsi2int(cmd+2);
@@ -406,6 +414,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 						   &sg_dma, GFP_ATOMIC);
 	if(SCpnt->host_scribble == NULL) {
 		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
@@ -500,6 +509,8 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 		DEB(printk("aha1740[%d] request queued.\n",ecbno));
 	} else
 		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
+
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 88ad848..93e1070 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -578,13 +578,17 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahd_softc *ahd;
 	struct	 ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 
 	cmd->scsi_done = scsi_done;
 	cmd->result = CAM_REQ_INPROG << 16;
 	rtn = ahd_linux_run_command(ahd, dev, cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index aeea7a6..198390a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -534,7 +534,10 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
 	ahc_lock(ahc, &flags);
@@ -545,6 +548,7 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	}
 	ahc_unlock(ahc, &flags);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index aee73fa..97c4efc 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10239,7 +10239,10 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
   struct aic_dev_data *aic_dev;
+  unsigned long irqflags;
 
+  spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+  scsi_cmd_get_serial(cmd->device->host, cmd);
   p = (struct aic7xxx_host *) cmd->device->host->hostdata;
 
   aic_dev = cmd->device->hostdata;  
@@ -10262,6 +10265,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
     {
       printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no,
              CTL_OF_CMD(cmd));
+      spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
       return 1;
     }
   }
@@ -10289,6 +10293,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 
   scbq_insert_tail(&p->waiting_scbs, scb);
   aic7xxx_run_waiting_queues(p);
+  spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
   return (0);
 }
 
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 05a78e5..bbb95db 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2090,6 +2090,9 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
 	int target = cmd->device->id;
 	int lun = cmd->device->lun;
 	uint8_t scsicmd = cmd->cmnd[0];
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 	cmd->result = 0;
@@ -2098,29 +2101,38 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
     			cmd->result = (DID_NO_CONNECT << 16);
 		}
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (target == 16) {
 		/* virtual device for iop message transfer */
 		arcmsr_handle_virtual_command(acb, cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (atomic_read(&acb->ccboutstandingcount) >=
-			ARCMSR_MAX_OUTSTANDING_CMD)
-		return SCSI_MLQUEUE_HOST_BUSY;
+			ARCMSR_MAX_OUTSTANDING_CMD) {
+				spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+				return SCSI_MLQUEUE_HOST_BUSY;
+			}
 	if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) {
 		printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	ccb = arcmsr_get_freeccb(acb);
-	if (!ccb)
+	if (!ccb) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	if (arcmsr_build_ccb( acb, ccb, cmd ) == FAILED) {
 		cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	arcmsr_post_ccb(acb, ccb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 918ccf8..6f1049e 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2515,7 +2515,10 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 		       void (*done)(struct scsi_cmnd *))
 {
     AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
     if (!done) {
 	/* there should be some way of rejecting errors like this without panicing... */
 	panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
@@ -2529,6 +2532,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    host->host->host_no, '0' + SCpnt->device->id);
 	SCpnt->result = DID_NO_CONNECT << 16;
 	done(SCpnt);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif
@@ -2551,6 +2555,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
 	    SCpnt->result = DID_ERROR << 16;
 	    done(SCpnt);
+	    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	    return 0;
 	}
 	local_irq_save(flags);
@@ -2558,6 +2563,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    acornscsi_kick(host);
 	local_irq_restore(flags);
     }
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 9e71ac6..8cd9311 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2203,7 +2203,10 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	fas216_log_command(info, LOG_CONNECT, SCpnt,
@@ -2237,6 +2240,7 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 	fas216_log_target(info, LOG_CONNECT, -1, "queue %s",
 		result ? "failure" : "success");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return result;
 }
 
@@ -2267,7 +2271,10 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 			   void (*done)(struct scsi_cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	/*
@@ -2307,6 +2314,7 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 
 	done(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index ab5bdda..0ec5c9d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -612,7 +612,10 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	unsigned int tmport,m;	
 	struct atp_unit *dev;
 	struct Scsi_Host *host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(req_p->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(req_p->device->host, req_p);
 	c = scmd_channel(req_p);
 	req_p->sense_buffer[0]=0;
 	scsi_set_resid(req_p, 0);
@@ -622,6 +625,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP		
 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");	
 #endif			
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -640,6 +644,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	if ((m & dev->active_id[c]) == 0) {
 		req_p->result = 0x00040000;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -651,6 +656,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #endif		
 		req_p->result = 0;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	
@@ -675,6 +681,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 		dev->quend[c]--;
 		req_p->result = 0x00020000;
 		done(req_p);	
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->quereq[c][dev->quend[c]] = req_p;
@@ -691,6 +698,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP	
 	printk("atp870u_queuecommand : exit\n");
 #endif	
+	spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index d950ee4..2796f73 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1131,17 +1131,23 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	int             rc;
 	int       sg_cnt = 0;
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	rc = fc_remote_port_chkready(rport);
 	if (rc) {
 		cmnd->result = rc;
 		done(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	sg_cnt = scsi_dma_map(cmnd);
-	if (sg_cnt < 0)
+	if (sg_cnt < 0) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	cmnd->scsi_done = done;
 
@@ -1167,6 +1173,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 		printk(KERN_WARNING "hal_io failure\n");
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		scsi_dma_unmap(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1175,6 +1182,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	bfa_ioim_start(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 out_fail_cmd:
@@ -1183,6 +1191,7 @@ out_fail_cmd:
 	if (done)
 		done(cmnd);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 54f50b0..15f4d1e 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1086,6 +1086,9 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 	struct ScsiReqBlk *srb;
 	struct AdapterCtlBlk *acb =
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
 		cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 
@@ -1127,6 +1130,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		 * point in time.
 		 */
 		dprintkdbg(DBG_0, "queue_command: No free srb's\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1141,6 +1145,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		send_srb(acb, srb);
 	}
 	dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 complete:
@@ -1151,6 +1156,7 @@ complete:
 	 * devices.
 	 */
 	done(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 23dec00..901f952 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -427,7 +427,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 {
 	adpt_hba* pHba = NULL;
 	struct adpt_device* pDev = NULL;	/* dpt per device information */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	/*
 	 * SCSI REQUEST_SENSE commands will be executed automatically by the 
@@ -439,11 +442,13 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
 		cmd->result = (DID_OK << 16);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	pHba = (adpt_hba*)cmd->device->host->hostdata[0];
 	if (!pHba) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
 
@@ -459,6 +464,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
 		pHba->host->last_reset = jiffies;
 		pHba->host->resetting = 1;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -475,6 +481,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 			// with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
 			cmd->result = (DID_NO_CONNECT << 16);
 			cmd->scsi_done(cmd);
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 		cmd->device->hostdata = pDev;
@@ -486,8 +493,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	 * delay processing of the command until later.
 	 */
 	if (pDev->state & DPTI_DEV_RESET ) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return adpt_scsi_to_i2o(pHba, cmd, pDev);
 }
 
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index d1c3137..6761716 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1765,7 +1765,10 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	struct hostdata *ha = (struct hostdata *)shost->hostdata;
 	unsigned int i, k;
 	struct mscp *cpp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (SCpnt->host_scribble)
 		panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
 		      ha->board_name, SCpnt->serial_number, SCpnt);
@@ -1785,6 +1788,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
 	if (k == shost->can_queue) {
 		printk("%s: qcomm, no free mailbox.\n", ha->board_name);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1827,6 +1831,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	    && TLDEV(SCpnt->device->type)) {
 		ha->cp_stat[i] = READY;
 		flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 0);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1836,10 +1841,12 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 		SCpnt->host_scribble = NULL;
 		scmd_printk(KERN_INFO, SCpnt,
 			"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
 	ha->cp_stat[i] = IN_USE;
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 60886c1..72de26e 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -344,7 +344,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 	hostdata *hd;
 	struct Scsi_Host *sh;
 	struct eata_ccb *cp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	queue_counter++;
 
 	hd = HD(cmd);
@@ -421,6 +424,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 			"returning DID_BUS_BUSY, done.\n", cmd->serial_number);
 		done(cmd);
 		cp->status = FREE;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	/* FIXME: timeout */
@@ -435,6 +439,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 		"Queued base %#.4lx pid: %ld "
 		"slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq));
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index e2bc779..c70efde 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -922,10 +922,15 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct esp *esp = shost_priv(dev->host);
 	struct esp_cmd_priv *spriv;
 	struct esp_cmd_entry *ent;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ent = esp_get_ent(esp);
-	if (!ent)
+	if (!ent) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	ent->cmd = cmd;
 
@@ -938,6 +943,7 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 
 	esp_maybe_execute_command(esp);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 2ad95aa..dc61481 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1075,7 +1075,10 @@ static int fd_mcs_release(struct Scsi_Host *shpnt)
 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (in_command) {
 		panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
 	}
@@ -1119,6 +1122,7 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(0x20, Interrupt_Cntl_port);
 	outb(0x14 | PARITY_MASK, TMC_Cntl_port);	/* Start arbitration */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index e296bcc..153bb64 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1422,6 +1422,9 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
 		void (*done)(struct scsi_cmnd *))
 {
+   unsigned long irqflags;
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    if (in_command) {
       panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
    }
@@ -1466,6 +1469,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
    outb(0x20, port_base + Interrupt_Cntl);
    outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
 
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 198cbab..2e4f40b 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -360,18 +360,24 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	int sg_count;
 	unsigned long flags;
 	unsigned long ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
 	rport = starget_to_rport(scsi_target(sc->device));
 	ret = fc_remote_port_chkready(rport);
 	if (ret) {
 		sc->result = ret;
 		done(sc);
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	lp = shost_priv(sc->device->host);
-	if (lp->state != LPORT_ST_READY || !(lp->link_up))
+	if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Release host lock, use driver resource specific locks from here.
@@ -454,6 +460,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 out:
 	/* acquire host lock before returning to SCSI */
 	spin_lock(lp->host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 5a3f931..e4a3ecb 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4009,7 +4009,10 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
 {
     gdth_ha_str *ha = shost_priv(scp->device->host);
     struct gdth_cmndinfo *cmndinfo;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(scp->device->host, scp);
     TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
 
     cmndinfo = gdth_get_cmndinfo(ha);
@@ -4019,6 +4022,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
     cmndinfo->timeout_count = 0;
     cmndinfo->priority = DEFAULT_PRI;
 
+    spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
     return __gdth_queuecommand(ha, scp, cmndinfo);
 }
 
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index c5d0606..8d0f51d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1934,13 +1934,17 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	unsigned char scsi3addr[8];
 	struct CommandList *c;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	/* Get the ptr to our adapter structure out of cmd->host. */
 	h = sdev_to_hba(cmd->device);
 	dev = cmd->device->hostdata;
 	if (!dev) {
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
@@ -1951,6 +1955,7 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	spin_unlock_irqrestore(&h->lock, flags);
 	if (c == NULL) {			/* trouble... */
 		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -2013,10 +2018,12 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 
 	if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */
 		cmd_free(h, c);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 0729f15..04903e4 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -759,13 +759,17 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 	struct hpt_iop_request_scsi_command *req;
 	int sg_count = 0;
 	struct hptiop_request *_req;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	BUG_ON(!done);
 	scp->scsi_done = done;
 
 	_req = get_req(hba);
 	if (_req == NULL) {
 		dprintk("hptiop_queuecmd : no free req\n");
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -811,11 +815,13 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 
 	memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
 	hba->ops->post_req(hba, _req);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 
 cmd_done:
 	dprintk("scsi_done(scp=%p)\n", scp);
 	scp->scsi_done(scp);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 9a4b69d..65595e2 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -1703,6 +1703,10 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	int max_pun;
 	int i;
 	struct scatterlist *sg;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 	shpnt = cmd->device->host;
 
@@ -1721,6 +1725,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		cmd->result = DID_NO_CONNECT << 16;
 		if (done)
 			done(cmd);
+
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1743,6 +1749,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 					cmd->result = DID_NO_CONNECT << 16;	/* return no connect */
 					if (done)
 						done(cmd);
+
+					spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 					return 0;
 				}
 			}
@@ -1804,6 +1812,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 			cmd->result = DID_BAD_TARGET << 16;
 			if (done)
 				done(cmd);
+
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -1993,6 +2003,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
 		IBM_DS(shpnt).scbs++;
 	}
+
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 00d08b2..98c9cc7 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1616,6 +1616,9 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 	u8 tag[2];
 	int rc;
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	if (unlikely((rc = fc_remote_port_chkready(rport))) ||
 	    unlikely((rc = ibmvfc_host_chkready(vhost)))) {
 		cmnd->result = rc;
@@ -1656,12 +1659,16 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 		};
 	}
 
-	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
+	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return ibmvfc_send_event(evt, vhost, 0);
+	}
 
 	ibmvfc_free_event(evt);
-	if (rc == -ENOMEM)
+	if (rc == -ENOMEM) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
 		scmd_printk(KERN_ERR, cmnd,
@@ -1669,6 +1676,7 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 
 	cmnd->result = DID_ERROR << 16;
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 67f78a4..c15bf25 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -723,10 +723,15 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	u16 lun = lun_from_dev(cmnd->device);
 	u8 out_fmt, in_fmt;
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	cmnd->result = (DID_OK << 16);
 	evt_struct = get_event_struct(&hostdata->pool);
-	if (!evt_struct)
+	if (!evt_struct) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Set up the actual SRP IU */
 	srp_cmd = &evt_struct->iu.srp.cmd;
@@ -740,6 +745,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			sdev_printk(KERN_ERR, cmnd->device,
 			            "couldn't convert cmd to srp_cmd\n");
 		free_event_struct(&hostdata->pool, evt_struct);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -763,6 +769,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			offsetof(struct srp_indirect_buf, desc_list);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
 }
 
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 4734ab0..57b7b92 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -930,7 +930,10 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 {
 	imm_struct *dev = imm_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk("IMM: bug in imm_queuecommand\n");
 		return 0;
@@ -946,6 +949,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 
 	imm_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 52bdc6d..2339bb3 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -339,7 +339,10 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance;
 	struct IN2000_hostdata *hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	instance = cmd->device->host;
 	hostdata = (struct IN2000_hostdata *) instance->hostdata;
 
@@ -428,6 +431,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	in2000_execute(cmd->device->host);
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
+	    spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	    return 0;
 }
 
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 1087977..0ef119e 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2644,15 +2644,21 @@ static int i91u_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
 	struct scsi_ctrl_blk *cmnd;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 
 	cmnd = initio_alloc_scb(host);
-	if (!cmnd)
+	if (!cmnd) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	initio_build_scb(host, cmnd, cmd);
 	initio_exec_scb(host, cmnd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index df9a12c..d0ca800 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -5717,7 +5717,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	struct ipr_ioarcb *ioarcb;
 	struct ipr_cmnd *ipr_cmd;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(&scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	scsi_cmd->scsi_done = done;
 	ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
 	res = scsi_cmd->device->hostdata;
@@ -5728,8 +5731,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	 * We have told the host to stop giving us new requests, but
 	 * ERP ops don't count. FIXME
 	 */
-	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
+	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead)) {
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * FIXME - Create scsi_set_host_offline interface
@@ -5739,11 +5744,15 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		memset(scsi_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
-	if (ipr_is_gata(res) && res->sata_port)
-		return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+	if (ipr_is_gata(res) && res->sata_port) {
+		rc = ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
+		return rc;
+	}
 
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
@@ -5786,9 +5795,11 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		ipr_send_command(ipr_cmd);
 	} else {
 		 list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+		 spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		 return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index f83a116..cd83a25 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1050,28 +1050,37 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 {
 	ips_ha_t *ha;
 	ips_passthru_t *pt;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SC->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SC->device->host, SC);
 	METHOD_TRACE("ips_queue", 1);
 
 	ha = (ips_ha_t *) SC->device->host->hostdata;
 
-	if (!ha)
+	if (!ha) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (1);
+	}
 
-	if (!ha->active)
+	if (!ha->active) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (DID_ERROR);
+	}
 
 	if (ips_is_passthru(SC)) {
 		if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
 			SC->result = DID_BUS_BUSY << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 	} else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
 		SC->result = DID_BUS_BUSY << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1089,6 +1098,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 		SC->result = DID_NO_CONNECT << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1105,12 +1115,14 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			if (ha->scb_activelist.count != 0) {
 				SC->result = DID_BUS_BUSY << 16;
 				done(SC);
+				spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 				return (0);
 			}
 			ha->ioctl_reset = 1;	/* This reset request is from an IOCTL */
 			__ips_eh_reset(SC);
 			SC->result = DID_OK << 16;
 			SC->scsi_done(SC);
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1121,6 +1133,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			SC->result = DID_ERROR << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1134,6 +1147,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 
 	ips_next(ha, IPS_INTR_IORL);
 
+	spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 	return (0);
 }
 
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index c797f6b..5a91e1d 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1763,13 +1763,17 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	int rval;
 	int rc = 0;
 	struct fcoe_dev_stats *stats;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc_cmd->device->host, sc_cmd);
 	lport = shost_priv(sc_cmd->device->host);
 
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
 		sc_cmd->result = rval;
 		done(sc_cmd);
+		spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	spin_unlock_irq(lport->host->host_lock);
@@ -1850,6 +1854,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	}
 out:
 	spin_lock_irq(lport->host->host_lock);
+	spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 EXPORT_SYMBOL(fc_queuecommand);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 633e090..f8b9dde 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1608,6 +1608,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 	struct iscsi_task *task = NULL;
+	unsigned long irqflags;
+
+	/* remove me */
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 
 	sc->scsi_done = done;
 	sc->result = 0;
@@ -1615,7 +1621,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 
 	host = sc->device->host;
 	ihost = shost_priv(host);
-	spin_unlock(host->host_lock);
 
 	cls_session = starget_to_session(scsi_target(sc->device));
 	session = cls_session->dd_data;
@@ -1706,7 +1711,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 
 	session->queued_cmdsn++;
 	spin_unlock(&session->lock);
-	spin_lock(host->host_lock);
 	return 0;
 
 prepd_reject:
@@ -1716,7 +1720,6 @@ reject:
 	spin_unlock(&session->lock);
 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
 			  sc->cmnd[0], reason);
-	spin_lock(host->host_lock);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 prepd_fault:
@@ -1733,7 +1736,6 @@ fault:
 		scsi_in(sc)->resid = scsi_in(sc)->length;
 	}
 	done(sc);
-	spin_lock(host->host_lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 55f09e9..5b4aaab 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -200,8 +200,12 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 	struct domain_device *dev = cmd_to_domain_dev(cmd);
 	struct Scsi_Host *host = cmd->device->host;
 	struct sas_internal *i = to_sas_internal(host->transportt);
+	unsigned long irqflags;
 
-	spin_unlock_irq(host->host_lock);
+	/* remove me */
+	spin_lock_irqsave(host->host_lock, irqflags);
+	scsi_cmd_get_serial(host, cmd);
+	spin_unlock_irqrestore(host->host_lock, irqflags);
 
 	{
 		struct sas_ha_struct *sas_ha = dev->port->ha;
@@ -250,7 +254,6 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 		}
 	}
 out:
-	spin_lock_irq(host->host_lock);
 	return res;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 3a65895..aed5280 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2906,6 +2906,9 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
 	int err;
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	err = fc_remote_port_chkready(rport);
 	if (err) {
 		cmnd->result = err;
@@ -3043,16 +3046,19 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 			lpfc_poll_rearm_timer(phba);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
  out_host_busy_free_buf:
 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
  out_host_busy:
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  out_fail_command:
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 3ddb4dc..37b01bd 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -82,6 +82,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	}
 #endif
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -96,6 +99,7 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	if (state->phase == idle)
 		mac53c94_start(state);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7ceb5cf..070fdd0 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -372,7 +372,10 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	scb_t	*scb;
 	int	busy=0;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	adapter = (adapter_t *)scmd->device->host->hostdata;
 
 	scmd->scsi_done = done;
@@ -406,6 +409,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	busy = 0;
  out:
 	spin_unlock_irqrestore(&adapter->lock, flags);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index a7810a1..07ade30 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1489,7 +1489,10 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	adapter_t	*adapter;
 	scb_t		*scb;
 	int		if_busy;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	adapter		= SCP2ADAPTER(scp);
 	scp->scsi_done	= done;
 	scp->result	= 0;
@@ -1506,10 +1509,12 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
 	if (!scb) {	// command already completed
 		done(scp);
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	megaraid_mbox_runpendq(adapter, scb);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return if_busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index d3c9cde..cb0b400 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1325,16 +1325,22 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	if (instance->issuepend_done == 0)
+	if (instance->issuepend_done == 0) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	spin_lock_irqsave(&instance->hba_lock, flags);
 	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
 		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1362,8 +1368,10 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	}
 
 	cmd = megasas_get_cmd(instance);
-	if (!cmd)
+	if (!cmd) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Logical drive command
@@ -1393,12 +1401,14 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 		tasklet_schedule(&instance->isr_tasklet);
 
 
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out_return_cmd:
 	megasas_return_cmd(instance, cmd);
  out_done:
 	done(scmd);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 1f784fd..93e6596 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1630,7 +1630,10 @@ static void cmd_complete(struct mesh_state *ms)
 static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct mesh_state *ms;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -1645,6 +1648,7 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	if (ms->phase == idle)
 		mesh_start(ms);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 16e99b6..e849aa2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -3323,18 +3323,23 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	Mpi2SCSIIORequest_t *mpi_request;
 	u32 mpi_control;
 	u16 smid;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	scmd->scsi_done = done;
 	sas_device_priv_data = scmd->device->hostdata;
 	if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (ioc->pci_error_recovery) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3343,19 +3348,25 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* host recovery or link resets sent via IOCTLs */
-	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
+	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	/* device busy with task management */
-	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
+	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 	/* device has been deleted */
 	else if (sas_target_priv_data->deleted) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3435,9 +3446,11 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 		    sas_device_priv_data->sas_target->handle);
 	else
 		mpt2sas_base_put_smid_default(ioc, smid);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out:
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index d013a2a..00a8b1e 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8034,7 +8034,10 @@ static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct
      struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb;
      unsigned long flags;
      int sts;
+     unsigned long irqflags;
 
+     spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+     scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG_NCR53C8XX
 printk("ncr53c8xx_queue_command\n");
 #endif
@@ -8065,6 +8068,7 @@ printk("ncr53c8xx : command successfully queued\n");
 	  sts = 0;
      }
 
+     spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
      return sts;
 }
 
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 4c1e545..42864e2 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -915,7 +915,10 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 	nsp32_target *target;
 	nsp32_lunt   *cur_lunt;
 	int ret;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND,
 		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
@@ -927,6 +930,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		data->CurrentSC = NULL;
 		SCpnt->result   = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -935,6 +939,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -943,6 +948,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "no more lun");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -975,6 +981,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_msg(KERN_ERR, "SGT fail");
 		SCpnt->result = DID_ERROR << 16;
 		nsp32_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1047,6 +1054,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_scsi_done(SCpnt);
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9326c2c..6c4277d 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -193,7 +193,10 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 	unsigned char target = scmd_id(SCpnt);
 #endif
 	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
 		"SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
 		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
@@ -206,6 +209,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
 		SCpnt->result   = DID_BAD_TARGET << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -253,6 +257,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
 		SCpnt->result   = DID_BUS_BUSY << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -261,6 +266,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 #ifdef NSP_DEBUG
 	data->CmdId++;
 #endif
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 0ae27cb..5f926bb 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -553,7 +553,10 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	int port_base = SCpnt->device->host->io_port;
 	struct sym53c500_data *data =
 	    (struct sym53c500_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("SYM53C500_queue called\n"));
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
@@ -580,6 +583,7 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	}
 	outb(SELECT_NO_ATN, port_base + CMD_REG);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 4b87657..607a3cf 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3482,7 +3482,10 @@ static int pmcraid_queuecommand(
 	struct pmcraid_cmd *cmd;
 	u32 fw_version;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	pinstance =
 		(struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
 	fw_version = be16_to_cpu(pinstance->inq_data->fw_version);
@@ -3497,12 +3500,15 @@ static int pmcraid_queuecommand(
 		pmcraid_info("IOA is dead, but queuecommand is scheduled\n");
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* If IOA reset is in progress, can't queue the commands */
-	if (pinstance->ioa_reset_in_progress)
+	if (pinstance->ioa_reset_in_progress) {
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Firmware doesn't support SYNCHRONIZE_CACHE command (0x35), complete
 	 * the command here itself with success return
@@ -3510,6 +3516,7 @@ static int pmcraid_queuecommand(
 	if (scsi_cmd->cmnd[0] == SYNCHRONIZE_CACHE) {
 		pmcraid_info("SYNC_CACHE(0x35), completing in driver itself\n");
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3518,6 +3525,7 @@ static int pmcraid_queuecommand(
 
 	if (cmd == NULL) {
 		pmcraid_err("free command block is not available\n");
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -3574,6 +3582,7 @@ static int pmcraid_queuecommand(
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 7bc2d79..6ffe805 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -802,7 +802,10 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 		void (*done) (struct scsi_cmnd *))
 {
 	ppa_struct *dev = ppa_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk(KERN_ERR "PPA: bug in ppa_queuecommand\n");
 		return 0;
@@ -818,6 +821,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 
 	ppa_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 92ffbb5..9cb6ad3 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -218,7 +218,10 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 	struct ps3_storage_device *dev = priv->dev;
 	unsigned char opcode;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG
 	scsi_print_command(cmd);
 #endif
@@ -257,6 +260,7 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 		cmd->scsi_done(cmd);
 	}
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index b8166ec..ca34ed1 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -733,7 +733,10 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 	struct srb *sp = (struct srb *)CMD_SP(cmd);
 	int status;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = fn;
 	sp->cmd = cmd;
 	sp->flags = 0;
@@ -753,6 +756,7 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 #else
 	status = qla1280_32bit_start_scsi(ha, sp);
 #endif
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return status;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 800ea92..2c2224e 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -538,7 +538,10 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 	srb_t *sp;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (ha->flags.eeh_busy) {
 		if (ha->flags.pci_channel_io_perm_failure)
 			cmd->result = DID_NO_CONNECT << 16;
@@ -586,6 +589,7 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	spin_lock_irq(vha->host->host_lock);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc24_host_busy_free_sp:
@@ -594,14 +598,17 @@ qc24_host_busy_free_sp:
 
 qc24_host_busy_lock:
 	spin_lock_irq(vha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc24_target_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 qc24_fail_command:
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 370d40f..568e61f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -474,7 +474,10 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 	struct iscsi_cls_session *sess = ddb_entry->sess;
 	struct srb *srb;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (test_bit(AF_EEH_BUSY, &ha->flags)) {
 		if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
 			cmd->result = DID_NO_CONNECT << 16;
@@ -499,6 +502,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 			cmd->result = DID_NO_CONNECT << 16;
 			goto qc_fail_command;
 		}
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_TARGET_BUSY;
 	}
 
@@ -522,6 +526,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 		goto qc_host_busy_free_sp;
 
 	spin_lock_irq(ha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc_host_busy_free_sp:
@@ -532,11 +537,13 @@ qc_host_busy_lock:
 	spin_lock_irq(ha->host->host_lock);
 
 qc_host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc_fail_command:
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 1ad5155..4146a5f 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -443,6 +443,9 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 			      void (*done) (struct scsi_cmnd *))
 {
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (scmd_id(cmd) == priv->qinitid) {
 		cmd->result = DID_BAD_TARGET << 16;
 		done(cmd);
@@ -456,6 +459,7 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 		cpu_relax();
 	}
 	ql_icmd(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index f8c561c..e1491e5 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1010,7 +1010,10 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 	struct Command_Entry *cmd;
 	u_int out_ptr;
 	int in_ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(Cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Cmnd->device->host, Cmnd);
 	Cmnd->scsi_done = done;
 
 	in_ptr = qpti->req_in_ptr;
@@ -1037,6 +1040,7 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 
 	update_can_queue(host, in_ptr, out_ptr);
 
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 toss_command:
@@ -1049,6 +1053,7 @@ toss_command:
 	 */
 	Cmnd->result = DID_BUS_BUSY;
 	done(Cmnd);
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 1;
 }
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 348fba0..d6d3c50 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -634,13 +634,15 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
  * Description: a serial number identifies a request for error recovery
  * and debugging purposes.  Protected by the Host_Lock of host.
  */
-static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
 	cmd->serial_number = host->cmd_serial_number++;
 	if (cmd->serial_number == 0) 
 		cmd->serial_number = host->cmd_serial_number++;
 }
 
+EXPORT_SYMBOL(scsi_cmd_get_serial);
+
 /**
  * scsi_dispatch_command - Dispatch a command to the low-level driver.
  * @cmd: command block we are dispatching.
@@ -651,7 +653,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd
 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 {
 	struct Scsi_Host *host = cmd->device->host;
-	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
 
@@ -737,15 +738,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		goto out;
 	}
 
-	spin_lock_irqsave(host->host_lock, flags);
-	/*
-	 * AK: unlikely race here: for some reason the timer could
-	 * expire before the serial number is set up below.
-	 *
-	 * TODO: kill serial or move to blk layer
-	 */
-	scsi_cmd_get_serial(host, cmd); 
-
 	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
@@ -753,7 +745,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		trace_scsi_dispatch_cmd_start(cmd);
 		rtn = host->hostt->queuecommand(cmd, scsi_done);
 	}
-	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
 		trace_scsi_dispatch_cmd_error(cmd, rtn);
 		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 9c73dbd..351872e 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -579,14 +579,19 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	unsigned int id, lun;
 	struct req_msg *req;
 	u16 tag;
+	unsigned long irqflags;
 
 	host = cmd->device->host;
+	spin_lock_irqsave(host->host_lock, irqflags);
+	scsi_cmd_get_serial(host, cmd);
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	hba = (struct st_hba *) &host->hostdata[0];
 
-	if (unlikely(hba->mu_status == MU_STATE_RESETTING))
+	if (unlikely(hba->mu_status == MU_STATE_RESETTING)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	switch (cmd->cmnd[0]) {
 	case MODE_SENSE_10:
@@ -603,6 +608,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	}
 	case REPORT_LUNS:
@@ -613,6 +620,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		 */
 		if (hba->cardtype == st_shasta || id == host->max_id - 1) {
 			stex_invalid_field(cmd, done);
+
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -620,6 +629,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (id == host->max_id - 1) {
 			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -627,6 +637,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (lun >= host->max_lun) {
 			cmd->result = DID_NO_CONNECT << 16;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		if (id != host->max_id - 1)
@@ -639,6 +650,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	case PASSTHRU_CMD:
 		if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
@@ -657,6 +669,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 				DID_OK << 16 | COMMAND_COMPLETE << 8 :
 				DID_ERROR << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 	default:
@@ -667,8 +680,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 
 	tag = cmd->request->tag;
 
-	if (unlikely(tag >= host->can_queue))
+	if (unlikely(tag >= host->can_queue)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	req = hba->alloc_rq(hba);
 
@@ -695,6 +710,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	}
 
 	hba->send(hba, req, tag);
+	spin_unlock_irqrestore(host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 713620e..82eaa21 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -914,6 +914,10 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
     SETUP_HOSTDATA(cmd->device->host);
     struct scsi_cmnd *tmp;
     unsigned long flags;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(cmd->device->host);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
     switch (cmd->cmnd[0]) {
@@ -923,6 +927,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	       H_NO(cmd));
 	cmd->result = (DID_ERROR << 16);
 	done(cmd);
+
+        spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1016,6 +1022,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	queue_main();
     else
 	NCR5380_main(NULL);
+
+    spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index e5c369b..28e24d2 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -739,7 +739,10 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	int base;
 	unsigned long flags = 0;
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* Store base register as we can have more than one controller in the system */
 	base = SCpnt->device->host->io_port;
 	current_command = SCpnt;                  /* set current command                */
@@ -758,6 +761,7 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
 	/* Now an interrupt will be generated which we will catch in out interrupt routine */
 	spin_unlock_irqrestore(&sym53c416_lock, flags);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 8b955b5..eb0734a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -511,7 +511,10 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 	struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
 	struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
 	int sts = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	memset(ucp, 0, sizeof(*ucp));
 
@@ -527,12 +530,17 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 		}
 	}
 
-	if (np->s.settle_time_valid)
+	if (np->s.settle_time_valid) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	sts = sym_queue_command(np, cmd);
-	if (sts)
+	if (sts) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 27866b0..fca1761 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -1890,7 +1890,10 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
 	struct dc390_dcb *dcb = sdev->hostdata;
 	struct dc390_srb *srb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (sdev->queue_depth <= dcb->GoingSRBCnt)
 		goto device_busy;
 	if (acb->pActiveDCB)
@@ -1935,9 +1938,11 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 
 	dc390_Going_append(dcb, srb);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
  host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  device_busy:
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 5d9fdee..2345891 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1251,7 +1251,10 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) {
 static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) {
    unsigned int i, j, k;
    struct mscp *cpp;
+   unsigned long irqflags;
 
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number;
 
@@ -1275,6 +1278,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox.\n", BN(j));
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1308,6 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
                                      && TLDEV(SCpnt->device->type)) {
       HD(j)->cp_stat[i] = READY;
       flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, FALSE);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 0;
       }
 
@@ -1316,6 +1321,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
       SCpnt->host_scribble = NULL;
       scmd_printk(KERN_INFO, SCpnt,
       		"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1326,6 +1332,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
 
    HD(j)->cp_stat[i] = IN_USE;
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 27aa40f..d3b968f 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -708,6 +708,10 @@ static int ultrastor_queuecommand(struct scsi_cmnd *SCpnt,
     int mscp_index;
 #endif
     unsigned int status;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -800,8 +804,10 @@ retry:
 #if ULTRASTOR_MAX_CMDS > 1
 	SCpnt->result = status;
 	done(SCpnt);
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 #else
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return status;
 #endif
     }
@@ -822,6 +828,7 @@ retry:
     printk("USx4F: queuecommand: returning\n");
 #endif
 
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 2689445..36e3dfb 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -697,6 +697,9 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct pvscsi_ctx *ctx;
 	unsigned long flags;
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_lock_irqsave(&adapter->hw_lock, flags);
 
 	ctx = pvscsi_acquire_context(adapter, cmd);
@@ -704,6 +707,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 		if (ctx)
 			pvscsi_release_context(adapter, ctx);
 		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -716,6 +720,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	pvscsi_kick_io(adapter, cmd->cmnd[0]);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index b701bf2..d552930 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -377,7 +377,10 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct WD33C93_hostdata *hostdata;
 	struct scsi_cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
 
 	DB(DB_QUEUE_COMMAND,
@@ -464,7 +467,8 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
 
-	spin_unlock_irq(&hostdata->lock);
+	spin_unlock(&hostdata->lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 333580b..70ff71b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1092,7 +1092,10 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	short cdblen;
 	int nseg;
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	cdblen = SCpnt->cmd_len;
 	idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7);
 	SCpnt->scsi_done = done;
@@ -1136,6 +1139,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	while (!mail_out(host, scb))
 		cpu_relax();	/* keep trying */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 62882a4..7d19576 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -616,6 +616,10 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 	int i;
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 
 	DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d "
 		   "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction,
@@ -648,6 +652,8 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 		DPRINT_ERR(STORVSC_DRV, "scmnd (%p) - unable to allocate "
 			   "storvsc_cmd_request...marking queue busy", scmnd);
 		scmnd->scsi_done = NULL;
+
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
@@ -718,6 +724,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 				kmem_cache_free(host_device_ctx->request_pool,
 						cmd_request);
 
+				spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 				return SCSI_MLQUEUE_HOST_BUSY;
 			}
 
@@ -782,6 +789,7 @@ retry_request:
 		ret = SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 5a47805..7543420 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -578,7 +578,10 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 	int err = 0;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	MTS_DEBUG_GOT_HERE();
 	mts_show_command(srb);
 	mts_debug_dump(desc);
@@ -623,6 +626,7 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 
 	}
 out:
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return err;
 }
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a688b1e..f1b0aa9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -289,13 +289,17 @@ static int queuecommand(struct scsi_cmnd *srb,
 			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = host_to_us(srb->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	US_DEBUGP("%s called\n", __func__);
 
 	/* check for state-transition errors */
 	if (us->srb != NULL) {
 		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
 			__func__, us->srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -304,6 +308,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 		US_DEBUGP("Fail command during disconnect\n");
 		srb->result = DID_NO_CONNECT << 16;
 		done(srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -312,6 +317,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 	us->srb = srb;
 	complete(&us->cmnd_ready);
 
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 2054b1e..d00db31 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -440,11 +440,16 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 	struct uas_dev_info *devinfo = sdev->hostdata;
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	int err;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+	if (!cmdinfo->sense_urb && sdev->current_cmnd) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 
 	if (blk_rq_tagged(cmnd->request)) {
 		cmdinfo->stream = cmnd->request->tag + 1;
@@ -480,6 +485,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		/* If we did nothing, give up now */
 		if (cmdinfo->state & SUBMIT_SENSE_URB) {
 			usb_free_urb(cmdinfo->sense_urb);
+			spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		}
 		spin_lock(&uas_work_lock);
@@ -488,6 +494,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		schedule_work(&uas_work);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d0a6a84..99a2da7 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -881,5 +881,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
 extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
+extern void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd);
 
 #endif /* _SCSI_SCSI_HOST_H */

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 20:10   ` Andi Kleen
@ 2010-10-28 20:22     ` James Bottomley
  2010-10-28 21:50       ` Andi Kleen
  0 siblings, 1 reply; 26+ messages in thread
From: James Bottomley @ 2010-10-28 20:22 UTC (permalink / raw)
  To: Andi Kleen; +Cc: nab, linux-scsi

On Thu, 2010-10-28 at 22:10 +0200, Andi Kleen wrote:
On Thu, Oct 28, 2010 at 02:28:43PM -0500, James Bottomley wrote:
> > On Thu, 2010-10-28 at 17:05 +0200, Andi Kleen wrote:
> > > Here's the promised attempt to do a full host_lock pushdown. This
> > > was done using coccinelle and some manual adjustments.
> > > 
> > > This is just a dumb pushdown of host lock and serial number into
> > > the driver, no attempt to remove any locks yet.
> > > 
> > > Currently lightly tested, but compiles with allmodconfig on 32bit x86.
> > > 
> > > I made no attempt to automatically add maintainers to Cc.
> > > 
> > > I'm not posting the patches because they are numerous and boring,
> > > but it's available in git.
> > > 
> > > This will likely bitrot quickly so if it's decided to do it this
> > > way I would prefer if this was merged quickly.
> > 
> > OK, so can you post an actual diff?  It obviously has to be done in one
> > commit rather than the 87 you have.
> 
> Why? I'm not sure a single commit is manageable. The multiple commits
> are not atomic, but at least they should all compile and boot
> and they minimze breakage.

To put this upstream, I need the single commit (with changelog and
signoff).  Otherwise the series won't bisect.  Murphys law says that if
I apply an unbisectable series like this, all the kernel bisections in
the next few months will end up in here, and I'll take a huge amount of
flack ...

> Anyways full diff appended.

Thanks,

James


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 20:22     ` James Bottomley
@ 2010-10-28 21:50       ` Andi Kleen
  2010-10-28 22:37         ` Nicholas A. Bellinger
  0 siblings, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2010-10-28 21:50 UTC (permalink / raw)
  To: James Bottomley; +Cc: Andi Kleen, nab, linux-scsi

> To put this upstream, I need the single commit (with changelog and
> signoff).  Otherwise the series won't bisect.  Murphys law says that if
> I apply an unbisectable series like this, all the kernel bisections in
> the next few months will end up in here, and I'll take a huge amount of
> flack ...

I expect even without the locking it should be safe enough for a bisect
test. Not for production of course. And most drivers don't really
need the lock anyways so they are safe in any case.

An alternative would be to use a different lock around the call
temporary during the series and drop it again at the end.

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 21:50       ` Andi Kleen
@ 2010-10-28 22:37         ` Nicholas A. Bellinger
  0 siblings, 0 replies; 26+ messages in thread
From: Nicholas A. Bellinger @ 2010-10-28 22:37 UTC (permalink / raw)
  To: Andi Kleen; +Cc: James Bottomley, linux-scsi, Boaz Harrosh

On Thu, 2010-10-28 at 23:50 +0200, Andi Kleen wrote:
> > To put this upstream, I need the single commit (with changelog and
> > signoff).  Otherwise the series won't bisect.  Murphys law says that if
> > I apply an unbisectable series like this, all the kernel bisections in
> > the next few months will end up in here, and I'll take a huge amount of
> > flack ...
> 
> I expect even without the locking it should be safe enough for a bisect
> test. Not for production of course. And most drivers don't really
> need the lock anyways so they are safe in any case.
> 
> An alternative would be to use a different lock around the call
> temporary during the series and drop it again at the end.
> 

Mmmmmm, I don't really have an perference here.   Unless we want to
agree to follow Boaz's recommendation from this morning:

http://marc.info/?l=linux-scsi&m=128826469826164&w=2

--nab


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 15:05 Full hostlock pushdown available Andi Kleen
  2010-10-28 19:28 ` James Bottomley
@ 2010-10-31 12:22 ` Boaz Harrosh
  2010-10-31 18:48   ` Stefan Richter
  1 sibling, 1 reply; 26+ messages in thread
From: Boaz Harrosh @ 2010-10-31 12:22 UTC (permalink / raw)
  To: Andi Kleen; +Cc: James.Bottomley, nab, linux-scsi

On 10/28/2010 05:05 PM, Andi Kleen wrote:
> 
> Here's the promised attempt to do a full host_lock pushdown. This
> was done using coccinelle and some manual adjustments.
> 

Hi Andi.
Could you please post the final coccinelle script you used.
I've never used coccinelle, it sounds like an interesting tool.
RTFM as we speak.

Thanks
Boaz

> This is just a dumb pushdown of host lock and serial number into
> the driver, no attempt to remove any locks yet.
> 
> Currently lightly tested, but compiles with allmodconfig on 32bit x86.
> 
> I made no attempt to automatically add maintainers to Cc.
> 
> I'm not posting the patches because they are numerous and boring,
> but it's available in git.
> 
> This will likely bitrot quickly so if it's decided to do it this
> way I would prefer if this was merged quickly.
> 
> Issues found:
> - I found a clear deadlock in aha1740, not sure if that driver ever
> worked since host_lock was introduced. Anyways I attempted to work
> around it. But if it's really that unused it may be better to 
> simply drop it.
> - I'm not sure how to compile cciss_scsi, is it even used?
> 
> -Andi
> 
> The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:
> 
>   Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)
> 
> are available in the git repository at:
> 
>   ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock
> 
> Andi Kleen (87):
>       SCSI: Remove hostlock for queuecommand
>       SCSI: ibmmca: hostlock pushdown
>       SCSI: ipr: hostlock pushdown
>       SCSI: ultrastor: hostlock pushdown
>       SCSI: aha1740: hostlock pushdown
>       SCSI: ia64 simscsi: hostlock pushdown
>       SCSI: sun3_NCR5380: pushdown of hostlock
>       SCSI: staging/hv/storvsc_drv: pushdown of hostlock
>       SCSI: s390/zfcp_scsi: hostlock pushdown
>       SCSI: libiscsi: hostlock pushdown
>       SCSI: libiscsi: remove hostlock drop
>       SCSI: NCR5380: hostlock pushdown
>       SCSI: libsas: hostlock pushdown
>       SCSI: stex: hostlock pushdown
>       SCSI: wd33c93: hostlock pushdown
>       SCSI: aha152x: hostlock pushdown
>       SCSI: microtek: hostlock pushdown
>       SCSI: scsiglue: hostlock pushdown
>       SCSI: uas: hostlock pushdown
>       SCSI: i2o_scsi: hostlock pushdown
>       SCSI: mptspi: hostlock pushdown
>       SCSI: mptsas: hostlock pushdown
>       SCSI: mptfc: hostlock pushdown
>       SCSI: sbp2: hostlock pushdown
>       SCSI: ib_srp: hostlock pushdown
>       SCSI: mesh: hostlock pushdown
>       SCSI: fd_mcs: hostlock pushdown
>       SCSI: fnic_main: hostlock pushdown
>       SCSI: gdth: hostlock pushdown
>       SCSI: ppa: hostlock pushdown
>       SCSI: qlogicpti: hostlock pushdown
>       SCSI: 3w-sas: hostlock pushdown
>       SCSI: 3w-9xxx: hostlock pushdown
>       SCSI: fcoe: hostlock pushdown
>       SCSI: ips: hostlock pushdown
>       SCSI: sym_glue: hostlock pushdown
>       SCSI: ql4_os: hostlock pushdown
>       SCSI: mpt2sas_scsih: hostlock pushdown
>       SCSI: fdomain: hostlock pushdown
>       SCSI: initio: hostlock pushdown
>       SCSI: in2000: hostlock pushdown
>       SCSI: nsp32: hostlock pushdown
>       SCSI: megaraid_sas: hostlock pushdown
>       SCSI: megaraid_mbox: hostlock pushdown
>       SCSI: BusLogic: hostlock pushdown
>       SCSI: dpt_i2o: hostlock pushdown
>       SCSI: 3w-xxxx: hostlock pushdown
>       SCSI: atp870u: hostlock pushdown
>       SCSI: qlogicfas: hostlock pushdown
>       SCSI: qla1280: hostlock pushdown
>       SCSI: dc395x: hostlock pushdown
>       SCSI: linit: hostlock pushdown
>       SCSI: ibmvfc: hostlock pushdown
>       SCSI: ibmvscsi: hostlock pushdown
>       SCSI: lpfc_scsi: hostlock pushdown
>       SCSI: ps3rom: hostlock pushdown
>       SCSI: pmcraid: hostlock pushdown
>       SCSI: eata: hostlock pushdown
>       SCSI: tmscsim: hostlock pushdown
>       SCSI: imm: hostlock pushdown
>       SCSI: wd7000: hostlock pushdown
>       SCSI: sym53c416: hostlock pushdown
>       SCSI: aic7xxx_old: hostlock pushdown
>       SCSI: megaraid: hostlock pushdown
>       SCSI: aha1542: hostlock pushdown
>       SCSI: eata_pio: hostlock pushdown
>       SCSI: esp_scsi: hostlock pushdown
>       SCSI: a100u2w: hostlock pushdown
>       SCSI: hpsa: hostlock pushdown
>       SCSI: NCR53c406a: hostlock pushdown
>       SCSI: mac53c94: hostlock pushdown
>       SCSI: vmw_pvscsi: hostlock pushdown
>       SCSI: 53c700: hostlock pushdown
>       SCSI: u14-34f: hostlock pushdown
>       SCSI: ncr53c8xx: hostlock pushdown
>       SCSI: advansys: hostlock pushdown
>       SCSI: hptiop: hostlock pushdown
>       SCSI: arcmsr_hba: hostlock pushdown
>       SCSI: aic79xx_osm: hostlock pushdown
>       SCSI: aic7xxx_osm: hostlock pushdown
>       SCSI: arm: hostlock pushdown
>       SCSI: qla_os: hostlock pushdown
>       SCSI: nsp_cs: hostlock pushdown
>       SCSI: sym53c500_cs: hostlock pushdown
>       SCSI: bfad_im: hostlock pushdown
>       SCSI: cciss_scsi: hostlock pushdown
>       SCSI: aha1740: Avoid instant deadlock
> 
>  arch/ia64/hp/sim/simscsi.c            |    7 +++++++
>  drivers/block/cciss_scsi.c            |    6 ++++++
>  drivers/firewire/sbp2.c               |    5 +++++
>  drivers/infiniband/ulp/srp/ib_srp.c   |    6 ++++++
>  drivers/message/fusion/mptfc.c        |    6 ++++++
>  drivers/message/fusion/mptsas.c       |    8 +++++++-
>  drivers/message/fusion/mptspi.c       |    5 +++++
>  drivers/message/i2o/i2o_scsi.c        |    5 +++++
>  drivers/s390/scsi/zfcp_scsi.c         |    8 ++++++++
>  drivers/scsi/3w-9xxx.c                |    4 ++++
>  drivers/scsi/3w-sas.c                 |    4 ++++
>  drivers/scsi/3w-xxxx.c                |    4 ++++
>  drivers/scsi/53c700.c                 |    6 ++++++
>  drivers/scsi/BusLogic.c               |    5 +++++
>  drivers/scsi/NCR5380.c                |    6 ++++++
>  drivers/scsi/NCR53c406a.c             |    4 ++++
>  drivers/scsi/a100u2w.c                |    9 ++++++++-
>  drivers/scsi/aacraid/linit.c          |   10 ++++++++--
>  drivers/scsi/advansys.c               |    4 ++++
>  drivers/scsi/aha152x.c                |   10 +++++++++-
>  drivers/scsi/aha1542.c                |   12 ++++++++++--
>  drivers/scsi/aha1740.c                |   11 +++++++++++
>  drivers/scsi/aic7xxx/aic79xx_osm.c    |    4 ++++
>  drivers/scsi/aic7xxx/aic7xxx_osm.c    |    4 ++++
>  drivers/scsi/aic7xxx_old.c            |    5 +++++
>  drivers/scsi/arcmsr/arcmsr_hba.c      |   18 +++++++++++++++---
>  drivers/scsi/arm/acornscsi.c          |    6 ++++++
>  drivers/scsi/arm/fas216.c             |    8 ++++++++
>  drivers/scsi/atp870u.c                |    8 ++++++++
>  drivers/scsi/bfa/bfad_im.c            |   11 ++++++++++-
>  drivers/scsi/dc395x.c                 |    6 ++++++
>  drivers/scsi/dpt_i2o.c                |    9 +++++++++
>  drivers/scsi/eata.c                   |    7 +++++++
>  drivers/scsi/eata_pio.c               |    5 +++++
>  drivers/scsi/esp_scsi.c               |    8 +++++++-
>  drivers/scsi/fd_mcs.c                 |    4 ++++
>  drivers/scsi/fdomain.c                |    4 ++++
>  drivers/scsi/fnic/fnic_scsi.c         |    9 ++++++++-
>  drivers/scsi/gdth.c                   |    4 ++++
>  drivers/scsi/hpsa.c                   |    7 +++++++
>  drivers/scsi/hptiop.c                 |    6 ++++++
>  drivers/scsi/ibmmca.c                 |   12 ++++++++++++
>  drivers/scsi/ibmvscsi/ibmvfc.c        |   12 ++++++++++--
>  drivers/scsi/ibmvscsi/ibmvscsi.c      |    9 ++++++++-
>  drivers/scsi/imm.c                    |    4 ++++
>  drivers/scsi/in2000.c                 |    4 ++++
>  drivers/scsi/initio.c                 |    8 +++++++-
>  drivers/scsi/ipr.c                    |   17 ++++++++++++++---
>  drivers/scsi/ips.c                    |   18 ++++++++++++++++--
>  drivers/scsi/libfc/fc_fcp.c           |    5 +++++
>  drivers/scsi/libiscsi.c               |   10 ++++++----
>  drivers/scsi/libsas/sas_scsi_host.c   |    7 +++++--
>  drivers/scsi/lpfc/lpfc_scsi.c         |    6 ++++++
>  drivers/scsi/mac53c94.c               |    4 ++++
>  drivers/scsi/megaraid.c               |    4 ++++
>  drivers/scsi/megaraid/megaraid_mbox.c |    5 +++++
>  drivers/scsi/megaraid/megaraid_sas.c  |   14 ++++++++++++--
>  drivers/scsi/mesh.c                   |    4 ++++
>  drivers/scsi/mpt2sas/mpt2sas_scsih.c  |   17 +++++++++++++++--
>  drivers/scsi/ncr53c8xx.c              |    4 ++++
>  drivers/scsi/nsp32.c                  |    8 ++++++++
>  drivers/scsi/pcmcia/nsp_cs.c          |    6 ++++++
>  drivers/scsi/pcmcia/sym53c500_cs.c    |    4 ++++
>  drivers/scsi/pmcraid.c                |   11 ++++++++++-
>  drivers/scsi/ppa.c                    |    4 ++++
>  drivers/scsi/ps3rom.c                 |    4 ++++
>  drivers/scsi/qla1280.c                |    4 ++++
>  drivers/scsi/qla2xxx/qla_os.c         |    7 +++++++
>  drivers/scsi/qla4xxx/ql4_os.c         |    7 +++++++
>  drivers/scsi/qlogicfas408.c           |    4 ++++
>  drivers/scsi/qlogicpti.c              |    5 +++++
>  drivers/scsi/scsi.c                   |   15 +++------------
>  drivers/scsi/stex.c                   |   20 ++++++++++++++++++--
>  drivers/scsi/sun3_NCR5380.c           |    8 ++++++++
>  drivers/scsi/sym53c416.c              |    4 ++++
>  drivers/scsi/sym53c8xx_2/sym_glue.c   |   12 ++++++++++--
>  drivers/scsi/tmscsim.c                |    5 +++++
>  drivers/scsi/u14-34f.c                |    7 +++++++
>  drivers/scsi/ultrastor.c              |    7 +++++++
>  drivers/scsi/vmw_pvscsi.c             |    5 +++++
>  drivers/scsi/wd33c93.c                |    6 +++++-
>  drivers/scsi/wd7000.c                 |    4 ++++
>  drivers/staging/hv/storvsc_drv.c      |    8 ++++++++
>  drivers/usb/image/microtek.c          |    4 ++++
>  drivers/usb/storage/scsiglue.c        |    6 ++++++
>  drivers/usb/storage/uas.c             |    9 ++++++++-
>  include/scsi/scsi_host.h              |    1 +
>  87 files changed, 576 insertions(+), 51 deletions(-)
> 


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-31 12:22 ` Boaz Harrosh
@ 2010-10-31 18:48   ` Stefan Richter
  2010-11-01  2:34     ` Jeff Garzik
  2010-11-01 13:54     ` Andi Kleen
  0 siblings, 2 replies; 26+ messages in thread
From: Stefan Richter @ 2010-10-31 18:48 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Boaz Harrosh, James.Bottomley, nab, linux-scsi

> On 10/28/2010 05:05 PM, Andi Kleen wrote:
>> The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:
>> 
>>   Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)
>> 
>> are available in the git repository at:
>> 
>>   ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock

Don't forget this one:

--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1087,8 +1087,7 @@ Details:
  *      non-zero return, it must not execute the command's done
  *      callback at any time.
  *
- *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
- *             and is expected to be held on return.
+ *      Locks: none
  *
  *      Calling context: in interrupt (soft irq) or process context
  *

-- 
Stefan Richter
-=====-==-=- =-=- =====
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-31 18:48   ` Stefan Richter
@ 2010-11-01  2:34     ` Jeff Garzik
  2010-11-01 13:53       ` Andi Kleen
  2010-11-01 13:54     ` Andi Kleen
  1 sibling, 1 reply; 26+ messages in thread
From: Jeff Garzik @ 2010-11-01  2:34 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi


>> On 10/28/2010 05:05 PM, Andi Kleen wrote:
>>> >> The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:
>>> >>
>>> >>   Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)
>>> >>
>>> >> are available in the git repository at:
>>> >>
>>> >>   ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock

Missing drivers/ata/libata-scsi.c modification?


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01  2:34     ` Jeff Garzik
@ 2010-11-01 13:53       ` Andi Kleen
  2010-11-01 15:56         ` Jeff Garzik
  0 siblings, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2010-11-01 13:53 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley, nab,
	linux-scsi

On Sun, Oct 31, 2010 at 10:34:05PM -0400, Jeff Garzik wrote:
> 
> >>On 10/28/2010 05:05 PM, Andi Kleen wrote:
> >>>>> The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:
> >>>>>
> >>>>>   Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)
> >>>>>
> >>>>> are available in the git repository at:
> >>>>>
> >>>>>   ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock
> 
> Missing drivers/ata/libata-scsi.c modification?

Ah thanks for noticing. I missed that because it defined queuecommand
in a header plus a macro. Fixed in the tree. I also did another grep to make
sure there a no other occurrences. And fixed some documentation.

Updated tree

-Andi



The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:

  Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)

are available in the git repository at:

  ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6 hostlock

Andi Kleen (90):
      SCSI: Remove hostlock for queuecommand
      SCSI: ibmmca: hostlock pushdown
      SCSI: ipr: hostlock pushdown
      SCSI: ultrastor: hostlock pushdown
      SCSI: aha1740: hostlock pushdown
      SCSI: ia64 simscsi: hostlock pushdown
      SCSI: sun3_NCR5380: pushdown of hostlock
      SCSI: staging/hv/storvsc_drv: pushdown of hostlock
      SCSI: s390/zfcp_scsi: hostlock pushdown
      SCSI: libiscsi: hostlock pushdown
      SCSI: libiscsi: remove hostlock drop
      SCSI: NCR5380: hostlock pushdown
      SCSI: libsas: hostlock pushdown
      SCSI: stex: hostlock pushdown
      SCSI: wd33c93: hostlock pushdown
      SCSI: aha152x: hostlock pushdown
      SCSI: microtek: hostlock pushdown
      SCSI: scsiglue: hostlock pushdown
      SCSI: uas: hostlock pushdown
      SCSI: i2o_scsi: hostlock pushdown
      SCSI: mptspi: hostlock pushdown
      SCSI: mptsas: hostlock pushdown
      SCSI: mptfc: hostlock pushdown
      SCSI: sbp2: hostlock pushdown
      SCSI: ib_srp: hostlock pushdown
      SCSI: mesh: hostlock pushdown
      SCSI: fd_mcs: hostlock pushdown
      SCSI: fnic_main: hostlock pushdown
      SCSI: gdth: hostlock pushdown
      SCSI: ppa: hostlock pushdown
      SCSI: qlogicpti: hostlock pushdown
      SCSI: 3w-sas: hostlock pushdown
      SCSI: 3w-9xxx: hostlock pushdown
      SCSI: fcoe: hostlock pushdown
      SCSI: ips: hostlock pushdown
      SCSI: sym_glue: hostlock pushdown
      SCSI: ql4_os: hostlock pushdown
      SCSI: mpt2sas_scsih: hostlock pushdown
      SCSI: fdomain: hostlock pushdown
      SCSI: initio: hostlock pushdown
      SCSI: in2000: hostlock pushdown
      SCSI: nsp32: hostlock pushdown
      SCSI: megaraid_sas: hostlock pushdown
      SCSI: megaraid_mbox: hostlock pushdown
      SCSI: BusLogic: hostlock pushdown
      SCSI: dpt_i2o: hostlock pushdown
      SCSI: 3w-xxxx: hostlock pushdown
      SCSI: atp870u: hostlock pushdown
      SCSI: qlogicfas: hostlock pushdown
      SCSI: qla1280: hostlock pushdown
      SCSI: dc395x: hostlock pushdown
      SCSI: linit: hostlock pushdown
      SCSI: ibmvfc: hostlock pushdown
      SCSI: ibmvscsi: hostlock pushdown
      SCSI: lpfc_scsi: hostlock pushdown
      SCSI: ps3rom: hostlock pushdown
      SCSI: pmcraid: hostlock pushdown
      SCSI: eata: hostlock pushdown
      SCSI: tmscsim: hostlock pushdown
      SCSI: imm: hostlock pushdown
      SCSI: wd7000: hostlock pushdown
      SCSI: sym53c416: hostlock pushdown
      SCSI: aic7xxx_old: hostlock pushdown
      SCSI: megaraid: hostlock pushdown
      SCSI: aha1542: hostlock pushdown
      SCSI: eata_pio: hostlock pushdown
      SCSI: esp_scsi: hostlock pushdown
      SCSI: a100u2w: hostlock pushdown
      SCSI: hpsa: hostlock pushdown
      SCSI: NCR53c406a: hostlock pushdown
      SCSI: mac53c94: hostlock pushdown
      SCSI: vmw_pvscsi: hostlock pushdown
      SCSI: 53c700: hostlock pushdown
      SCSI: u14-34f: hostlock pushdown
      SCSI: ncr53c8xx: hostlock pushdown
      SCSI: advansys: hostlock pushdown
      SCSI: hptiop: hostlock pushdown
      SCSI: arcmsr_hba: hostlock pushdown
      SCSI: aic79xx_osm: hostlock pushdown
      SCSI: aic7xxx_osm: hostlock pushdown
      SCSI: arm: hostlock pushdown
      SCSI: qla_os: hostlock pushdown
      SCSI: nsp_cs: hostlock pushdown
      SCSI: sym53c500_cs: hostlock pushdown
      SCSI: bfad_im: hostlock pushdown
      SCSI: cciss_scsi: hostlock pushdown
      SCSI: aha1740: Avoid instant deadlock
      SCSI: Fix ps3rom
      SCSI: libata-scsi: hostlock pushdown
      SCSI: Fix documentation for queuecommand for new locking

 Documentation/scsi/scsi_mid_low_api.txt |    8 ++++++--
 arch/ia64/hp/sim/simscsi.c              |    7 +++++++
 drivers/ata/libata-scsi.c               |    8 ++++++--
 drivers/block/cciss_scsi.c              |    6 ++++++
 drivers/firewire/sbp2.c                 |    5 +++++
 drivers/infiniband/ulp/srp/ib_srp.c     |    6 ++++++
 drivers/message/fusion/mptfc.c          |    6 ++++++
 drivers/message/fusion/mptsas.c         |    8 +++++++-
 drivers/message/fusion/mptspi.c         |    5 +++++
 drivers/message/i2o/i2o_scsi.c          |    5 +++++
 drivers/s390/scsi/zfcp_scsi.c           |    8 ++++++++
 drivers/scsi/3w-9xxx.c                  |    4 ++++
 drivers/scsi/3w-sas.c                   |    4 ++++
 drivers/scsi/3w-xxxx.c                  |    4 ++++
 drivers/scsi/53c700.c                   |    6 ++++++
 drivers/scsi/BusLogic.c                 |    5 +++++
 drivers/scsi/NCR5380.c                  |    6 ++++++
 drivers/scsi/NCR53c406a.c               |    4 ++++
 drivers/scsi/a100u2w.c                  |    9 ++++++++-
 drivers/scsi/aacraid/linit.c            |   10 ++++++++--
 drivers/scsi/advansys.c                 |    4 ++++
 drivers/scsi/aha152x.c                  |   10 +++++++++-
 drivers/scsi/aha1542.c                  |   12 ++++++++++--
 drivers/scsi/aha1740.c                  |   11 +++++++++++
 drivers/scsi/aic7xxx/aic79xx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx/aic7xxx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx_old.c              |    5 +++++
 drivers/scsi/arcmsr/arcmsr_hba.c        |   18 +++++++++++++++---
 drivers/scsi/arm/acornscsi.c            |    6 ++++++
 drivers/scsi/arm/fas216.c               |    8 ++++++++
 drivers/scsi/atp870u.c                  |    8 ++++++++
 drivers/scsi/bfa/bfad_im.c              |   11 ++++++++++-
 drivers/scsi/dc395x.c                   |    6 ++++++
 drivers/scsi/dpt_i2o.c                  |    9 +++++++++
 drivers/scsi/eata.c                     |    7 +++++++
 drivers/scsi/eata_pio.c                 |    5 +++++
 drivers/scsi/esp_scsi.c                 |    8 +++++++-
 drivers/scsi/fd_mcs.c                   |    4 ++++
 drivers/scsi/fdomain.c                  |    4 ++++
 drivers/scsi/fnic/fnic_scsi.c           |    9 ++++++++-
 drivers/scsi/gdth.c                     |    4 ++++
 drivers/scsi/hpsa.c                     |    7 +++++++
 drivers/scsi/hptiop.c                   |    6 ++++++
 drivers/scsi/ibmmca.c                   |   12 ++++++++++++
 drivers/scsi/ibmvscsi/ibmvfc.c          |   12 ++++++++++--
 drivers/scsi/ibmvscsi/ibmvscsi.c        |    9 ++++++++-
 drivers/scsi/imm.c                      |    4 ++++
 drivers/scsi/in2000.c                   |    4 ++++
 drivers/scsi/initio.c                   |    8 +++++++-
 drivers/scsi/ipr.c                      |   17 ++++++++++++++---
 drivers/scsi/ips.c                      |   18 ++++++++++++++++--
 drivers/scsi/libfc/fc_fcp.c             |    5 +++++
 drivers/scsi/libiscsi.c                 |   10 ++++++----
 drivers/scsi/libsas/sas_scsi_host.c     |    7 +++++--
 drivers/scsi/lpfc/lpfc_scsi.c           |    6 ++++++
 drivers/scsi/mac53c94.c                 |    4 ++++
 drivers/scsi/megaraid.c                 |    4 ++++
 drivers/scsi/megaraid/megaraid_mbox.c   |    5 +++++
 drivers/scsi/megaraid/megaraid_sas.c    |   14 ++++++++++++--
 drivers/scsi/mesh.c                     |    4 ++++
 drivers/scsi/mpt2sas/mpt2sas_scsih.c    |   17 +++++++++++++++--
 drivers/scsi/ncr53c8xx.c                |    4 ++++
 drivers/scsi/nsp32.c                    |    8 ++++++++
 drivers/scsi/pcmcia/nsp_cs.c            |    6 ++++++
 drivers/scsi/pcmcia/sym53c500_cs.c      |    4 ++++
 drivers/scsi/pmcraid.c                  |   11 ++++++++++-
 drivers/scsi/ppa.c                      |    4 ++++
 drivers/scsi/ps3rom.c                   |    4 ++++
 drivers/scsi/qla1280.c                  |    4 ++++
 drivers/scsi/qla2xxx/qla_os.c           |    7 +++++++
 drivers/scsi/qla4xxx/ql4_os.c           |    7 +++++++
 drivers/scsi/qlogicfas408.c             |    4 ++++
 drivers/scsi/qlogicpti.c                |    5 +++++
 drivers/scsi/scsi.c                     |   15 +++------------
 drivers/scsi/stex.c                     |   20 ++++++++++++++++++--
 drivers/scsi/sun3_NCR5380.c             |    8 ++++++++
 drivers/scsi/sym53c416.c                |    4 ++++
 drivers/scsi/sym53c8xx_2/sym_glue.c     |   12 ++++++++++--
 drivers/scsi/tmscsim.c                  |    5 +++++
 drivers/scsi/u14-34f.c                  |    7 +++++++
 drivers/scsi/ultrastor.c                |    7 +++++++
 drivers/scsi/vmw_pvscsi.c               |    5 +++++
 drivers/scsi/wd33c93.c                  |    6 +++++-
 drivers/scsi/wd7000.c                   |    4 ++++
 drivers/staging/hv/storvsc_drv.c        |    8 ++++++++
 drivers/usb/image/microtek.c            |    4 ++++
 drivers/usb/storage/scsiglue.c          |    6 ++++++
 drivers/usb/storage/uas.c               |    9 ++++++++-
 include/scsi/scsi_host.h                |    1 +
 89 files changed, 588 insertions(+), 55 deletions(-)

-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-31 18:48   ` Stefan Richter
  2010-11-01  2:34     ` Jeff Garzik
@ 2010-11-01 13:54     ` Andi Kleen
  1 sibling, 0 replies; 26+ messages in thread
From: Andi Kleen @ 2010-11-01 13:54 UTC (permalink / raw)
  To: Stefan Richter; +Cc: Andi Kleen, Boaz Harrosh, James.Bottomley, nab, linux-scsi

On Sun, Oct 31, 2010 at 07:48:21PM +0100, Stefan Richter wrote:
> > On 10/28/2010 05:05 PM, Andi Kleen wrote:
> >> The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:
> >> 
> >>   Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)
> >> 
> >> are available in the git repository at:
> >> 
> >>   ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6.git hostlock
> 
> Don't forget this one:

Already done, but yes I forgot it first time. Thanks for looking.
-Andi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-10-28 19:32   ` Nicholas A. Bellinger
@ 2010-11-01 14:06     ` Andi Kleen
  2010-11-01 14:29       ` James Bottomley
  0 siblings, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2010-11-01 14:06 UTC (permalink / raw)
  To: Nicholas A. Bellinger; +Cc: James Bottomley, Andi Kleen, linux-scsi

> > OK, so can you post an actual diff?  It obviously has to be done in one
> > commit rather than the 87 you have.
> > 
> 
> So it appears this series will still need the atomic_add_return() usage
> in scsi_cmd_get_serial() and drop host_lock usage from those LLDs that
> we know can be converted to 'host_lock-less', yes..?

Yes that is correct. The series is just a dumb push down, no additional
improvements (except some very minor ones).  These patches
are still needed in addition, so it would be just a base for it

Also James if you use the patch and don't pull 
please regenerate it from the git tree (or tell me to send it again) -- 
i did some fixes based on feedback.

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 14:06     ` Andi Kleen
@ 2010-11-01 14:29       ` James Bottomley
  0 siblings, 0 replies; 26+ messages in thread
From: James Bottomley @ 2010-11-01 14:29 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Nicholas A. Bellinger, linux-scsi

On Mon, 2010-11-01 at 15:06 +0100, Andi Kleen wrote:
> > > OK, so can you post an actual diff?  It obviously has to be done in one
> > > commit rather than the 87 you have.
> > > 
> > 
> > So it appears this series will still need the atomic_add_return() usage
> > in scsi_cmd_get_serial() and drop host_lock usage from those LLDs that
> > we know can be converted to 'host_lock-less', yes..?
> 
> Yes that is correct. The series is just a dumb push down, no additional
> improvements (except some very minor ones).  These patches
> are still needed in addition, so it would be just a base for it
> 
> Also James if you use the patch and don't pull 
> please regenerate it from the git tree (or tell me to send it again) -- 
> i did some fixes based on feedback.

You can separate the Doc commits, but the lock pushdown still has to be
a single commit for bisectability.  If you respin the patch, I can add
the description if you want.

James



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 13:53       ` Andi Kleen
@ 2010-11-01 15:56         ` Jeff Garzik
  2010-11-01 17:57           ` Andi Kleen
  0 siblings, 1 reply; 26+ messages in thread
From: Jeff Garzik @ 2010-11-01 15:56 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi

On 11/01/2010 09:53 AM, Andi Kleen wrote:
>> > Missing drivers/ata/libata-scsi.c modification?

> Ah thanks for noticing. I missed that because it defined queuecommand
> in a header plus a macro. Fixed in the tree. I also did another grep to make
> sure there a no other occurrences. And fixed some documentation.
>
> Updated tree

You have just recreated the same bug Nicholas did:  you incorrectly 
removed the required _irqsave and _irqrestore from ap->lock.

Please check your changes closely to make sure you haven't duplicated 
this bug in other drivers.

This is _precisely_ why I like Boaz' suggestion:  it better guarantees 
the locking remains unchanged.  Apparently your change, like Nicholas's, 
is not so mechanical after all.

	Jeff



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 15:56         ` Jeff Garzik
@ 2010-11-01 17:57           ` Andi Kleen
  2010-11-01 18:42             ` Jeff Garzik
  2010-11-01 18:59             ` Jeff Garzik
  0 siblings, 2 replies; 26+ messages in thread
From: Andi Kleen @ 2010-11-01 17:57 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley, nab,
	linux-scsi

On Mon, Nov 01, 2010 at 11:56:47AM -0400, Jeff Garzik wrote:
> On 11/01/2010 09:53 AM, Andi Kleen wrote:
> >>> Missing drivers/ata/libata-scsi.c modification?
> 
> >Ah thanks for noticing. I missed that because it defined queuecommand
> >in a header plus a macro. Fixed in the tree. I also did another grep to make
> >sure there a no other occurrences. And fixed some documentation.
> >
> >Updated tree
> 
> You have just recreated the same bug Nicholas did:  you incorrectly
> removed the required _irqsave and _irqrestore from ap->lock.
> 

Hi Jeff,

Yes you caught me -- i had one or two non mechanical ones and that
was one of them. Here's an improved version which is truly mechanical,
but has some very redundant lock sequences. I also fixed some other
issues.

James, unless anyone else finds issues this one seems good to pull.

-Andi

Git tree with consolidated patch

The following changes since commit 39764981e772adc832d8a96e6540be346a830ca2:

  Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 (2010-10-27 20:54:34 +0200)

are available in the git repository at:

  ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6 hostlock2

Andi Kleen (2):
      SCSI: The great hostlock pushdown
      SCSI: aha1740: Avoid instant deadlock

 Documentation/scsi/scsi_mid_low_api.txt |    8 ++++++--
 arch/ia64/hp/sim/simscsi.c              |    7 +++++++
 drivers/ata/libata-scsi.c               |    6 +++++-
 drivers/block/cciss_scsi.c              |    6 ++++++
 drivers/firewire/sbp2.c                 |    6 ++++++
 drivers/infiniband/ulp/srp/ib_srp.c     |    6 ++++++
 drivers/message/fusion/mptfc.c          |    7 +++++++
 drivers/message/fusion/mptsas.c         |    9 ++++++++-
 drivers/message/fusion/mptspi.c         |    6 ++++++
 drivers/message/i2o/i2o_scsi.c          |    5 +++++
 drivers/s390/scsi/zfcp_scsi.c           |    8 ++++++++
 drivers/scsi/3w-9xxx.c                  |    4 ++++
 drivers/scsi/3w-sas.c                   |    4 ++++
 drivers/scsi/3w-xxxx.c                  |    4 ++++
 drivers/scsi/53c700.c                   |    7 +++++++
 drivers/scsi/BusLogic.c                 |    7 +++++++
 drivers/scsi/NCR5380.c                  |    6 ++++++
 drivers/scsi/NCR53c406a.c               |    4 ++++
 drivers/scsi/a100u2w.c                  |    9 ++++++++-
 drivers/scsi/aacraid/linit.c            |   15 ++++++++++++---
 drivers/scsi/advansys.c                 |    4 ++++
 drivers/scsi/aha152x.c                  |   10 +++++++++-
 drivers/scsi/aha1542.c                  |   12 ++++++++++--
 drivers/scsi/aha1740.c                  |   11 +++++++++++
 drivers/scsi/aic7xxx/aic79xx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx/aic7xxx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx_old.c              |    5 +++++
 drivers/scsi/arcmsr/arcmsr_hba.c        |   19 ++++++++++++++++---
 drivers/scsi/arm/acornscsi.c            |    6 ++++++
 drivers/scsi/arm/fas216.c               |    8 ++++++++
 drivers/scsi/atp870u.c                  |    8 ++++++++
 drivers/scsi/bfa/bfad_im.c              |   11 ++++++++++-
 drivers/scsi/dc395x.c                   |    7 +++++++
 drivers/scsi/dpt_i2o.c                  |    9 +++++++++
 drivers/scsi/eata.c                     |    7 +++++++
 drivers/scsi/eata_pio.c                 |    5 +++++
 drivers/scsi/esp_scsi.c                 |    8 +++++++-
 drivers/scsi/fd_mcs.c                   |    4 ++++
 drivers/scsi/fdomain.c                  |    4 ++++
 drivers/scsi/fnic/fnic_scsi.c           |    9 ++++++++-
 drivers/scsi/gdth.c                     |    4 ++++
 drivers/scsi/hpsa.c                     |    7 +++++++
 drivers/scsi/hptiop.c                   |    6 ++++++
 drivers/scsi/ibmmca.c                   |   12 ++++++++++++
 drivers/scsi/ibmvscsi/ibmvfc.c          |   13 +++++++++++--
 drivers/scsi/ibmvscsi/ibmvscsi.c        |    9 ++++++++-
 drivers/scsi/imm.c                      |    5 +++++
 drivers/scsi/in2000.c                   |    4 ++++
 drivers/scsi/initio.c                   |    8 +++++++-
 drivers/scsi/ipr.c                      |   17 ++++++++++++++---
 drivers/scsi/ips.c                      |   18 ++++++++++++++++--
 drivers/scsi/libfc/fc_fcp.c             |    5 +++++
 drivers/scsi/libiscsi.c                 |    7 +++++++
 drivers/scsi/libsas/sas_scsi_host.c     |    4 ++++
 drivers/scsi/lpfc/lpfc_scsi.c           |    7 +++++++
 drivers/scsi/mac53c94.c                 |    4 ++++
 drivers/scsi/megaraid.c                 |    4 ++++
 drivers/scsi/megaraid/megaraid_mbox.c   |    5 +++++
 drivers/scsi/megaraid/megaraid_sas.c    |   14 ++++++++++++--
 drivers/scsi/mesh.c                     |    4 ++++
 drivers/scsi/mpt2sas/mpt2sas_scsih.c    |   17 +++++++++++++++--
 drivers/scsi/ncr53c8xx.c                |    4 ++++
 drivers/scsi/nsp32.c                    |    8 ++++++++
 drivers/scsi/pcmcia/nsp_cs.c            |    6 ++++++
 drivers/scsi/pcmcia/sym53c500_cs.c      |    4 ++++
 drivers/scsi/pmcraid.c                  |   11 ++++++++++-
 drivers/scsi/ppa.c                      |    5 +++++
 drivers/scsi/ps3rom.c                   |    4 ++++
 drivers/scsi/qla1280.c                  |    4 ++++
 drivers/scsi/qla2xxx/qla_os.c           |    7 +++++++
 drivers/scsi/qla4xxx/ql4_os.c           |    7 +++++++
 drivers/scsi/qlogicfas408.c             |    4 ++++
 drivers/scsi/qlogicpti.c                |    5 +++++
 drivers/scsi/scsi.c                     |   15 +++------------
 drivers/scsi/stex.c                     |   20 ++++++++++++++++++--
 drivers/scsi/sun3_NCR5380.c             |    8 ++++++++
 drivers/scsi/sym53c416.c                |    4 ++++
 drivers/scsi/sym53c8xx_2/sym_glue.c     |   12 ++++++++++--
 drivers/scsi/tmscsim.c                  |    5 +++++
 drivers/scsi/u14-34f.c                  |    7 +++++++
 drivers/scsi/ultrastor.c                |    7 +++++++
 drivers/scsi/vmw_pvscsi.c               |    5 +++++
 drivers/scsi/wd33c93.c                  |    6 +++++-
 drivers/scsi/wd7000.c                   |    4 ++++
 drivers/staging/hv/storvsc_drv.c        |    8 ++++++++
 drivers/usb/image/microtek.c            |    4 ++++
 drivers/usb/storage/scsiglue.c          |    6 ++++++
 drivers/usb/storage/uas.c               |    9 ++++++++-
 include/scsi/scsi_host.h                |    1 +
 89 files changed, 604 insertions(+), 49 deletions(-)


diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 570ef2b..9dabc7f 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1087,11 +1087,15 @@ Details:
  *      non-zero return, it must not execute the command's done
  *      callback at any time.
  *
- *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
- *             and is expected to be held on return.
+ *	Locks: No locks are hold. If host_lock is needed this function
+ *	needs to take it by itself.
  *
  *      Calling context: in interrupt (soft irq) or process context
  *
+ *	When this function needs a serial number in the SCSI command
+ *	it needs to call scsi_cmd_get_serial with the lock hold
+ *	to get it. Usually it's not needed.
+ *
  *      Notes: This function should be relatively fast. Normally it will
  *      not wait for IO to complete. Hence the 'done' callback is invoked 
  *      (often directly from an interrupt service routine) some time after
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index 3a078ad..ce32f2c 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -209,6 +209,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	size_t disk_size;
 	char *buf;
 	char localbuf[36];
+	unsigned long irqflags;
+
 #if DEBUG_SIMSCSI
 	register long sp asm ("sp");
 
@@ -217,6 +219,9 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 		       target_id, sc->cmnd[0], sc->serial_number, sp, done);
 #endif
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host);
+
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
 	if (target_id <= 15 && sc->device->lun == 0) {
@@ -323,6 +328,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN;
 
 	tasklet_schedule(&simscsi_tasklet);
+
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d050e07..3e2f3e3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3186,11 +3186,14 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct ata_device *dev;
 	struct scsi_device *scsidev = cmd->device;
 	struct Scsi_Host *shost = scsidev->host;
+	unsigned long irqflags;
 	int rc = 0;
 
 	ap = ata_shost_to_port(shost);
 
-	spin_unlock(shost->host_lock);
+	spin_lock_irqsave(shost->host_lock, irqflags);
+	scsi_cmd_get_serial(shost, cmd);
+
 	spin_lock(ap->lock);
 
 	ata_scsi_dump_cdb(ap, cmd);
@@ -3205,6 +3208,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	spin_unlock(ap->lock);
 	spin_lock(shost->host_lock);
+	spin_unlock_irqrestore(shost->host_lock, irqflags);
 	return rc;
 }
 
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 575495f..4122788 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1413,9 +1413,12 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 	unsigned char scsi3addr[8];
 	CommandList_struct *c;
 	unsigned long flags;
+	unsigned long irqflags;
 
 	// Get the ptr to our adapter structure (hba[i]) out of cmd->host.
 	// We violate cmd->host privacy here.  (Is there another way?)
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	h = (ctlr_info_t *) cmd->device->host->hostdata[0];
 
 	rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
@@ -1427,6 +1430,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		done(cmd);
 		/* we might want to think about registering controller itself
 		   as a processor device on the bus so sg binds to it. */
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1441,6 +1445,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		/* FIXME: next 3 lines are -> BAD! <- */
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1501,6 +1506,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 	cciss_scatter_gather(h, c, cmd);
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index bfae4b3..23266fc 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1474,21 +1474,26 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	struct fw_device *device = target_device(lu->tgt);
 	struct sbp2_command_orb *orb;
 	int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
+	unsigned long irqflags;
 
 	/*
 	 * Bidirectional commands are not yet implemented, and unknown
 	 * transfer direction not handled.
 	 */
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
 		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
 	if (orb == NULL) {
 		fw_notify("failed to alloc orb\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1531,6 +1536,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	retval = 0;
  out:
 	kref_put(&orb->base.kref, free_orb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return retval;
 }
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index cfc1d65..52c9d2e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1132,7 +1132,10 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	struct srp_cmd *cmd;
 	struct ib_device *dev;
 	int len;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 	if (target->state == SRP_TARGET_CONNECTING)
 		goto err;
 
@@ -1140,6 +1143,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
 		done(scmnd);
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1187,12 +1191,14 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 
 	list_move_tail(&req->list, &target->req_queue);
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return 0;
 
 err_unmap:
 	srp_unmap_data(scmnd, target, req);
 
 err:
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index e15220f..6e5a2b0 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -656,10 +656,14 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -667,6 +671,7 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(err)) {
 		SCpnt->result = err;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -675,9 +680,11 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(!ri)) {
 		SCpnt->result = DID_IMM_RETRY << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 83a5115..7e9fcf5 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1894,22 +1894,29 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	MPT_SCSI_HOST	*hd;
 	MPT_ADAPTER	*ioc;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	hd = shost_priv(SCpnt->device->host);
 	ioc = hd->ioc;
 
-	if (ioc->sas_discovery_quiesce_io)
+	if (ioc->sas_discovery_quiesce_io) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (ioc->debug_level & MPT_DEBUG_SCSI)
 		scsi_print_command(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 0e28031..2a75e9a 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -785,10 +785,14 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host);
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
 	MPT_ADAPTER *ioc = hd->ioc;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -796,12 +800,14 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 		mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (spi_dv_pending(scsi_target(SCpnt->device)))
 		ddvprintk(ioc, scsi_print_command(SCpnt));
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index ea6b219..21056dd 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -527,6 +527,9 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	/*
 	 *      Do the incoming paperwork
 	 */
+	unsigned long irqflags;
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	i2o_dev = SCpnt->device->hostdata;
 
 	SCpnt->scsi_done = done;
@@ -680,6 +683,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 
 	osm_debug("Issued %ld\n", SCpnt->serial_number);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 
       nomem:
@@ -687,6 +691,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	i2o_msg_nop(c, msg);
 
       exit:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return rc;
 };
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 50286d8..c28e5fe 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -83,6 +83,10 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
 	int    status, scsi_result, ret;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scpnt->device->host, scpnt);
 
 	/* reset the status for this request */
 	scpnt->result = 0;
@@ -94,6 +98,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		scpnt->result = scsi_result;
 		zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt);
 		scpnt->scsi_done(scpnt);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -104,6 +109,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		/* only LUN access denied, but port is good
 		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -115,10 +121,12 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
 		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	ret = zfcp_fsf_fcp_cmnd(scpnt);
+	spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	else if (unlikely(ret < 0))
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index fcf08b3..3ad0f51 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1769,7 +1769,10 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1809,6 +1812,7 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twa_scsi_queue() */
 
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 6a95d11..de5d845 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1505,7 +1505,10 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1533,6 +1536,7 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twl_scsi_queue() */
 
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index b112534..6812acc 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1953,7 +1953,10 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 	int request_id = 0;
 	int retval = 1;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags))
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -2020,6 +2023,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		done(SCpnt);
 		retval = 0;
 	}
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End tw_scsi_queue() */
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 89fc1c8..6bd1c22 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1757,11 +1757,15 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	__u32 move_ins;
 	enum dma_data_direction direction;
 	struct NCR_700_command_slot *slot;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCp->device->host, SCp);
 	if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) {
 		/* We're over our allocation, this should never happen
 		 * since we report the max allocation to the mid layer */
 		printk(KERN_WARNING "scsi%d: Command depth has gone over queue depth\n", SCp->device->host->host_no);
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return 1;
 	}
 	/* check for untagged commands.  We cannot have any outstanding
@@ -1775,11 +1779,13 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	       || !blk_rq_tagged(SCp->request))) {
 		CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) {
 		CDEBUG(KERN_ERR, SCp, "has max tag depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
@@ -1901,6 +1907,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
 				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
+	spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index fc0b4b8..10ce6fb 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2819,14 +2819,19 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 	int BufferLength = scsi_bufflen(Command);
 	int Count;
 	struct BusLogic_CCB *CCB;
+	unsigned long irqflags;
 	/*
 	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
 	   Adapter for any errors, so they should not be executed explicitly unless
 	   the Sense Data is zero indicating that no error occurred.
 	 */
+
+	spin_lock_irqsave(Command->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Command->device->host, Command);
 	if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
 		Command->result = DID_OK << 16;
 		CompletionRoutine(Command);
+		spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 		return 0;
 	}
 	/*
@@ -2844,6 +2849,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB == NULL) {
 			Command->result = DID_ERROR << 16;
 			CompletionRoutine(Command);
+			spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -2991,6 +2997,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB->Status == BusLogic_CCB_Completed)
 			BusLogic_ProcessCompletedCCBs(HostAdapter);
 	}
+	spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 5d2f148..f4bd889 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -957,6 +957,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance = cmd->device->host;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
 	switch (cmd->cmnd[0]) {
@@ -965,6 +969,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no);
 		cmd->result = (DID_ERROR << 16);
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1018,6 +1023,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	/* Run the coroutine if it isn't already running. */
 	/* Kick off command processing */
 	schedule_delayed_work(&hostdata->coroutine, 0);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 6961f78..b84bfe6 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -696,7 +696,10 @@ static void wait_intr(void)
 static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("NCR53c406a_queue called\n"));
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
 
@@ -723,6 +726,7 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(SELECT_NO_ATN, CMD_REG);
 
 	rtrc(1);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index dbbc601..1aa33f0 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -915,18 +915,25 @@ static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd
 {
 	struct orc_scb *scb;
 	struct orc_host *host;		/* Point to Host adapter control block */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	host = (struct orc_host *) cmd->device->host->hostdata;
 	cmd->scsi_done = done;
 	/* Get free SCSI control block  */
-	if ((scb = orc_alloc_scb(host)) == NULL)
+	if ((scb = orc_alloc_scb(host)) == NULL) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (inia100_build_scb(host, scb, cmd)) {
 		orc_release_scb(host, scb);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	orc_exec_scb(host, scb);	/* Start execute SCB            */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 29c0ed1..1736fa2 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -253,6 +253,11 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct Scsi_Host *host = cmd->device->host;
 	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	u32 count = 0;
+	unsigned long irqflags;
+	int ret;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
 		struct fib * fib = &dev->fibs[count];
@@ -260,11 +265,15 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 		if (fib->hw_fib_va->header.XferState &&
 		    ((command = fib->callback_data)) &&
 		    (command == cmd) &&
-		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
-			return 0; /* Already owned by Adapter */
+		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) {
+		    	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+		    	return 0;
+		    } /* Already owned by Adapter */
 	}
 	cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
-	return (aac_scsi_cmd(cmd) ? FAILED : 0);
+	ret = (aac_scsi_cmd(cmd) ? FAILED : 0);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+	return ret;
 }
 
 /**
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0ec3da6..cb5e7c2 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9504,7 +9504,10 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
 	struct Scsi_Host *shost = scp->device->host;
 	int asc_res, result = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	ASC_STATS(shost, queuecommand);
 	scp->scsi_done = done;
 
@@ -9522,6 +9525,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 		break;
 	}
 
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return result;
 }
 
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 8eab858..055e953 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1058,6 +1058,12 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
  */
 static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
+	unsigned long irqflags;
+	int ret;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 #if 0
 	if(*SCpnt->cmnd == REQUEST_SENSE) {
 		SCpnt->result = 0;
@@ -1067,7 +1073,9 @@ static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	}
 #endif
 
-	return aha152x_internal_queue(SCpnt, NULL, 0, done);
+	ret = aha152x_internal_queue(SCpnt, NULL, 0, done);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+	return ret;
 }
 
 
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 4f785f2..f33b417 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -570,7 +570,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	int mbo;
 	struct mailbox *mb;
 	struct ccb *ccb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	DEB(int i);
 
 	mb = HOSTDATA(SCpnt->device->host)->mb;
@@ -593,6 +596,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 #endif
 		SCpnt->result = 0;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 #ifdef DEBUG
@@ -611,8 +615,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	for (i = 0; i < SCpnt->cmd_len; i++)
 		printk("%02x ", cmd[i]);
 	printk("\n");
-	if (*cmd == WRITE_10 || *cmd == WRITE_6)
-		return 0;	/* we are still testing, so *don't* write */
+	if (*cmd == WRITE_10 || *cmd == WRITE_6) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+		return 0;
+	}	/* we are still testing, so *don't* write */
 #endif
 	/* Use the outgoing mailboxes in a round-robin fashion, because this
 	   is how the host adapter will scan for them */
@@ -671,6 +677,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 		if (cptr == NULL) {
 			/* free the claimed mailbox slot */
 			HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL;
+			spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_HOST_BUSY;
 		}
 		scsi_for_each_sg(SCpnt, sg, sg_count, i) {
@@ -715,6 +722,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	} else
 		printk("aha1542_queuecommand: done can't be NULL\n");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 0107a4c..b973e15 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -331,6 +331,7 @@ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
+/* AK: Did this driver ever work? */
 static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
 	unchar direction;
@@ -341,14 +342,21 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 	dma_addr_t sg_dma;
 	struct aha1740_sg *sgptr;
 	int ecbno, nseg;
+	unsigned long irqflags;
 	DEB(int i);
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 	if(*cmd == REQUEST_SENSE) {
 		SCpnt->result = 0;
 		done(SCpnt); 
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+
 #ifdef DEBUG
 	if (*cmd == READ_10 || *cmd == WRITE_10)
 		i = xscsi2int(cmd+2);
@@ -406,6 +414,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 						   &sg_dma, GFP_ATOMIC);
 	if(SCpnt->host_scribble == NULL) {
 		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
@@ -500,6 +509,8 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 		DEB(printk("aha1740[%d] request queued.\n",ecbno));
 	} else
 		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
+
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 88ad848..93e1070 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -578,13 +578,17 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahd_softc *ahd;
 	struct	 ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 
 	cmd->scsi_done = scsi_done;
 	cmd->result = CAM_REQ_INPROG << 16;
 	rtn = ahd_linux_run_command(ahd, dev, cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index aeea7a6..198390a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -534,7 +534,10 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
 	ahc_lock(ahc, &flags);
@@ -545,6 +548,7 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	}
 	ahc_unlock(ahc, &flags);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index aee73fa..97c4efc 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10239,7 +10239,10 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
   struct aic_dev_data *aic_dev;
+  unsigned long irqflags;
 
+  spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+  scsi_cmd_get_serial(cmd->device->host, cmd);
   p = (struct aic7xxx_host *) cmd->device->host->hostdata;
 
   aic_dev = cmd->device->hostdata;  
@@ -10262,6 +10265,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
     {
       printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no,
              CTL_OF_CMD(cmd));
+      spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
       return 1;
     }
   }
@@ -10289,6 +10293,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 
   scbq_insert_tail(&p->waiting_scbs, scb);
   aic7xxx_run_waiting_queues(p);
+  spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
   return (0);
 }
 
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 05a78e5..8cddef3 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2090,6 +2090,10 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
 	int target = cmd->device->id;
 	int lun = cmd->device->lun;
 	uint8_t scsicmd = cmd->cmnd[0];
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 	cmd->result = 0;
@@ -2098,29 +2102,38 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
     			cmd->result = (DID_NO_CONNECT << 16);
 		}
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (target == 16) {
 		/* virtual device for iop message transfer */
 		arcmsr_handle_virtual_command(acb, cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (atomic_read(&acb->ccboutstandingcount) >=
-			ARCMSR_MAX_OUTSTANDING_CMD)
-		return SCSI_MLQUEUE_HOST_BUSY;
+			ARCMSR_MAX_OUTSTANDING_CMD) {
+				spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+				return SCSI_MLQUEUE_HOST_BUSY;
+			}
 	if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) {
 		printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	ccb = arcmsr_get_freeccb(acb);
-	if (!ccb)
+	if (!ccb) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	if (arcmsr_build_ccb( acb, ccb, cmd ) == FAILED) {
 		cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	arcmsr_post_ccb(acb, ccb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 918ccf8..6f1049e 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2515,7 +2515,10 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 		       void (*done)(struct scsi_cmnd *))
 {
     AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
     if (!done) {
 	/* there should be some way of rejecting errors like this without panicing... */
 	panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
@@ -2529,6 +2532,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    host->host->host_no, '0' + SCpnt->device->id);
 	SCpnt->result = DID_NO_CONNECT << 16;
 	done(SCpnt);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif
@@ -2551,6 +2555,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
 	    SCpnt->result = DID_ERROR << 16;
 	    done(SCpnt);
+	    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	    return 0;
 	}
 	local_irq_save(flags);
@@ -2558,6 +2563,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    acornscsi_kick(host);
 	local_irq_restore(flags);
     }
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 9e71ac6..8cd9311 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2203,7 +2203,10 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	fas216_log_command(info, LOG_CONNECT, SCpnt,
@@ -2237,6 +2240,7 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 	fas216_log_target(info, LOG_CONNECT, -1, "queue %s",
 		result ? "failure" : "success");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return result;
 }
 
@@ -2267,7 +2271,10 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 			   void (*done)(struct scsi_cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	/*
@@ -2307,6 +2314,7 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 
 	done(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index ab5bdda..0ec5c9d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -612,7 +612,10 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	unsigned int tmport,m;	
 	struct atp_unit *dev;
 	struct Scsi_Host *host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(req_p->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(req_p->device->host, req_p);
 	c = scmd_channel(req_p);
 	req_p->sense_buffer[0]=0;
 	scsi_set_resid(req_p, 0);
@@ -622,6 +625,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP		
 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");	
 #endif			
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -640,6 +644,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	if ((m & dev->active_id[c]) == 0) {
 		req_p->result = 0x00040000;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -651,6 +656,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #endif		
 		req_p->result = 0;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	
@@ -675,6 +681,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 		dev->quend[c]--;
 		req_p->result = 0x00020000;
 		done(req_p);	
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->quereq[c][dev->quend[c]] = req_p;
@@ -691,6 +698,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP	
 	printk("atp870u_queuecommand : exit\n");
 #endif	
+	spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index d950ee4..2796f73 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1131,17 +1131,23 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	int             rc;
 	int       sg_cnt = 0;
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	rc = fc_remote_port_chkready(rport);
 	if (rc) {
 		cmnd->result = rc;
 		done(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	sg_cnt = scsi_dma_map(cmnd);
-	if (sg_cnt < 0)
+	if (sg_cnt < 0) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	cmnd->scsi_done = done;
 
@@ -1167,6 +1173,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 		printk(KERN_WARNING "hal_io failure\n");
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		scsi_dma_unmap(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1175,6 +1182,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	bfa_ioim_start(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 out_fail_cmd:
@@ -1183,6 +1191,7 @@ out_fail_cmd:
 	if (done)
 		done(cmnd);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 54f50b0..891614a 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1086,6 +1086,10 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 	struct ScsiReqBlk *srb;
 	struct AdapterCtlBlk *acb =
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
 		cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 
@@ -1127,6 +1131,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		 * point in time.
 		 */
 		dprintkdbg(DBG_0, "queue_command: No free srb's\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1141,6 +1146,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		send_srb(acb, srb);
 	}
 	dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 complete:
@@ -1151,6 +1157,7 @@ complete:
 	 * devices.
 	 */
 	done(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 23dec00..901f952 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -427,7 +427,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 {
 	adpt_hba* pHba = NULL;
 	struct adpt_device* pDev = NULL;	/* dpt per device information */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	/*
 	 * SCSI REQUEST_SENSE commands will be executed automatically by the 
@@ -439,11 +442,13 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
 		cmd->result = (DID_OK << 16);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	pHba = (adpt_hba*)cmd->device->host->hostdata[0];
 	if (!pHba) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
 
@@ -459,6 +464,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
 		pHba->host->last_reset = jiffies;
 		pHba->host->resetting = 1;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -475,6 +481,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 			// with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
 			cmd->result = (DID_NO_CONNECT << 16);
 			cmd->scsi_done(cmd);
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 		cmd->device->hostdata = pDev;
@@ -486,8 +493,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	 * delay processing of the command until later.
 	 */
 	if (pDev->state & DPTI_DEV_RESET ) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return adpt_scsi_to_i2o(pHba, cmd, pDev);
 }
 
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index d1c3137..6761716 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1765,7 +1765,10 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	struct hostdata *ha = (struct hostdata *)shost->hostdata;
 	unsigned int i, k;
 	struct mscp *cpp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (SCpnt->host_scribble)
 		panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
 		      ha->board_name, SCpnt->serial_number, SCpnt);
@@ -1785,6 +1788,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
 	if (k == shost->can_queue) {
 		printk("%s: qcomm, no free mailbox.\n", ha->board_name);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1827,6 +1831,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	    && TLDEV(SCpnt->device->type)) {
 		ha->cp_stat[i] = READY;
 		flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 0);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1836,10 +1841,12 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 		SCpnt->host_scribble = NULL;
 		scmd_printk(KERN_INFO, SCpnt,
 			"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
 	ha->cp_stat[i] = IN_USE;
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 60886c1..72de26e 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -344,7 +344,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 	hostdata *hd;
 	struct Scsi_Host *sh;
 	struct eata_ccb *cp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	queue_counter++;
 
 	hd = HD(cmd);
@@ -421,6 +424,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 			"returning DID_BUS_BUSY, done.\n", cmd->serial_number);
 		done(cmd);
 		cp->status = FREE;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	/* FIXME: timeout */
@@ -435,6 +439,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 		"Queued base %#.4lx pid: %ld "
 		"slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq));
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index e2bc779..c70efde 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -922,10 +922,15 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct esp *esp = shost_priv(dev->host);
 	struct esp_cmd_priv *spriv;
 	struct esp_cmd_entry *ent;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ent = esp_get_ent(esp);
-	if (!ent)
+	if (!ent) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	ent->cmd = cmd;
 
@@ -938,6 +943,7 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 
 	esp_maybe_execute_command(esp);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 2ad95aa..dc61481 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1075,7 +1075,10 @@ static int fd_mcs_release(struct Scsi_Host *shpnt)
 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (in_command) {
 		panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
 	}
@@ -1119,6 +1122,7 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(0x20, Interrupt_Cntl_port);
 	outb(0x14 | PARITY_MASK, TMC_Cntl_port);	/* Start arbitration */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index e296bcc..153bb64 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1422,6 +1422,9 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
 		void (*done)(struct scsi_cmnd *))
 {
+   unsigned long irqflags;
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    if (in_command) {
       panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
    }
@@ -1466,6 +1469,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
    outb(0x20, port_base + Interrupt_Cntl);
    outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
 
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 198cbab..2e4f40b 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -360,18 +360,24 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	int sg_count;
 	unsigned long flags;
 	unsigned long ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
 	rport = starget_to_rport(scsi_target(sc->device));
 	ret = fc_remote_port_chkready(rport);
 	if (ret) {
 		sc->result = ret;
 		done(sc);
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	lp = shost_priv(sc->device->host);
-	if (lp->state != LPORT_ST_READY || !(lp->link_up))
+	if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Release host lock, use driver resource specific locks from here.
@@ -454,6 +460,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 out:
 	/* acquire host lock before returning to SCSI */
 	spin_lock(lp->host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 5a3f931..e4a3ecb 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4009,7 +4009,10 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
 {
     gdth_ha_str *ha = shost_priv(scp->device->host);
     struct gdth_cmndinfo *cmndinfo;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(scp->device->host, scp);
     TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
 
     cmndinfo = gdth_get_cmndinfo(ha);
@@ -4019,6 +4022,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
     cmndinfo->timeout_count = 0;
     cmndinfo->priority = DEFAULT_PRI;
 
+    spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
     return __gdth_queuecommand(ha, scp, cmndinfo);
 }
 
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index c5d0606..8d0f51d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1934,13 +1934,17 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	unsigned char scsi3addr[8];
 	struct CommandList *c;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	/* Get the ptr to our adapter structure out of cmd->host. */
 	h = sdev_to_hba(cmd->device);
 	dev = cmd->device->hostdata;
 	if (!dev) {
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
@@ -1951,6 +1955,7 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	spin_unlock_irqrestore(&h->lock, flags);
 	if (c == NULL) {			/* trouble... */
 		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -2013,10 +2018,12 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 
 	if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */
 		cmd_free(h, c);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 0729f15..04903e4 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -759,13 +759,17 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 	struct hpt_iop_request_scsi_command *req;
 	int sg_count = 0;
 	struct hptiop_request *_req;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	BUG_ON(!done);
 	scp->scsi_done = done;
 
 	_req = get_req(hba);
 	if (_req == NULL) {
 		dprintk("hptiop_queuecmd : no free req\n");
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -811,11 +815,13 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 
 	memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
 	hba->ops->post_req(hba, _req);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 
 cmd_done:
 	dprintk("scsi_done(scp=%p)\n", scp);
 	scp->scsi_done(scp);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 9a4b69d..65595e2 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -1703,6 +1703,10 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	int max_pun;
 	int i;
 	struct scatterlist *sg;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 	shpnt = cmd->device->host;
 
@@ -1721,6 +1725,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		cmd->result = DID_NO_CONNECT << 16;
 		if (done)
 			done(cmd);
+
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1743,6 +1749,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 					cmd->result = DID_NO_CONNECT << 16;	/* return no connect */
 					if (done)
 						done(cmd);
+
+					spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 					return 0;
 				}
 			}
@@ -1804,6 +1812,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 			cmd->result = DID_BAD_TARGET << 16;
 			if (done)
 				done(cmd);
+
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -1993,6 +2003,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
 		IBM_DS(shpnt).scbs++;
 	}
+
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 00d08b2..fb1e719 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1615,11 +1615,15 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 	struct ibmvfc_event *evt;
 	u8 tag[2];
 	int rc;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	if (unlikely((rc = fc_remote_port_chkready(rport))) ||
 	    unlikely((rc = ibmvfc_host_chkready(vhost)))) {
 		cmnd->result = rc;
 		done(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1656,12 +1660,16 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 		};
 	}
 
-	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
+	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return ibmvfc_send_event(evt, vhost, 0);
+	}
 
 	ibmvfc_free_event(evt);
-	if (rc == -ENOMEM)
+	if (rc == -ENOMEM) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
 		scmd_printk(KERN_ERR, cmnd,
@@ -1669,6 +1677,7 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 
 	cmnd->result = DID_ERROR << 16;
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 67f78a4..81be256 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -722,11 +722,16 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host);
 	u16 lun = lun_from_dev(cmnd->device);
 	u8 out_fmt, in_fmt;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	cmnd->result = (DID_OK << 16);
 	evt_struct = get_event_struct(&hostdata->pool);
-	if (!evt_struct)
+	if (!evt_struct) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Set up the actual SRP IU */
 	srp_cmd = &evt_struct->iu.srp.cmd;
@@ -740,6 +745,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			sdev_printk(KERN_ERR, cmnd->device,
 			            "couldn't convert cmd to srp_cmd\n");
 		free_event_struct(&hostdata->pool, evt_struct);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -763,6 +769,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			offsetof(struct srp_indirect_buf, desc_list);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
 }
 
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 4734ab0..be88999 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -930,9 +930,13 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 {
 	imm_struct *dev = imm_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk("IMM: bug in imm_queuecommand\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->failed = 0;
@@ -946,6 +950,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 
 	imm_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 52bdc6d..2339bb3 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -339,7 +339,10 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance;
 	struct IN2000_hostdata *hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	instance = cmd->device->host;
 	hostdata = (struct IN2000_hostdata *) instance->hostdata;
 
@@ -428,6 +431,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	in2000_execute(cmd->device->host);
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
+	    spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	    return 0;
 }
 
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 1087977..0ef119e 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2644,15 +2644,21 @@ static int i91u_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
 	struct scsi_ctrl_blk *cmnd;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 
 	cmnd = initio_alloc_scb(host);
-	if (!cmnd)
+	if (!cmnd) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	initio_build_scb(host, cmnd, cmd);
 	initio_exec_scb(host, cmnd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index df9a12c..d0ca800 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -5717,7 +5717,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	struct ipr_ioarcb *ioarcb;
 	struct ipr_cmnd *ipr_cmd;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(&scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	scsi_cmd->scsi_done = done;
 	ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
 	res = scsi_cmd->device->hostdata;
@@ -5728,8 +5731,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	 * We have told the host to stop giving us new requests, but
 	 * ERP ops don't count. FIXME
 	 */
-	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
+	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead)) {
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * FIXME - Create scsi_set_host_offline interface
@@ -5739,11 +5744,15 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		memset(scsi_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
-	if (ipr_is_gata(res) && res->sata_port)
-		return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+	if (ipr_is_gata(res) && res->sata_port) {
+		rc = ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
+		return rc;
+	}
 
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
@@ -5786,9 +5795,11 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		ipr_send_command(ipr_cmd);
 	} else {
 		 list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+		 spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		 return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index f83a116..cd83a25 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1050,28 +1050,37 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 {
 	ips_ha_t *ha;
 	ips_passthru_t *pt;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SC->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SC->device->host, SC);
 	METHOD_TRACE("ips_queue", 1);
 
 	ha = (ips_ha_t *) SC->device->host->hostdata;
 
-	if (!ha)
+	if (!ha) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (1);
+	}
 
-	if (!ha->active)
+	if (!ha->active) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (DID_ERROR);
+	}
 
 	if (ips_is_passthru(SC)) {
 		if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
 			SC->result = DID_BUS_BUSY << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 	} else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
 		SC->result = DID_BUS_BUSY << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1089,6 +1098,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 		SC->result = DID_NO_CONNECT << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1105,12 +1115,14 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			if (ha->scb_activelist.count != 0) {
 				SC->result = DID_BUS_BUSY << 16;
 				done(SC);
+				spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 				return (0);
 			}
 			ha->ioctl_reset = 1;	/* This reset request is from an IOCTL */
 			__ips_eh_reset(SC);
 			SC->result = DID_OK << 16;
 			SC->scsi_done(SC);
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1121,6 +1133,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			SC->result = DID_ERROR << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1134,6 +1147,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 
 	ips_next(ha, IPS_INTR_IORL);
 
+	spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 	return (0);
 }
 
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index c797f6b..5a91e1d 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1763,13 +1763,17 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	int rval;
 	int rc = 0;
 	struct fcoe_dev_stats *stats;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc_cmd->device->host, sc_cmd);
 	lport = shost_priv(sc_cmd->device->host);
 
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
 		sc_cmd->result = rval;
 		done(sc_cmd);
+		spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	spin_unlock_irq(lport->host->host_lock);
@@ -1850,6 +1854,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	}
 out:
 	spin_lock_irq(lport->host->host_lock);
+	spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 EXPORT_SYMBOL(fc_queuecommand);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 633e090..444488d 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1608,6 +1608,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 	struct iscsi_task *task = NULL;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
 
 	sc->scsi_done = done;
 	sc->result = 0;
@@ -1707,6 +1711,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	session->queued_cmdsn++;
 	spin_unlock(&session->lock);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 
 prepd_reject:
@@ -1717,6 +1722,7 @@ reject:
 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
 			  sc->cmnd[0], reason);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 prepd_fault:
@@ -1734,6 +1740,7 @@ fault:
 	}
 	done(sc);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 55f09e9..28375e2 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -200,7 +200,10 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 	struct domain_device *dev = cmd_to_domain_dev(cmd);
 	struct Scsi_Host *host = cmd->device->host;
 	struct sas_internal *i = to_sas_internal(host->transportt);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_unlock_irq(host->host_lock);
 
 	{
@@ -251,6 +254,7 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 	}
 out:
 	spin_lock_irq(host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return res;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 3a65895..3828e00 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2906,6 +2906,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
 	int err;
 
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	err = fc_remote_port_chkready(rport);
 	if (err) {
 		cmnd->result = err;
@@ -3043,16 +3047,19 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 			lpfc_poll_rearm_timer(phba);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
  out_host_busy_free_buf:
 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
  out_host_busy:
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  out_fail_command:
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 3ddb4dc..37b01bd 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -82,6 +82,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	}
 #endif
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -96,6 +99,7 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	if (state->phase == idle)
 		mac53c94_start(state);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7ceb5cf..070fdd0 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -372,7 +372,10 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	scb_t	*scb;
 	int	busy=0;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	adapter = (adapter_t *)scmd->device->host->hostdata;
 
 	scmd->scsi_done = done;
@@ -406,6 +409,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	busy = 0;
  out:
 	spin_unlock_irqrestore(&adapter->lock, flags);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index a7810a1..07ade30 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1489,7 +1489,10 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	adapter_t	*adapter;
 	scb_t		*scb;
 	int		if_busy;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	adapter		= SCP2ADAPTER(scp);
 	scp->scsi_done	= done;
 	scp->result	= 0;
@@ -1506,10 +1509,12 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
 	if (!scb) {	// command already completed
 		done(scp);
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	megaraid_mbox_runpendq(adapter, scb);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return if_busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index d3c9cde..cb0b400 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1325,16 +1325,22 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	if (instance->issuepend_done == 0)
+	if (instance->issuepend_done == 0) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	spin_lock_irqsave(&instance->hba_lock, flags);
 	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
 		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1362,8 +1368,10 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	}
 
 	cmd = megasas_get_cmd(instance);
-	if (!cmd)
+	if (!cmd) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Logical drive command
@@ -1393,12 +1401,14 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 		tasklet_schedule(&instance->isr_tasklet);
 
 
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out_return_cmd:
 	megasas_return_cmd(instance, cmd);
  out_done:
 	done(scmd);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 1f784fd..93e6596 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1630,7 +1630,10 @@ static void cmd_complete(struct mesh_state *ms)
 static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct mesh_state *ms;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -1645,6 +1648,7 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	if (ms->phase == idle)
 		mesh_start(ms);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 16e99b6..e849aa2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -3323,18 +3323,23 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	Mpi2SCSIIORequest_t *mpi_request;
 	u32 mpi_control;
 	u16 smid;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	scmd->scsi_done = done;
 	sas_device_priv_data = scmd->device->hostdata;
 	if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (ioc->pci_error_recovery) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3343,19 +3348,25 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* host recovery or link resets sent via IOCTLs */
-	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
+	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	/* device busy with task management */
-	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
+	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 	/* device has been deleted */
 	else if (sas_target_priv_data->deleted) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3435,9 +3446,11 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 		    sas_device_priv_data->sas_target->handle);
 	else
 		mpt2sas_base_put_smid_default(ioc, smid);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out:
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index d013a2a..00a8b1e 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8034,7 +8034,10 @@ static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct
      struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb;
      unsigned long flags;
      int sts;
+     unsigned long irqflags;
 
+     spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+     scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG_NCR53C8XX
 printk("ncr53c8xx_queue_command\n");
 #endif
@@ -8065,6 +8068,7 @@ printk("ncr53c8xx : command successfully queued\n");
 	  sts = 0;
      }
 
+     spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
      return sts;
 }
 
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 4c1e545..42864e2 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -915,7 +915,10 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 	nsp32_target *target;
 	nsp32_lunt   *cur_lunt;
 	int ret;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND,
 		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
@@ -927,6 +930,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		data->CurrentSC = NULL;
 		SCpnt->result   = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -935,6 +939,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -943,6 +948,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "no more lun");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -975,6 +981,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_msg(KERN_ERR, "SGT fail");
 		SCpnt->result = DID_ERROR << 16;
 		nsp32_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1047,6 +1054,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_scsi_done(SCpnt);
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9326c2c..6c4277d 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -193,7 +193,10 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 	unsigned char target = scmd_id(SCpnt);
 #endif
 	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
 		"SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
 		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
@@ -206,6 +209,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
 		SCpnt->result   = DID_BAD_TARGET << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -253,6 +257,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
 		SCpnt->result   = DID_BUS_BUSY << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -261,6 +266,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 #ifdef NSP_DEBUG
 	data->CmdId++;
 #endif
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 0ae27cb..5f926bb 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -553,7 +553,10 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	int port_base = SCpnt->device->host->io_port;
 	struct sym53c500_data *data =
 	    (struct sym53c500_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("SYM53C500_queue called\n"));
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
@@ -580,6 +583,7 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	}
 	outb(SELECT_NO_ATN, port_base + CMD_REG);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 4b87657..607a3cf 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3482,7 +3482,10 @@ static int pmcraid_queuecommand(
 	struct pmcraid_cmd *cmd;
 	u32 fw_version;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	pinstance =
 		(struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
 	fw_version = be16_to_cpu(pinstance->inq_data->fw_version);
@@ -3497,12 +3500,15 @@ static int pmcraid_queuecommand(
 		pmcraid_info("IOA is dead, but queuecommand is scheduled\n");
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* If IOA reset is in progress, can't queue the commands */
-	if (pinstance->ioa_reset_in_progress)
+	if (pinstance->ioa_reset_in_progress) {
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Firmware doesn't support SYNCHRONIZE_CACHE command (0x35), complete
 	 * the command here itself with success return
@@ -3510,6 +3516,7 @@ static int pmcraid_queuecommand(
 	if (scsi_cmd->cmnd[0] == SYNCHRONIZE_CACHE) {
 		pmcraid_info("SYNC_CACHE(0x35), completing in driver itself\n");
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3518,6 +3525,7 @@ static int pmcraid_queuecommand(
 
 	if (cmd == NULL) {
 		pmcraid_err("free command block is not available\n");
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -3574,6 +3582,7 @@ static int pmcraid_queuecommand(
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 7bc2d79..8f03631 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -802,9 +802,13 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 		void (*done) (struct scsi_cmnd *))
 {
 	ppa_struct *dev = ppa_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk(KERN_ERR "PPA: bug in ppa_queuecommand\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->failed = 0;
@@ -818,6 +822,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 
 	ppa_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 92ffbb5..9cb6ad3 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -218,7 +218,10 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 	struct ps3_storage_device *dev = priv->dev;
 	unsigned char opcode;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG
 	scsi_print_command(cmd);
 #endif
@@ -257,6 +260,7 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 		cmd->scsi_done(cmd);
 	}
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index b8166ec..ca34ed1 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -733,7 +733,10 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 	struct srb *sp = (struct srb *)CMD_SP(cmd);
 	int status;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = fn;
 	sp->cmd = cmd;
 	sp->flags = 0;
@@ -753,6 +756,7 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 #else
 	status = qla1280_32bit_start_scsi(ha, sp);
 #endif
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return status;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 800ea92..2c2224e 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -538,7 +538,10 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 	srb_t *sp;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (ha->flags.eeh_busy) {
 		if (ha->flags.pci_channel_io_perm_failure)
 			cmd->result = DID_NO_CONNECT << 16;
@@ -586,6 +589,7 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	spin_lock_irq(vha->host->host_lock);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc24_host_busy_free_sp:
@@ -594,14 +598,17 @@ qc24_host_busy_free_sp:
 
 qc24_host_busy_lock:
 	spin_lock_irq(vha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc24_target_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 qc24_fail_command:
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 370d40f..568e61f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -474,7 +474,10 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 	struct iscsi_cls_session *sess = ddb_entry->sess;
 	struct srb *srb;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (test_bit(AF_EEH_BUSY, &ha->flags)) {
 		if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
 			cmd->result = DID_NO_CONNECT << 16;
@@ -499,6 +502,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 			cmd->result = DID_NO_CONNECT << 16;
 			goto qc_fail_command;
 		}
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_TARGET_BUSY;
 	}
 
@@ -522,6 +526,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 		goto qc_host_busy_free_sp;
 
 	spin_lock_irq(ha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc_host_busy_free_sp:
@@ -532,11 +537,13 @@ qc_host_busy_lock:
 	spin_lock_irq(ha->host->host_lock);
 
 qc_host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc_fail_command:
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 1ad5155..4146a5f 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -443,6 +443,9 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 			      void (*done) (struct scsi_cmnd *))
 {
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (scmd_id(cmd) == priv->qinitid) {
 		cmd->result = DID_BAD_TARGET << 16;
 		done(cmd);
@@ -456,6 +459,7 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 		cpu_relax();
 	}
 	ql_icmd(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index f8c561c..e1491e5 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1010,7 +1010,10 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 	struct Command_Entry *cmd;
 	u_int out_ptr;
 	int in_ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(Cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Cmnd->device->host, Cmnd);
 	Cmnd->scsi_done = done;
 
 	in_ptr = qpti->req_in_ptr;
@@ -1037,6 +1040,7 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 
 	update_can_queue(host, in_ptr, out_ptr);
 
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 toss_command:
@@ -1049,6 +1053,7 @@ toss_command:
 	 */
 	Cmnd->result = DID_BUS_BUSY;
 	done(Cmnd);
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 1;
 }
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 348fba0..d6d3c50 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -634,13 +634,15 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
  * Description: a serial number identifies a request for error recovery
  * and debugging purposes.  Protected by the Host_Lock of host.
  */
-static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
 	cmd->serial_number = host->cmd_serial_number++;
 	if (cmd->serial_number == 0) 
 		cmd->serial_number = host->cmd_serial_number++;
 }
 
+EXPORT_SYMBOL(scsi_cmd_get_serial);
+
 /**
  * scsi_dispatch_command - Dispatch a command to the low-level driver.
  * @cmd: command block we are dispatching.
@@ -651,7 +653,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd
 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 {
 	struct Scsi_Host *host = cmd->device->host;
-	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
 
@@ -737,15 +738,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		goto out;
 	}
 
-	spin_lock_irqsave(host->host_lock, flags);
-	/*
-	 * AK: unlikely race here: for some reason the timer could
-	 * expire before the serial number is set up below.
-	 *
-	 * TODO: kill serial or move to blk layer
-	 */
-	scsi_cmd_get_serial(host, cmd); 
-
 	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
@@ -753,7 +745,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		trace_scsi_dispatch_cmd_start(cmd);
 		rtn = host->hostt->queuecommand(cmd, scsi_done);
 	}
-	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
 		trace_scsi_dispatch_cmd_error(cmd, rtn);
 		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 9c73dbd..351872e 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -579,14 +579,19 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	unsigned int id, lun;
 	struct req_msg *req;
 	u16 tag;
+	unsigned long irqflags;
 
 	host = cmd->device->host;
+	spin_lock_irqsave(host->host_lock, irqflags);
+	scsi_cmd_get_serial(host, cmd);
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	hba = (struct st_hba *) &host->hostdata[0];
 
-	if (unlikely(hba->mu_status == MU_STATE_RESETTING))
+	if (unlikely(hba->mu_status == MU_STATE_RESETTING)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	switch (cmd->cmnd[0]) {
 	case MODE_SENSE_10:
@@ -603,6 +608,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	}
 	case REPORT_LUNS:
@@ -613,6 +620,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		 */
 		if (hba->cardtype == st_shasta || id == host->max_id - 1) {
 			stex_invalid_field(cmd, done);
+
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -620,6 +629,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (id == host->max_id - 1) {
 			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -627,6 +637,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (lun >= host->max_lun) {
 			cmd->result = DID_NO_CONNECT << 16;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		if (id != host->max_id - 1)
@@ -639,6 +650,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	case PASSTHRU_CMD:
 		if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
@@ -657,6 +669,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 				DID_OK << 16 | COMMAND_COMPLETE << 8 :
 				DID_ERROR << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 	default:
@@ -667,8 +680,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 
 	tag = cmd->request->tag;
 
-	if (unlikely(tag >= host->can_queue))
+	if (unlikely(tag >= host->can_queue)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	req = hba->alloc_rq(hba);
 
@@ -695,6 +710,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	}
 
 	hba->send(hba, req, tag);
+	spin_unlock_irqrestore(host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 713620e..82eaa21 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -914,6 +914,10 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
     SETUP_HOSTDATA(cmd->device->host);
     struct scsi_cmnd *tmp;
     unsigned long flags;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(cmd->device->host);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
     switch (cmd->cmnd[0]) {
@@ -923,6 +927,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	       H_NO(cmd));
 	cmd->result = (DID_ERROR << 16);
 	done(cmd);
+
+        spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1016,6 +1022,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	queue_main();
     else
 	NCR5380_main(NULL);
+
+    spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index e5c369b..28e24d2 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -739,7 +739,10 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	int base;
 	unsigned long flags = 0;
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* Store base register as we can have more than one controller in the system */
 	base = SCpnt->device->host->io_port;
 	current_command = SCpnt;                  /* set current command                */
@@ -758,6 +761,7 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
 	/* Now an interrupt will be generated which we will catch in out interrupt routine */
 	spin_unlock_irqrestore(&sym53c416_lock, flags);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 8b955b5..eb0734a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -511,7 +511,10 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 	struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
 	struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
 	int sts = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	memset(ucp, 0, sizeof(*ucp));
 
@@ -527,12 +530,17 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 		}
 	}
 
-	if (np->s.settle_time_valid)
+	if (np->s.settle_time_valid) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	sts = sym_queue_command(np, cmd);
-	if (sts)
+	if (sts) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 27866b0..fca1761 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -1890,7 +1890,10 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
 	struct dc390_dcb *dcb = sdev->hostdata;
 	struct dc390_srb *srb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (sdev->queue_depth <= dcb->GoingSRBCnt)
 		goto device_busy;
 	if (acb->pActiveDCB)
@@ -1935,9 +1938,11 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 
 	dc390_Going_append(dcb, srb);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
  host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  device_busy:
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 5d9fdee..2345891 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1251,7 +1251,10 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) {
 static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) {
    unsigned int i, j, k;
    struct mscp *cpp;
+   unsigned long irqflags;
 
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number;
 
@@ -1275,6 +1278,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox.\n", BN(j));
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1308,6 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
                                      && TLDEV(SCpnt->device->type)) {
       HD(j)->cp_stat[i] = READY;
       flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, FALSE);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 0;
       }
 
@@ -1316,6 +1321,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
       SCpnt->host_scribble = NULL;
       scmd_printk(KERN_INFO, SCpnt,
       		"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1326,6 +1332,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
 
    HD(j)->cp_stat[i] = IN_USE;
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 27aa40f..d3b968f 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -708,6 +708,10 @@ static int ultrastor_queuecommand(struct scsi_cmnd *SCpnt,
     int mscp_index;
 #endif
     unsigned int status;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -800,8 +804,10 @@ retry:
 #if ULTRASTOR_MAX_CMDS > 1
 	SCpnt->result = status;
 	done(SCpnt);
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 #else
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return status;
 #endif
     }
@@ -822,6 +828,7 @@ retry:
     printk("USx4F: queuecommand: returning\n");
 #endif
 
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 2689445..bfb85b0 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -696,7 +696,10 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct pvscsi_adapter *adapter = shost_priv(host);
 	struct pvscsi_ctx *ctx;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_lock_irqsave(&adapter->hw_lock, flags);
 
 	ctx = pvscsi_acquire_context(adapter, cmd);
@@ -704,6 +707,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 		if (ctx)
 			pvscsi_release_context(adapter, ctx);
 		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -716,6 +720,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	pvscsi_kick_io(adapter, cmd->cmnd[0]);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index b701bf2..d552930 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -377,7 +377,10 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct WD33C93_hostdata *hostdata;
 	struct scsi_cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
 
 	DB(DB_QUEUE_COMMAND,
@@ -464,7 +467,8 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
 
-	spin_unlock_irq(&hostdata->lock);
+	spin_unlock(&hostdata->lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 333580b..70ff71b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1092,7 +1092,10 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	short cdblen;
 	int nseg;
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	cdblen = SCpnt->cmd_len;
 	idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7);
 	SCpnt->scsi_done = done;
@@ -1136,6 +1139,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	while (!mail_out(host, scb))
 		cpu_relax();	/* keep trying */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 62882a4..7d19576 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -616,6 +616,10 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 	int i;
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 
 	DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d "
 		   "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction,
@@ -648,6 +652,8 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 		DPRINT_ERR(STORVSC_DRV, "scmnd (%p) - unable to allocate "
 			   "storvsc_cmd_request...marking queue busy", scmnd);
 		scmnd->scsi_done = NULL;
+
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
@@ -718,6 +724,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 				kmem_cache_free(host_device_ctx->request_pool,
 						cmd_request);
 
+				spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 				return SCSI_MLQUEUE_HOST_BUSY;
 			}
 
@@ -782,6 +789,7 @@ retry_request:
 		ret = SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 5a47805..7543420 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -578,7 +578,10 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 	int err = 0;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	MTS_DEBUG_GOT_HERE();
 	mts_show_command(srb);
 	mts_debug_dump(desc);
@@ -623,6 +626,7 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 
 	}
 out:
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return err;
 }
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a688b1e..f1b0aa9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -289,13 +289,17 @@ static int queuecommand(struct scsi_cmnd *srb,
 			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = host_to_us(srb->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	US_DEBUGP("%s called\n", __func__);
 
 	/* check for state-transition errors */
 	if (us->srb != NULL) {
 		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
 			__func__, us->srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -304,6 +308,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 		US_DEBUGP("Fail command during disconnect\n");
 		srb->result = DID_NO_CONNECT << 16;
 		done(srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -312,6 +317,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 	us->srb = srb;
 	complete(&us->cmnd_ready);
 
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 2054b1e..d00db31 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -440,11 +440,16 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 	struct uas_dev_info *devinfo = sdev->hostdata;
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	int err;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+	if (!cmdinfo->sense_urb && sdev->current_cmnd) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 
 	if (blk_rq_tagged(cmnd->request)) {
 		cmdinfo->stream = cmnd->request->tag + 1;
@@ -480,6 +485,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		/* If we did nothing, give up now */
 		if (cmdinfo->state & SUBMIT_SENSE_URB) {
 			usb_free_urb(cmdinfo->sense_urb);
+			spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		}
 		spin_lock(&uas_work_lock);
@@ -488,6 +494,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		schedule_work(&uas_work);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d0a6a84..99a2da7 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -881,5 +881,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
 extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
+extern void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd);
 
 #endif /* _SCSI_SCSI_HOST_H */

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 17:57           ` Andi Kleen
@ 2010-11-01 18:42             ` Jeff Garzik
  2010-11-02 15:05               ` Andi Kleen
  2010-11-01 18:59             ` Jeff Garzik
  1 sibling, 1 reply; 26+ messages in thread
From: Jeff Garzik @ 2010-11-01 18:42 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi

On 11/01/2010 01:57 PM, Andi Kleen wrote:
> ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6 hostlock2

FYI there is a merge conflict, when pulling this into current upstream:

 From ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6
  * branch            hostlock2  -> FETCH_HEAD
Auto-merging drivers/scsi/bfa/bfad_im.c
Auto-merging drivers/scsi/gdth.c
Auto-merging drivers/scsi/ipr.c
Auto-merging drivers/scsi/libfc/fc_fcp.c
Auto-merging drivers/scsi/lpfc/lpfc_scsi.c
Auto-merging drivers/scsi/megaraid/megaraid_sas.c
Auto-merging drivers/scsi/pmcraid.c
Auto-merging drivers/scsi/qla2xxx/qla_os.c
CONFLICT (content): Merge conflict in drivers/scsi/qla2xxx/qla_os.c
Auto-merging drivers/scsi/qla4xxx/ql4_os.c
Auto-merging drivers/staging/hv/storvsc_drv.c
Auto-merging net/core/sock.c
Automatic merge failed; fix conflicts and then commit the result.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 17:57           ` Andi Kleen
  2010-11-01 18:42             ` Jeff Garzik
@ 2010-11-01 18:59             ` Jeff Garzik
  2010-11-01 21:06               ` Nicholas A. Bellinger
  2010-11-02  9:21               ` Andi Kleen
  1 sibling, 2 replies; 26+ messages in thread
From: Jeff Garzik @ 2010-11-01 18:59 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi,
	Linux IDE mailing list

On 11/01/2010 01:57 PM, Andi Kleen wrote:
> @@ -3186,11 +3186,14 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done
>         struct ata_device *dev;
>         struct scsi_device *scsidev = cmd->device;
>         struct Scsi_Host *shost = scsidev->host;
> +       unsigned long irqflags;
>         int rc = 0;
>
>         ap = ata_shost_to_port(shost);
>
> -       spin_unlock(shost->host_lock);
> +       spin_lock_irqsave(shost->host_lock, irqflags);
> +       scsi_cmd_get_serial(shost, cmd);
> +
>         spin_lock(ap->lock);
>
>         ata_scsi_dump_cdb(ap, cmd);
> @@ -3205,6 +3208,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(
>
>         spin_unlock(ap->lock);
>         spin_lock(shost->host_lock);
> +       spin_unlock_irqrestore(shost->host_lock, irqflags);
>         return rc;
>  }
>

It's a bit disappointing that libata's lock profile in this patch is 
quite different than that of current upstream: with your patch, libata 
holds the scsi host lock for a considerably longer period of time, while 
also holding the ATA port/host spinlock.

IOW, it's doing the exact opposite of what the previous code did 
(release the scsi host lock, before acquiring the ATA port/host 
spinlock), not at all an equivalent transformation.

The following sequence would seem to better preserve the existing lock 
profile, correct?

	local_irq_save(flags)

	spin_lock(shost->host_lock)
	scsi_cmd_get_serial()
	spin_unlock(shost->host_lock)

	spin_lock(ap->lock)
	...
	spin_unlock(ap->lock)

	local_irq_restore(flags)

Regards,

	Jeff



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 18:59             ` Jeff Garzik
@ 2010-11-01 21:06               ` Nicholas A. Bellinger
  2010-11-02  9:21               ` Andi Kleen
  1 sibling, 0 replies; 26+ messages in thread
From: Nicholas A. Bellinger @ 2010-11-01 21:06 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley,
	linux-scsi, Linux IDE mailing list

On Mon, 2010-11-01 at 14:59 -0400, Jeff Garzik wrote:
> On 11/01/2010 01:57 PM, Andi Kleen wrote:
> > @@ -3186,11 +3186,14 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done
> >         struct ata_device *dev;
> >         struct scsi_device *scsidev = cmd->device;
> >         struct Scsi_Host *shost = scsidev->host;
> > +       unsigned long irqflags;
> >         int rc = 0;
> >
> >         ap = ata_shost_to_port(shost);
> >
> > -       spin_unlock(shost->host_lock);
> > +       spin_lock_irqsave(shost->host_lock, irqflags);
> > +       scsi_cmd_get_serial(shost, cmd);
> > +
> >         spin_lock(ap->lock);
> >
> >         ata_scsi_dump_cdb(ap, cmd);
> > @@ -3205,6 +3208,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(
> >
> >         spin_unlock(ap->lock);
> >         spin_lock(shost->host_lock);
> > +       spin_unlock_irqrestore(shost->host_lock, irqflags);
> >         return rc;
> >  }
> >
> 
> It's a bit disappointing that libata's lock profile in this patch is 
> quite different than that of current upstream: with your patch, libata 
> holds the scsi host lock for a considerably longer period of time, while 
> also holding the ATA port/host spinlock.
> 
> IOW, it's doing the exact opposite of what the previous code did 
> (release the scsi host lock, before acquiring the ATA port/host 
> spinlock), not at all an equivalent transformation.
> 
> The following sequence would seem to better preserve the existing lock 
> profile, correct?
> 
> 	local_irq_save(flags)
> 
> 	spin_lock(shost->host_lock)
> 	scsi_cmd_get_serial()
> 	spin_unlock(shost->host_lock)
> 
> 	spin_lock(ap->lock)
> 	...
> 	spin_unlock(ap->lock)
> 
> 	local_irq_restore(flags)
> 

Hmmmmm yes..   Along with Andi's generated patches I think we should
strongly consider including the atomic_t Scsi_Host->cmd_serial_number
patch here as well for scsi_cmd_get_serial() (which needs EXPORT_SYMBOL)

http://git.kernel.org/?p=linux/kernel/git/nab/lio-4.0.git;a=commitdiff;h=c047a53c52ee6c90daf048b045750e18173fd011#patch68
http://git.kernel.org/?p=linux/kernel/git/nab/lio-4.0.git;a=commitdiff;h=c047a53c52ee6c90daf048b045750e18173fd011#patch37
http://git.kernel.org/?p=linux/kernel/git/nab/lio-4.0.git;a=commitdiff;h=c047a53c52ee6c90daf048b045750e18173fd011#patch82

This ends up being a very simple change, and would allow libata to
immediately go host_lock less for scsi_cmd_dispatch() operation.

FYI, the current scoreboard for the global push down is available in
lio-core-4.0.git/host_lock-less-for-37-v9 at the top of the above
commit..  I think Andi is missing a few LLDs outside of /drivers/scsi/

Best,

--nab



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 18:59             ` Jeff Garzik
  2010-11-01 21:06               ` Nicholas A. Bellinger
@ 2010-11-02  9:21               ` Andi Kleen
  2010-11-02 15:59                 ` Jeff Garzik
  1 sibling, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2010-11-02  9:21 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley, nab,
	linux-scsi, Linux IDE mailing list

> It's a bit disappointing that libata's lock profile in this patch is
> quite different than that of current upstream: with your patch,
> libata holds the scsi host lock for a considerably longer period of
> time, while also holding the ATA port/host spinlock.

The goal here is not really what comes out of this patch,
but dropping the host lock completely. This is just the first step.

> 
> IOW, it's doing the exact opposite of what the previous code did
> (release the scsi host lock, before acquiring the ATA port/host
> spinlock), not at all an equivalent transformation.
> 
> The following sequence would seem to better preserve the existing
> lock profile, correct?

Possibly, but it's not a mechanic change.

-Andi


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-01 18:42             ` Jeff Garzik
@ 2010-11-02 15:05               ` Andi Kleen
  0 siblings, 0 replies; 26+ messages in thread
From: Andi Kleen @ 2010-11-02 15:05 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley, nab,
	linux-scsi

On Mon, Nov 01, 2010 at 02:42:20PM -0400, Jeff Garzik wrote:
> On 11/01/2010 01:57 PM, Andi Kleen wrote:
> >ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6 hostlock2
> 
> FYI there is a merge conflict, when pulling this into current upstream:


Good catch. I pushed out a new tree latest with Linus' latest.
Pull and patch appended again.

-Andi


The following changes since commit 7fe19da4ca38fc20cdbc7020fcf2eca8fc756410:

  preempt: fix kernel build with !CONFIG_BKL (2010-11-02 08:39:13 -0400)

are available in the git repository at:
  ssh://master.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc-2.6 hostlock2

Andi Kleen (2):
      SCSI: The great hostlock pushdown
      SCSI: aha1740: Avoid instant deadlock

 Documentation/scsi/scsi_mid_low_api.txt |    8 ++++++--
 arch/ia64/hp/sim/simscsi.c              |    7 +++++++
 drivers/ata/libata-scsi.c               |    6 +++++-
 drivers/block/cciss_scsi.c              |    6 ++++++
 drivers/firewire/sbp2.c                 |    6 ++++++
 drivers/infiniband/ulp/srp/ib_srp.c     |    6 ++++++
 drivers/message/fusion/mptfc.c          |    7 +++++++
 drivers/message/fusion/mptsas.c         |    9 ++++++++-
 drivers/message/fusion/mptspi.c         |    6 ++++++
 drivers/message/i2o/i2o_scsi.c          |    5 +++++
 drivers/s390/scsi/zfcp_scsi.c           |    8 ++++++++
 drivers/scsi/3w-9xxx.c                  |    4 ++++
 drivers/scsi/3w-sas.c                   |    4 ++++
 drivers/scsi/3w-xxxx.c                  |    4 ++++
 drivers/scsi/53c700.c                   |    7 +++++++
 drivers/scsi/BusLogic.c                 |    7 +++++++
 drivers/scsi/NCR5380.c                  |    6 ++++++
 drivers/scsi/NCR53c406a.c               |    4 ++++
 drivers/scsi/a100u2w.c                  |    9 ++++++++-
 drivers/scsi/aacraid/linit.c            |   15 ++++++++++++---
 drivers/scsi/advansys.c                 |    4 ++++
 drivers/scsi/aha152x.c                  |   10 +++++++++-
 drivers/scsi/aha1542.c                  |   12 ++++++++++--
 drivers/scsi/aha1740.c                  |   11 +++++++++++
 drivers/scsi/aic7xxx/aic79xx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx/aic7xxx_osm.c      |    4 ++++
 drivers/scsi/aic7xxx_old.c              |    5 +++++
 drivers/scsi/arcmsr/arcmsr_hba.c        |   19 ++++++++++++++++---
 drivers/scsi/arm/acornscsi.c            |    6 ++++++
 drivers/scsi/arm/fas216.c               |    8 ++++++++
 drivers/scsi/atp870u.c                  |    8 ++++++++
 drivers/scsi/bfa/bfad_im.c              |   11 ++++++++++-
 drivers/scsi/dc395x.c                   |    7 +++++++
 drivers/scsi/dpt_i2o.c                  |    9 +++++++++
 drivers/scsi/eata.c                     |    7 +++++++
 drivers/scsi/eata_pio.c                 |    5 +++++
 drivers/scsi/esp_scsi.c                 |    8 +++++++-
 drivers/scsi/fd_mcs.c                   |    4 ++++
 drivers/scsi/fdomain.c                  |    4 ++++
 drivers/scsi/fnic/fnic_scsi.c           |    9 ++++++++-
 drivers/scsi/gdth.c                     |    4 ++++
 drivers/scsi/hpsa.c                     |    7 +++++++
 drivers/scsi/hptiop.c                   |    6 ++++++
 drivers/scsi/ibmmca.c                   |   12 ++++++++++++
 drivers/scsi/ibmvscsi/ibmvfc.c          |   13 +++++++++++--
 drivers/scsi/ibmvscsi/ibmvscsi.c        |    9 ++++++++-
 drivers/scsi/imm.c                      |    5 +++++
 drivers/scsi/in2000.c                   |    4 ++++
 drivers/scsi/initio.c                   |    8 +++++++-
 drivers/scsi/ipr.c                      |   17 ++++++++++++++---
 drivers/scsi/ips.c                      |   18 ++++++++++++++++--
 drivers/scsi/libfc/fc_fcp.c             |    5 +++++
 drivers/scsi/libiscsi.c                 |    7 +++++++
 drivers/scsi/libsas/sas_scsi_host.c     |    4 ++++
 drivers/scsi/lpfc/lpfc_scsi.c           |    7 +++++++
 drivers/scsi/mac53c94.c                 |    4 ++++
 drivers/scsi/megaraid.c                 |    4 ++++
 drivers/scsi/megaraid/megaraid_mbox.c   |    5 +++++
 drivers/scsi/megaraid/megaraid_sas.c    |   14 ++++++++++++--
 drivers/scsi/mesh.c                     |    4 ++++
 drivers/scsi/mpt2sas/mpt2sas_scsih.c    |   17 +++++++++++++++--
 drivers/scsi/ncr53c8xx.c                |    4 ++++
 drivers/scsi/nsp32.c                    |    8 ++++++++
 drivers/scsi/pcmcia/nsp_cs.c            |    6 ++++++
 drivers/scsi/pcmcia/sym53c500_cs.c      |    4 ++++
 drivers/scsi/pmcraid.c                  |   11 ++++++++++-
 drivers/scsi/ppa.c                      |    5 +++++
 drivers/scsi/ps3rom.c                   |    4 ++++
 drivers/scsi/qla1280.c                  |    4 ++++
 drivers/scsi/qla2xxx/qla_os.c           |    7 +++++++
 drivers/scsi/qla4xxx/ql4_os.c           |    7 +++++++
 drivers/scsi/qlogicfas408.c             |    4 ++++
 drivers/scsi/qlogicpti.c                |    5 +++++
 drivers/scsi/scsi.c                     |   15 +++------------
 drivers/scsi/stex.c                     |   20 ++++++++++++++++++--
 drivers/scsi/sun3_NCR5380.c             |    8 ++++++++
 drivers/scsi/sym53c416.c                |    4 ++++
 drivers/scsi/sym53c8xx_2/sym_glue.c     |   12 ++++++++++--
 drivers/scsi/tmscsim.c                  |    5 +++++
 drivers/scsi/u14-34f.c                  |    7 +++++++
 drivers/scsi/ultrastor.c                |    7 +++++++
 drivers/scsi/vmw_pvscsi.c               |    5 +++++
 drivers/scsi/wd33c93.c                  |    6 +++++-
 drivers/scsi/wd7000.c                   |    4 ++++
 drivers/staging/hv/storvsc_drv.c        |    8 ++++++++
 drivers/usb/image/microtek.c            |    4 ++++
 drivers/usb/storage/scsiglue.c          |    6 ++++++
 drivers/usb/storage/uas.c               |    9 ++++++++-
 include/scsi/scsi_host.h                |    1 +
 89 files changed, 604 insertions(+), 49 deletions(-)


>From 3e8b6ea8f4ad49f820f4cf7a1be28a8f71e9cfc0 Mon Sep 17 00:00:00 2001
From: Andi Kleen <ak@linux.intel.com>
Date: Thu, 28 Oct 2010 12:02:20 +0200
Subject: [PATCH] SCSI: The great hostlock pushdown

This patch globally pushes down the host_lock taking and the
serial number setup into SCSI driver's queuecommand

This is all done in a global atomic patchkit to allow bisectability.

This is just a dumb pushdown, no real improvements in scalability.
Since it is very mechanic some of the resulting code immediately
takes and then drops the lock. This can be addressed in future
patches.

The driver changes follow this semantic patch:

@ rule1 @
struct scsi_host_template t;
identifier qc;
@@
t.queuecommand = qc;

@@
identifier rule1.qc;
identifier cmnd;
expression E, E2;
statement S, S2;
typedef Scsi_Cmnd;
@@
int qc(Scsi_Cmnd *cmnd, ...)
{
	... when != S
+	unsigned long irqflags;

+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
(
	if (...) {
		...
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
		return E2;
	}
|
	S2
)
	...
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
	return E;
}

@@
identifier rule1.qc;
identifier cmnd;
expression E, E2;
statement S, S2;
@@
int qc(struct scsi_cmnd *cmnd, ...)
{
	... when != S
+	unsigned long irqflags;

+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
(
	if (...) {
		...
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
		return E2;
	}
|
	S2
)
	...
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
	return E;
}

Signed-off-by: Andi Kleen <ak@linux.intel.com>

diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 570ef2b..9dabc7f 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1087,11 +1087,15 @@ Details:
  *      non-zero return, it must not execute the command's done
  *      callback at any time.
  *
- *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
- *             and is expected to be held on return.
+ *	Locks: No locks are hold. If host_lock is needed this function
+ *	needs to take it by itself.
  *
  *      Calling context: in interrupt (soft irq) or process context
  *
+ *	When this function needs a serial number in the SCSI command
+ *	it needs to call scsi_cmd_get_serial with the lock hold
+ *	to get it. Usually it's not needed.
+ *
  *      Notes: This function should be relatively fast. Normally it will
  *      not wait for IO to complete. Hence the 'done' callback is invoked 
  *      (often directly from an interrupt service routine) some time after
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index 3a078ad..ce32f2c 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -209,6 +209,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	size_t disk_size;
 	char *buf;
 	char localbuf[36];
+	unsigned long irqflags;
+
 #if DEBUG_SIMSCSI
 	register long sp asm ("sp");
 
@@ -217,6 +219,9 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 		       target_id, sc->cmnd[0], sc->serial_number, sp, done);
 #endif
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host);
+
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
 	if (target_id <= 15 && sc->device->lun == 0) {
@@ -323,6 +328,8 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN;
 
 	tasklet_schedule(&simscsi_tasklet);
+
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d050e07..3e2f3e3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3186,11 +3186,14 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct ata_device *dev;
 	struct scsi_device *scsidev = cmd->device;
 	struct Scsi_Host *shost = scsidev->host;
+	unsigned long irqflags;
 	int rc = 0;
 
 	ap = ata_shost_to_port(shost);
 
-	spin_unlock(shost->host_lock);
+	spin_lock_irqsave(shost->host_lock, irqflags);
+	scsi_cmd_get_serial(shost, cmd);
+
 	spin_lock(ap->lock);
 
 	ata_scsi_dump_cdb(ap, cmd);
@@ -3205,6 +3208,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	spin_unlock(ap->lock);
 	spin_lock(shost->host_lock);
+	spin_unlock_irqrestore(shost->host_lock, irqflags);
 	return rc;
 }
 
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 575495f..4122788 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1413,9 +1413,12 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 	unsigned char scsi3addr[8];
 	CommandList_struct *c;
 	unsigned long flags;
+	unsigned long irqflags;
 
 	// Get the ptr to our adapter structure (hba[i]) out of cmd->host.
 	// We violate cmd->host privacy here.  (Is there another way?)
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	h = (ctlr_info_t *) cmd->device->host->hostdata[0];
 
 	rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
@@ -1427,6 +1430,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		done(cmd);
 		/* we might want to think about registering controller itself
 		   as a processor device on the bus so sg binds to it. */
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1441,6 +1445,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 		/* FIXME: next 3 lines are -> BAD! <- */
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1501,6 +1506,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
 	cciss_scatter_gather(h, c, cmd);
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index bfae4b3..23266fc 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1474,21 +1474,26 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	struct fw_device *device = target_device(lu->tgt);
 	struct sbp2_command_orb *orb;
 	int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
+	unsigned long irqflags;
 
 	/*
 	 * Bidirectional commands are not yet implemented, and unknown
 	 * transfer direction not handled.
 	 */
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
 		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
 	if (orb == NULL) {
 		fw_notify("failed to alloc orb\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1531,6 +1536,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	retval = 0;
  out:
 	kref_put(&orb->base.kref, free_orb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return retval;
 }
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index cfc1d65..52c9d2e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1132,7 +1132,10 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	struct srp_cmd *cmd;
 	struct ib_device *dev;
 	int len;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 	if (target->state == SRP_TARGET_CONNECTING)
 		goto err;
 
@@ -1140,6 +1143,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
 		done(scmnd);
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1187,12 +1191,14 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 
 	list_move_tail(&req->list, &target->req_queue);
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return 0;
 
 err_unmap:
 	srp_unmap_data(scmnd, target, req);
 
 err:
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index e15220f..6e5a2b0 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -656,10 +656,14 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -667,6 +671,7 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(err)) {
 		SCpnt->result = err;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -675,9 +680,11 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if (unlikely(!ri)) {
 		SCpnt->result = DID_IMM_RETRY << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 83a5115..7e9fcf5 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1894,22 +1894,29 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	MPT_SCSI_HOST	*hd;
 	MPT_ADAPTER	*ioc;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	hd = shost_priv(SCpnt->device->host);
 	ioc = hd->ioc;
 
-	if (ioc->sas_discovery_quiesce_io)
+	if (ioc->sas_discovery_quiesce_io) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (ioc->debug_level & MPT_DEBUG_SCSI)
 		scsi_print_command(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 0e28031..2a75e9a 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -785,10 +785,14 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host);
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
 	MPT_ADAPTER *ioc = hd->ioc;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (!vdevice || !vdevice->vtarget) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -796,12 +800,14 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 		mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (spi_dv_pending(scsi_target(SCpnt->device)))
 		ddvprintk(ioc, scsi_print_command(SCpnt));
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return mptscsih_qcmd(SCpnt,done);
 }
 
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index ea6b219..21056dd 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -527,6 +527,9 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	/*
 	 *      Do the incoming paperwork
 	 */
+	unsigned long irqflags;
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	i2o_dev = SCpnt->device->hostdata;
 
 	SCpnt->scsi_done = done;
@@ -680,6 +683,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 
 	osm_debug("Issued %ld\n", SCpnt->serial_number);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 
       nomem:
@@ -687,6 +691,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	i2o_msg_nop(c, msg);
 
       exit:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return rc;
 };
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 50286d8..c28e5fe 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -83,6 +83,10 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
 	int    status, scsi_result, ret;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scpnt->device->host, scpnt);
 
 	/* reset the status for this request */
 	scpnt->result = 0;
@@ -94,6 +98,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		scpnt->result = scsi_result;
 		zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt);
 		scpnt->scsi_done(scpnt);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -104,6 +109,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		/* only LUN access denied, but port is good
 		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -115,10 +121,12 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
 		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
+		spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	ret = zfcp_fsf_fcp_cmnd(scpnt);
+	spin_unlock_irqrestore(scpnt->device->host->host_lock, irqflags);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	else if (unlikely(ret < 0))
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index fcf08b3..3ad0f51 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1769,7 +1769,10 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1809,6 +1812,7 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twa_scsi_queue() */
 
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 6a95d11..de5d845 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1505,7 +1505,10 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 {
 	int request_id, retval;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
 		retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -1533,6 +1536,7 @@ static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		retval = 0;
 	}
 out:
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End twl_scsi_queue() */
 
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index b112534..6812acc 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1953,7 +1953,10 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 	int request_id = 0;
 	int retval = 1;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* If we are resetting due to timed out ioctl, report as busy */
 	if (test_bit(TW_IN_RESET, &tw_dev->flags))
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -2020,6 +2023,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
 		done(SCpnt);
 		retval = 0;
 	}
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return retval;
 } /* End tw_scsi_queue() */
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 89fc1c8..6bd1c22 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1757,11 +1757,15 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	__u32 move_ins;
 	enum dma_data_direction direction;
 	struct NCR_700_command_slot *slot;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCp->device->host, SCp);
 	if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) {
 		/* We're over our allocation, this should never happen
 		 * since we report the max allocation to the mid layer */
 		printk(KERN_WARNING "scsi%d: Command depth has gone over queue depth\n", SCp->device->host->host_no);
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return 1;
 	}
 	/* check for untagged commands.  We cannot have any outstanding
@@ -1775,11 +1779,13 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	       || !blk_rq_tagged(SCp->request))) {
 		CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) {
 		CDEBUG(KERN_ERR, SCp, "has max tag depth %d\n",
 		       NCR_700_get_depth(SCp->device));
+		spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 	NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
@@ -1901,6 +1907,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
 				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
+	spin_unlock_irqrestore(SCp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index fc0b4b8..10ce6fb 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2819,14 +2819,19 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 	int BufferLength = scsi_bufflen(Command);
 	int Count;
 	struct BusLogic_CCB *CCB;
+	unsigned long irqflags;
 	/*
 	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
 	   Adapter for any errors, so they should not be executed explicitly unless
 	   the Sense Data is zero indicating that no error occurred.
 	 */
+
+	spin_lock_irqsave(Command->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Command->device->host, Command);
 	if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
 		Command->result = DID_OK << 16;
 		CompletionRoutine(Command);
+		spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 		return 0;
 	}
 	/*
@@ -2844,6 +2849,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB == NULL) {
 			Command->result = DID_ERROR << 16;
 			CompletionRoutine(Command);
+			spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -2991,6 +2997,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
 		if (CCB->Status == BusLogic_CCB_Completed)
 			BusLogic_ProcessCompletedCCBs(HostAdapter);
 	}
+	spin_unlock_irqrestore(Command->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 5d2f148..f4bd889 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -957,6 +957,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance = cmd->device->host;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
 	switch (cmd->cmnd[0]) {
@@ -965,6 +969,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no);
 		cmd->result = (DID_ERROR << 16);
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1018,6 +1023,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	/* Run the coroutine if it isn't already running. */
 	/* Kick off command processing */
 	schedule_delayed_work(&hostdata->coroutine, 0);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 6961f78..b84bfe6 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -696,7 +696,10 @@ static void wait_intr(void)
 static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("NCR53c406a_queue called\n"));
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
 
@@ -723,6 +726,7 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(SELECT_NO_ATN, CMD_REG);
 
 	rtrc(1);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index dbbc601..1aa33f0 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -915,18 +915,25 @@ static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd
 {
 	struct orc_scb *scb;
 	struct orc_host *host;		/* Point to Host adapter control block */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	host = (struct orc_host *) cmd->device->host->hostdata;
 	cmd->scsi_done = done;
 	/* Get free SCSI control block  */
-	if ((scb = orc_alloc_scb(host)) == NULL)
+	if ((scb = orc_alloc_scb(host)) == NULL) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (inia100_build_scb(host, scb, cmd)) {
 		orc_release_scb(host, scb);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	orc_exec_scb(host, scb);	/* Start execute SCB            */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 29c0ed1..1736fa2 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -253,6 +253,11 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct Scsi_Host *host = cmd->device->host;
 	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	u32 count = 0;
+	unsigned long irqflags;
+	int ret;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
 		struct fib * fib = &dev->fibs[count];
@@ -260,11 +265,15 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 		if (fib->hw_fib_va->header.XferState &&
 		    ((command = fib->callback_data)) &&
 		    (command == cmd) &&
-		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
-			return 0; /* Already owned by Adapter */
+		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) {
+		    	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+		    	return 0;
+		    } /* Already owned by Adapter */
 	}
 	cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
-	return (aac_scsi_cmd(cmd) ? FAILED : 0);
+	ret = (aac_scsi_cmd(cmd) ? FAILED : 0);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+	return ret;
 }
 
 /**
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0ec3da6..cb5e7c2 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9504,7 +9504,10 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
 	struct Scsi_Host *shost = scp->device->host;
 	int asc_res, result = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	ASC_STATS(shost, queuecommand);
 	scp->scsi_done = done;
 
@@ -9522,6 +9525,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 		break;
 	}
 
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return result;
 }
 
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 8eab858..055e953 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1058,6 +1058,12 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
  */
 static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
+	unsigned long irqflags;
+	int ret;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 #if 0
 	if(*SCpnt->cmnd == REQUEST_SENSE) {
 		SCpnt->result = 0;
@@ -1067,7 +1073,9 @@ static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	}
 #endif
 
-	return aha152x_internal_queue(SCpnt, NULL, 0, done);
+	ret = aha152x_internal_queue(SCpnt, NULL, 0, done);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+	return ret;
 }
 
 
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 4f785f2..f33b417 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -570,7 +570,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	int mbo;
 	struct mailbox *mb;
 	struct ccb *ccb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	DEB(int i);
 
 	mb = HOSTDATA(SCpnt->device->host)->mb;
@@ -593,6 +596,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 #endif
 		SCpnt->result = 0;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 #ifdef DEBUG
@@ -611,8 +615,10 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	for (i = 0; i < SCpnt->cmd_len; i++)
 		printk("%02x ", cmd[i]);
 	printk("\n");
-	if (*cmd == WRITE_10 || *cmd == WRITE_6)
-		return 0;	/* we are still testing, so *don't* write */
+	if (*cmd == WRITE_10 || *cmd == WRITE_6) {
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
+		return 0;
+	}	/* we are still testing, so *don't* write */
 #endif
 	/* Use the outgoing mailboxes in a round-robin fashion, because this
 	   is how the host adapter will scan for them */
@@ -671,6 +677,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 		if (cptr == NULL) {
 			/* free the claimed mailbox slot */
 			HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL;
+			spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_HOST_BUSY;
 		}
 		scsi_for_each_sg(SCpnt, sg, sg_count, i) {
@@ -715,6 +722,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	} else
 		printk("aha1542_queuecommand: done can't be NULL\n");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 0107a4c..d5486cf 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -331,6 +331,7 @@ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
+/* AK: Did this driver ever work? */
 static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
 	unchar direction;
@@ -341,11 +342,16 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 	dma_addr_t sg_dma;
 	struct aha1740_sg *sgptr;
 	int ecbno, nseg;
+	unsigned long irqflags;
 	DEB(int i);
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
+
 	if(*cmd == REQUEST_SENSE) {
 		SCpnt->result = 0;
 		done(SCpnt); 
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -364,6 +370,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 #endif
 
 	/* locate an available ecb */
+	/* AK: deadlock?!? */
 	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 	ecbno = host->last_ecb_used + 1; /* An optimization */
 	if (ecbno >= AHA1740_ECBS)
@@ -406,6 +413,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 						   &sg_dma, GFP_ATOMIC);
 	if(SCpnt->host_scribble == NULL) {
 		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
@@ -500,6 +508,8 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 		DEB(printk("aha1740[%d] request queued.\n",ecbno));
 	} else
 		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
+
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 88ad848..93e1070 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -578,13 +578,17 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahd_softc *ahd;
 	struct	 ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 
 	cmd->scsi_done = scsi_done;
 	cmd->result = CAM_REQ_INPROG << 16;
 	rtn = ahd_linux_run_command(ahd, dev, cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index aeea7a6..198390a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -534,7 +534,10 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	struct	 ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
 	ahc_lock(ahc, &flags);
@@ -545,6 +548,7 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 	}
 	ahc_unlock(ahc, &flags);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return rtn;
 }
 
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index aee73fa..97c4efc 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10239,7 +10239,10 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
   struct aic_dev_data *aic_dev;
+  unsigned long irqflags;
 
+  spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+  scsi_cmd_get_serial(cmd->device->host, cmd);
   p = (struct aic7xxx_host *) cmd->device->host->hostdata;
 
   aic_dev = cmd->device->hostdata;  
@@ -10262,6 +10265,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
     {
       printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no,
              CTL_OF_CMD(cmd));
+      spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
       return 1;
     }
   }
@@ -10289,6 +10293,7 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 
   scbq_insert_tail(&p->waiting_scbs, scb);
   aic7xxx_run_waiting_queues(p);
+  spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
   return (0);
 }
 
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 05a78e5..8cddef3 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2090,6 +2090,10 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
 	int target = cmd->device->id;
 	int lun = cmd->device->lun;
 	uint8_t scsicmd = cmd->cmnd[0];
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 	cmd->result = 0;
@@ -2098,29 +2102,38 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
     			cmd->result = (DID_NO_CONNECT << 16);
 		}
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (target == 16) {
 		/* virtual device for iop message transfer */
 		arcmsr_handle_virtual_command(acb, cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	if (atomic_read(&acb->ccboutstandingcount) >=
-			ARCMSR_MAX_OUTSTANDING_CMD)
-		return SCSI_MLQUEUE_HOST_BUSY;
+			ARCMSR_MAX_OUTSTANDING_CMD) {
+				spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
+				return SCSI_MLQUEUE_HOST_BUSY;
+			}
 	if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) {
 		printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	ccb = arcmsr_get_freeccb(acb);
-	if (!ccb)
+	if (!ccb) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	if (arcmsr_build_ccb( acb, ccb, cmd ) == FAILED) {
 		cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	arcmsr_post_ccb(acb, ccb);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 918ccf8..6f1049e 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2515,7 +2515,10 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 		       void (*done)(struct scsi_cmnd *))
 {
     AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
     if (!done) {
 	/* there should be some way of rejecting errors like this without panicing... */
 	panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
@@ -2529,6 +2532,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    host->host->host_no, '0' + SCpnt->device->id);
 	SCpnt->result = DID_NO_CONNECT << 16;
 	done(SCpnt);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif
@@ -2551,6 +2555,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
 	    SCpnt->result = DID_ERROR << 16;
 	    done(SCpnt);
+	    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	    return 0;
 	}
 	local_irq_save(flags);
@@ -2558,6 +2563,7 @@ int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
 	    acornscsi_kick(host);
 	local_irq_restore(flags);
     }
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 9e71ac6..8cd9311 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2203,7 +2203,10 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	fas216_log_command(info, LOG_CONNECT, SCpnt,
@@ -2237,6 +2240,7 @@ int fas216_queue_command(struct scsi_cmnd *SCpnt,
 	fas216_log_target(info, LOG_CONNECT, -1, "queue %s",
 		result ? "failure" : "success");
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return result;
 }
 
@@ -2267,7 +2271,10 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 			   void (*done)(struct scsi_cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	fas216_checkmagic(info);
 
 	/*
@@ -2307,6 +2314,7 @@ int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
 
 	done(SCpnt);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index ab5bdda..0ec5c9d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -612,7 +612,10 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	unsigned int tmport,m;	
 	struct atp_unit *dev;
 	struct Scsi_Host *host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(req_p->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(req_p->device->host, req_p);
 	c = scmd_channel(req_p);
 	req_p->sense_buffer[0]=0;
 	scsi_set_resid(req_p, 0);
@@ -622,6 +625,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP		
 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");	
 #endif			
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -640,6 +644,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 	if ((m & dev->active_id[c]) == 0) {
 		req_p->result = 0x00040000;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -651,6 +656,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #endif		
 		req_p->result = 0;
 		done(req_p);
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	
@@ -675,6 +681,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 		dev->quend[c]--;
 		req_p->result = 0x00020000;
 		done(req_p);	
+		spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->quereq[c][dev->quend[c]] = req_p;
@@ -691,6 +698,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
 #ifdef ED_DBGP	
 	printk("atp870u_queuecommand : exit\n");
 #endif	
+	spin_unlock_irqrestore(req_p->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 8daa716..38dac19 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1132,17 +1132,23 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	int             rc;
 	int       sg_cnt = 0;
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	rc = fc_remote_port_chkready(rport);
 	if (rc) {
 		cmnd->result = rc;
 		done(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	sg_cnt = scsi_dma_map(cmnd);
-	if (sg_cnt < 0)
+	if (sg_cnt < 0) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	cmnd->scsi_done = done;
 
@@ -1168,6 +1174,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 		printk(KERN_WARNING "hal_io failure\n");
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		scsi_dma_unmap(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1176,6 +1183,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	bfa_ioim_start(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 out_fail_cmd:
@@ -1184,6 +1192,7 @@ out_fail_cmd:
 	if (done)
 		done(cmnd);
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 54f50b0..891614a 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1086,6 +1086,10 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 	struct ScsiReqBlk *srb;
 	struct AdapterCtlBlk *acb =
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
 		cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 
@@ -1127,6 +1131,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		 * point in time.
 		 */
 		dprintkdbg(DBG_0, "queue_command: No free srb's\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1141,6 +1146,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
 		send_srb(acb, srb);
 	}
 	dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 complete:
@@ -1151,6 +1157,7 @@ complete:
 	 * devices.
 	 */
 	done(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 23dec00..901f952 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -427,7 +427,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 {
 	adpt_hba* pHba = NULL;
 	struct adpt_device* pDev = NULL;	/* dpt per device information */
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	/*
 	 * SCSI REQUEST_SENSE commands will be executed automatically by the 
@@ -439,11 +442,13 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
 		cmd->result = (DID_OK << 16);
 		cmd->scsi_done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	pHba = (adpt_hba*)cmd->device->host->hostdata[0];
 	if (!pHba) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
 
@@ -459,6 +464,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
 		pHba->host->last_reset = jiffies;
 		pHba->host->resetting = 1;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -475,6 +481,7 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 			// with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
 			cmd->result = (DID_NO_CONNECT << 16);
 			cmd->scsi_done(cmd);
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 		cmd->device->hostdata = pDev;
@@ -486,8 +493,10 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 	 * delay processing of the command until later.
 	 */
 	if (pDev->state & DPTI_DEV_RESET ) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return FAILED;
 	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return adpt_scsi_to_i2o(pHba, cmd, pDev);
 }
 
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index d1c3137..6761716 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1765,7 +1765,10 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	struct hostdata *ha = (struct hostdata *)shost->hostdata;
 	unsigned int i, k;
 	struct mscp *cpp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (SCpnt->host_scribble)
 		panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
 		      ha->board_name, SCpnt->serial_number, SCpnt);
@@ -1785,6 +1788,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
 	if (k == shost->can_queue) {
 		printk("%s: qcomm, no free mailbox.\n", ha->board_name);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
@@ -1827,6 +1831,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 	    && TLDEV(SCpnt->device->type)) {
 		ha->cp_stat[i] = READY;
 		flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 0);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1836,10 +1841,12 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 		SCpnt->host_scribble = NULL;
 		scmd_printk(KERN_INFO, SCpnt,
 			"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 1;
 	}
 
 	ha->cp_stat[i] = IN_USE;
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 60886c1..72de26e 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -344,7 +344,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 	hostdata *hd;
 	struct Scsi_Host *sh;
 	struct eata_ccb *cp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	queue_counter++;
 
 	hd = HD(cmd);
@@ -421,6 +424,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 			"returning DID_BUS_BUSY, done.\n", cmd->serial_number);
 		done(cmd);
 		cp->status = FREE;
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	/* FIXME: timeout */
@@ -435,6 +439,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 		"Queued base %#.4lx pid: %ld "
 		"slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq));
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index e2bc779..c70efde 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -922,10 +922,15 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 	struct esp *esp = shost_priv(dev->host);
 	struct esp_cmd_priv *spriv;
 	struct esp_cmd_entry *ent;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	ent = esp_get_ent(esp);
-	if (!ent)
+	if (!ent) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	ent->cmd = cmd;
 
@@ -938,6 +943,7 @@ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
 
 	esp_maybe_execute_command(esp);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 2ad95aa..dc61481 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1075,7 +1075,10 @@ static int fd_mcs_release(struct Scsi_Host *shpnt)
 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	if (in_command) {
 		panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
 	}
@@ -1119,6 +1122,7 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 	outb(0x20, Interrupt_Cntl_port);
 	outb(0x14 | PARITY_MASK, TMC_Cntl_port);	/* Start arbitration */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index e296bcc..153bb64 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1422,6 +1422,9 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
 		void (*done)(struct scsi_cmnd *))
 {
+   unsigned long irqflags;
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    if (in_command) {
       panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
    }
@@ -1466,6 +1469,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
    outb(0x20, port_base + Interrupt_Cntl);
    outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
 
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 198cbab..2e4f40b 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -360,18 +360,24 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	int sg_count;
 	unsigned long flags;
 	unsigned long ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
 	rport = starget_to_rport(scsi_target(sc->device));
 	ret = fc_remote_port_chkready(rport);
 	if (ret) {
 		sc->result = ret;
 		done(sc);
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	lp = shost_priv(sc->device->host);
-	if (lp->state != LPORT_ST_READY || !(lp->link_up))
+	if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
+		spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Release host lock, use driver resource specific locks from here.
@@ -454,6 +460,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 out:
 	/* acquire host lock before returning to SCSI */
 	spin_lock(lp->host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 8411018..08a8f14 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4009,7 +4009,10 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
 {
     gdth_ha_str *ha = shost_priv(scp->device->host);
     struct gdth_cmndinfo *cmndinfo;
+    unsigned long irqflags;
 
+    spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(scp->device->host, scp);
     TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
 
     cmndinfo = gdth_get_cmndinfo(ha);
@@ -4019,6 +4022,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
     cmndinfo->timeout_count = 0;
     cmndinfo->priority = DEFAULT_PRI;
 
+    spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
     return __gdth_queuecommand(ha, scp, cmndinfo);
 }
 
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index c5d0606..8d0f51d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1934,13 +1934,17 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	unsigned char scsi3addr[8];
 	struct CommandList *c;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	/* Get the ptr to our adapter structure out of cmd->host. */
 	h = sdev_to_hba(cmd->device);
 	dev = cmd->device->hostdata;
 	if (!dev) {
 		cmd->result = DID_NO_CONNECT << 16;
 		done(cmd);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
@@ -1951,6 +1955,7 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 	spin_unlock_irqrestore(&h->lock, flags);
 	if (c == NULL) {			/* trouble... */
 		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -2013,10 +2018,12 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
 
 	if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */
 		cmd_free(h, c);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 	enqueue_cmd_and_start_io(h, c);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 0729f15..04903e4 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -759,13 +759,17 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 	struct hpt_iop_request_scsi_command *req;
 	int sg_count = 0;
 	struct hptiop_request *_req;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	BUG_ON(!done);
 	scp->scsi_done = done;
 
 	_req = get_req(hba);
 	if (_req == NULL) {
 		dprintk("hptiop_queuecmd : no free req\n");
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -811,11 +815,13 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 
 	memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
 	hba->ops->post_req(hba, _req);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 
 cmd_done:
 	dprintk("scsi_done(scp=%p)\n", scp);
 	scp->scsi_done(scp);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 9a4b69d..65595e2 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -1703,6 +1703,10 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	int max_pun;
 	int i;
 	struct scatterlist *sg;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 
 	shpnt = cmd->device->host;
 
@@ -1721,6 +1725,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		cmd->result = DID_NO_CONNECT << 16;
 		if (done)
 			done(cmd);
+
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1743,6 +1749,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 					cmd->result = DID_NO_CONNECT << 16;	/* return no connect */
 					if (done)
 						done(cmd);
+
+					spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 					return 0;
 				}
 			}
@@ -1804,6 +1812,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 			cmd->result = DID_BAD_TARGET << 16;
 			if (done)
 				done(cmd);
+
+			spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 			return 0;
 		}
 	}
@@ -1993,6 +2003,8 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
 		IBM_DS(shpnt).scbs++;
 	}
+
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 00d08b2..fb1e719 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1615,11 +1615,15 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 	struct ibmvfc_event *evt;
 	u8 tag[2];
 	int rc;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	if (unlikely((rc = fc_remote_port_chkready(rport))) ||
 	    unlikely((rc = ibmvfc_host_chkready(vhost)))) {
 		cmnd->result = rc;
 		done(cmnd);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1656,12 +1660,16 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 		};
 	}
 
-	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
+	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return ibmvfc_send_event(evt, vhost, 0);
+	}
 
 	ibmvfc_free_event(evt);
-	if (rc == -ENOMEM)
+	if (rc == -ENOMEM) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
 		scmd_printk(KERN_ERR, cmnd,
@@ -1669,6 +1677,7 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
 
 	cmnd->result = DID_ERROR << 16;
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 67f78a4..81be256 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -722,11 +722,16 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host);
 	u16 lun = lun_from_dev(cmnd->device);
 	u8 out_fmt, in_fmt;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	cmnd->result = (DID_OK << 16);
 	evt_struct = get_event_struct(&hostdata->pool);
-	if (!evt_struct)
+	if (!evt_struct) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Set up the actual SRP IU */
 	srp_cmd = &evt_struct->iu.srp.cmd;
@@ -740,6 +745,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			sdev_printk(KERN_ERR, cmnd->device,
 			            "couldn't convert cmd to srp_cmd\n");
 		free_event_struct(&hostdata->pool, evt_struct);
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -763,6 +769,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 			offsetof(struct srp_indirect_buf, desc_list);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
 }
 
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 4734ab0..be88999 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -930,9 +930,13 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 {
 	imm_struct *dev = imm_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk("IMM: bug in imm_queuecommand\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->failed = 0;
@@ -946,6 +950,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd,
 
 	imm_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 52bdc6d..2339bb3 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -339,7 +339,10 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	struct Scsi_Host *instance;
 	struct IN2000_hostdata *hostdata;
 	Scsi_Cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	instance = cmd->device->host;
 	hostdata = (struct IN2000_hostdata *) instance->hostdata;
 
@@ -428,6 +431,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	in2000_execute(cmd->device->host);
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
+	    spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	    return 0;
 }
 
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 1087977..0ef119e 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2644,15 +2644,21 @@ static int i91u_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
 	struct scsi_ctrl_blk *cmnd;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 
 	cmnd = initio_alloc_scb(host);
-	if (!cmnd)
+	if (!cmnd) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	initio_build_scb(host, cmnd, cmd);
 	initio_exec_scb(host, cmnd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fa60d7d..68b921c 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -5717,7 +5717,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	struct ipr_ioarcb *ioarcb;
 	struct ipr_cmnd *ipr_cmd;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(&scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	scsi_cmd->scsi_done = done;
 	ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
 	res = scsi_cmd->device->hostdata;
@@ -5728,8 +5731,10 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	 * We have told the host to stop giving us new requests, but
 	 * ERP ops don't count. FIXME
 	 */
-	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
+	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead)) {
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * FIXME - Create scsi_set_host_offline interface
@@ -5739,11 +5744,15 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		memset(scsi_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
-	if (ipr_is_gata(res) && res->sata_port)
-		return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+	if (ipr_is_gata(res) && res->sata_port) {
+		rc = ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+		spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
+		return rc;
+	}
 
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
@@ -5786,9 +5795,11 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 		ipr_send_command(ipr_cmd);
 	} else {
 		 list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+		 spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 		 return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(&scsi_cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index f83a116..cd83a25 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1050,28 +1050,37 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 {
 	ips_ha_t *ha;
 	ips_passthru_t *pt;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SC->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SC->device->host, SC);
 	METHOD_TRACE("ips_queue", 1);
 
 	ha = (ips_ha_t *) SC->device->host->hostdata;
 
-	if (!ha)
+	if (!ha) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (1);
+	}
 
-	if (!ha->active)
+	if (!ha->active) {
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (DID_ERROR);
+	}
 
 	if (ips_is_passthru(SC)) {
 		if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
 			SC->result = DID_BUS_BUSY << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 	} else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
 		SC->result = DID_BUS_BUSY << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1089,6 +1098,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 		SC->result = DID_NO_CONNECT << 16;
 		done(SC);
 
+		spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 		return (0);
 	}
 
@@ -1105,12 +1115,14 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			if (ha->scb_activelist.count != 0) {
 				SC->result = DID_BUS_BUSY << 16;
 				done(SC);
+				spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 				return (0);
 			}
 			ha->ioctl_reset = 1;	/* This reset request is from an IOCTL */
 			__ips_eh_reset(SC);
 			SC->result = DID_OK << 16;
 			SC->scsi_done(SC);
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1121,6 +1133,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 			SC->result = DID_ERROR << 16;
 			done(SC);
 
+			spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 			return (0);
 		}
 
@@ -1134,6 +1147,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 
 	ips_next(ha, IPS_INTR_IORL);
 
+	spin_unlock_irqrestore(SC->device->host->host_lock, irqflags);
 	return (0);
 }
 
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index e340373..a697c99 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1762,13 +1762,17 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	int rval;
 	int rc = 0;
 	struct fcoe_dev_stats *stats;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(sc_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc_cmd->device->host, sc_cmd);
 	lport = shost_priv(sc_cmd->device->host);
 
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
 		sc_cmd->result = rval;
 		done(sc_cmd);
+		spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	spin_unlock_irq(lport->host->host_lock);
@@ -1849,6 +1853,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
 	}
 out:
 	spin_lock_irq(lport->host->host_lock);
+	spin_unlock_irqrestore(sc_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 EXPORT_SYMBOL(fc_queuecommand);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 633e090..444488d 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1608,6 +1608,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 	struct iscsi_task *task = NULL;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(sc->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(sc->device->host, sc);
 
 	sc->scsi_done = done;
 	sc->result = 0;
@@ -1707,6 +1711,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 	session->queued_cmdsn++;
 	spin_unlock(&session->lock);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 
 prepd_reject:
@@ -1717,6 +1722,7 @@ reject:
 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
 			  sc->cmnd[0], reason);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 prepd_fault:
@@ -1734,6 +1740,7 @@ fault:
 	}
 	done(sc);
 	spin_lock(host->host_lock);
+	spin_unlock_irqrestore(sc->device->host->host_lock, irqflags);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 55f09e9..28375e2 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -200,7 +200,10 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 	struct domain_device *dev = cmd_to_domain_dev(cmd);
 	struct Scsi_Host *host = cmd->device->host;
 	struct sas_internal *i = to_sas_internal(host->transportt);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_unlock_irq(host->host_lock);
 
 	{
@@ -251,6 +254,7 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
 	}
 out:
 	spin_lock_irq(host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return res;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index f64b65a..0487e15 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2910,6 +2910,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
 	int err;
 
+	unsigned long irqflags;
+
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	err = fc_remote_port_chkready(rport);
 	if (err) {
 		cmnd->result = err;
@@ -3047,16 +3051,19 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 			lpfc_poll_rearm_timer(phba);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 
  out_host_busy_free_buf:
 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
  out_host_busy:
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  out_fail_command:
 	done(cmnd);
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 3ddb4dc..37b01bd 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -82,6 +82,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	}
 #endif
 
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -96,6 +99,7 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
 	if (state->phase == idle)
 		mac53c94_start(state);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7ceb5cf..070fdd0 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -372,7 +372,10 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	scb_t	*scb;
 	int	busy=0;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	adapter = (adapter_t *)scmd->device->host->hostdata;
 
 	scmd->scsi_done = done;
@@ -406,6 +409,7 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *))
 	busy = 0;
  out:
 	spin_unlock_irqrestore(&adapter->lock, flags);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index a7810a1..07ade30 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1489,7 +1489,10 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	adapter_t	*adapter;
 	scb_t		*scb;
 	int		if_busy;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scp->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scp->device->host, scp);
 	adapter		= SCP2ADAPTER(scp);
 	scp->scsi_done	= done;
 	scp->result	= 0;
@@ -1506,10 +1509,12 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 	scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
 	if (!scb) {	// command already completed
 		done(scp);
+		spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	megaraid_mbox_runpendq(adapter, scb);
+	spin_unlock_irqrestore(scp->device->host->host_lock, irqflags);
 	return if_busy;
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index eb29d50..00fce48 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1340,16 +1340,22 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	if (instance->issuepend_done == 0)
+	if (instance->issuepend_done == 0) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	spin_lock_irqsave(&instance->hba_lock, flags);
 	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
 		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -1377,8 +1383,10 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 	}
 
 	cmd = megasas_get_cmd(instance);
-	if (!cmd)
+	if (!cmd) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/*
 	 * Logical drive command
@@ -1408,12 +1416,14 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 		tasklet_schedule(&instance->isr_tasklet);
 
 
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out_return_cmd:
 	megasas_return_cmd(instance, cmd);
  out_done:
 	done(scmd);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 1f784fd..93e6596 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1630,7 +1630,10 @@ static void cmd_complete(struct mesh_state *ms)
 static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct mesh_state *ms;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -1645,6 +1648,7 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	if (ms->phase == idle)
 		mesh_start(ms);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 16e99b6..e849aa2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -3323,18 +3323,23 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	Mpi2SCSIIORequest_t *mpi_request;
 	u32 mpi_control;
 	u16 smid;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmd->device->host, scmd);
 	scmd->scsi_done = done;
 	sas_device_priv_data = scmd->device->hostdata;
 	if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	if (ioc->pci_error_recovery) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3343,19 +3348,25 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 	if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* host recovery or link resets sent via IOCTLs */
-	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
+	if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	/* device busy with task management */
-	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
+	else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) {
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 	/* device has been deleted */
 	else if (sas_target_priv_data->deleted) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
+		spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3435,9 +3446,11 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 		    sas_device_priv_data->sas_target->handle);
 	else
 		mpt2sas_base_put_smid_default(ioc, smid);
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return 0;
 
  out:
+	spin_unlock_irqrestore(scmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index d013a2a..00a8b1e 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8034,7 +8034,10 @@ static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct
      struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb;
      unsigned long flags;
      int sts;
+     unsigned long irqflags;
 
+     spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+     scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG_NCR53C8XX
 printk("ncr53c8xx_queue_command\n");
 #endif
@@ -8065,6 +8068,7 @@ printk("ncr53c8xx : command successfully queued\n");
 	  sts = 0;
      }
 
+     spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
      return sts;
 }
 
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 4c1e545..42864e2 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -915,7 +915,10 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 	nsp32_target *target;
 	nsp32_lunt   *cur_lunt;
 	int ret;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND,
 		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
@@ -927,6 +930,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		data->CurrentSC = NULL;
 		SCpnt->result   = DID_NO_CONNECT << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -935,6 +939,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -943,6 +948,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "no more lun");
 		SCpnt->result = DID_BAD_TARGET << 16;
 		done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -975,6 +981,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_msg(KERN_ERR, "SGT fail");
 		SCpnt->result = DID_ERROR << 16;
 		nsp32_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -1047,6 +1054,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 		nsp32_scsi_done(SCpnt);
 	}
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9326c2c..6c4277d 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -193,7 +193,10 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 	unsigned char target = scmd_id(SCpnt);
 #endif
 	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
 		"SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
 		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
@@ -206,6 +209,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
 		SCpnt->result   = DID_BAD_TARGET << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -253,6 +257,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 		nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
 		SCpnt->result   = DID_BUS_BUSY << 16;
 		nsp_scsi_done(SCpnt);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -261,6 +266,7 @@ static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 #ifdef NSP_DEBUG
 	data->CmdId++;
 #endif
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 0ae27cb..5f926bb 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -553,7 +553,10 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	int port_base = SCpnt->device->host->io_port;
 	struct sym53c500_data *data =
 	    (struct sym53c500_data *)SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	VDEB(printk("SYM53C500_queue called\n"));
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
@@ -580,6 +583,7 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	}
 	outb(SELECT_NO_ATN, port_base + CMD_REG);
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index cf89091..c6800eb 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3489,7 +3489,10 @@ static int pmcraid_queuecommand(
 	struct pmcraid_cmd *cmd;
 	u32 fw_version;
 	int rc = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(scsi_cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scsi_cmd->device->host, scsi_cmd);
 	pinstance =
 		(struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
 	fw_version = be16_to_cpu(pinstance->inq_data->fw_version);
@@ -3504,12 +3507,15 @@ static int pmcraid_queuecommand(
 		pmcraid_info("IOA is dead, but queuecommand is scheduled\n");
 		scsi_cmd->result = (DID_NO_CONNECT << 16);
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
 	/* If IOA reset is in progress, can't queue the commands */
-	if (pinstance->ioa_reset_in_progress)
+	if (pinstance->ioa_reset_in_progress) {
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	/* Firmware doesn't support SYNCHRONIZE_CACHE command (0x35), complete
 	 * the command here itself with success return
@@ -3517,6 +3523,7 @@ static int pmcraid_queuecommand(
 	if (scsi_cmd->cmnd[0] == SYNCHRONIZE_CACHE) {
 		pmcraid_info("SYNC_CACHE(0x35), completing in driver itself\n");
 		scsi_cmd->scsi_done(scsi_cmd);
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -3525,6 +3532,7 @@ static int pmcraid_queuecommand(
 
 	if (cmd == NULL) {
 		pmcraid_err("free command block is not available\n");
+		spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -3581,6 +3589,7 @@ static int pmcraid_queuecommand(
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, irqflags);
 	return rc;
 }
 
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 7bc2d79..8f03631 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -802,9 +802,13 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 		void (*done) (struct scsi_cmnd *))
 {
 	ppa_struct *dev = ppa_dev(cmd->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (dev->cur_cmd) {
 		printk(KERN_ERR "PPA: bug in ppa_queuecommand\n");
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return 0;
 	}
 	dev->failed = 0;
@@ -818,6 +822,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd,
 
 	ppa_pb_claim(dev);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 92ffbb5..9cb6ad3 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -218,7 +218,10 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 	struct ps3_storage_device *dev = priv->dev;
 	unsigned char opcode;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 #ifdef DEBUG
 	scsi_print_command(cmd);
 #endif
@@ -257,6 +260,7 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
 		cmd->scsi_done(cmd);
 	}
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index b8166ec..ca34ed1 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -733,7 +733,10 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 	struct srb *sp = (struct srb *)CMD_SP(cmd);
 	int status;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = fn;
 	sp->cmd = cmd;
 	sp->flags = 0;
@@ -753,6 +756,7 @@ qla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 #else
 	status = qla1280_32bit_start_scsi(ha, sp);
 #endif
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return status;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1830e6e..53bf2a6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -544,7 +544,10 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
 	srb_t *sp;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_unlock_irq(vha->host->host_lock);
 	if (ha->flags.eeh_busy) {
 		if (ha->flags.pci_channel_io_perm_failure)
@@ -588,6 +591,7 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	spin_lock_irq(vha->host->host_lock);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc24_host_busy_free_sp:
@@ -596,16 +600,19 @@ qc24_host_busy_free_sp:
 
 qc24_host_busy_lock:
 	spin_lock_irq(vha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc24_target_busy:
 	spin_lock_irq(vha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 qc24_fail_command:
 	spin_lock_irq(vha->host->host_lock);
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f4cd846..7d55b1d 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -472,7 +472,10 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 	struct iscsi_cls_session *sess = ddb_entry->sess;
 	struct srb *srb;
 	int rval;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (test_bit(AF_EEH_BUSY, &ha->flags)) {
 		if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))
 			cmd->result = DID_NO_CONNECT << 16;
@@ -497,6 +500,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 			cmd->result = DID_NO_CONNECT << 16;
 			goto qc_fail_command;
 		}
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_TARGET_BUSY;
 	}
 
@@ -520,6 +524,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
 		goto qc_host_busy_free_sp;
 
 	spin_lock_irq(ha->host->host_lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
 qc_host_busy_free_sp:
@@ -530,11 +535,13 @@ qc_host_busy_lock:
 	spin_lock_irq(ha->host->host_lock);
 
 qc_host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc_fail_command:
 	done(cmd);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 1ad5155..4146a5f 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -443,6 +443,9 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 			      void (*done) (struct scsi_cmnd *))
 {
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
+	unsigned long irqflags;
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (scmd_id(cmd) == priv->qinitid) {
 		cmd->result = DID_BAD_TARGET << 16;
 		done(cmd);
@@ -456,6 +459,7 @@ int qlogicfas408_queuecommand(struct scsi_cmnd *cmd,
 		cpu_relax();
 	}
 	ql_icmd(cmd);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index f8c561c..e1491e5 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1010,7 +1010,10 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 	struct Command_Entry *cmd;
 	u_int out_ptr;
 	int in_ptr;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(Cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(Cmnd->device->host, Cmnd);
 	Cmnd->scsi_done = done;
 
 	in_ptr = qpti->req_in_ptr;
@@ -1037,6 +1040,7 @@ static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct sc
 
 	update_can_queue(host, in_ptr, out_ptr);
 
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 0;
 
 toss_command:
@@ -1049,6 +1053,7 @@ toss_command:
 	 */
 	Cmnd->result = DID_BUS_BUSY;
 	done(Cmnd);
+	spin_unlock_irqrestore(Cmnd->device->host->host_lock, irqflags);
 	return 1;
 }
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 348fba0..d6d3c50 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -634,13 +634,15 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
  * Description: a serial number identifies a request for error recovery
  * and debugging purposes.  Protected by the Host_Lock of host.
  */
-static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
 	cmd->serial_number = host->cmd_serial_number++;
 	if (cmd->serial_number == 0) 
 		cmd->serial_number = host->cmd_serial_number++;
 }
 
+EXPORT_SYMBOL(scsi_cmd_get_serial);
+
 /**
  * scsi_dispatch_command - Dispatch a command to the low-level driver.
  * @cmd: command block we are dispatching.
@@ -651,7 +653,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd
 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 {
 	struct Scsi_Host *host = cmd->device->host;
-	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
 
@@ -737,15 +738,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		goto out;
 	}
 
-	spin_lock_irqsave(host->host_lock, flags);
-	/*
-	 * AK: unlikely race here: for some reason the timer could
-	 * expire before the serial number is set up below.
-	 *
-	 * TODO: kill serial or move to blk layer
-	 */
-	scsi_cmd_get_serial(host, cmd); 
-
 	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
@@ -753,7 +745,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		trace_scsi_dispatch_cmd_start(cmd);
 		rtn = host->hostt->queuecommand(cmd, scsi_done);
 	}
-	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
 		trace_scsi_dispatch_cmd_error(cmd, rtn);
 		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 9c73dbd..351872e 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -579,14 +579,19 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	unsigned int id, lun;
 	struct req_msg *req;
 	u16 tag;
+	unsigned long irqflags;
 
 	host = cmd->device->host;
+	spin_lock_irqsave(host->host_lock, irqflags);
+	scsi_cmd_get_serial(host, cmd);
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	hba = (struct st_hba *) &host->hostdata[0];
 
-	if (unlikely(hba->mu_status == MU_STATE_RESETTING))
+	if (unlikely(hba->mu_status == MU_STATE_RESETTING)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	switch (cmd->cmnd[0]) {
 	case MODE_SENSE_10:
@@ -603,6 +608,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	}
 	case REPORT_LUNS:
@@ -613,6 +620,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		 */
 		if (hba->cardtype == st_shasta || id == host->max_id - 1) {
 			stex_invalid_field(cmd, done);
+
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -620,6 +629,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (id == host->max_id - 1) {
 			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		break;
@@ -627,6 +637,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 		if (lun >= host->max_lun) {
 			cmd->result = DID_NO_CONNECT << 16;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 		if (id != host->max_id - 1)
@@ -639,6 +650,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 			done(cmd);
 		} else
 			stex_invalid_field(cmd, done);
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return 0;
 	case PASSTHRU_CMD:
 		if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
@@ -657,6 +669,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 				DID_OK << 16 | COMMAND_COMPLETE << 8 :
 				DID_ERROR << 16 | COMMAND_COMPLETE << 8;
 			done(cmd);
+			spin_unlock_irqrestore(host->host_lock, irqflags);
 			return 0;
 		}
 	default:
@@ -667,8 +680,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 
 	tag = cmd->request->tag;
 
-	if (unlikely(tag >= host->can_queue))
+	if (unlikely(tag >= host->can_queue)) {
+		spin_unlock_irqrestore(host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	req = hba->alloc_rq(hba);
 
@@ -695,6 +710,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 	}
 
 	hba->send(hba, req, tag);
+	spin_unlock_irqrestore(host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 713620e..82eaa21 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -914,6 +914,10 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
     SETUP_HOSTDATA(cmd->device->host);
     struct scsi_cmnd *tmp;
     unsigned long flags;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(cmd->device->host);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
     switch (cmd->cmnd[0]) {
@@ -923,6 +927,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	       H_NO(cmd));
 	cmd->result = (DID_ERROR << 16);
 	done(cmd);
+
+        spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
     }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
@@ -1016,6 +1022,8 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
 	queue_main();
     else
 	NCR5380_main(NULL);
+
+    spin_lock_irqrestore(cmd->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index e5c369b..28e24d2 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -739,7 +739,10 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	int base;
 	unsigned long flags = 0;
 	int i;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	/* Store base register as we can have more than one controller in the system */
 	base = SCpnt->device->host->io_port;
 	current_command = SCpnt;                  /* set current command                */
@@ -758,6 +761,7 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 	outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
 	/* Now an interrupt will be generated which we will catch in out interrupt routine */
 	spin_unlock_irqrestore(&sym53c416_lock, flags);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 8b955b5..eb0734a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -511,7 +511,10 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 	struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
 	struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
 	int sts = 0;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	cmd->scsi_done = done;
 	memset(ucp, 0, sizeof(*ucp));
 
@@ -527,12 +530,17 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
 		}
 	}
 
-	if (np->s.settle_time_valid)
+	if (np->s.settle_time_valid) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
 	sts = sym_queue_command(np, cmd);
-	if (sts)
+	if (sts) {
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 27866b0..fca1761 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -1890,7 +1890,10 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
 	struct dc390_dcb *dcb = sdev->hostdata;
 	struct dc390_srb *srb;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	if (sdev->queue_depth <= dcb->GoingSRBCnt)
 		goto device_busy;
 	if (acb->pActiveDCB)
@@ -1935,9 +1938,11 @@ static int DC390_queuecommand(struct scsi_cmnd *cmd,
 
 	dc390_Going_append(dcb, srb);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 
  host_busy:
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return SCSI_MLQUEUE_HOST_BUSY;
 
  device_busy:
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 5d9fdee..2345891 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1251,7 +1251,10 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) {
 static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) {
    unsigned int i, j, k;
    struct mscp *cpp;
+   unsigned long irqflags;
 
+   spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+   scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number;
 
@@ -1275,6 +1278,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox.\n", BN(j));
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1308,6 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
                                      && TLDEV(SCpnt->device->type)) {
       HD(j)->cp_stat[i] = READY;
       flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, FALSE);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 0;
       }
 
@@ -1316,6 +1321,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
       SCpnt->host_scribble = NULL;
       scmd_printk(KERN_INFO, SCpnt,
       		"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
+      spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
       return 1;
       }
 
@@ -1326,6 +1332,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
 
    HD(j)->cp_stat[i] = IN_USE;
+   spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
    return 0;
 }
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 27aa40f..d3b968f 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -708,6 +708,10 @@ static int ultrastor_queuecommand(struct scsi_cmnd *SCpnt,
     int mscp_index;
 #endif
     unsigned int status;
+    unsigned long irqflags;
+
+    spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+    scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -800,8 +804,10 @@ retry:
 #if ULTRASTOR_MAX_CMDS > 1
 	SCpnt->result = status;
 	done(SCpnt);
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 #else
+        spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return status;
 #endif
     }
@@ -822,6 +828,7 @@ retry:
     printk("USx4F: queuecommand: returning\n");
 #endif
 
+    spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
     return 0;
 }
 
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 2689445..bfb85b0 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -696,7 +696,10 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	struct pvscsi_adapter *adapter = shost_priv(host);
 	struct pvscsi_ctx *ctx;
 	unsigned long flags;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	spin_lock_irqsave(&adapter->hw_lock, flags);
 
 	ctx = pvscsi_acquire_context(adapter, cmd);
@@ -704,6 +707,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 		if (ctx)
 			pvscsi_release_context(adapter, ctx);
 		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -716,6 +720,7 @@ static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
 	pvscsi_kick_io(adapter, cmd->cmnd[0]);
 
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index b701bf2..d552930 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -377,7 +377,10 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 {
 	struct WD33C93_hostdata *hostdata;
 	struct scsi_cmnd *tmp;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmd->device->host, cmd);
 	hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
 
 	DB(DB_QUEUE_COMMAND,
@@ -464,7 +467,8 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 
 	DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
 
-	spin_unlock_irq(&hostdata->lock);
+	spin_unlock(&hostdata->lock);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 333580b..70ff71b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1092,7 +1092,10 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	short cdblen;
 	int nseg;
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(SCpnt->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(SCpnt->device->host, SCpnt);
 	cdblen = SCpnt->cmd_len;
 	idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7);
 	SCpnt->scsi_done = done;
@@ -1136,6 +1139,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
 	while (!mail_out(host, scb))
 		cpu_relax();	/* keep trying */
 
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 41d9acf..d89d132 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -614,6 +614,10 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 	int i;
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(scmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(scmnd->device->host, scmnd);
 
 	DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d "
 		   "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction,
@@ -646,6 +650,8 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 		DPRINT_ERR(STORVSC_DRV, "scmnd (%p) - unable to allocate "
 			   "storvsc_cmd_request...marking queue busy", scmnd);
 		scmnd->scsi_done = NULL;
+
+		spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
@@ -716,6 +722,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
 				kmem_cache_free(host_device_ctx->request_pool,
 						cmd_request);
 
+				spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 				return SCSI_MLQUEUE_HOST_BUSY;
 			}
 
@@ -780,6 +787,7 @@ retry_request:
 		ret = SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
+	spin_unlock_irqrestore(scmnd->device->host->host_lock, irqflags);
 	return ret;
 }
 
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 5a47805..7543420 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -578,7 +578,10 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 	int err = 0;
 	int res;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	MTS_DEBUG_GOT_HERE();
 	mts_show_command(srb);
 	mts_debug_dump(desc);
@@ -623,6 +626,7 @@ mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 
 	}
 out:
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return err;
 }
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a688b1e..f1b0aa9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -289,13 +289,17 @@ static int queuecommand(struct scsi_cmnd *srb,
 			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = host_to_us(srb->device->host);
+	unsigned long irqflags;
 
+	spin_lock_irqsave(srb->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(srb->device->host, srb);
 	US_DEBUGP("%s called\n", __func__);
 
 	/* check for state-transition errors */
 	if (us->srb != NULL) {
 		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
 			__func__, us->srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
@@ -304,6 +308,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 		US_DEBUGP("Fail command during disconnect\n");
 		srb->result = DID_NO_CONNECT << 16;
 		done(srb);
+		spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 		return 0;
 	}
 
@@ -312,6 +317,7 @@ static int queuecommand(struct scsi_cmnd *srb,
 	us->srb = srb;
 	complete(&us->cmnd_ready);
 
+	spin_unlock_irqrestore(srb->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 2054b1e..d00db31 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -440,11 +440,16 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 	struct uas_dev_info *devinfo = sdev->hostdata;
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	int err;
+	unsigned long irqflags;
 
+	spin_lock_irqsave(cmnd->device->host->host_lock, irqflags);
+	scsi_cmd_get_serial(cmnd->device->host, cmnd);
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+	if (!cmdinfo->sense_urb && sdev->current_cmnd) {
+		spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
 
 	if (blk_rq_tagged(cmnd->request)) {
 		cmdinfo->stream = cmnd->request->tag + 1;
@@ -480,6 +485,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		/* If we did nothing, give up now */
 		if (cmdinfo->state & SUBMIT_SENSE_URB) {
 			usb_free_urb(cmdinfo->sense_urb);
+			spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		}
 		spin_lock(&uas_work_lock);
@@ -488,6 +494,7 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
 		schedule_work(&uas_work);
 	}
 
+	spin_unlock_irqrestore(cmnd->device->host->host_lock, irqflags);
 	return 0;
 }
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d0a6a84..99a2da7 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -881,5 +881,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
 extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
+extern void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd);
 
 #endif /* _SCSI_SCSI_HOST_H */

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-02  9:21               ` Andi Kleen
@ 2010-11-02 15:59                 ` Jeff Garzik
  2010-11-02 17:53                   ` Andi Kleen
  0 siblings, 1 reply; 26+ messages in thread
From: Jeff Garzik @ 2010-11-02 15:59 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi,
	Linux IDE mailing list

On 11/02/2010 05:21 AM, Andi Kleen wrote:
>> IOW, it's doing the exact opposite of what the previous code did
>> (release the scsi host lock, before acquiring the ATA port/host
>> spinlock), not at all an equivalent transformation.
>>
>> The following sequence would seem to better preserve the existing
>> lock profile, correct?
>
> Possibly, but it's not a mechanic change.

Oh come on.  Anybody can run a script.  It's not a mechanical change if 
you failed to create an equivalent transformation, fail to maintain 
existing lock order, _inverting_ the existing locking.

Have you done any analysis on the correctness of this new locking?


> The goal here is not really what comes out of this patch,
> but dropping the host lock completely. This is just the first step.

That doesn't excuse lack of analysis or correctness.

Boaz' approach is OBVIOUSLY mechanical, correct and bisectable.  Yours 
is not.

	Jeff




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-02 15:59                 ` Jeff Garzik
@ 2010-11-02 17:53                   ` Andi Kleen
  2010-11-02 18:13                     ` Jeff Garzik
  2010-11-02 18:38                     ` Nicholas A. Bellinger
  0 siblings, 2 replies; 26+ messages in thread
From: Andi Kleen @ 2010-11-02 17:53 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Andi Kleen, Stefan Richter, Boaz Harrosh, James.Bottomley, nab,
	linux-scsi, Linux IDE mailing list

> Boaz' approach is OBVIOUSLY mechanical, correct and bisectable.
> Yours is not.

Sorry Jeff, but my patch has 100% the same locking order as Boaz.
The only difference is in which function it is.

-Andi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-02 17:53                   ` Andi Kleen
@ 2010-11-02 18:13                     ` Jeff Garzik
  2010-11-02 18:38                     ` Nicholas A. Bellinger
  1 sibling, 0 replies; 26+ messages in thread
From: Jeff Garzik @ 2010-11-02 18:13 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, nab, linux-scsi,
	Linux IDE mailing list

On 11/02/2010 01:53 PM, Andi Kleen wrote:
>> Boaz' approach is OBVIOUSLY mechanical, correct and bisectable.
>> Yours is not.
>
> Sorry Jeff, but my patch has 100% the same locking order as Boaz.
> The only difference is in which function it is.

Incorrect.  Please re-read your own code.

Your code eliminates the drop+reacquire of the host_lock, choosing 
instead a brand new, untested, unreviewing locking scheme of holding the 
host_lock for the entirety of libata's queuecommand run.

In contrast, Boaz' proposed pattern of adding stub functions such as

	int queuecmd_unlocked(scsi_cmd cmd, callback done)
	{
		lock_irqsave
		get serial

		call driver's existing queuecommand

		unlock_irqrestore
	}

does not change libata's locking at all, because it does not modify a 
driver's queuecommand at all.  It is obviously correct.

Or to restate another way,

	Current libata locking
	----------------------
	spin_lock_irqsave(host_lock)
	spin_unlock(host_lock)
	spin_lock(ap lock)
	...
	spin_unlock(ap lock)
	spin_lock(host_lock)
	spin_unlock_irqrestore(host_lock)


	Andi's brand new locking scheme
	(missing the release of host lock)
	----------------------------------
	spin_lock_irqsave(host_lock)
	spin_lock(ap lock)
	...
	spin_unlock(ap lock)
	spin_unlock_irqrestore(host_lock)

The two versions are quite obviously NOT equivalent in any way, because 
you have ADDED the holding of host_lock for the duration of libata's 
queuecommand.

	Jeff




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-02 17:53                   ` Andi Kleen
  2010-11-02 18:13                     ` Jeff Garzik
@ 2010-11-02 18:38                     ` Nicholas A. Bellinger
  2010-11-02 18:50                       ` Jeff Garzik
  1 sibling, 1 reply; 26+ messages in thread
From: Nicholas A. Bellinger @ 2010-11-02 18:38 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Jeff Garzik, Stefan Richter, Boaz Harrosh, James.Bottomley,
	linux-scsi, Linux IDE mailing list

On Tue, 2010-11-02 at 18:53 +0100, Andi Kleen wrote:
> > Boaz' approach is OBVIOUSLY mechanical, correct and bisectable.
> > Yours is not.
> 
> Sorry Jeff, but my patch has 100% the same locking order as Boaz.
> The only difference is in which function it is.
> 
> -Andi

Hey Guys,

Just a heads up..  I am respinning a host_lock-less-for-37-v10 that
converts to use macros following Boaz's suggesstion and Jeff's
recommendations to ensure consistency for those LLDs that we have
identified as being able to run in 'lock-less' mode.

I was hoping to have this pushed out last night but ended up getting
sidetracked.  This should be ready to go later this afternoon.

Best,

--nab


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Full hostlock pushdown available
  2010-11-02 18:38                     ` Nicholas A. Bellinger
@ 2010-11-02 18:50                       ` Jeff Garzik
  0 siblings, 0 replies; 26+ messages in thread
From: Jeff Garzik @ 2010-11-02 18:50 UTC (permalink / raw)
  To: Nicholas A. Bellinger, Andi Kleen
  Cc: Stefan Richter, Boaz Harrosh, James.Bottomley, linux-scsi,
	Linux IDE mailing list


A proper host-lock pushdown should be two one-line changes to each driver:


1) call

	DEF_SCSI_QUEUECMD_NOLCK(function name of existing queuecommand);

2) in each driver's Scsi_Host_Template, rename .queuecommand hook from

	XXX

to

	XXX_unlocked

Then define DEF_SCSI_QUEUECMD_NOLCK() macro in some common scsi header.

Simple.  Easy to review.  Obviously correct.  Fewest LOC changed.

	Jeff





^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2010-11-02 18:50 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-28 15:05 Full hostlock pushdown available Andi Kleen
2010-10-28 19:28 ` James Bottomley
2010-10-28 19:32   ` Nicholas A. Bellinger
2010-11-01 14:06     ` Andi Kleen
2010-11-01 14:29       ` James Bottomley
2010-10-28 20:10   ` Andi Kleen
2010-10-28 20:22     ` James Bottomley
2010-10-28 21:50       ` Andi Kleen
2010-10-28 22:37         ` Nicholas A. Bellinger
2010-10-31 12:22 ` Boaz Harrosh
2010-10-31 18:48   ` Stefan Richter
2010-11-01  2:34     ` Jeff Garzik
2010-11-01 13:53       ` Andi Kleen
2010-11-01 15:56         ` Jeff Garzik
2010-11-01 17:57           ` Andi Kleen
2010-11-01 18:42             ` Jeff Garzik
2010-11-02 15:05               ` Andi Kleen
2010-11-01 18:59             ` Jeff Garzik
2010-11-01 21:06               ` Nicholas A. Bellinger
2010-11-02  9:21               ` Andi Kleen
2010-11-02 15:59                 ` Jeff Garzik
2010-11-02 17:53                   ` Andi Kleen
2010-11-02 18:13                     ` Jeff Garzik
2010-11-02 18:38                     ` Nicholas A. Bellinger
2010-11-02 18:50                       ` Jeff Garzik
2010-11-01 13:54     ` Andi Kleen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.