Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism

2016-12-15 Thread Madhani, Himanshu
Hi Bart, Christoph, 



On 12/15/16, 1:27 AM, "Bart Van Assche"  wrote:

>On 12/14/2016 10:06 PM, Christoph Hellwig wrote:
>> On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
>>> From: Quinn Tran 
>>>
>>> This patch adds capability to poll for an interrupt, If hardware
>>> does not generate any interrupt for 2 seconds.
>> 
>> This description sounds like the hardware might be buggy and not
>> generate interrupts, in which case 2 seconds is a very long time.
>> 
>> Can you explain the intention a bit better?
>
>In addition to Christoph's question: is this a workaround for a hardware
>bug or for a firmware bug? If it is a workaround for a firmware bug,
>since the qla2xxx firmware can be upgraded, why is an interrupt polling
>mechanism added to the kernel driver instead of fixing the firmware?
>
>Bart.

This issue was seen where we were debugging intermittent slow switch response
related to cable pull in a small set of test environment.  We thought it was
a HW issue but turns out to be the switch.  We left the patch in the test
cycle to see if the problem re-occur and missed taking it out before 
submission.  Since then we have not seen the problem re-occur. We’ll drop
this patch from the series. 


Thanks,
- Himanshu

>


Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism

2016-12-15 Thread Bart Van Assche
On 12/14/2016 10:06 PM, Christoph Hellwig wrote:
> On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
>> From: Quinn Tran 
>>
>> This patch adds capability to poll for an interrupt, If hardware
>> does not generate any interrupt for 2 seconds.
> 
> This description sounds like the hardware might be buggy and not
> generate interrupts, in which case 2 seconds is a very long time.
> 
> Can you explain the intention a bit better?

In addition to Christoph's question: is this a workaround for a hardware
bug or for a firmware bug? If it is a workaround for a firmware bug,
since the qla2xxx firmware can be upgraded, why is an interrupt polling
mechanism added to the kernel driver instead of fixing the firmware?

Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism

2016-12-14 Thread Christoph Hellwig
On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
> From: Quinn Tran 
> 
> This patch adds capability to poll for an interrupt, If hardware
> does not generate any interrupt for 2 seconds.

This description sounds like the hardware might be buggy and not
generate interrupts, in which case 2 seconds is a very long time.

Can you explain the intention a bit better?
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/22] qla2xxx: Add interrupt polling mechanism

2016-12-06 Thread Himanshu Madhani
From: Quinn Tran 

This patch adds capability to poll for an interrupt, If hardware
does not generate any interrupt for 2 seconds.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|  8 +
 drivers/scsi/qla2xxx/qla_dfs.c| 75 +++
 drivers/scsi/qla2xxx/qla_gbl.h|  1 +
 drivers/scsi/qla2xxx/qla_isr.c| 22 ++--
 drivers/scsi/qla2xxx/qla_os.c | 31 
 drivers/scsi/qla2xxx/qla_target.c |  6 
 6 files changed, 141 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6bf7ff9..09da61f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2921,6 +2921,10 @@ struct qla_msix_entry {
void *handle;
struct irq_affinity_notify irq_notify;
int cpuid;
+   irqreturn_t (*irq_handler)(int, void *);
+   u32 intr_cnt;
+   u32 last_intr_cnt;
+   struct work_struct intr_work;
 };
 
 #defineWATCH_INTERVAL  1   /* number of seconds */
@@ -3826,6 +3830,10 @@ struct qla_hw_data {
 
struct qlt_hw_data tgt;
int allow_cna_fw_dump;
+
+   int irqpoll_interval, irqpoll_cnt;
+   struct dentry *dfs_irqpoll;
+#define MAX_IRQPOLL_INTV 30
 };
 
 struct qla_tgt_counters {
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index f69ff52..18cedf7 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -12,6 +12,68 @@
 static struct dentry *qla2x00_dfs_root;
 static atomic_t qla2x00_dfs_root_count;
 
+
+static int
+qla_dfs_irqpoll_show(struct seq_file *s,  void *unused)
+{
+   struct scsi_qla_host *vha = s->private;
+   struct qla_hw_data *ha = vha->hw;
+
+   seq_printf(s, "IRQ poll interval: %d Seconds (max=%d, def=0/off)\n",
+ha->irqpoll_interval, MAX_IRQPOLL_INTV);
+
+   return 0;
+}
+
+static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user 
*ubuf,
+   size_t len, loff_t *offp)
+{
+   struct seq_file *s = file->private_data;
+   char *buf;
+   int ret = 0;
+   int interval = 0;
+   struct scsi_qla_host *vha = s->private;
+   struct qla_hw_data *ha = vha->hw;
+
+   buf = memdup_user(ubuf, len);
+   if (IS_ERR(buf))
+   return PTR_ERR(buf);
+
+   if (sscanf(buf, "%d", &interval) != 1)
+   return -EINVAL;
+
+   if (interval > MAX_IRQPOLL_INTV  || interval < 0)
+   return -ERANGE;
+
+   ha->irqpoll_interval = interval;
+
+   if (ha->irqpoll_interval == 0)
+   ql_log(ql_log_info, vha, 0x,
+   "IRQ Poll turned off.\n");
+   else
+   ql_log(ql_log_info, vha, 0x,
+   "IRQ Poll turned on(%d).\n", ha->irqpoll_interval);
+
+
+   kfree(buf);
+   return (ret) ? ret : len;
+}
+
+static int
+qla_dfs_irqpoll_open(struct inode *inode, struct file *file)
+{
+   struct scsi_qla_host *vha = inode->i_private;
+   return single_open(file, qla_dfs_irqpoll_show, vha);
+}
+
+static const struct file_operations dfs_irqpoll = {
+   .open   = qla_dfs_irqpoll_open,
+   .read   = seq_read,
+   .llseek = seq_lseek,
+   .release= single_release,
+   .write  = qla_dfs_irqpoll_write,
+};
+
 static int
 qla2x00_dfs_irq_cpuid_show(struct seq_file *s, void *unused)
 {
@@ -357,6 +419,14 @@
goto out;
}
 
+   ha->dfs_irqpoll = debugfs_create_file("irq_poll_interval",
+   S_IRUSR, ha->dfs_dir, vha, &dfs_irqpoll);
+   if (!ha->dfs_irqpoll) {
+   ql_log(ql_log_warn, vha, 0x,
+   "Unable to create debugFS irq_poll_interval node.\n");
+   goto out;
+   }
+
 
 out:
return 0;
@@ -367,6 +437,11 @@
 {
struct qla_hw_data *ha = vha->hw;
 
+   if (ha->dfs_irqpoll) {
+   debugfs_remove(ha->dfs_irqpoll);
+   ha->dfs_irqpoll = NULL;
+   }
+
if (ha->dfs_irq_cpuid) {
debugfs_remove(ha->dfs_irq_cpuid);
ha->dfs_irq_cpuid = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3593a39..944f37a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -140,6 +140,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, 
port_id_t *,
 extern int ql2xexlogins;
 extern int ql2xexchoffld;
 extern int ql2xfwholdabts;
+extern struct workqueue_struct *qla_wq;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c7f73b1..eee98c9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3003,6 +3003,7 @@ void qla24xx_process_respon