2 * Adaptec AAC series RAID controller driver
3 * (c) Copyright 2001 Red Hat Inc.
5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux.
8 * Copyright (c) 2000-2010 Adaptec, Inc.
9 * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Abstract: All DPC processing routines for the cyclone board occur here.
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/types.h>
36 #include <linux/spinlock.h>
37 #include <linux/slab.h>
38 #include <linux/completion.h>
39 #include <linux/blkdev.h>
40 #include <linux/semaphore.h>
45 * aac_response_normal - Handle command replies
46 * @q: Queue to read from
48 * This DPC routine will be run when the adapter interrupts us to let us
49 * know there is a response on our normal priority queue. We will pull off
50 * all QE there are and wake up all the waiters before exiting. We will
51 * take a spinlock out on the queue before operating on it.
54 unsigned int aac_response_normal(struct aac_queue
* q
)
56 struct aac_dev
* dev
= q
->dev
;
57 struct aac_entry
*entry
;
58 struct hw_fib
* hwfib
;
61 unsigned long flags
, mflags
;
63 spin_lock_irqsave(q
->lock
, flags
);
65 * Keep pulling response QEs off the response queue and waking
66 * up the waiters until there are no more QEs. We then return
67 * back to the system. If no response was requesed we just
68 * deallocate the Fib here and continue.
70 while(aac_consumer_get(dev
, q
, &entry
))
73 u32 index
= le32_to_cpu(entry
->addr
);
75 fib
= &dev
->fibs
[index
>> 2];
76 hwfib
= fib
->hw_fib_va
;
78 aac_consumer_free(dev
, q
, HostNormRespQueue
);
80 * Remove this fib from the Outstanding I/O queue.
81 * But only if it has not already been timed out.
83 * If the fib has been timed out already, then just
84 * continue. The caller has already been notified that
87 dev
->queues
->queue
[AdapNormCmdQueue
].numpending
--;
89 if (unlikely(fib
->flags
& FIB_CONTEXT_FLAG_TIMED_OUT
)) {
90 spin_unlock_irqrestore(q
->lock
, flags
);
91 aac_fib_complete(fib
);
93 spin_lock_irqsave(q
->lock
, flags
);
96 spin_unlock_irqrestore(q
->lock
, flags
);
102 *(__le32
*)hwfib
->data
= cpu_to_le32(ST_OK
);
103 hwfib
->header
.XferState
|= cpu_to_le32(AdapterProcessed
);
104 fib
->flags
|= FIB_CONTEXT_FLAG_FASTRESP
;
107 FIB_COUNTER_INCREMENT(aac_config
.FibRecved
);
109 if (hwfib
->header
.Command
== cpu_to_le16(NuFileSystem
))
111 __le32
*pstatus
= (__le32
*)hwfib
->data
;
112 if (*pstatus
& cpu_to_le32(0xffff0000))
113 *pstatus
= cpu_to_le32(ST_OK
);
115 if (hwfib
->header
.XferState
& cpu_to_le32(NoResponseExpected
| Async
))
117 if (hwfib
->header
.XferState
& cpu_to_le32(NoResponseExpected
))
118 FIB_COUNTER_INCREMENT(aac_config
.NoResponseRecved
);
120 FIB_COUNTER_INCREMENT(aac_config
.AsyncRecved
);
122 * NOTE: we cannot touch the fib after this
123 * call, because it may have been deallocated.
125 fib
->flags
&= FIB_CONTEXT_FLAG_FASTRESP
;
126 fib
->callback(fib
->callback_data
, fib
);
129 spin_lock_irqsave(&fib
->event_lock
, flagv
);
132 up(&fib
->event_wait
);
134 spin_unlock_irqrestore(&fib
->event_lock
, flagv
);
136 spin_lock_irqsave(&dev
->manage_lock
, mflags
);
137 dev
->management_fib_count
--;
138 spin_unlock_irqrestore(&dev
->manage_lock
, mflags
);
140 FIB_COUNTER_INCREMENT(aac_config
.NormalRecved
);
141 if (fib
->done
== 2) {
142 spin_lock_irqsave(&fib
->event_lock
, flagv
);
144 spin_unlock_irqrestore(&fib
->event_lock
, flagv
);
145 aac_fib_complete(fib
);
150 spin_lock_irqsave(q
->lock
, flags
);
153 if (consumed
> aac_config
.peak_fibs
)
154 aac_config
.peak_fibs
= consumed
;
156 aac_config
.zero_fibs
++;
158 spin_unlock_irqrestore(q
->lock
, flags
);
164 * aac_command_normal - handle commands
165 * @q: queue to process
167 * This DPC routine will be queued when the adapter interrupts us to
168 * let us know there is a command on our normal priority queue. We will
169 * pull off all QE there are and wake up all the waiters before exiting.
170 * We will take a spinlock out on the queue before operating on it.
173 unsigned int aac_command_normal(struct aac_queue
*q
)
175 struct aac_dev
* dev
= q
->dev
;
176 struct aac_entry
*entry
;
179 spin_lock_irqsave(q
->lock
, flags
);
182 * Keep pulling response QEs off the response queue and waking
183 * up the waiters until there are no more QEs. We then return
184 * back to the system.
186 while(aac_consumer_get(dev
, q
, &entry
))
189 struct hw_fib
* hw_fib
;
191 struct fib
*fib
= &fibctx
;
193 index
= le32_to_cpu(entry
->addr
) / sizeof(struct hw_fib
);
194 hw_fib
= &dev
->aif_base_va
[index
];
197 * Allocate a FIB at all costs. For non queued stuff
198 * we can just use the stack so we are happy. We need
199 * a fib object in order to manage the linked lists
202 if((fib
= kmalloc(sizeof(struct fib
), GFP_ATOMIC
)) == NULL
)
205 memset(fib
, 0, sizeof(struct fib
));
206 INIT_LIST_HEAD(&fib
->fiblink
);
207 fib
->type
= FSAFS_NTC_FIB_CONTEXT
;
208 fib
->size
= sizeof(struct fib
);
209 fib
->hw_fib_va
= hw_fib
;
210 fib
->data
= hw_fib
->data
;
214 if (dev
->aif_thread
&& fib
!= &fibctx
) {
215 list_add_tail(&fib
->fiblink
, &q
->cmdq
);
216 aac_consumer_free(dev
, q
, HostNormCmdQueue
);
217 wake_up_interruptible(&q
->cmdready
);
219 aac_consumer_free(dev
, q
, HostNormCmdQueue
);
220 spin_unlock_irqrestore(q
->lock
, flags
);
222 * Set the status of this FIB
224 *(__le32
*)hw_fib
->data
= cpu_to_le32(ST_OK
);
225 aac_fib_adapter_complete(fib
, sizeof(u32
));
226 spin_lock_irqsave(q
->lock
, flags
);
229 spin_unlock_irqrestore(q
->lock
, flags
);
236 * @context: the context set in the fib - here it is scsi cmd
237 * @fibptr: pointer to the fib
239 * Handles the AIFs - new method (SRC)
243 static void aac_aif_callback(void *context
, struct fib
* fibptr
)
247 struct aac_aifcmd
*cmd
;
250 fibctx
= (struct fib
*)context
;
251 BUG_ON(fibptr
== NULL
);
254 if (fibptr
->hw_fib_va
->header
.XferState
&
255 cpu_to_le32(NoMoreAifDataAvailable
)) {
256 aac_fib_complete(fibptr
);
257 aac_fib_free(fibptr
);
261 aac_intr_normal(dev
, 0, 1, 0, fibptr
->hw_fib_va
);
263 aac_fib_init(fibctx
);
264 cmd
= (struct aac_aifcmd
*) fib_data(fibctx
);
265 cmd
->command
= cpu_to_le32(AifReqEvent
);
267 status
= aac_fib_send(AifRequest
,
269 sizeof(struct hw_fib
)-sizeof(struct aac_fibhdr
),
272 (fib_callback
)aac_aif_callback
, fibctx
);
277 * aac_intr_normal - Handle command replies
279 * @index: completion reference
281 * This DPC routine will be run when the adapter interrupts us to let us
282 * know there is a response on our normal priority queue. We will pull off
283 * all QE there are and wake up all the waiters before exiting.
285 unsigned int aac_intr_normal(struct aac_dev
*dev
, u32 index
,
286 int isAif
, int isFastResponse
, struct hw_fib
*aif_fib
)
288 unsigned long mflags
;
289 dprintk((KERN_INFO
"aac_intr_normal(%p,%x)\n", dev
, index
));
290 if (isAif
== 1) { /* AIF - common */
291 struct hw_fib
* hw_fib
;
293 struct aac_queue
*q
= &dev
->queues
->queue
[HostNormCmdQueue
];
297 * Allocate a FIB. For non queued stuff we can just use
298 * the stack so we are happy. We need a fib object in order to
299 * manage the linked lists.
301 if ((!dev
->aif_thread
)
302 || (!(fib
= kzalloc(sizeof(struct fib
),GFP_ATOMIC
))))
304 if (!(hw_fib
= kzalloc(sizeof(struct hw_fib
),GFP_ATOMIC
))) {
308 if (aif_fib
!= NULL
) {
309 memcpy(hw_fib
, aif_fib
, sizeof(struct hw_fib
));
312 (struct hw_fib
*)(((uintptr_t)(dev
->regs
.sa
)) +
313 index
), sizeof(struct hw_fib
));
315 INIT_LIST_HEAD(&fib
->fiblink
);
316 fib
->type
= FSAFS_NTC_FIB_CONTEXT
;
317 fib
->size
= sizeof(struct fib
);
318 fib
->hw_fib_va
= hw_fib
;
319 fib
->data
= hw_fib
->data
;
322 spin_lock_irqsave(q
->lock
, flags
);
323 list_add_tail(&fib
->fiblink
, &q
->cmdq
);
324 wake_up_interruptible(&q
->cmdready
);
325 spin_unlock_irqrestore(q
->lock
, flags
);
327 } else if (isAif
== 2) { /* AIF - new (SRC) */
329 struct aac_aifcmd
*cmd
;
331 fibctx
= aac_fib_alloc(dev
);
334 aac_fib_init(fibctx
);
336 cmd
= (struct aac_aifcmd
*) fib_data(fibctx
);
337 cmd
->command
= cpu_to_le32(AifReqEvent
);
339 return aac_fib_send(AifRequest
,
341 sizeof(struct hw_fib
)-sizeof(struct aac_fibhdr
),
344 (fib_callback
)aac_aif_callback
, fibctx
);
346 struct fib
*fib
= &dev
->fibs
[index
];
347 struct hw_fib
* hwfib
= fib
->hw_fib_va
;
350 * Remove this fib from the Outstanding I/O queue.
351 * But only if it has not already been timed out.
353 * If the fib has been timed out already, then just
354 * continue. The caller has already been notified that
357 dev
->queues
->queue
[AdapNormCmdQueue
].numpending
--;
359 if (unlikely(fib
->flags
& FIB_CONTEXT_FLAG_TIMED_OUT
)) {
360 aac_fib_complete(fib
);
365 if (isFastResponse
) {
369 *(__le32
*)hwfib
->data
= cpu_to_le32(ST_OK
);
370 hwfib
->header
.XferState
|= cpu_to_le32(AdapterProcessed
);
371 fib
->flags
|= FIB_CONTEXT_FLAG_FASTRESP
;
374 FIB_COUNTER_INCREMENT(aac_config
.FibRecved
);
376 if (hwfib
->header
.Command
== cpu_to_le16(NuFileSystem
))
378 __le32
*pstatus
= (__le32
*)hwfib
->data
;
379 if (*pstatus
& cpu_to_le32(0xffff0000))
380 *pstatus
= cpu_to_le32(ST_OK
);
382 if (hwfib
->header
.XferState
& cpu_to_le32(NoResponseExpected
| Async
))
384 if (hwfib
->header
.XferState
& cpu_to_le32(NoResponseExpected
))
385 FIB_COUNTER_INCREMENT(aac_config
.NoResponseRecved
);
387 FIB_COUNTER_INCREMENT(aac_config
.AsyncRecved
);
389 * NOTE: we cannot touch the fib after this
390 * call, because it may have been deallocated.
392 fib
->flags
&= FIB_CONTEXT_FLAG_FASTRESP
;
393 fib
->callback(fib
->callback_data
, fib
);
396 dprintk((KERN_INFO
"event_wait up\n"));
397 spin_lock_irqsave(&fib
->event_lock
, flagv
);
400 up(&fib
->event_wait
);
402 spin_unlock_irqrestore(&fib
->event_lock
, flagv
);
404 spin_lock_irqsave(&dev
->manage_lock
, mflags
);
405 dev
->management_fib_count
--;
406 spin_unlock_irqrestore(&dev
->manage_lock
, mflags
);
408 FIB_COUNTER_INCREMENT(aac_config
.NormalRecved
);
409 if (fib
->done
== 2) {
410 spin_lock_irqsave(&fib
->event_lock
, flagv
);
412 spin_unlock_irqrestore(&fib
->event_lock
, flagv
);
413 aac_fib_complete(fib
);