Reworked aac_command_thread into aac_process_events Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@xxxxxxxxxxxxx> Signed-off-by: Dave Carroll <David.Carroll@xxxxxxxxxxxxx> --- Changes in V2: None drivers/scsi/aacraid/commsup.c | 410 ++++++++++++++++++++++------------------- 1 file changed, 217 insertions(+), 193 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 31c65ca..dd5819c 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1729,6 +1729,222 @@ int aac_check_health(struct aac_dev * aac) return BlinkLED; } +static void aac_process_events(struct aac_dev *dev) +{ + struct hw_fib *hw_fib, *hw_newfib; + struct fib *fib, *newfib; + struct aac_fib_context *fibctx; + unsigned long flags; + spinlock_t *t_lock; + + spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); + while (!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { + struct list_head *entry; + struct aac_aifcmd *aifcmd; + u32 time_now, time_last; + unsigned long flagv; + 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)); + continue; + } + /* + * 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); + } + + time_now = jiffies/HZ; + + /* + * Warning: no sleep allowed while + * holding spinlock. We take the estimate + * and pre-allocate a set of fibs outside the + * lock. + */ + num = le32_to_cpu(dev->init->r7.AdapterFibsSize) + / sizeof(struct hw_fib); /* some extra */ + spin_lock_irqsave(&dev->fib_lock, flagv); + entry = dev->fib_list.next; + while (entry != &dev->fib_list) { + entry = entry->next; + ++num; + } + spin_unlock_irqrestore(&dev->fib_lock, flagv); + hw_fib_pool = kmalloc_array(num, sizeof(struct hw_fib *), + GFP_KERNEL); + fib_pool = kmalloc_array(num, sizeof(struct fib *), + GFP_KERNEL); + if (num && fib_pool && hw_fib_pool) { + hw_fib_p = hw_fib_pool; + fib_p = fib_pool; + while (hw_fib_p < &hw_fib_pool[num]) { + *(hw_fib_p) = kmalloc(sizeof(struct hw_fib), + GFP_KERNEL); + if (!(*(hw_fib_p++))) { + --hw_fib_p; + break; + } + *(fib_p) = kmalloc(sizeof(struct fib), + GFP_KERNEL); + if (!(*(fib_p++))) { + kfree(*(--hw_fib_p)); + break; + } + } + num = hw_fib_p - hw_fib_pool; + if (!num) { + kfree(fib_pool); + fib_pool = NULL; + kfree(hw_fib_pool); + hw_fib_pool = NULL; + continue; + } + } else { + kfree(hw_fib_pool); + hw_fib_pool = NULL; + kfree(fib_pool); + fib_pool = NULL; + } + spin_lock_irqsave(&dev->fib_lock, flagv); + entry = dev->fib_list.next; + /* + * For each Context that is on the + * fibctxList, make a copy of the + * 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); + /* + * Check if the queue is getting + * backlogged + */ + if (fibctx->count > 20) { + /* + * It's *not* jiffies folks, + * but jiffies / HZ so do not + * panic ... + */ + time_last = fibctx->jiffies; + /* + * Has it been > 2 minutes + * since the last read off + * the queue? + */ + if ((time_now - time_last) > aif_timeout) { + entry = entry->next; + aac_close_fib_context(dev, fibctx); + continue; + } + } + /* + * Warning: no sleep allowed while + * holding spinlock + */ + if (hw_fib_p < &hw_fib_pool[num]) { + hw_newfib = *hw_fib_p; + *(hw_fib_p++) = NULL; + newfib = *fib_p; + *(fib_p++) = NULL; + /* + * Make the copy of the FIB + */ + memcpy(hw_newfib, hw_fib, + sizeof(struct hw_fib)); + memcpy(newfib, fib, sizeof(struct fib)); + newfib->hw_fib_va = hw_newfib; + /* + * Put the FIB onto the + * fibctx's fibs + */ + list_add_tail(&newfib->fiblink, + &fibctx->fib_list); + fibctx->count++; + /* + * Set the event to wake up the + * thread that is waiting. + */ + up(&fibctx->wait_sem); + } else { + pr_warn("aifd: didn't allocate NewFib.\n"); + } + entry = entry->next; + } + /* + * Set the status of this FIB + */ + *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); + aac_fib_adapter_complete(fib, sizeof(u32)); + spin_unlock_irqrestore(&dev->fib_lock, flagv); + /* Free up the remaining resources */ + hw_fib_p = hw_fib_pool; + fib_p = fib_pool; + while (hw_fib_p < &hw_fib_pool[num]) { + kfree(*hw_fib_p); + kfree(*fib_p); + ++fib_p; + ++hw_fib_p; + } + kfree(hw_fib_pool); + kfree(fib_pool); + kfree(fib); + spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, + flags); + } + /* + * There are no more AIF's + */ + spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, + flags); +} /** * aac_command_thread - command processing thread @@ -1743,10 +1959,6 @@ int aac_check_health(struct aac_dev * aac) int aac_command_thread(void *data) { 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; @@ -1766,196 +1978,8 @@ int aac_command_thread(void *data) 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 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 - * holding spinlock. We take the estimate - * and pre-allocate a set of fibs outside the - * lock. - */ - num = le32_to_cpu(dev->init->r7.AdapterFibsSize) - / sizeof(struct hw_fib); /* some extra */ - spin_lock_irqsave(&dev->fib_lock, flagv); - entry = dev->fib_list.next; - while (entry != &dev->fib_list) { - entry = entry->next; - ++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)))) { - 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; - break; - } - if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) { - 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; - } - spin_lock_irqsave(&dev->fib_lock, flagv); - entry = dev->fib_list.next; - /* - * For each Context that is on the - * fibctxList, make a copy of the - * 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); - /* - * Check if the queue is getting - * backlogged - */ - if (fibctx->count > 20) - { - /* - * It's *not* jiffies folks, - * but jiffies / HZ so do not - * panic ... - */ - time_last = fibctx->jiffies; - /* - * Has it been > 2 minutes - * since the last read off - * the queue? - */ - if ((time_now - time_last) > aif_timeout) { - entry = entry->next; - aac_close_fib_context(dev, fibctx); - continue; - } - } - /* - * Warning: no sleep allowed while - * holding spinlock - */ - if (hw_fib_p < &hw_fib_pool[num]) { - hw_newfib = *hw_fib_p; - *(hw_fib_p++) = NULL; - newfib = *fib_p; - *(fib_p++) = NULL; - /* - * Make the copy of the FIB - */ - memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); - memcpy(newfib, fib, sizeof(struct fib)); - newfib->hw_fib_va = hw_newfib; - /* - * Put the FIB onto the - * fibctx's fibs - */ - list_add_tail(&newfib->fiblink, &fibctx->fib_list); - fibctx->count++; - /* - * Set the event to wake up the - * thread that is waiting. - */ - up(&fibctx->wait_sem); - } else { - printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); - } - entry = entry->next; - } - /* - * Set the status of this FIB - */ - *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); - aac_fib_adapter_complete(fib, sizeof(u32)); - spin_unlock_irqrestore(&dev->fib_lock, flagv); - /* Free up the remaining resources */ - hw_fib_p = hw_fib_pool; - fib_p = fib_pool; - while (hw_fib_p < &hw_fib_pool[num]) { - kfree(*hw_fib_p); - kfree(*fib_p); - ++fib_p; - ++hw_fib_p; - } - kfree(hw_fib_pool); - kfree(fib_pool); - } - kfree(fib); - spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); - } - /* - * There are no more AIF's - */ - spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); + aac_process_events(dev); /* * Background activity -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html