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

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

diff -u --recursive --new-file v2.3.16/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
@@ -39,19 +39,19 @@
 
 /*
  * TODO:
- *	1) Prevent multiple traversals of list to look for commands to
- *	   queue.
- *	2) Protect against multiple insertions of list at the same time.
+ *      1) Prevent multiple traversals of list to look for commands to
+ *         queue.
+ *      2) Protect against multiple insertions of list at the same time.
  * DONE:
- *	1) Set state of scsi command to a new state value for ml queue.
- *	2) Insert into queue when host rejects command.
- *	3) Make sure status code is properly passed from low-level queue func
- *	   so that internal_cmnd properly returns the right value.
- *	4) Insert into queue when QUEUE_FULL.
- *	5) Cull queue in bottom half handler.
- *	6) Check usage count prior to queue insertion.  Requeue if usage
- *	   count is 0.
- *	7) Don't send down any more commands if the host/device is busy.
+ *      1) Set state of scsi command to a new state value for ml queue.
+ *      2) Insert into queue when host rejects command.
+ *      3) Make sure status code is properly passed from low-level queue func
+ *         so that internal_cmnd properly returns the right value.
+ *      4) Insert into queue when QUEUE_FULL.
+ *      5) Cull queue in bottom half handler.
+ *      6) Check usage count prior to queue insertion.  Requeue if usage
+ *         count is 0.
+ *      7) Don't send down any more commands if the host/device is busy.
  */
 
 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 $";
@@ -61,8 +61,9 @@
  * 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;
+
+spinlock_t scsi_mlqueue_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t scsi_mlqueue_remove_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Function:    scsi_mlqueue_insert()
@@ -70,127 +71,110 @@
  * Purpose:     Insert a command in the midlevel queue.
  *
  * Arguments:   cmd    - command that we are adding to queue.
- *		reason - why we are inserting command to queue.
+ *              reason - why we are inserting command to queue.
  *
  * Returns:     Nothing.
  *
- * Notes:	We do this for one of two cases.  Either the host is busy
- *		and it cannot accept any more commands for the time being,
- *		or the device returned QUEUE_FULL and can accept no more
- *		commands.
- * Notes:	This could be called either from an interrupt context or a
- *		normal process context.
+ * Notes:       We do this for one of two cases.  Either the host is busy
+ *              and it cannot accept any more commands for the time being,
+ *              or the device returned QUEUE_FULL and can accept no more
+ *              commands.
+ * Notes:       This could be called either from an interrupt context or a
+ *              normal process context.
  */
-int
-scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
+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));
-
-    /*
-     * We are inserting the command into the ml queue.  First, we
-     * cancel the timer, so it doesn't time out.
-     */
-    scsi_delete_timer(cmd);
-
-    host = cmd->host;
-
-    /*
-     * Next, set the appropriate busy bit for the device/host.
-     */
-    if( reason == SCSI_MLQUEUE_HOST_BUSY )
-    {
-	/*
-	 * Protect against race conditions.  If the host isn't busy,
-	 * assume that something actually completed, and that we should
-	 * be able to queue a command now.  Note that there is an implicit
-	 * assumption that every host can always queue at least one command.
-	 * If a host is inactive and cannot queue any commands, I don't see
-	 * how things could possibly work anyways.
-	 */
-	if( host->host_busy == 0 )
-	{
-	    if( scsi_retry_command(cmd) == 0 )
-	    {
-		return 0;
-	    }
+	Scsi_Cmnd *cpnt;
+	unsigned long flags;
+	struct Scsi_Host *host;
+
+	SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd));
+
+	/*
+	 * We are inserting the command into the ml queue.  First, we
+	 * cancel the timer, so it doesn't time out.
+	 */
+	scsi_delete_timer(cmd);
+
+	host = cmd->host;
+
+	/*
+	 * Next, set the appropriate busy bit for the device/host.
+	 */
+	if (reason == SCSI_MLQUEUE_HOST_BUSY) {
+		/*
+		 * Protect against race conditions.  If the host isn't busy,
+		 * assume that something actually completed, and that we should
+		 * be able to queue a command now.  Note that there is an implicit
+		 * assumption that every host can always queue at least one command.
+		 * If a host is inactive and cannot queue any commands, I don't see
+		 * how things could possibly work anyways.
+		 */
+		if (host->host_busy == 0) {
+			if (scsi_retry_command(cmd) == 0) {
+				return 0;
+			}
+		}
+		host->host_blocked = TRUE;
+		cmd->host_wait = TRUE;
+	} else {
+		/*
+		 * Protect against race conditions.  If the device isn't busy,
+		 * assume that something actually completed, and that we should
+		 * be able to queue a command now.  Note that there is an implicit
+		 * assumption that every host can always queue at least one command.
+		 * 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 (scsi_retry_command(cmd) == 0) {
+				return 0;
+			}
+		}
+		cmd->device->device_busy = TRUE;
+		cmd->device_wait = TRUE;
+	}
+
+	/*
+	 * Register the fact that we own the thing for now.
+	 */
+	cmd->state = SCSI_STATE_MLQUEUE;
+	cmd->owner = SCSI_OWNER_MIDLEVEL;
+	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.
+	 */
+	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;
 	}
-
-	host->host_blocked   = TRUE;
-	cmd->host_wait       = TRUE;
-    }
-    else
-    {
-	/*
-	 * Protect against race conditions.  If the device isn't busy,
-	 * assume that something actually completed, and that we should
-	 * be able to queue a command now.  Note that there is an implicit
-	 * assumption that every host can always queue at least one command.
-	 * 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( scsi_retry_command(cmd) == 0 )
-	    {
-		return 0;
-	    }
+	if (cpnt != NULL) {
+		cpnt->bh_next = cmd;
+	} else {
+		host->pending_commands = cmd;
 	}
 
-	cmd->device->device_busy = TRUE;
-	cmd->device_wait         = TRUE;
-    }
-
-    /*
-     * Register the fact that we own the thing for now.
-     */
-    cmd->state = SCSI_STATE_MLQUEUE;
-    cmd->owner = SCSI_OWNER_MIDLEVEL;
-    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.
-     */
-    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;
+	spin_unlock_irqrestore(&scsi_mlqueue_lock, flags);
+	return 0;
 }
 
 /*
@@ -199,118 +183,102 @@
  * Purpose:     Try and queue commands from the midlevel queue.
  *
  * Arguments:   host    - host that just finished a command.
- *		device  - device 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.
+ * 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)
+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_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));
 	}
-	SCSI_LOG_MLQUEUE(1,printk("Removed command %p from mlqueue\n", cpnt));
-    }
 
-    spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
+	spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
 finish:
-    SCSI_LOG_MLQUEUE(2,printk("scsi_mlqueue_finish returning\n"));
-    return 0;
+	SCSI_LOG_MLQUEUE(2, printk("scsi_mlqueue_finish returning\n"));
+	return 0;
 }

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