From: Andrew Morton <akpm@osdl.org>

ahd_linux_queue() forgets to drop the lock on an error return path.  Fix that
up and convert the function to single-exit so it doesn't happen again.

Cc: James Bottomley <James.Bottomley@steeleye.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/scsi/aic7xxx/aic79xx_osm.c |   16 +++++++++-------
 1 files changed, 9 insertions(+), 7 deletions(-)

diff -puN drivers/scsi/aic7xxx/aic79xx_osm.c~aic79xx-deadlock-fix drivers/scsi/aic7xxx/aic79xx_osm.c
--- 25/drivers/scsi/aic7xxx/aic79xx_osm.c~aic79xx-deadlock-fix	2005-06-18 23:17:04.000000000 -0700
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm.c	2005-06-18 23:17:04.000000000 -0700
@@ -933,6 +933,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 	struct	 ahd_softc *ahd;
 	struct	 ahd_linux_device *dev;
 	u_long	 flags;
+	int	 ret = 0;
 
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 
@@ -955,8 +956,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 		ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
-		ahd_unlock(ahd, &flags);
-		return (0);
+		goto out;
 	}
 	dev = ahd_linux_get_device(ahd, cmd->device->channel,
 				   cmd->device->id, cmd->device->lun,
@@ -965,13 +965,14 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 		ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
-		ahd_unlock(ahd, &flags);
 		printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
 		       ahd_name(ahd));
-		return (0);
+		goto out;
+	}
+	if (cmd->cmd_len > MAX_CDB_LEN) {
+		ret = -EINVAL;
+		goto out;
 	}
-	if (cmd->cmd_len > MAX_CDB_LEN)
-		return (-EINVAL);
 	cmd->result = CAM_REQ_INPROG << 16;
 	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);
 	if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
@@ -979,8 +980,9 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 		dev->flags |= AHD_DEV_ON_RUN_LIST;
 		ahd_linux_run_device_queues(ahd);
 	}
+out:
 	ahd_unlock(ahd, &flags);
-	return (0);
+	return ret;
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
_