Import 2.3.18pre1
[davej-history.git] / drivers / scsi / scsi_queue.c
blob95c1cac69598bf4af40c35a49bf98676a8fcacc4
1 /*
2 * scsi_queue.c Copyright (C) 1997 Eric Youngdale
4 * generic mid-level SCSI queueing.
6 * The point of this is that we need to track when hosts are unable to
7 * accept a command because they are busy. In addition, we track devices
8 * that cannot accept a command because of a QUEUE_FULL condition. In both
9 * of these cases, we enter the command in the queue. At some later point,
10 * we attempt to remove commands from the queue and retry them.
13 #define __NO_VERSION__
14 #include <linux/module.h>
16 #include <linux/sched.h>
17 #include <linux/timer.h>
18 #include <linux/string.h>
19 #include <linux/malloc.h>
20 #include <linux/ioport.h>
21 #include <linux/kernel.h>
22 #include <linux/stat.h>
23 #include <linux/blk.h>
24 #include <linux/interrupt.h>
25 #include <linux/delay.h>
26 #include <linux/smp_lock.h>
28 #define __KERNEL_SYSCALLS__
30 #include <linux/unistd.h>
32 #include <asm/system.h>
33 #include <asm/irq.h>
34 #include <asm/dma.h>
36 #include"scsi.h"
37 #include"hosts.h"
38 #include"constants.h"
41 * TODO:
42 * 1) Prevent multiple traversals of list to look for commands to
43 * queue.
44 * 2) Protect against multiple insertions of list at the same time.
45 * DONE:
46 * 1) Set state of scsi command to a new state value for ml queue.
47 * 2) Insert into queue when host rejects command.
48 * 3) Make sure status code is properly passed from low-level queue func
49 * so that internal_cmnd properly returns the right value.
50 * 4) Insert into queue when QUEUE_FULL.
51 * 5) Cull queue in bottom half handler.
52 * 6) Check usage count prior to queue insertion. Requeue if usage
53 * count is 0.
54 * 7) Don't send down any more commands if the host/device is busy.
57 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 $";
60 * Lock used to prevent more than one process from frobbing the list at the
61 * same time. FIXME(eric) - there should be separate spinlocks for each host.
62 * This will reduce contention.
65 spinlock_t scsi_mlqueue_lock = SPIN_LOCK_UNLOCKED;
66 spinlock_t scsi_mlqueue_remove_lock = SPIN_LOCK_UNLOCKED;
69 * Function: scsi_mlqueue_insert()
71 * Purpose: Insert a command in the midlevel queue.
73 * Arguments: cmd - command that we are adding to queue.
74 * reason - why we are inserting command to queue.
76 * Returns: Nothing.
78 * Notes: We do this for one of two cases. Either the host is busy
79 * and it cannot accept any more commands for the time being,
80 * or the device returned QUEUE_FULL and can accept no more
81 * commands.
82 * Notes: This could be called either from an interrupt context or a
83 * normal process context.
85 intscsi_mlqueue_insert(Scsi_Cmnd * cmd,int reason)
87 Scsi_Cmnd *cpnt;
88 unsigned long flags;
89 struct Scsi_Host *host;
91 SCSI_LOG_MLQUEUE(1,printk("Inserting command %p into mlqueue\n", cmd));
94 * We are inserting the command into the ml queue. First, we
95 * cancel the timer, so it doesn't time out.
97 scsi_delete_timer(cmd);
99 host = cmd->host;
102 * Next, set the appropriate busy bit for the device/host.
104 if(reason == SCSI_MLQUEUE_HOST_BUSY) {
106 * Protect against race conditions. If the host isn't busy,
107 * assume that something actually completed, and that we should
108 * be able to queue a command now. Note that there is an implicit
109 * assumption that every host can always queue at least one command.
110 * If a host is inactive and cannot queue any commands, I don't see
111 * how things could possibly work anyways.
113 if(host->host_busy ==0) {
114 if(scsi_retry_command(cmd) ==0) {
115 return0;
118 host->host_blocked = TRUE;
119 cmd->host_wait = TRUE;
120 }else{
122 * Protect against race conditions. If the device isn't busy,
123 * assume that something actually completed, and that we should
124 * be able to queue a command now. Note that there is an implicit
125 * assumption that every host can always queue at least one command.
126 * If a host is inactive and cannot queue any commands, I don't see
127 * how things could possibly work anyways.
129 if(cmd->device->device_busy ==0) {
130 if(scsi_retry_command(cmd) ==0) {
131 return0;
134 cmd->device->device_busy = TRUE;
135 cmd->device_wait = TRUE;
139 * Register the fact that we own the thing for now.
141 cmd->state = SCSI_STATE_MLQUEUE;
142 cmd->owner = SCSI_OWNER_MIDLEVEL;
143 cmd->bh_next = NULL;
146 * As a performance enhancement, look to see whether the list is
147 * empty. If it is, then we can just atomicly insert the command
148 * in the list and return without locking.
150 if(host->pending_commands == NULL) {
151 cpnt =xchg(&host->pending_commands, cmd);
152 if(cpnt == NULL) {
153 return0;
156 * Rats. Something slipped in while we were exchanging.
157 * Swap it back and fall through to do it the hard way.
159 cmd =xchg(&host->pending_commands, cpnt);
163 * Next append the command to the list of pending commands.
165 spin_lock_irqsave(&scsi_mlqueue_lock, flags);
166 for(cpnt = host->pending_commands; cpnt && cpnt->bh_next;
167 cpnt = cpnt->bh_next) {
168 continue;
170 if(cpnt != NULL) {
171 cpnt->bh_next = cmd;
172 }else{
173 host->pending_commands = cmd;
176 spin_unlock_irqrestore(&scsi_mlqueue_lock, flags);
177 return0;
181 * Function: scsi_mlqueue_finish()
183 * Purpose: Try and queue commands from the midlevel queue.
185 * Arguments: host - host that just finished a command.
186 * device - device that just finished a command.
188 * Returns: Nothing.
190 * Notes: This could be called either from an interrupt context or a
191 * normal process context.
193 intscsi_mlqueue_finish(struct Scsi_Host *host, Scsi_Device * device)
195 Scsi_Cmnd *cpnt;
196 unsigned long flags;
197 Scsi_Cmnd *next;
198 Scsi_Cmnd *prev;
199 int reason =0;
200 int rtn;
202 SCSI_LOG_MLQUEUE(2,printk("scsi_mlqueue_finish starting\n"));
204 * First, clear the flag for the host/device. We will then start
205 * pushing commands through until either something else blocks, or
206 * the queue is empty.
208 if(host->host_blocked) {
209 reason = SCSI_MLQUEUE_HOST_BUSY;
210 host->host_blocked = FALSE;
212 if(device->device_busy) {
213 reason = SCSI_MLQUEUE_DEVICE_BUSY;
214 device->device_busy = FALSE;
217 * Walk the list of commands to see if there is anything we can
218 * queue. This probably needs to be optimized for performance at
219 * some point.
221 prev = NULL;
222 spin_lock_irqsave(&scsi_mlqueue_remove_lock, flags);
223 for(cpnt = host->pending_commands; cpnt; cpnt = next) {
224 next = cpnt->bh_next;
226 * First, see if this command is suitable for being retried now.
228 if(reason == SCSI_MLQUEUE_HOST_BUSY) {
230 * The host was busy, but isn't any more. Thus we may be
231 * able to queue the command now, but we were waiting for
232 * the device, then we should keep waiting. Similarily, if
233 * the device is now busy, we should also keep waiting.
235 if((cpnt->host_wait == FALSE)
236 || (device->device_busy == TRUE)) {
237 prev = cpnt;
238 continue;
241 if(reason == SCSI_MLQUEUE_DEVICE_BUSY) {
243 * The device was busy, but isn't any more. Thus we may be
244 * able to queue the command now, but we were waiting for
245 * the host, then we should keep waiting. Similarily, if
246 * the host is now busy, we should also keep waiting.
248 if((cpnt->device_wait == FALSE)
249 || (host->host_blocked == TRUE)) {
250 prev = cpnt;
251 continue;
255 * First, remove the command from the list.
257 if(prev == NULL) {
258 host->pending_commands = next;
259 }else{
260 prev->bh_next = next;
262 cpnt->bh_next = NULL;
264 rtn =scsi_retry_command(cpnt);
267 * If we got a non-zero return value, it means that the host rejected
268 * the command. The internal_cmnd function will have added the
269 * command back to the end of the list, so we don't have anything
270 * more to do here except return.
272 if(rtn) {
273 spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
274 SCSI_LOG_MLQUEUE(1,printk("Unable to remove command %p from mlqueue\n", cpnt));
275 goto finish;
277 SCSI_LOG_MLQUEUE(1,printk("Removed command %p from mlqueue\n", cpnt));
280 spin_unlock_irqrestore(&scsi_mlqueue_remove_lock, flags);
281 finish:
282 SCSI_LOG_MLQUEUE(2,printk("scsi_mlqueue_finish returning\n"));
283 return0;
close