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) ...@@ -1729,96 +1729,11 @@ int aac_check_health(struct aac_dev * aac)
return BlinkLED; return BlinkLED;
} }
static int get_fib_count(struct aac_dev *dev)
/**
* 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; unsigned int num = 0;
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))) {
struct list_head *entry; 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 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 * Warning: no sleep allowed while
...@@ -1826,8 +1741,7 @@ int aac_command_thread(void *data) ...@@ -1826,8 +1741,7 @@ int aac_command_thread(void *data)
* and pre-allocate a set of fibs outside the * and pre-allocate a set of fibs outside the
* lock. * lock.
*/ */
num = le32_to_cpu(dev->init-> num = le32_to_cpu(dev->init->r7.adapter_fibs_size)
r7.adapter_fibs_size)
/ sizeof(struct hw_fib); /* some extra */ / sizeof(struct hw_fib); /* some extra */
spin_lock_irqsave(&dev->fib_lock, flagv); spin_lock_irqsave(&dev->fib_lock, flagv);
entry = dev->fib_list.next; entry = dev->fib_list.next;
...@@ -1836,33 +1750,58 @@ int aac_command_thread(void *data) ...@@ -1836,33 +1750,58 @@ int aac_command_thread(void *data)
++num; ++num;
} }
spin_unlock_irqrestore(&dev->fib_lock, flagv); spin_unlock_irqrestore(&dev->fib_lock, flagv);
hw_fib_pool = NULL;
fib_pool = NULL; return num;
if (num }
&& ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL)))
&& ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) { 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; hw_fib_p = hw_fib_pool;
fib_p = fib_pool; fib_p = fib_pool;
while (hw_fib_p < &hw_fib_pool[num]) { 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; --hw_fib_p;
break; 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)); kfree(*(--hw_fib_p));
break; break;
} }
} }
if ((num = hw_fib_p - hw_fib_pool) == 0) {
kfree(fib_pool); num = hw_fib_p - hw_fib_pool;
fib_pool = NULL; if (!num)
kfree(hw_fib_pool); rcode = 0;
hw_fib_pool = NULL;
} return rcode;
} else { }
kfree(hw_fib_pool);
hw_fib_pool = NULL; 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); spin_lock_irqsave(&dev->fib_lock, flagv);
entry = dev->fib_list.next; entry = dev->fib_list.next;
/* /*
...@@ -1871,19 +1810,20 @@ int aac_command_thread(void *data) ...@@ -1871,19 +1810,20 @@ int aac_command_thread(void *data)
* fib, and then set the event to wake up the * fib, and then set the event to wake up the
* thread that is waiting for it. * thread that is waiting for it.
*/ */
hw_fib_p = hw_fib_pool; hw_fib_p = hw_fib_pool;
fib_p = fib_pool; fib_p = fib_pool;
while (entry != &dev->fib_list) { while (entry != &dev->fib_list) {
/* /*
* Extract the fibctx * 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 * Check if the queue is getting
* backlogged * backlogged
*/ */
if (fibctx->count > 20) if (fibctx->count > 20) {
{
/* /*
* It's *not* jiffies folks, * It's *not* jiffies folks,
* but jiffies / HZ so do not * but jiffies / HZ so do not
...@@ -1905,7 +1845,12 @@ int aac_command_thread(void *data) ...@@ -1905,7 +1845,12 @@ int aac_command_thread(void *data)
* Warning: no sleep allowed while * Warning: no sleep allowed while
* holding spinlock * 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_newfib = *hw_fib_p;
*(hw_fib_p++) = NULL; *(hw_fib_p++) = NULL;
newfib = *fib_p; newfib = *fib_p;
...@@ -1927,9 +1872,7 @@ int aac_command_thread(void *data) ...@@ -1927,9 +1872,7 @@ int aac_command_thread(void *data)
* thread that is waiting. * thread that is waiting.
*/ */
up(&fibctx->wait_sem); up(&fibctx->wait_sem);
} else {
printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
}
entry = entry->next; entry = entry->next;
} }
/* /*
...@@ -1938,6 +1881,104 @@ int aac_command_thread(void *data) ...@@ -1938,6 +1881,104 @@ int aac_command_thread(void *data)
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
aac_fib_adapter_complete(fib, sizeof(u32)); aac_fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv); 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 */ /* Free up the remaining resources */
hw_fib_p = hw_fib_pool; hw_fib_p = hw_fib_pool;
fib_p = fib_pool; fib_p = fib_pool;
...@@ -1947,16 +1988,55 @@ int aac_command_thread(void *data) ...@@ -1947,16 +1988,55 @@ int aac_command_thread(void *data)
++fib_p; ++fib_p;
++hw_fib_p; ++hw_fib_p;
} }
kfree(hw_fib_pool);
kfree(fib_pool); kfree(fib_pool);
} free_hw_fib_pool:
kfree(hw_fib_pool);
free_fib:
kfree(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 * 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 * 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