// SPDX-License-Identifier: GPL-2.0-or-later /* * Adaptec AAC series RAID controller driver * (c) Copyright 2001 Red Hat Inc. * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * * Copyright (c) 2000-2010 Adaptec, Inc. * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) * * Module Name: * dpcsup.c * * Abstract: All DPC processing routines for the cyclone board occur here.
*/
/** * aac_response_normal - Handle command replies * @q: Queue to read from * * This DPC routine will be run when the adapter interrupts us to let us * know there is a response on our normal priority queue. We will pull off * all QE there are and wake up all the waiters before exiting. We will * take a spinlock out on the queue before operating on it.
*/
spin_lock_irqsave(q->lock, flags); /* * Keep pulling response QEs off the response queue and waking * up the waiters until there are no more QEs. We then return * back to the system. If no response was requested we just * deallocate the Fib here and continue.
*/ while(aac_consumer_get(dev, q, &entry))
{ int fast;
u32 index = le32_to_cpu(entry->addr);
fast = index & 0x01;
fib = &dev->fibs[index >> 2];
hwfib = fib->hw_fib_va;
aac_consumer_free(dev, q, HostNormRespQueue); /* * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. * * If the fib has been timed out already, then just * continue. The caller has already been notified that * the fib timed out.
*/
atomic_dec(&dev->queues->queue[AdapNormCmdQueue].numpending);
/** * aac_command_normal - handle commands * @q: queue to process * * This DPC routine will be queued when the adapter interrupts us to * let us know there is a command on our normal priority queue. We will * pull off all QE there are and wake up all the waiters before exiting. * We will take a spinlock out on the queue before operating on it.
*/
/* * Keep pulling response QEs off the response queue and waking * up the waiters until there are no more QEs. We then return * back to the system.
*/ while(aac_consumer_get(dev, q, &entry))
{ struct fib fibctx; struct hw_fib * hw_fib;
u32 index; struct fib *fib = &fibctx;
index = le32_to_cpu(entry->addr) / sizeof(struct hw_fib);
hw_fib = &dev->aif_base_va[index];
/* * Allocate a FIB at all costs. For non queued stuff * we can just use the stack so we are happy. We need * a fib object in order to manage the linked lists
*/ if (dev->aif_thread) if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC)) == NULL)
fib = &fibctx;
if (dev->aif_thread && fib != &fibctx) {
list_add_tail(&fib->fiblink, &q->cmdq);
aac_consumer_free(dev, q, HostNormCmdQueue);
wake_up_interruptible(&q->cmdready);
} else {
aac_consumer_free(dev, q, HostNormCmdQueue);
spin_unlock_irqrestore(q->lock, flags); /* * Set the status of this FIB
*/
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
aac_fib_adapter_complete(fib, sizeof(u32));
spin_lock_irqsave(q->lock, flags);
}
}
spin_unlock_irqrestore(q->lock, flags); return 0;
}
/* * * aac_aif_callback * @context: the context set in the fib - here it is scsi cmd * @fibptr: pointer to the fib * * Handles the AIFs - new method (SRC) *
*/
/* * aac_intr_normal - Handle command replies * @dev: Device * @index: completion reference * * This DPC routine will be run when the adapter interrupts us to let us * know there is a response on our normal priority queue. We will pull off * all QE there are and wake up all the waiters before exiting.
*/ unsignedint aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, int isFastResponse, struct hw_fib *aif_fib)
{ unsignedlong mflags;
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); if (isAif == 1) { /* AIF - common */ struct hw_fib * hw_fib; struct fib * fib; struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue]; unsignedlong flags;
/* * Allocate a FIB. For non queued stuff we can just use * the stack so we are happy. We need a fib object in order to * manage the linked lists.
*/ if ((!dev->aif_thread)
|| (!(fib = kzalloc(sizeof(struct fib),GFP_ATOMIC)))) return 1; if (!(hw_fib = kzalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
kfree (fib); return 1;
} if (dev->sa_firmware) {
fib->hbacmd_size = index; /* store event type */
} elseif (aif_fib != NULL) {
memcpy(hw_fib, aif_fib, sizeof(struct hw_fib));
} else {
memcpy(hw_fib, (struct hw_fib *)
(((uintptr_t)(dev->regs.sa)) + index), sizeof(struct hw_fib));
}
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
fib->size = sizeof(struct fib);
fib->hw_fib_va = hw_fib;
fib->data = hw_fib->data;
fib->dev = dev;
/* * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. * * If the fib has been timed out already, then just * continue. The caller has already been notified that * the fib timed out.
*/
atomic_dec(&dev->queues->queue[AdapNormCmdQueue].numpending);
if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
aac_fib_complete(fib);
aac_fib_free(fib); return 0;
}
FIB_COUNTER_INCREMENT(aac_config.FibRecved);
if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) {
if (isFastResponse)
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
if (fib->callback) {
start_callback = 1;
} else { unsignedlong flagv; int completed = 0;
FIB_COUNTER_INCREMENT(aac_config.NormalRecved); if (completed)
aac_fib_complete(fib);
}
}
if (start_callback) { /* * NOTE: we cannot touch the fib after this * call, because it may have been deallocated.
*/ if (likely(fib->callback && fib->callback_data)) {
fib->callback(fib->callback_data, fib);
} else {
aac_fib_complete(fib);
aac_fib_free(fib);
}
} return 0;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.