patch-2.3.32 linux/drivers/scsi/scsi_queue.c

Next file: linux/drivers/scsi/scsi_syms.c
Previous file: linux/drivers/scsi/scsi_obsolete.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.31/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
@@ -56,14 +56,6 @@
 
 static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_queue.c,v 1.1 1997/10/21 11:16:38 eric Exp $";
 
-/*
- * Lock used to prevent more than one process from frobbing the list at the
- * same time.  FIXME(eric) - there should be separate spinlocks for each host.
- * This will reduce contention.
- */
-
-spinlock_t scsi_mlqueue_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t scsi_mlqueue_remove_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Function:    scsi_mlqueue_insert()
@@ -73,6 +65,8 @@
  * Arguments:   cmd    - command that we are adding to queue.
  *              reason - why we are inserting command to queue.
  *
+ * Lock status: Assumed that lock is not held upon entry.
+ *
  * Returns:     Nothing.
  *
  * Notes:       We do this for one of two cases.  Either the host is busy
@@ -84,8 +78,6 @@
  */
 int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
 {
-	Scsi_Cmnd *cpnt;
-	unsigned long flags;
 	struct Scsi_Host *host;
 
 	SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd));
@@ -126,12 +118,12 @@
 		 * If a host is inactive and cannot queue any commands, I don't see
 		 * how things could possibly work anyways.
 		 */
-		if (cmd->device->device_busy == 0) {
+		if (cmd->device->device_blocked == 0) {
 			if (scsi_retry_command(cmd) == 0) {
 				return 0;
 			}
 		}
-		cmd->device->device_busy = TRUE;
+		cmd->device->device_blocked = TRUE;
 		cmd->device_wait = TRUE;
 	}
 
@@ -143,142 +135,9 @@
 	cmd->bh_next = NULL;
 
 	/*
-	 * As a performance enhancement, look to see whether the list is
-	 * empty.  If it is, then we can just atomicly insert the command
-	 * in the list and return without locking.
+	 * Insert this command at the head of the queue for it's device.
+	 * It will go before all other commands that are already in the queue.
 	 */
-	if (host->pending_commands == NULL) {
-		cpnt = xchg(&host->pending_commands, cmd);
-		if (cpnt == NULL) {
-			return 0;
-		}
-		/*
-		 * Rats.  Something slipped in while we were exchanging.
-		 * Swap it back and fall through to do it the hard way.
-		 */
-		cmd = xchg(&host->pending_commands, cpnt);
-
-	}
-	/*
-	 * Next append the command to the list of pending commands.
-	 */
-	spin_lock_irqsave(&scsi_mlqueue_lock, flags);
-	for (cpnt = host->pending_commands; cpnt && cpnt->bh_next;
-	     cpnt = cpnt->bh_next) {
-		continue;
-	}
-	if (cpnt != NULL) {
-		cpnt->bh_next = cmd;
-	} else {
-		host->pending_commands = cmd;
-	}
-
-	spin_unlock_irqrestore(&scsi_mlqueue_lock, flags);
-	return 0;
-}
-
-/*
- * Function:    scsi_mlqueue_finish()
- *
- * Purpose:     Try and queue commands from the midlevel queue.
- *
- * Arguments:   host    - host that just finished a command.
- *              device  - device that just finished a command.
- *
- * Returns:     Nothing.
- *
- * Notes:       This could be called either from an interrupt context or a
- *              normal process context.
- */
-int scsi_mlqueue_finish(struct Scsi_Host *host, Scsi_Device * device)
-{
-	Scsi_Cmnd *cpnt;
-	unsigned long flags;
-	Scsi_Cmnd *next;
-	Scsi_Cmnd *prev;
-	int reason = 0;
-	int rtn;
-
-	SCSI_LOG_MLQUEUE(2, printk("scsi_mlqueue_finish starting\n"));
-	/*
-	 * First, clear the flag for the host/device.  We will then start
-	 * pushing commands through until either something else blocks, or
-	 * the queue is empty.
-	 */
-	if (host->host_blocked) {
-		reason = SCSI_MLQUEUE_HOST_BUSY;
-		host->host_blocked = FALSE;
-	}
-	if (device->device_busy) {
-		reason = SCSI_MLQUEUE_DEVICE_BUSY;
-		device->device_busy = FALSE;
-	}
-	/*
-	 * Walk the list of commands to see if there is anything we can
-	 * queue.  This probably needs to be optimized for performance at
-	 * some point.
-	 */
-	prev = NULL;
-	spin_lock_irqsave(&scsi_mlqueue_remove_lock, flags);
-	for (cpnt = host->pending_commands; cpnt; cpnt = next) {
-		next = cpnt->bh_next;
-		/*
-		 * First, see if this command is suitable for being retried now.
-		 */
-		if (reason == SCSI_MLQUEUE_HOST_BUSY) {
-			/*
-			 * The host was busy, but isn't any more.  Thus we may be
-			 * able to queue the command now, but we were waiting for
-			 * the device, then we should keep waiting.  Similarily, if
-			 * the device is now busy, we should also keep waiting.
-			 */
-			if ((cpnt->host_wait == FALSE)
-			    || (device->device_busy == TRUE)) {
-				prev = cpnt;
-				continue;
-			}
-		}
-		if (reason == SCSI_MLQUEUE_DEVICE_BUSY) {
-			/*
-			 * The device was busy, but isn't any more.  Thus we may be
-			 * able to queue the command now, but we were waiting for
-			 * the host, then we should keep waiting.  Similarily, if
-			 * the host is now busy, we should also keep waiting.
-			 */
-			if ((cpnt->device_wait == FALSE)
-			    || (host->host_blocked == TRUE)) {
-				prev = cpnt;
-				continue;
-			}
-		}
-		/*
-		 * First, remove the command from the list.
-		 */
-		if (prev == NULL) {
-			host->pending_commands = next;
-		} else {
-			prev->bh_next = next;
-		}
-		cpnt->bh_next = NULL;
-
-		rtn = scsi_retry_command(cpnt);
-
-		/*
-		 * If we got a non-zero return value, it means that the host rejected
-		 * the command.  The internal_cmnd function will have added the
-		 * command back to the end of the list, so we don't have anything
-		 * more to do here except return.
-		 */
-		if (rtn) {
-			spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
-			SCSI_LOG_MLQUEUE(1, printk("Unable to remove command %p from mlqueue\n", cpnt));
-			goto finish;
-		}
-		SCSI_LOG_MLQUEUE(1, printk("Removed command %p from mlqueue\n", cpnt));
-	}
-
-	spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
-finish:
-	SCSI_LOG_MLQUEUE(2, printk("scsi_mlqueue_finish returning\n"));
+	scsi_insert_special_cmd(cmd, 1);
 	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)