Commit 113156bc authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen

scsi: aacraid: Reworked aac_command_thread

Reworked aac_command_thread into aac_process_events
Signed-off-by: default avatarRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: default avatarDave Carroll <David.Carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f956a669
......@@ -1729,96 +1729,11 @@ int aac_check_health(struct aac_dev * aac)
return BlinkLED;
}
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
*
* Waits on the commandready event in it's queue. When the event gets set
* it will pull FIBs off it's queue. It will continue to pull FIBs off
* until the queue is empty. When the queue is empty it will wait for
* more FIBs.
*/
int aac_command_thread(void *data)
static int get_fib_count(struct aac_dev *dev)
{
struct aac_dev *dev = data;
struct hw_fib *hw_fib, *hw_newfib;
struct fib *fib, *newfib;
struct aac_fib_context *fibctx;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
unsigned long next_jiffies = jiffies + HZ;
unsigned long next_check_jiffies = next_jiffies;
long difference = HZ;
/*
* We can only have one thread per adapter for AIF's.
*/
if (dev->aif_thread)
return -EINVAL;
/*
* Let the DPC know it has a place to send the AIF's to.
*/
dev->aif_thread = 1;
add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
set_current_state(TASK_INTERRUPTIBLE);
dprintk ((KERN_INFO "aac_command_thread start\n"));
while (1) {
spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
unsigned int num = 0;
struct list_head *entry;
struct aac_aifcmd * aifcmd;
set_current_state(TASK_RUNNING);
entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
list_del(entry);
spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
fib = list_entry(entry, struct fib, fiblink);
/*
* We will process the FIB here or pass it to a
* worker thread that is TBD. We Really can't
* do anything at this point since we don't have
* anything defined for this thread to do.
*/
hw_fib = fib->hw_fib_va;
memset(fib, 0, sizeof(struct fib));
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;
/*
* We only handle AifRequest fibs from the adapter.
*/
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
aac_handle_aif(dev, fib);
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
aac_fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
/* The u32 here is important and intended. We are using
32bit wrapping time to fit the adapter field */
u32 time_now, time_last;
unsigned long flagv;
unsigned num;
struct hw_fib ** hw_fib_pool, ** hw_fib_p;
struct fib ** fib_pool, ** fib_p;
/* Sniff events */
if ((aifcmd->command ==
cpu_to_le32(AifCmdEventNotify)) ||
(aifcmd->command ==
cpu_to_le32(AifCmdJobProgress))) {
aac_handle_aif(dev, fib);
}
time_now = jiffies/HZ;
/*
* Warning: no sleep allowed while
......@@ -1826,8 +1741,7 @@ int aac_command_thread(void *data)
* and pre-allocate a set of fibs outside the
* lock.
*/
num = le32_to_cpu(dev->init->
r7.adapter_fibs_size)
num = le32_to_cpu(dev->init->r7.adapter_fibs_size)
/ sizeof(struct hw_fib); /* some extra */
spin_lock_irqsave(&dev->fib_lock, flagv);
entry = dev->fib_list.next;
......@@ -1836,33 +1750,58 @@ int aac_command_thread(void *data)
++num;
}
spin_unlock_irqrestore(&dev->fib_lock, flagv);
hw_fib_pool = NULL;
fib_pool = NULL;
if (num
&& ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL)))
&& ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) {
return num;
}
static int fillup_pools(struct aac_dev *dev, struct hw_fib **hw_fib_pool,
struct fib **fib_pool,
unsigned int num)
{
struct hw_fib **hw_fib_p;
struct fib **fib_p;
int rcode = 1;
hw_fib_p = hw_fib_pool;
fib_p = fib_pool;
while (hw_fib_p < &hw_fib_pool[num]) {
if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) {
*(hw_fib_p) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL);
if (!(*(hw_fib_p++))) {
--hw_fib_p;
break;
}
if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) {
*(fib_p) = kmalloc(sizeof(struct fib), GFP_KERNEL);
if (!(*(fib_p++))) {
kfree(*(--hw_fib_p));
break;
}
}
if ((num = hw_fib_p - hw_fib_pool) == 0) {
kfree(fib_pool);
fib_pool = NULL;
kfree(hw_fib_pool);
hw_fib_pool = NULL;
}
} else {
kfree(hw_fib_pool);
hw_fib_pool = NULL;
}
num = hw_fib_p - hw_fib_pool;
if (!num)
rcode = 0;
return rcode;
}
static void wakeup_fibctx_threads(struct aac_dev *dev,
struct hw_fib **hw_fib_pool,
struct fib **fib_pool,
struct fib *fib,
struct hw_fib *hw_fib,
unsigned int num)
{
unsigned long flagv;
struct list_head *entry;
struct hw_fib **hw_fib_p;
struct fib **fib_p;
u32 time_now, time_last;
struct hw_fib *hw_newfib;
struct fib *newfib;
struct aac_fib_context *fibctx;
time_now = jiffies/HZ;
spin_lock_irqsave(&dev->fib_lock, flagv);
entry = dev->fib_list.next;
/*
......@@ -1871,19 +1810,20 @@ int aac_command_thread(void *data)
* fib, and then set the event to wake up the
* thread that is waiting for it.
*/
hw_fib_p = hw_fib_pool;
fib_p = fib_pool;
while (entry != &dev->fib_list) {
/*
* Extract the fibctx
*/
fibctx = list_entry(entry, struct aac_fib_context, next);
fibctx = list_entry(entry, struct aac_fib_context,
next);
/*
* Check if the queue is getting
* backlogged
*/
if (fibctx->count > 20)
{
if (fibctx->count > 20) {
/*
* It's *not* jiffies folks,
* but jiffies / HZ so do not
......@@ -1905,7 +1845,12 @@ int aac_command_thread(void *data)
* Warning: no sleep allowed while
* holding spinlock
*/
if (hw_fib_p < &hw_fib_pool[num]) {
if (hw_fib_p >= &hw_fib_pool[num]) {
pr_warn("aifd: didn't allocate NewFib\n");
entry = entry->next;
continue;
}
hw_newfib = *hw_fib_p;
*(hw_fib_p++) = NULL;
newfib = *fib_p;
......@@ -1927,9 +1872,7 @@ int aac_command_thread(void *data)
* thread that is waiting.
*/
up(&fibctx->wait_sem);
} else {
printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
}
entry = entry->next;
}
/*
......@@ -1938,6 +1881,104 @@ int aac_command_thread(void *data)
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
aac_fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
}
static void aac_process_events(struct aac_dev *dev)
{
struct hw_fib *hw_fib;
struct fib *fib;
unsigned long flags;
spinlock_t *t_lock;
unsigned int rcode;
t_lock = dev->queues->queue[HostNormCmdQueue].lock;
spin_lock_irqsave(t_lock, flags);
while (!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
struct list_head *entry;
struct aac_aifcmd *aifcmd;
unsigned int num;
struct hw_fib **hw_fib_pool, **hw_fib_p;
struct fib **fib_pool, **fib_p;
set_current_state(TASK_RUNNING);
entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
list_del(entry);
t_lock = dev->queues->queue[HostNormCmdQueue].lock;
spin_unlock_irqrestore(t_lock, flags);
fib = list_entry(entry, struct fib, fiblink);
hw_fib = fib->hw_fib_va;
/*
* We will process the FIB here or pass it to a
* worker thread that is TBD. We Really can't
* do anything at this point since we don't have
* anything defined for this thread to do.
*/
memset(fib, 0, sizeof(struct fib));
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;
/*
* We only handle AifRequest fibs from the adapter.
*/
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
aac_handle_aif(dev, fib);
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
aac_fib_adapter_complete(fib, (u16)sizeof(u32));
goto free_fib;
}
/*
* The u32 here is important and intended. We are using
* 32bit wrapping time to fit the adapter field
*/
/* Sniff events */
if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)
|| aifcmd->command == cpu_to_le32(AifCmdJobProgress)) {
aac_handle_aif(dev, fib);
}
/*
* get number of fibs to process
*/
num = get_fib_count(dev);
if (!num)
goto free_fib;
hw_fib_pool = kmalloc_array(num, sizeof(struct hw_fib *),
GFP_KERNEL);
if (!hw_fib_pool)
goto free_fib;
fib_pool = kmalloc_array(num, sizeof(struct fib *), GFP_KERNEL);
if (!fib_pool)
goto free_hw_fib_pool;
/*
* Fill up fib pointer pools with actual fibs
* and hw_fibs
*/
rcode = fillup_pools(dev, hw_fib_pool, fib_pool, num);
if (!rcode)
goto free_mem;
/*
* wakeup the thread that is waiting for
* the response from fw (ioctl)
*/
wakeup_fibctx_threads(dev, hw_fib_pool, fib_pool,
fib, hw_fib, num);
free_mem:
/* Free up the remaining resources */
hw_fib_p = hw_fib_pool;
fib_p = fib_pool;
......@@ -1947,16 +1988,55 @@ int aac_command_thread(void *data)
++fib_p;
++hw_fib_p;
}
kfree(hw_fib_pool);
kfree(fib_pool);
}
free_hw_fib_pool:
kfree(hw_fib_pool);
free_fib:
kfree(fib);
spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
t_lock = dev->queues->queue[HostNormCmdQueue].lock;
spin_lock_irqsave(t_lock, flags);
}
/*
* There are no more AIF's
*/
spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
t_lock = dev->queues->queue[HostNormCmdQueue].lock;
spin_unlock_irqrestore(t_lock, flags);
}
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
*
* Waits on the commandready event in it's queue. When the event gets set
* it will pull FIBs off it's queue. It will continue to pull FIBs off
* until the queue is empty. When the queue is empty it will wait for
* more FIBs.
*/
int aac_command_thread(void *data)
{
struct aac_dev *dev = data;
DECLARE_WAITQUEUE(wait, current);
unsigned long next_jiffies = jiffies + HZ;
unsigned long next_check_jiffies = next_jiffies;
long difference = HZ;
/*
* We can only have one thread per adapter for AIF's.
*/
if (dev->aif_thread)
return -EINVAL;
/*
* Let the DPC know it has a place to send the AIF's to.
*/
dev->aif_thread = 1;
add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
set_current_state(TASK_INTERRUPTIBLE);
dprintk ((KERN_INFO "aac_command_thread start\n"));
while (1) {
aac_process_events(dev);
/*
* Background activity
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment