Driver will call cmd completion routine from Reset path without waiting for cmd completion from isr context.
Signed-off-by: Bo Yang <[email protected]>
---
drivers/scsi/megaraid/megaraid_sas.c | 122 +++++++++++++------------
drivers/scsi/megaraid/megaraid_sas.h | 2
2 files changed, 70 insertions(+), 54 deletions(-)
diff -rupN linux-2.6.22_orig/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.22_new/drivers/scsi/megaraid/megaraid_sas.c
--- linux-2.6.22_orig/drivers/scsi/megaraid/megaraid_sas.c 2007-11-07 02:33:01.252078600 -0500
+++ linux-2.6.22_new/drivers/scsi/megaraid/megaraid_sas.c 2007-11-07 02:33:32.746290752 -0500
@@ -76,6 +76,10 @@ static DEFINE_MUTEX(megasas_async_queue_
static u32 megasas_dbg_lvl;
+static void
+megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ u8 alt_status);
+
/**
* megasas_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
@@ -886,6 +890,64 @@ static int megasas_slave_configure(struc
}
/**
+ * megasas_complete_cmd_dpc - Returns FW's controller structure
+ * @instance_addr: Address of adapter soft state
+ *
+ * Tasklet to complete cmds
+ */
+static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+{
+ u32 producer;
+ u32 consumer;
+ u32 context;
+ struct megasas_cmd *cmd;
+ struct megasas_instance *instance =
+ (struct megasas_instance *)instance_addr;
+ unsigned long flags;
+
+ /* If we have already declared adapter dead, donot complete cmds */
+ if (instance->hw_crit_error)
+ return;
+
+ spin_lock_irqsave(&instance->completion_lock, flags);
+
+ producer = *instance->producer;
+ consumer = *instance->consumer;
+
+ while (consumer != producer) {
+ context = instance->reply_queue[consumer];
+
+ cmd = instance->cmd_list[context];
+
+ megasas_complete_cmd(instance, cmd, DID_OK);
+
+ consumer++;
+ if (consumer == (instance->max_fw_cmds + 1)) {
+ consumer = 0;
+ }
+ }
+
+ *instance->consumer = producer;
+
+ spin_unlock_irqrestore(&instance->completion_lock, flags);
+
+ /*
+ * Check if we can restore can_queue
+ */
+ if (instance->flag & MEGASAS_FW_BUSY
+ && time_after(jiffies, instance->last_time + 5 * HZ)
+ && atomic_read(&instance->fw_outstanding) < 17) {
+
+ spin_lock_irqsave(instance->host->host_lock, flags);
+ instance->flag &= ~MEGASAS_FW_BUSY;
+ instance->host->can_queue =
+ instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+ spin_unlock_irqrestore(instance->host->host_lock, flags);
+ }
+}
+
+/**
* megasas_wait_for_outstanding - Wait for all outstanding cmds
* @instance: Adapter soft state
*
@@ -908,6 +970,11 @@ static int megasas_wait_for_outstanding(
if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
"commands to complete\n",i,outstanding);
+ /*
+ * Call cmd completion routine. Cmd to be
+ * be completed directly without depending on isr.
+ */
+ megasas_complete_cmd_dpc((unsigned long)instance);
}
msleep(1000);
@@ -1749,60 +1816,6 @@ megasas_get_ctrl_info(struct megasas_ins
}
/**
- * megasas_complete_cmd_dpc - Returns FW's controller structure
- * @instance_addr: Address of adapter soft state
- *
- * Tasklet to complete cmds
- */
-static void megasas_complete_cmd_dpc(unsigned long instance_addr)
-{
- u32 producer;
- u32 consumer;
- u32 context;
- struct megasas_cmd *cmd;
- struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
- unsigned long flags;
-
- /* If we have already declared adapter dead, donot complete cmds */
- if (instance->hw_crit_error)
- return;
-
- producer = *instance->producer;
- consumer = *instance->consumer;
-
- while (consumer != producer) {
- context = instance->reply_queue[consumer];
-
- cmd = instance->cmd_list[context];
-
- megasas_complete_cmd(instance, cmd, DID_OK);
-
- consumer++;
- if (consumer == (instance->max_fw_cmds + 1)) {
- consumer = 0;
- }
- }
-
- *instance->consumer = producer;
-
- /*
- * Check if we can restore can_queue
- */
- if (instance->flag & MEGASAS_FW_BUSY
- && time_after(jiffies, instance->last_time + 5 * HZ)
- && atomic_read(&instance->fw_outstanding) < 17) {
-
- spin_lock_irqsave(instance->host->host_lock, flags);
- instance->flag &= ~MEGASAS_FW_BUSY;
- instance->host->can_queue =
- instance->max_fw_cmds - MEGASAS_INT_CMDS;
-
- spin_unlock_irqrestore(instance->host->host_lock, flags);
- }
-
-}
-
-/**
* megasas_issue_init_mfi - Initializes the FW
* @instance: Adapter soft state
*
@@ -2394,6 +2407,7 @@ megasas_probe_one(struct pci_dev *pdev,
init_waitqueue_head(&instance->abort_cmd_wait_q);
spin_lock_init(&instance->cmd_pool_lock);
+ spin_lock_init(&instance->completion_lock);
sema_init(&instance->aen_mutex, 1);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
diff -rupN linux-2.6.22_orig/drivers/scsi/megaraid/megaraid_sas.h linux-2.6.22_new/drivers/scsi/megaraid/megaraid_sas.h
--- linux-2.6.22_orig/drivers/scsi/megaraid/megaraid_sas.h 2007-11-07 02:33:01.711008832 -0500
+++ linux-2.6.22_new/drivers/scsi/megaraid/megaraid_sas.h 2007-11-07 02:33:32.748290448 -0500
@@ -1084,6 +1084,8 @@ struct megasas_instance {
struct megasas_cmd **cmd_list;
struct list_head cmd_pool;
spinlock_t cmd_pool_lock;
+ /* used to synch producer, consumer ptrs in dpc */
+ spinlock_t completion_lock;
struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool;
On Fri, 2007-11-09 at 04:35 -0500, bo yang wrote:
> Driver will call cmd completion routine from Reset path without waiting for cmd completion from isr context.
Thanks. I'm going to take a look at this, as well as the other recent 2
patches for a couple of test kernels we have that are based on the -RT
patchset. We are seeing occasional problems with megasas (so far only
exhibited on specific systems based upon the PERC 5 cards) when:
* Using an -RT kernel.
* Lots of outstanding IO.
My analysis suggests that this happens because the -RT patch changes
tasklet behavior such that we won't run nearly as quickly as in vanilla
Linux, and we might end up with a lot more IO cmds outstanding with the
FW before we get around to dequeing them. I think there exists (but I
haven't proved it yet) a timing problem in that driver.
In a 2.6.21 test kernel we have, there's an inconsistency wrt. upstream
changes that happened at that time - James and Christoph were racing
wrt. oneanother and the use of the additional (optional) scsi host
callback that sas happens to use to handle io throttling. In later
kernels, this behavior almost seems to be working - I backported this to
2.6.21 and can see the throttle function get called a few times before
we finally go out to lunch. I'm planning to finish debugging tomorrow.
This is an FYI really, just to say that I'm actively poking at megasas
at the moment. I would also love to hear from yourself, and anyone else
who is (or who has) test[ing|ed] these ongoing patches on -RT.
Jon.