update atp870u driver to 0.78 from D-Link source
[linux-2.4.git] / drivers / scsi / aacraid / dpcsup.c
1 /*
2  *      Adaptec AAC series RAID controller driver
3  *      (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
4  *
5  * based on the old aacraid driver that is..
6  * Adaptec aacraid device driver for Linux.
7  *
8  * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2, or (at your option)
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; see the file COPYING.  If not, write to
22  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  * Module Name:
25  *  dpcsup.c
26  *
27  * Abstract: All DPC processing routines for the cyclone board occur here.
28  *
29  *
30  */
31
32 #include <linux/config.h>
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/types.h>
36 #include <linux/sched.h>
37 #include <linux/pci.h>
38 #include <linux/spinlock.h>
39 #include <linux/slab.h>
40 #include <linux/completion.h>
41 #include <linux/blk.h>
42 #include <asm/semaphore.h>
43 #include "scsi.h"
44 #include "hosts.h"
45
46 #include "aacraid.h"
47
48 /**
49  *      aac_response_normal     -       Handle command replies
50  *      @q: Queue to read from
51  *
52  *      This DPC routine will be run when the adapter interrupts us to let us
53  *      know there is a response on our normal priority queue. We will pull off
54  *      all QE there are and wake up all the waiters before exiting. We will
55  *      take a spinlock out on the queue before operating on it.
56  */
57
58 unsigned int aac_response_normal(struct aac_queue * q)
59 {
60         struct aac_dev * dev = q->dev;
61         struct aac_entry *entry;
62         struct hw_fib * hwfib;
63         struct fib * fib;
64         int consumed = 0;
65         unsigned long flags;
66
67         spin_lock_irqsave(q->lock, flags);      
68
69         /*
70          *      Keep pulling response QEs off the response queue and waking
71          *      up the waiters until there are no more QEs. We then return
72          *      back to the system. If no response was requesed we just
73          *      deallocate the Fib here and continue.
74          */
75         while(aac_consumer_get(dev, q, &entry))
76         {
77                 int fast;
78                 u32 index;
79                 index = le32_to_cpu(entry->addr);
80                 fast = index & 0x01;
81                 fib = &dev->fibs[index >> 1];
82                 hwfib = fib->hw_fib;
83
84                 aac_consumer_free(dev, q, HostNormRespQueue);
85                 /*
86                  *      Remove this fib from the Outstanding I/O queue.
87                  *      But only if it has not already been timed out.
88                  *
89                  *      If the fib has been timed out already, then just 
90                  *      continue. The caller has already been notified that
91                  *      the fib timed out.
92                  */
93                 if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
94                         list_del(&fib->queue);
95                         dev->queues->queue[AdapNormCmdQueue].numpending--;
96                 } else {
97                         printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
98                         continue;
99                 }
100                 spin_unlock_irqrestore(q->lock, flags);
101
102                 if (fast) {
103                         /*
104                          *      Doctor the fib
105                          */
106                         *(u32 *)hwfib->data = cpu_to_le32(ST_OK);
107                         hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
108                 }
109
110                 FIB_COUNTER_INCREMENT(aac_config.FibRecved);
111
112                 if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
113                 {
114                         u32 *pstatus = (u32 *)hwfib->data;
115                         if (*pstatus & cpu_to_le32(0xffff0000))
116                                 *pstatus = cpu_to_le32(ST_OK);
117                 }
118                 if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) 
119                 {
120                         if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected))
121                                 FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
122                         else 
123                                 FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
124                         /*
125                          *      NOTE:  we cannot touch the fib after this
126                          *          call, because it may have been deallocated.
127                          */
128                         fib->callback(fib->callback_data, fib);
129                 } else {
130                         unsigned long flagv;
131                         spin_lock_irqsave(&fib->event_lock, flagv);
132                         fib->done = 1;
133                         up(&fib->event_wait);
134                         spin_unlock_irqrestore(&fib->event_lock, flagv);
135                         FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
136                 }
137                 consumed++;
138                 spin_lock_irqsave(q->lock, flags);
139         }
140
141         if (consumed > aac_config.peak_fibs)
142                 aac_config.peak_fibs = consumed;
143         if (consumed == 0) 
144                 aac_config.zero_fibs++;
145
146         spin_unlock_irqrestore(q->lock, flags);
147         return 0;
148 }
149
150
151 /**
152  *      aac_command_normal      -       handle commands
153  *      @q: queue to process
154  *
155  *      This DPC routine will be queued when the adapter interrupts us to 
156  *      let us know there is a command on our normal priority queue. We will 
157  *      pull off all QE there are and wake up all the waiters before exiting.
158  *      We will take a spinlock out on the queue before operating on it.
159  */
160  
161 unsigned int aac_command_normal(struct aac_queue *q)
162 {
163         struct aac_dev * dev = q->dev;
164         struct aac_entry *entry;
165         unsigned long flags;
166
167         spin_lock_irqsave(q->lock, flags);
168
169         /*
170          *      Keep pulling response QEs off the response queue and waking
171          *      up the waiters until there are no more QEs. We then return
172          *      back to the system.
173          */
174         dprintk((KERN_INFO
175           "dev=%p, dev->comm_phys=%x, dev->comm_addr=%p, dev->comm_size=%u\n",
176           dev, (u32)dev->comm_phys, dev->comm_addr, (unsigned)dev->comm_size));
177
178         while(aac_consumer_get(dev, q, &entry))
179         {
180                 struct fib fibctx;
181                 struct hw_fib * hw_fib;
182                 u32 index;
183                 struct fib *fib = &fibctx;
184
185                 index = le32_to_cpu(entry->addr / sizeof(struct hw_fib));
186                 hw_fib = &dev->aif_base_va[index];
187
188                 /*
189                  *      Allocate a FIB at all costs. For non queued stuff
190                  *      we can just use the stack so we are happy. We need
191                  *      a fib object in order to manage the linked lists
192                  */
193                 if (dev->aif_thread)
194                         if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC))==NULL)
195                                 fib = &fibctx;
196                         
197                 memset(fib, 0, sizeof(struct fib));
198                 INIT_LIST_HEAD(&fib->fiblink);
199                 fib->type = FSAFS_NTC_FIB_CONTEXT;
200                 fib->size = sizeof(struct fib);
201                 fib->hw_fib = hw_fib;
202                 fib->data = hw_fib->data;
203                 fib->dev = dev;
204                 
205                 if (dev->aif_thread && fib != &fibctx)
206                 {               
207                         list_add_tail(&fib->fiblink, &q->cmdq);
208                         aac_consumer_free(dev, q, HostNormCmdQueue);
209                         wake_up_interruptible(&q->cmdready);
210                 } else {
211                         aac_consumer_free(dev, q, HostNormCmdQueue);
212                         spin_unlock_irqrestore(q->lock, flags);
213                         /*
214                          *      Set the status of this FIB
215                          */
216                         *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
217                         fib_adapter_complete(fib, sizeof(u32));
218                         spin_lock_irqsave(q->lock, flags);
219                 }               
220         }
221         spin_unlock_irqrestore(q->lock, flags);
222         return 0;
223 }