All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17
@ 2012-04-24  5:32 vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 1/6] qla4xxx: Correct early completion of pending mbox vikas.chaudhary
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

James,

Please apply the following patches to scsi-misc for inclusion in mainline.

Lalit Chandivade (1):
      qla4xxx: Correct early completion of pending mbox.

Manish Rangankar (2):
      qla4xxx: Fix kernel panic during discovery logout.
      qla4xxx: Fix clear ddb mbx command failure issue.

Tej Parkash (2):
      qla4xxx: Add change_queue_depth API support
      qla4xxx: Capture minidump for ISP82XX on firmware failure

Vikas Chaudhary (1):
      qla4xxx: Update driver version to 5.02.00-k17

 drivers/scsi/qla4xxx/ql4_attr.c    |  127 +++++++
 drivers/scsi/qla4xxx/ql4_def.h     |   22 ++
 drivers/scsi/qla4xxx/ql4_fw.h      |   28 ++
 drivers/scsi/qla4xxx/ql4_glbl.h    |    8 +
 drivers/scsi/qla4xxx/ql4_init.c    |   95 ++++-
 drivers/scsi/qla4xxx/ql4_mbx.c     |  111 +++++-
 drivers/scsi/qla4xxx/ql4_nx.c      |  738 +++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla4xxx/ql4_nx.h      |  192 ++++++++++
 drivers/scsi/qla4xxx/ql4_os.c      |   80 +++-
 drivers/scsi/qla4xxx/ql4_version.h |    2 +-

Thanks,
Vikas.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] qla4xxx: Correct early completion of pending mbox.
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 2/6] qla4xxx: Fix kernel panic during discovery logout vikas.chaudhary
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Lalit Chandivade <lalit.chandivade@qlogic.com>

Check for Firmware Hang (AF_FW_RECOVERY) after mailbox command
has gained access to ensure that the mailbox command does not
wait un-necessarily during a firmware recovery and prevent
premature mailbox timeout which will lead to back to back reset's.

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_mbx.c |   38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 7ac21da..c7d101e 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -51,25 +51,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
 		}
 	}
 
-	if (is_qla8022(ha)) {
-		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
-			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
-			    "prematurely completing mbx cmd as firmware "
-			    "recovery detected\n", ha->host_no, __func__));
-			return status;
-		}
-		/* Do not send any mbx cmd if h/w is in failed state*/
-		qla4_8xxx_idc_lock(ha);
-		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-		qla4_8xxx_idc_unlock(ha);
-		if (dev_state == QLA82XX_DEV_FAILED) {
-			ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in "
-			    "failed state, do not send any mailbox commands\n",
-			    ha->host_no, __func__);
-			return status;
-		}
-	}
-
 	if ((is_aer_supported(ha)) &&
 	    (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) {
 		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, "
@@ -96,6 +77,25 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
 		msleep(10);
 	}
 
+	if (is_qla8022(ha)) {
+		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
+			DEBUG2(ql4_printk(KERN_WARNING, ha,
+					  "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
+					  ha->host_no, __func__));
+			goto mbox_exit;
+		}
+		/* Do not send any mbx cmd if h/w is in failed state*/
+		qla4_8xxx_idc_lock(ha);
+		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		qla4_8xxx_idc_unlock(ha);
+		if (dev_state == QLA82XX_DEV_FAILED) {
+			ql4_printk(KERN_WARNING, ha,
+				   "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n",
+				   ha->host_no, __func__);
+			goto mbox_exit;
+		}
+	}
+
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
 	ha->mbox_status_count = outCount;
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/6] qla4xxx: Fix kernel panic during discovery logout.
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 1/6] qla4xxx: Correct early completion of pending mbox vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 3/6] qla4xxx: Fix clear ddb mbx command failure issue vikas.chaudhary
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Manish Rangankar

From: Manish Rangankar <manish.rangankar@qlogic.com>

Update the session and connection parameter before sending
connection logged in event to iscsiadm because in some
scenario logout may come in just after we send the logged
in event to user, which free up session, connection and ddb,
but DPC is still updating session and connect parameter
which can lead to panic.

Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_init.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 90ee5d8..0548436 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -884,8 +884,8 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
 		switch (state) {
 		case DDB_DS_SESSION_ACTIVE:
 		case DDB_DS_DISCOVERY:
-			ddb_entry->unblock_sess(ddb_entry->sess);
 			qla4xxx_update_session_conn_param(ha, ddb_entry);
+			ddb_entry->unblock_sess(ddb_entry->sess);
 			status = QLA_SUCCESS;
 			break;
 		case DDB_DS_SESSION_FAILED:
@@ -897,6 +897,7 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
 		}
 		break;
 	case DDB_DS_SESSION_ACTIVE:
+	case DDB_DS_DISCOVERY:
 		switch (state) {
 		case DDB_DS_SESSION_FAILED:
 			/*
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/6] qla4xxx: Fix clear ddb mbx command failure issue.
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 1/6] qla4xxx: Correct early completion of pending mbox vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 2/6] qla4xxx: Fix kernel panic during discovery logout vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 4/6] qla4xxx: Add change_queue_depth API support vikas.chaudhary
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Manish Rangankar

From: Manish Rangankar <manish.rangankar@qlogic.com>

Allow ddb state to change to DDB_DS_NO_CONNECTION_ACTIVE or
DDB_DS_SESSION_FAILED before issuing clear ddb mailbox cmd,
because clear ddb mailbox cmd fails if the ddb state is not
equal to DDB_DS_NO_CONNECTION_ACTIVE or DDB_DS_SESSION_FAILED.

Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_os.c |   36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ee47820..45144aa 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1555,19 +1555,53 @@ static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)
 	struct iscsi_session *sess;
 	struct ddb_entry *ddb_entry;
 	struct scsi_qla_host *ha;
-	unsigned long flags;
+	unsigned long flags, wtime;
+	struct dev_db_entry *fw_ddb_entry = NULL;
+	dma_addr_t fw_ddb_entry_dma;
+	uint32_t ddb_state;
+	int ret;
 
 	DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
 	sess = cls_sess->dd_data;
 	ddb_entry = sess->dd_data;
 	ha = ddb_entry->ha;
 
+	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+					  &fw_ddb_entry_dma, GFP_KERNEL);
+	if (!fw_ddb_entry) {
+		ql4_printk(KERN_ERR, ha,
+			   "%s: Unable to allocate dma buffer\n", __func__);
+		goto destroy_session;
+	}
+
+	wtime = jiffies + (HZ * LOGOUT_TOV);
+	do {
+		ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,
+					      fw_ddb_entry, fw_ddb_entry_dma,
+					      NULL, NULL, &ddb_state, NULL,
+					      NULL, NULL);
+		if (ret == QLA_ERROR)
+			goto destroy_session;
+
+		if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) ||
+		    (ddb_state == DDB_DS_SESSION_FAILED))
+			goto destroy_session;
+
+		schedule_timeout_uninterruptible(HZ);
+	} while ((time_after(wtime, jiffies)));
+
+destroy_session:
 	qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	qla4xxx_free_ddb(ha, ddb_entry);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
 	iscsi_session_teardown(cls_sess);
+
+	if (fw_ddb_entry)
+		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+				  fw_ddb_entry, fw_ddb_entry_dma);
 }
 
 static struct iscsi_cls_conn *
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/6] qla4xxx: Add change_queue_depth API support
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
                   ` (2 preceding siblings ...)
  2012-04-24  5:32 ` [PATCH 3/6] qla4xxx: Fix clear ddb mbx command failure issue vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  2012-04-27 15:43   ` Mike Christie
  2012-04-24  5:32 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure vikas.chaudhary
  2012-04-24  5:32 ` [PATCH 6/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
  5 siblings, 1 reply; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Tej Parkash

From: Tej Parkash <tej.parkash@qlogic.com>

change_queue_depth will adjust device queuedepth upon receiving
"SAM_STAT_TASK_SET_FULL" scsi status from the target.
Also added ql4xqfulltracking command line param to enable or disable
queuefull tracking. One can disabling queuefull tracking to ensure
user set scsi device queuedepth is not altered.

Signed-off-by: Tej Parkash <tej.parkash@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_os.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 45144aa..613c119 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -68,6 +68,14 @@ MODULE_PARM_DESC(ql4xmaxqdepth,
 		 " Maximum queue depth to report for target devices.\n"
 		 "\t\t  Default: 32.");
 
+static int ql4xqfulltracking = 1;
+module_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql4xqfulltracking,
+		 " Enable or disable dynamic tracking and adjustment of\n"
+		 "\t\t scsi device queue depth.\n"
+		 "\t\t  0 - Disable.\n"
+		 "\t\t  1 - Enable. (Default)");
+
 static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
 module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
 MODULE_PARM_DESC(ql4xsess_recovery_tmo,
@@ -140,6 +148,8 @@ static int qla4xxx_slave_configure(struct scsi_device *device);
 static void qla4xxx_slave_destroy(struct scsi_device *sdev);
 static umode_t ql4_attr_is_visible(int param_type, int param);
 static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
+static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				      int reason);
 
 static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
     QLA82XX_LEGACY_INTR_CONFIG;
@@ -159,6 +169,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
 	.slave_configure	= qla4xxx_slave_configure,
 	.slave_alloc		= qla4xxx_slave_alloc,
 	.slave_destroy		= qla4xxx_slave_destroy,
+	.change_queue_depth	= qla4xxx_change_queue_depth,
 
 	.this_id		= -1,
 	.cmd_per_lun		= 3,
@@ -5251,6 +5262,17 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev)
 	scsi_deactivate_tcq(sdev, 1);
 }
 
+static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
+				      int reason)
+{
+	int queue_depth;
+	if (!ql4xqfulltracking)
+		return -EOPNOTSUPP;
+
+	queue_depth = iscsi_change_queue_depth(sdev, qdepth, reason);
+	return queue_depth;
+}
+
 /**
  * qla4xxx_del_from_active_array - returns an active srb
  * @ha: Pointer to host adapter structure.
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
                   ` (3 preceding siblings ...)
  2012-04-24  5:32 ` [PATCH 4/6] qla4xxx: Add change_queue_depth API support vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  2012-04-27 16:05   ` Mike Christie
  2012-04-24  5:32 ` [PATCH 6/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
  5 siblings, 1 reply; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand,
	Tej Parkash, Shyam Sundar

From: Tej Parkash <tej.parkash@qlogic.com>

Added support to capture dump (Minidump) which allows us to
catpure a snapshot of the firmware/hardware states at the time
of firmware failure

Signed-off-by: Tej Parkash <tej.parkash@qlogic.com>
Signed-off-by: Shyam Sundar <shyam.sundar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_attr.c |  127 +++++++
 drivers/scsi/qla4xxx/ql4_def.h  |   22 ++
 drivers/scsi/qla4xxx/ql4_fw.h   |   28 ++
 drivers/scsi/qla4xxx/ql4_glbl.h |    8 +
 drivers/scsi/qla4xxx/ql4_init.c |   92 +++++
 drivers/scsi/qla4xxx/ql4_mbx.c  |   73 ++++
 drivers/scsi/qla4xxx/ql4_nx.c   |  738 ++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla4xxx/ql4_nx.h   |  192 ++++++++++
 drivers/scsi/qla4xxx/ql4_os.c   |   22 ++
 9 files changed, 1286 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c
index 0b0a7d4..4068348 100644
--- a/drivers/scsi/qla4xxx/ql4_attr.c
+++ b/drivers/scsi/qla4xxx/ql4_attr.c
@@ -9,6 +9,133 @@
 #include "ql4_glbl.h"
 #include "ql4_dbg.h"
 
+static ssize_t
+qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj,
+			     struct bin_attribute *ba, char *buf, loff_t off,
+			     size_t count)
+{
+	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+					       struct device, kobj)));
+
+	if (!is_qla8022(ha))
+		return -EINVAL;
+
+	if (!test_bit(AF_82XX_DUMP_READING, &ha->flags))
+		return 0;
+
+	return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+				       ha->fw_dump_size);
+}
+
+static ssize_t
+qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj,
+			      struct bin_attribute *ba, char *buf, loff_t off,
+			      size_t count)
+{
+	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+					       struct device, kobj)));
+	uint32_t dev_state;
+	int reading;
+
+	if (!is_qla8022(ha))
+		return -EINVAL;
+
+	if (off != 0)
+		return 0;
+
+	reading = simple_strtol(buf, NULL, 10);
+	switch (reading) {
+	case 0:
+		/* clear dump collection flags */
+		if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) {
+			clear_bit(AF_82XX_FW_DUMPED, &ha->flags);
+			/* Reload minidump template */
+			qla4xxx_alloc_fw_dump(ha);
+			DEBUG2(ql4_printk(KERN_INFO, ha,
+					  "Firmware template reloaded\n"));
+		}
+
+		break;
+	case 1:
+		/* Set flag to read dump */
+		if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) &&
+		    !test_bit(AF_82XX_DUMP_READING, &ha->flags)) {
+			set_bit(AF_82XX_DUMP_READING, &ha->flags);
+			DEBUG2(ql4_printk(KERN_INFO, ha,
+					  "Raw firmware dump ready for read on (%ld).\n",
+					  ha->host_no));
+		}
+		break;
+	case 2:
+		/* Reset HBA */
+		qla4_8xxx_idc_lock(ha);
+		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		if (dev_state == QLA82XX_DEV_READY) {
+			ql4_printk(KERN_INFO, ha,
+				   "%s: Setting Need reset, reset_owner is 0x%x.\n",
+				   __func__, ha->func_num);
+			qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+					QLA82XX_DEV_NEED_RESET);
+			set_bit(AF_82XX_RST_OWNER, &ha->flags);
+		} else
+			ql4_printk(KERN_INFO, ha,
+				   "%s: Reset not performed as device state is 0x%x\n",
+				   __func__, dev_state);
+
+		qla4_8xxx_idc_unlock(ha);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+
+	return count;
+}
+
+static struct bin_attribute sysfs_fw_dump_attr = {
+	.attr = {
+		.name = "fw_dump",
+		.mode = S_IRUSR | S_IWUSR,
+	},
+	.size = 0,
+	.read = qla4_8xxx_sysfs_read_fw_dump,
+	.write = qla4_8xxx_sysfs_write_fw_dump,
+};
+
+static struct sysfs_entry {
+	char *name;
+	struct bin_attribute *attr;
+} bin_file_entries[] = {
+	{ "fw_dump", &sysfs_fw_dump_attr },
+	{ NULL },
+};
+
+void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha)
+{
+	struct Scsi_Host *host = ha->host;
+	struct sysfs_entry *iter;
+	int ret;
+
+	for (iter = bin_file_entries; iter->name; iter++) {
+		ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
+					    iter->attr);
+		if (ret)
+			ql4_printk(KERN_ERR, ha,
+				   "Unable to create sysfs %s binary attribute (%d).\n",
+				   iter->name, ret);
+	}
+}
+
+void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha)
+{
+	struct Scsi_Host *host = ha->host;
+	struct sysfs_entry *iter;
+
+	for (iter = bin_file_entries; iter->name; iter++)
+		sysfs_remove_bin_file(&host->shost_gendev.kobj,
+				      iter->attr);
+}
+
 /* Scsi_Host attributes. */
 static ssize_t
 qla4xxx_fw_version_show(struct device *dev,
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 7f2492e..96a5616 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -398,6 +398,16 @@ struct isp_operations {
 	int (*get_sys_info) (struct scsi_qla_host *);
 };
 
+struct ql4_mdump_size_table {
+	uint32_t size;
+	uint32_t size_cmask_02;
+	uint32_t size_cmask_04;
+	uint32_t size_cmask_08;
+	uint32_t size_cmask_10;
+	uint32_t size_cmask_FF;
+	uint32_t version;
+};
+
 /*qla4xxx ipaddress configuration details */
 struct ipaddress_config {
 	uint16_t ipv4_options;
@@ -485,6 +495,10 @@ struct scsi_qla_host {
 #define AF_EEH_BUSY			20 /* 0x00100000 */
 #define AF_PCI_CHANNEL_IO_PERM_FAILURE	21 /* 0x00200000 */
 #define AF_BUILD_DDB_LIST		22 /* 0x00400000 */
+#define AF_82XX_FW_DUMPED		24 /* 0x01000000 */
+#define AF_82XX_RST_OWNER		25 /* 0x02000000 */
+#define AF_82XX_DUMP_READING		26 /* 0x04000000 */
+
 	unsigned long dpc_flags;
 
 #define DPC_RESET_HA			1 /* 0x00000002 */
@@ -662,6 +676,11 @@ struct scsi_qla_host {
 
 	uint32_t nx_dev_init_timeout;
 	uint32_t nx_reset_timeout;
+	void *fw_dump;
+	uint32_t fw_dump_size;
+	uint32_t fw_dump_capture_mask;
+	void *fw_dump_tmplt_hdr;
+	uint32_t fw_dump_tmplt_size;
 
 	struct completion mbx_intr_comp;
 
@@ -936,4 +955,7 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha)
 #define PROCESS_ALL_AENS	 0
 #define FLUSH_DDB_CHANGED_AENS	 1
 
+/* Defines for udev events */
+#define QL4_UEVENT_CODE_FW_DUMP		0
+
 #endif	/*_QLA4XXX_H */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 210cd1d..7240948 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -385,6 +385,11 @@ struct qla_flt_region {
 #define MBOX_CMD_GET_IP_ADDR_STATE		0x0091
 #define MBOX_CMD_SEND_IPV6_ROUTER_SOL		0x0092
 #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR	0x0093
+#define MBOX_CMD_MINIDUMP			0x0129
+
+/* Minidump subcommand */
+#define MINIDUMP_GET_SIZE_SUBCOMMAND		0x00
+#define MINIDUMP_GET_TMPLT_SUBCOMMAND		0x01
 
 /* Mailbox 1 */
 #define FW_STATE_READY				0x0000
@@ -1190,4 +1195,27 @@ struct ql_iscsi_stats {
 	uint8_t reserved2[264]; /* 0x0308 - 0x040F */
 };
 
+#define QLA82XX_DBG_STATE_ARRAY_LEN		16
+#define QLA82XX_DBG_CAP_SIZE_ARRAY_LEN		8
+#define QLA82XX_DBG_RSVD_ARRAY_LEN		8
+
+struct qla4_8xxx_minidump_template_hdr {
+	uint32_t entry_type;
+	uint32_t first_entry_offset;
+	uint32_t size_of_template;
+	uint32_t capture_debug_level;
+	uint32_t num_of_entries;
+	uint32_t version;
+	uint32_t driver_timestamp;
+	uint32_t checksum;
+
+	uint32_t driver_capture_mask;
+	uint32_t driver_info_word2;
+	uint32_t driver_info_word3;
+	uint32_t driver_info_word4;
+
+	uint32_t saved_state_array[QLA82XX_DBG_STATE_ARRAY_LEN];
+	uint32_t capture_size_array[QLA82XX_DBG_CAP_SIZE_ARRAY_LEN];
+};
+
 #endif /*  _QLA4X_FW_H */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 9105366..20b49d0 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -196,10 +196,18 @@ int qla4xxx_bsg_request(struct bsg_job *bsg_job);
 int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job);
 
 void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry);
+int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
+				  dma_addr_t phys_addr);
+int qla4xxx_req_template_size(struct scsi_qla_host *ha);
+void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha);
+void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha);
+void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdontresethba;
 extern int ql4xenablemsix;
+extern int ql4xmdcapmask;
+extern int ql4xenablemd;
 
 extern struct device_attribute *qla4xxx_host_attrs[];
 #endif /* _QLA4x_GBL_H */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 0548436..bf36723 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -277,6 +277,94 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
 	return ipv4_wait|ipv6_wait;
 }
 
+/**
+ * qla4xxx_alloc_fw_dump - Allocate memory for minidump data.
+ * @ha: pointer to host adapter structure.
+ **/
+void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha)
+{
+	int status;
+	uint32_t capture_debug_level;
+	int hdr_entry_bit, k;
+	void *md_tmp;
+	dma_addr_t md_tmp_dma;
+	struct qla4_8xxx_minidump_template_hdr *md_hdr;
+
+	if (ha->fw_dump) {
+		ql4_printk(KERN_WARNING, ha,
+			   "Firmware dump previously allocated.\n");
+		return;
+	}
+
+	status = qla4xxx_req_template_size(ha);
+	if (status != QLA_SUCCESS) {
+		ql4_printk(KERN_INFO, ha,
+			   "scsi%ld: Failed to get template size\n",
+			   ha->host_no);
+		return;
+	}
+
+	clear_bit(AF_82XX_FW_DUMPED, &ha->flags);
+
+	/* Allocate memory for saving the template */
+	md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size,
+				    &md_tmp_dma, GFP_KERNEL);
+
+	/* Request template */
+	status =  qla4xxx_get_minidump_template(ha, md_tmp_dma);
+	if (status != QLA_SUCCESS) {
+		ql4_printk(KERN_INFO, ha,
+			   "scsi%ld: Failed to get minidump template\n",
+			   ha->host_no);
+		goto alloc_cleanup;
+	}
+
+	md_hdr = (struct qla4_8xxx_minidump_template_hdr *)md_tmp;
+
+	capture_debug_level = md_hdr->capture_debug_level;
+
+	/* Get capture mask based on module loadtime setting. */
+	if (ql4xmdcapmask >= 0x3 && ql4xmdcapmask <= 0x7F)
+		ha->fw_dump_capture_mask = ql4xmdcapmask;
+	else
+		ha->fw_dump_capture_mask = capture_debug_level;
+
+	md_hdr->driver_capture_mask = ha->fw_dump_capture_mask;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Minimum num of entries = %d\n",
+			  md_hdr->num_of_entries));
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Dump template size  = %d\n",
+			  ha->fw_dump_tmplt_size));
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Selected Capture mask =0x%x\n",
+			  ha->fw_dump_capture_mask));
+
+	/* Calculate fw_dump_size */
+	for (hdr_entry_bit = 0x2, k = 1; (hdr_entry_bit & 0xFF);
+	     hdr_entry_bit <<= 1, k++) {
+		if (hdr_entry_bit & ha->fw_dump_capture_mask)
+			ha->fw_dump_size += md_hdr->capture_size_array[k];
+	}
+
+	/* Total firmware dump size including command header */
+	ha->fw_dump_size += ha->fw_dump_tmplt_size;
+	ha->fw_dump = vmalloc(ha->fw_dump_size);
+	if (!ha->fw_dump)
+		goto alloc_cleanup;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "Minidump Tempalate Size = 0x%x KB\n",
+			  ha->fw_dump_tmplt_size));
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "Total Minidump size = 0x%x KB\n", ha->fw_dump_size));
+
+	memcpy(ha->fw_dump, md_tmp, ha->fw_dump_tmplt_size);
+	ha->fw_dump_tmplt_hdr = ha->fw_dump;
+
+alloc_cleanup:
+	dma_free_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size,
+			  md_tmp, md_tmp_dma);
+}
+
 static int qla4xxx_fw_ready(struct scsi_qla_host *ha)
 {
 	uint32_t timeout_count;
@@ -445,9 +533,13 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
 			      "control block\n", ha->host_no, __func__));
 		return status;
 	}
+
 	if (!qla4xxx_fw_ready(ha))
 		return status;
 
+	if (is_qla8022(ha) && !test_bit(AF_INIT_DONE, &ha->flags))
+		qla4xxx_alloc_fw_dump(ha);
+
 	return qla4xxx_get_firmware_status(ha);
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index c7d101e..cab8f66 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -270,6 +270,79 @@ mbox_exit:
 	return status;
 }
 
+/**
+ * qla4xxx_get_minidump_template - Get the firmware template
+ * @ha: Pointer to host adapter structure.
+ * @phys_addr: dma address for template
+ *
+ * Obtain the minidump template from firmware during initialization
+ * as it may not be available when minidump is desired.
+ **/
+int qla4xxx_get_minidump_template(struct scsi_qla_host *ha,
+				  dma_addr_t phys_addr)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
+	mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND;
+	mbox_cmd[2] = LSDW(phys_addr);
+	mbox_cmd[3] = MSDW(phys_addr);
+	mbox_cmd[4] = ha->fw_dump_tmplt_size;
+	mbox_cmd[5] = 0;
+
+	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+					 &mbox_sts[0]);
+	if (status != QLA_SUCCESS) {
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n",
+				  ha->host_no, __func__, mbox_cmd[0],
+				  mbox_sts[0], mbox_sts[1]));
+	}
+	return status;
+}
+
+/**
+ * qla4xxx_req_template_size - Get minidump template size from firmware.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_req_template_size(struct scsi_qla_host *ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_MINIDUMP;
+	mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND;
+
+	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0],
+					 &mbox_sts[0]);
+	if (status == QLA_SUCCESS) {
+		ha->fw_dump_tmplt_size = mbox_sts[1];
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "%s: sts[0]=0x%04x, template  size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n",
+				  __func__, mbox_sts[0], mbox_sts[1],
+				  mbox_sts[2], mbox_sts[3], mbox_sts[4],
+				  mbox_sts[5], mbox_sts[6], mbox_sts[7]));
+		if (ha->fw_dump_tmplt_size == 0)
+			status = QLA_ERROR;
+	} else {
+		ql4_printk(KERN_WARNING, ha,
+			   "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n",
+			   __func__, mbox_sts[0], mbox_sts[1]);
+		status = QLA_ERROR;
+	}
+
+	return status;
+}
+
 void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha)
 {
 	set_bit(AF_FW_RECOVERY, &ha->flags);
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index e1e46b6..228b670 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -7,6 +7,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pci.h>
+#include <linux/ratelimit.h>
 #include "ql4_def.h"
 #include "ql4_glbl.h"
 
@@ -420,6 +421,38 @@ qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off)
 	return data;
 }
 
+/* Minidump related functions */
+static int qla4_8xxx_md_rw_32(struct scsi_qla_host *ha, uint32_t off,
+			      u32 data, uint8_t flag)
+{
+	uint32_t win_read, off_value, rval = QLA_SUCCESS;
+
+	off_value  = off & 0xFFFF0000;
+	writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
+
+	/* Read back value to make sure write has gone through before trying
+	 * to use it.
+	 */
+	win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
+	if (win_read != off_value) {
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "%s: Written (0x%x) != Read (0x%x), off=0x%x\n",
+				   __func__, off_value, win_read, off));
+		return QLA_ERROR;
+	}
+
+	off_value  = off & 0x0000FFFF;
+
+	if (flag)
+		writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M +
+					      ha->nx_pcibase));
+	else
+		rval = readl((void __iomem *)(off_value + CRB_INDIRECT_2M +
+					      ha->nx_pcibase));
+
+	return rval;
+}
+
 #define CRB_WIN_LOCK_TIMEOUT 100000000
 
 int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha)
@@ -1252,9 +1285,9 @@ qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha,
 		}
 
 		if (j >= MAX_CTL_CHECK) {
-			if (printk_ratelimit())
-				ql4_printk(KERN_ERR, ha,
-				    "failed to read through agent\n");
+			printk_ratelimited(KERN_ERR
+					   "%s: failed to read through agent\n",
+					   __func__);
 			break;
 		}
 
@@ -1390,7 +1423,8 @@ qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha,
 		if (j >= MAX_CTL_CHECK) {
 			if (printk_ratelimit())
 				ql4_printk(KERN_ERR, ha,
-				    "failed to write through agent\n");
+					   "%s: failed to read through agent\n",
+					   __func__);
 			ret = -1;
 			break;
 		}
@@ -1462,6 +1496,8 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha)
 
 	drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
 	drv_active |= (1 << (ha->func_num * 4));
+	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",
+		   __func__, ha->host_no, drv_active);
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -1472,6 +1508,8 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha)
 
 	drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
 	drv_active &= ~(1 << (ha->func_num * 4));
+	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",
+		   __func__, ha->host_no, drv_active);
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -1497,6 +1535,8 @@ qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha)
 
 	drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
 	drv_state |= (1 << (ha->func_num * 4));
+	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",
+		   __func__, ha->host_no, drv_state);
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
 }
 
@@ -1507,6 +1547,8 @@ qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha)
 
 	drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
 	drv_state &= ~(1 << (ha->func_num * 4));
+	ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",
+		   __func__, ha->host_no, drv_state);
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
 }
 
@@ -1601,6 +1643,629 @@ static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha)
 	qla4_8xxx_rom_unlock(ha);
 }
 
+static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+	struct qla82xx_minidump_entry_crb *crb_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	crb_hdr = (struct qla82xx_minidump_entry_crb *)entry_hdr;
+	r_addr = crb_hdr->addr;
+	r_stride = crb_hdr->crb_strd.addr_stride;
+	loop_cnt = crb_hdr->op_count;
+
+	for (i = 0; i < loop_cnt; i++) {
+		r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0);
+		*data_ptr++ = cpu_to_le32(r_addr);
+		*data_ptr++ = cpu_to_le32(r_value);
+		r_addr += r_stride;
+	}
+	*d_ptr = data_ptr;
+}
+
+static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha,
+				 struct qla82xx_minidump_entry_hdr *entry_hdr,
+				 uint32_t **d_ptr)
+{
+	uint32_t addr, r_addr, c_addr, t_r_addr;
+	uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+	unsigned long p_wait, w_time, p_mask;
+	uint32_t c_value_w, c_value_r;
+	struct qla82xx_minidump_entry_cache *cache_hdr;
+	int rval = QLA_ERROR;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr;
+
+	loop_count = cache_hdr->op_count;
+	r_addr = cache_hdr->read_addr;
+	c_addr = cache_hdr->control_addr;
+	c_value_w = cache_hdr->cache_ctrl.write_value;
+
+	t_r_addr = cache_hdr->tag_reg_addr;
+	t_value = cache_hdr->addr_ctrl.init_tag_value;
+	r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+	p_wait = cache_hdr->cache_ctrl.poll_wait;
+	p_mask = cache_hdr->cache_ctrl.poll_mask;
+
+	for (i = 0; i < loop_count; i++) {
+		qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1);
+
+		if (c_value_w)
+			qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1);
+
+		if (p_mask) {
+			w_time = jiffies + p_wait;
+			do {
+				c_value_r = qla4_8xxx_md_rw_32(ha, c_addr,
+								0, 0);
+				if ((c_value_r & p_mask) == 0) {
+					break;
+				} else if (time_after_eq(jiffies, w_time)) {
+					/* capturing dump failed */
+					return rval;
+				}
+			} while (1);
+		}
+
+		addr = r_addr;
+		for (k = 0; k < r_cnt; k++) {
+			r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0);
+			*data_ptr++ = cpu_to_le32(r_value);
+			addr += cache_hdr->read_ctrl.read_addr_stride;
+		}
+
+		t_value += cache_hdr->addr_ctrl.tag_value_stride;
+	}
+	*d_ptr = data_ptr;
+	return QLA_SUCCESS;
+}
+
+static int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr)
+{
+	struct qla82xx_minidump_entry_crb *crb_entry;
+	uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS;
+	uint32_t crb_addr;
+	unsigned long wtime;
+	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr;
+	int i;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)
+						ha->fw_dump_tmplt_hdr;
+	crb_entry = (struct qla82xx_minidump_entry_crb *)entry_hdr;
+
+	crb_addr = crb_entry->addr;
+	for (i = 0; i < crb_entry->op_count; i++) {
+		opcode = crb_entry->crb_ctrl.opcode;
+		if (opcode & QLA82XX_DBG_OPCODE_WR) {
+			qla4_8xxx_md_rw_32(ha, crb_addr,
+					   crb_entry->value_1, 1);
+			opcode &= ~QLA82XX_DBG_OPCODE_WR;
+		}
+		if (opcode & QLA82XX_DBG_OPCODE_RW) {
+			read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0);
+			qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1);
+			opcode &= ~QLA82XX_DBG_OPCODE_RW;
+		}
+		if (opcode & QLA82XX_DBG_OPCODE_AND) {
+			read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0);
+			read_value &= crb_entry->value_2;
+			opcode &= ~QLA82XX_DBG_OPCODE_AND;
+			if (opcode & QLA82XX_DBG_OPCODE_OR) {
+				read_value |= crb_entry->value_3;
+				opcode &= ~QLA82XX_DBG_OPCODE_OR;
+			}
+			qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1);
+		}
+		if (opcode & QLA82XX_DBG_OPCODE_OR) {
+			read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0);
+			read_value |= crb_entry->value_3;
+			qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1);
+			opcode &= ~QLA82XX_DBG_OPCODE_OR;
+		}
+		if (opcode & QLA82XX_DBG_OPCODE_POLL) {
+			poll_time = crb_entry->crb_strd.poll_timeout;
+			wtime = jiffies + poll_time;
+			read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0);
+
+			do {
+				if ((read_value & crb_entry->value_2) ==
+				    crb_entry->value_1)
+					break;
+				else if (time_after_eq(jiffies, wtime)) {
+					/* capturing dump failed */
+					rval = QLA_ERROR;
+					break;
+				} else
+					read_value = qla4_8xxx_md_rw_32(ha,
+								crb_addr, 0, 0);
+			} while (1);
+			opcode &= ~QLA82XX_DBG_OPCODE_POLL;
+		}
+
+		if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
+			if (crb_entry->crb_strd.state_index_a) {
+				index = crb_entry->crb_strd.state_index_a;
+				addr = tmplt_hdr->saved_state_array[index];
+			} else {
+				addr = crb_addr;
+			}
+
+			read_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0);
+			index = crb_entry->crb_ctrl.state_index_v;
+			tmplt_hdr->saved_state_array[index] = read_value;
+			opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
+		}
+
+		if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
+			if (crb_entry->crb_strd.state_index_a) {
+				index = crb_entry->crb_strd.state_index_a;
+				addr = tmplt_hdr->saved_state_array[index];
+			} else {
+				addr = crb_addr;
+			}
+
+			if (crb_entry->crb_ctrl.state_index_v) {
+				index = crb_entry->crb_ctrl.state_index_v;
+				read_value =
+					tmplt_hdr->saved_state_array[index];
+			} else {
+				read_value = crb_entry->value_1;
+			}
+
+			qla4_8xxx_md_rw_32(ha, addr, read_value, 1);
+			opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
+		}
+
+		if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
+			index = crb_entry->crb_ctrl.state_index_v;
+			read_value = tmplt_hdr->saved_state_array[index];
+			read_value <<= crb_entry->crb_ctrl.shl;
+			read_value >>= crb_entry->crb_ctrl.shr;
+			if (crb_entry->value_2)
+				read_value &= crb_entry->value_2;
+			read_value |= crb_entry->value_3;
+			read_value += crb_entry->value_1;
+			tmplt_hdr->saved_state_array[index] = read_value;
+			opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
+		}
+		crb_addr += crb_entry->crb_strd.addr_stride;
+	}
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__));
+	return rval;
+}
+
+static void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+	struct qla82xx_minidump_entry_rdocm *ocm_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	ocm_hdr = (struct qla82xx_minidump_entry_rdocm *)entry_hdr;
+	r_addr = ocm_hdr->read_addr;
+	r_stride = ocm_hdr->read_addr_stride;
+	loop_cnt = ocm_hdr->op_count;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n",
+			  __func__, r_addr, r_stride, loop_cnt));
+
+	for (i = 0; i < loop_cnt; i++) {
+		r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase));
+		*data_ptr++ = cpu_to_le32(r_value);
+		r_addr += r_stride;
+	}
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n",
+			  __func__, (loop_cnt * sizeof(uint32_t))));
+	*d_ptr = data_ptr;
+}
+
+static void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
+	struct qla82xx_minidump_entry_mux *mux_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	mux_hdr = (struct qla82xx_minidump_entry_mux *)entry_hdr;
+	r_addr = mux_hdr->read_addr;
+	s_addr = mux_hdr->select_addr;
+	s_stride = mux_hdr->select_value_stride;
+	s_value = mux_hdr->select_value;
+	loop_cnt = mux_hdr->op_count;
+
+	for (i = 0; i < loop_cnt; i++) {
+		qla4_8xxx_md_rw_32(ha, s_addr, s_value, 1);
+		r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0);
+		*data_ptr++ = cpu_to_le32(s_value);
+		*data_ptr++ = cpu_to_le32(r_value);
+		s_value += s_stride;
+	}
+	*d_ptr = data_ptr;
+}
+
+static void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t addr, r_addr, c_addr, t_r_addr;
+	uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+	uint32_t c_value_w;
+	struct qla82xx_minidump_entry_cache *cache_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr;
+	loop_count = cache_hdr->op_count;
+	r_addr = cache_hdr->read_addr;
+	c_addr = cache_hdr->control_addr;
+	c_value_w = cache_hdr->cache_ctrl.write_value;
+
+	t_r_addr = cache_hdr->tag_reg_addr;
+	t_value = cache_hdr->addr_ctrl.init_tag_value;
+	r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+
+	for (i = 0; i < loop_count; i++) {
+		qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1);
+		qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1);
+		addr = r_addr;
+		for (k = 0; k < r_cnt; k++) {
+			r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0);
+			*data_ptr++ = cpu_to_le32(r_value);
+			addr += cache_hdr->read_ctrl.read_addr_stride;
+		}
+		t_value += cache_hdr->addr_ctrl.tag_value_stride;
+	}
+	*d_ptr = data_ptr;
+}
+
+static void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t s_addr, r_addr;
+	uint32_t r_stride, r_value, r_cnt, qid = 0;
+	uint32_t i, k, loop_cnt;
+	struct qla82xx_minidump_entry_queue *q_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	q_hdr = (struct qla82xx_minidump_entry_queue *)entry_hdr;
+	s_addr = q_hdr->select_addr;
+	r_cnt = q_hdr->rd_strd.read_addr_cnt;
+	r_stride = q_hdr->rd_strd.read_addr_stride;
+	loop_cnt = q_hdr->op_count;
+
+	for (i = 0; i < loop_cnt; i++) {
+		qla4_8xxx_md_rw_32(ha, s_addr, qid, 1);
+		r_addr = q_hdr->read_addr;
+		for (k = 0; k < r_cnt; k++) {
+			r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0);
+			*data_ptr++ = cpu_to_le32(r_value);
+			r_addr += r_stride;
+		}
+		qid += q_hdr->q_strd.queue_id_stride;
+	}
+	*d_ptr = data_ptr;
+}
+
+#define MD_DIRECT_ROM_WINDOW		0x42110030
+#define MD_DIRECT_ROM_READ_BASE		0x42150000
+
+static void qla4_8xxx_minidump_process_rdrom(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t r_addr, r_value;
+	uint32_t i, loop_cnt;
+	struct qla82xx_minidump_entry_rdrom *rom_hdr;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	rom_hdr = (struct qla82xx_minidump_entry_rdrom *)entry_hdr;
+	r_addr = rom_hdr->read_addr;
+	loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t);
+
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n",
+			   __func__, r_addr, loop_cnt));
+
+	for (i = 0; i < loop_cnt; i++) {
+		qla4_8xxx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW,
+				   (r_addr & 0xFFFF0000), 1);
+		r_value = qla4_8xxx_md_rw_32(ha,
+					     MD_DIRECT_ROM_READ_BASE +
+					     (r_addr & 0x0000FFFF), 0, 0);
+		*data_ptr++ = cpu_to_le32(r_value);
+		r_addr += sizeof(uint32_t);
+	}
+	*d_ptr = data_ptr;
+}
+
+#define MD_MIU_TEST_AGT_CTRL		0x41000090
+#define MD_MIU_TEST_AGT_ADDR_LO		0x41000094
+#define MD_MIU_TEST_AGT_ADDR_HI		0x41000098
+
+static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				uint32_t **d_ptr)
+{
+	uint32_t r_addr, r_value, r_data;
+	uint32_t i, j, loop_cnt;
+	struct qla82xx_minidump_entry_rdmem *m_hdr;
+	unsigned long flags;
+	uint32_t *data_ptr = *d_ptr;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__));
+	m_hdr = (struct qla82xx_minidump_entry_rdmem *)entry_hdr;
+	r_addr = m_hdr->read_addr;
+	loop_cnt = m_hdr->read_data_size/16;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n",
+			  __func__, r_addr, m_hdr->read_data_size));
+
+	if (r_addr & 0xf) {
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "[%s]: Read addr 0x%x not 16 bytes alligned\n",
+				  __func__, r_addr));
+		return QLA_ERROR;
+	}
+
+	if (m_hdr->read_data_size % 16) {
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "[%s]: Read data[0x%x] not multiple of 16 bytes\n",
+				  __func__, m_hdr->read_data_size));
+		return QLA_ERROR;
+	}
+
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
+			  __func__, r_addr, m_hdr->read_data_size, loop_cnt));
+
+	write_lock_irqsave(&ha->hw_lock, flags);
+	for (i = 0; i < loop_cnt; i++) {
+		qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1);
+		r_value = 0;
+		qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1);
+		r_value = MIU_TA_CTL_ENABLE;
+		qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+		r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+		qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			r_value = qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL,
+						     0, 0);
+			if ((r_value & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			printk_ratelimited(KERN_ERR
+					   "%s: failed to read through agent\n",
+					    __func__);
+			write_unlock_irqrestore(&ha->hw_lock, flags);
+			return QLA_SUCCESS;
+		}
+
+		for (j = 0; j < 4; j++) {
+			r_data = qla4_8xxx_md_rw_32(ha,
+						    MD_MIU_TEST_AGT_RDDATA[j],
+						    0, 0);
+			*data_ptr++ = cpu_to_le32(r_data);
+		}
+
+		r_addr += 16;
+	}
+	write_unlock_irqrestore(&ha->hw_lock, flags);
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n",
+			  __func__, (loop_cnt * 16)));
+
+	*d_ptr = data_ptr;
+	return QLA_SUCCESS;
+}
+
+static void ql4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha,
+				struct qla82xx_minidump_entry_hdr *entry_hdr,
+				int index)
+{
+	entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
+	DEBUG2(ql4_printk(KERN_INFO, ha,
+			  "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n",
+			  ha->host_no, index, entry_hdr->entry_type,
+			  entry_hdr->d_ctrl.entry_capture_mask));
+}
+
+/**
+ * qla82xx_collect_md_data - Retrieve firmware minidump data.
+ * @ha: pointer to adapter structure
+ **/
+static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)
+{
+	int num_entry_hdr = 0;
+	struct qla82xx_minidump_entry_hdr *entry_hdr;
+	struct qla4_8xxx_minidump_template_hdr *tmplt_hdr;
+	uint32_t *data_ptr;
+	uint32_t data_collected = 0;
+	int i, rval = QLA_ERROR;
+	uint64_t now;
+	uint32_t timestamp;
+
+	if (!ha->fw_dump) {
+		ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n",
+			   __func__, ha->host_no);
+		return rval;
+	}
+
+	tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *)
+						ha->fw_dump_tmplt_hdr;
+	data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump +
+						ha->fw_dump_tmplt_size);
+	data_collected += ha->fw_dump_tmplt_size;
+
+	num_entry_hdr = tmplt_hdr->num_of_entries;
+	ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n",
+		   __func__, data_ptr);
+	ql4_printk(KERN_INFO, ha,
+		   "[%s]: no of entry headers in Template: 0x%x\n",
+		   __func__, num_entry_hdr);
+	ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n",
+		   __func__, ha->fw_dump_capture_mask);
+	ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n",
+		   __func__, ha->fw_dump_size, ha->fw_dump_size);
+
+	/* Update current timestamp before taking dump */
+	now = get_jiffies_64();
+	timestamp = (u32)(jiffies_to_msecs(now) / 1000);
+	tmplt_hdr->driver_timestamp = timestamp;
+
+	entry_hdr = (struct qla82xx_minidump_entry_hdr *)
+					(((uint8_t *)ha->fw_dump_tmplt_hdr) +
+					 tmplt_hdr->first_entry_offset);
+
+	/* Walk through the entry headers - validate/perform required action */
+	for (i = 0; i < num_entry_hdr; i++) {
+		if (data_collected >= ha->fw_dump_size) {
+			ql4_printk(KERN_INFO, ha,
+				   "Data collected: [0x%x], Total Dump size: [0x%x]\n",
+				   data_collected, ha->fw_dump_size);
+			return rval;
+		}
+
+		if (!(entry_hdr->d_ctrl.entry_capture_mask &
+		      ha->fw_dump_capture_mask)) {
+			entry_hdr->d_ctrl.driver_flags |=
+						QLA82XX_DBG_SKIPPED_FLAG;
+			goto skip_nxt_entry;
+		}
+
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "Data collected: [0x%x], Dump size left:[0x%x]\n",
+				  data_collected,
+				  (ha->fw_dump_size - data_collected)));
+
+		/* Decode the entry type and take required action to capture
+		 * debug data
+		 */
+		switch (entry_hdr->entry_type) {
+		case QLA82XX_RDEND:
+			ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
+			break;
+		case QLA82XX_CNTRL:
+			rval = qla4_8xxx_minidump_process_control(ha,
+								  entry_hdr);
+			if (rval != QLA_SUCCESS) {
+				ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
+				goto md_failed;
+			}
+			break;
+		case QLA82XX_RDCRB:
+			qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr,
+							 &data_ptr);
+			break;
+		case QLA82XX_RDMEM:
+			rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr,
+								&data_ptr);
+			if (rval != QLA_SUCCESS) {
+				ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
+				goto md_failed;
+			}
+			break;
+		case QLA82XX_BOARD:
+		case QLA82XX_RDROM:
+			qla4_8xxx_minidump_process_rdrom(ha, entry_hdr,
+							 &data_ptr);
+			break;
+		case QLA82XX_L2DTG:
+		case QLA82XX_L2ITG:
+		case QLA82XX_L2DAT:
+		case QLA82XX_L2INS:
+			rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr,
+								&data_ptr);
+			if (rval != QLA_SUCCESS) {
+				ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
+				goto md_failed;
+			}
+			break;
+		case QLA82XX_L1DAT:
+		case QLA82XX_L1INS:
+			qla4_8xxx_minidump_process_l1cache(ha, entry_hdr,
+							   &data_ptr);
+			break;
+		case QLA82XX_RDOCM:
+			qla4_8xxx_minidump_process_rdocm(ha, entry_hdr,
+							 &data_ptr);
+			break;
+		case QLA82XX_RDMUX:
+			qla4_8xxx_minidump_process_rdmux(ha, entry_hdr,
+							 &data_ptr);
+			break;
+		case QLA82XX_QUEUE:
+			qla4_8xxx_minidump_process_queue(ha, entry_hdr,
+							 &data_ptr);
+			break;
+		case QLA82XX_RDNOP:
+		default:
+			ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
+			break;
+		}
+
+		data_collected = (uint8_t *)data_ptr -
+				 ((uint8_t *)((uint8_t *)ha->fw_dump +
+						ha->fw_dump_tmplt_size));
+skip_nxt_entry:
+		/*  next entry in the template */
+		entry_hdr = (struct qla82xx_minidump_entry_hdr *)
+				(((uint8_t *)entry_hdr) +
+				 entry_hdr->entry_size);
+	}
+
+	if ((data_collected + ha->fw_dump_tmplt_size) != ha->fw_dump_size) {
+		ql4_printk(KERN_INFO, ha,
+			   "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n",
+			   data_collected, ha->fw_dump_size);
+		goto md_failed;
+	}
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n",
+			  __func__, i));
+md_failed:
+	return rval;
+}
+
+/**
+ * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready.
+ * @ha: pointer to adapter structure
+ **/
+static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code)
+{
+	char event_string[40];
+	char *envp[] = { event_string, NULL };
+
+	switch (code) {
+	case QL4_UEVENT_CODE_FW_DUMP:
+		snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld",
+			 ha->host_no);
+		break;
+	default:
+		/*do nothing*/
+		break;
+	}
+
+	kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp);
+}
+
 /**
  * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw
  * @ha: pointer to adapter structure
@@ -1659,6 +2324,15 @@ dev_initialize:
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION);
 
 	qla4_8xxx_idc_unlock(ha);
+	if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) &&
+	    !test_and_set_bit(AF_82XX_FW_DUMPED, &ha->flags)) {
+		if (!qla4_8xxx_collect_md_data(ha)) {
+			qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP);
+		} else {
+			ql4_printk(KERN_INFO, ha, "Unable to collect minidump\n");
+			clear_bit(AF_82XX_FW_DUMPED, &ha->flags);
+		}
+	}
 	rval = qla4_8xxx_try_start_fw(ha);
 	qla4_8xxx_idc_lock(ha);
 
@@ -1686,6 +2360,7 @@ static void
 qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha)
 {
 	uint32_t dev_state, drv_state, drv_active;
+	uint32_t active_mask = 0xFFFFFFFF;
 	unsigned long reset_timeout;
 
 	ql4_printk(KERN_INFO, ha,
@@ -1697,7 +2372,14 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha)
 		qla4_8xxx_idc_lock(ha);
 	}
 
-	qla4_8xxx_set_rst_ready(ha);
+	if (!test_bit(AF_82XX_RST_OWNER, &ha->flags)) {
+		DEBUG2(ql4_printk(KERN_INFO, ha,
+				  "%s(%ld): reset acknowledged\n",
+				  __func__, ha->host_no));
+		qla4_8xxx_set_rst_ready(ha);
+	} else {
+		active_mask = (~(1 << (ha->func_num * 4)));
+	}
 
 	/* wait for 10 seconds for reset ack from all functions */
 	reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
@@ -1709,12 +2391,24 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha)
 		"%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n",
 		__func__, ha->host_no, drv_state, drv_active);
 
-	while (drv_state != drv_active) {
+	while (drv_state != (drv_active & active_mask)) {
 		if (time_after_eq(jiffies, reset_timeout)) {
-			printk("%s: RESET TIMEOUT!\n", DRIVER_NAME);
+			ql4_printk(KERN_INFO, ha,
+				   "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n",
+				   DRIVER_NAME, drv_state, drv_active);
 			break;
 		}
 
+		/*
+		 * When reset_owner times out, check which functions
+		 * acked/did not ack
+		 */
+		if (test_bit(AF_82XX_RST_OWNER, &ha->flags)) {
+			ql4_printk(KERN_INFO, ha,
+				   "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n",
+				   __func__, ha->host_no, drv_state,
+				   drv_active);
+		}
 		qla4_8xxx_idc_unlock(ha);
 		msleep(1000);
 		qla4_8xxx_idc_lock(ha);
@@ -1723,14 +2417,18 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha)
 		drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
 	}
 
+	/* Clear RESET OWNER as we are not going to use it any further */
+	clear_bit(AF_82XX_RST_OWNER, &ha->flags);
+
 	dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-	ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state,
-		dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+	ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state,
+		   dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
 
 	/* Force to DEV_COLD unless someone else is starting a reset */
 	if (dev_state != QLA82XX_DEV_INITIALIZING) {
 		ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n");
 		qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
+		qla4_8xxx_set_rst_ready(ha);
 	}
 }
 
@@ -1765,8 +2463,9 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
 	}
 
 	dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-	ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state,
-		dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n",
+			  dev_state, dev_state < MAX_STATES ?
+			  qdev_state[dev_state] : "Unknown"));
 
 	/* wait for 30 seconds for device to go ready */
 	dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
@@ -1775,15 +2474,19 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
 	while (1) {
 
 		if (time_after_eq(jiffies, dev_init_timeout)) {
-			ql4_printk(KERN_WARNING, ha, "Device init failed!\n");
+			ql4_printk(KERN_WARNING, ha,
+				   "%s: Device Init Failed 0x%x = %s\n",
+				   DRIVER_NAME,
+				   dev_state, dev_state < MAX_STATES ?
+				   qdev_state[dev_state] : "Unknown");
 			qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 				QLA82XX_DEV_FAILED);
 		}
 
 		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-		ql4_printk(KERN_INFO, ha,
-		    "2:Device state is 0x%x = %s\n", dev_state,
-		    dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+		ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n",
+			   dev_state, dev_state < MAX_STATES ?
+			   qdev_state[dev_state] : "Unknown");
 
 		/* NOTE: Make sure idc unlocked upon exit of switch statement */
 		switch (dev_state) {
@@ -2184,6 +2887,7 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha)
 		ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n");
 		qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 		    QLA82XX_DEV_NEED_RESET);
+		set_bit(AF_82XX_RST_OWNER, &ha->flags);
 	} else
 		ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n");
 
@@ -2195,8 +2899,10 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha)
 	qla4_8xxx_clear_rst_ready(ha);
 	qla4_8xxx_idc_unlock(ha);
 
-	if (rval == QLA_SUCCESS)
+	if (rval == QLA_SUCCESS) {
+		ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_8xxx_isp_reset\n");
 		clear_bit(AF_FW_RECOVERY, &ha->flags);
+	}
 
 	return rval;
 }
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index dc7500e..3025847 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -792,4 +792,196 @@ struct crb_addr_pair {
 #define MIU_TEST_AGT_WRDATA_UPPER_LO	(0x0b0)
 #define	MIU_TEST_AGT_WRDATA_UPPER_HI	(0x0b4)
 
+/* Minidump related */
+
+/* Entry Type Defines */
+#define QLA82XX_RDNOP	0
+#define QLA82XX_RDCRB	1
+#define QLA82XX_RDMUX	2
+#define QLA82XX_QUEUE	3
+#define QLA82XX_BOARD	4
+#define QLA82XX_RDOCM	6
+#define QLA82XX_PREGS	7
+#define QLA82XX_L1DTG	8
+#define QLA82XX_L1ITG	9
+#define QLA82XX_L1DAT	11
+#define QLA82XX_L1INS	12
+#define QLA82XX_L2DTG	21
+#define QLA82XX_L2ITG	22
+#define QLA82XX_L2DAT	23
+#define QLA82XX_L2INS	24
+#define QLA82XX_RDROM	71
+#define QLA82XX_RDMEM	72
+#define QLA82XX_CNTRL	98
+#define QLA82XX_RDEND	255
+
+/* Opcodes for Control Entries.
+ * These Flags are bit fields.
+ */
+#define QLA82XX_DBG_OPCODE_WR		0x01
+#define QLA82XX_DBG_OPCODE_RW		0x02
+#define QLA82XX_DBG_OPCODE_AND		0x04
+#define QLA82XX_DBG_OPCODE_OR		0x08
+#define QLA82XX_DBG_OPCODE_POLL		0x10
+#define QLA82XX_DBG_OPCODE_RDSTATE	0x20
+#define QLA82XX_DBG_OPCODE_WRSTATE	0x40
+#define QLA82XX_DBG_OPCODE_MDSTATE	0x80
+
+/* Driver Flags */
+#define QLA82XX_DBG_SKIPPED_FLAG	0x80 /* driver skipped this entry  */
+#define QLA82XX_DBG_SIZE_ERR_FLAG	0x40 /* Entry vs Capture size
+					      * mismatch */
+
+/* Driver_code is for driver to write some info about the entry
+ * currently not used.
+ */
+struct qla82xx_minidump_entry_hdr {
+	uint32_t entry_type;
+	uint32_t entry_size;
+	uint32_t entry_capture_size;
+	struct {
+		uint8_t entry_capture_mask;
+		uint8_t entry_code;
+		uint8_t driver_code;
+		uint8_t driver_flags;
+	} d_ctrl;
+};
+
+/*  Read CRB entry header */
+struct qla82xx_minidump_entry_crb {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t addr;
+	struct {
+		uint8_t addr_stride;
+		uint8_t state_index_a;
+		uint16_t poll_timeout;
+	} crb_strd;
+	uint32_t data_size;
+	uint32_t op_count;
+
+	struct {
+		uint8_t opcode;
+		uint8_t state_index_v;
+		uint8_t shl;
+		uint8_t shr;
+	} crb_ctrl;
+
+	uint32_t value_1;
+	uint32_t value_2;
+	uint32_t value_3;
+};
+
+struct qla82xx_minidump_entry_cache {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t tag_reg_addr;
+	struct {
+		uint16_t tag_value_stride;
+		uint16_t init_tag_value;
+	} addr_ctrl;
+	uint32_t data_size;
+	uint32_t op_count;
+	uint32_t control_addr;
+	struct {
+		uint16_t write_value;
+		uint8_t poll_mask;
+		uint8_t poll_wait;
+	} cache_ctrl;
+	uint32_t read_addr;
+	struct {
+		uint8_t read_addr_stride;
+		uint8_t read_addr_cnt;
+		uint16_t rsvd_1;
+	} read_ctrl;
+};
+
+/* Read OCM */
+struct qla82xx_minidump_entry_rdocm {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t rsvd_0;
+	uint32_t rsvd_1;
+	uint32_t data_size;
+	uint32_t op_count;
+	uint32_t rsvd_2;
+	uint32_t rsvd_3;
+	uint32_t read_addr;
+	uint32_t read_addr_stride;
+};
+
+/* Read Memory */
+struct qla82xx_minidump_entry_rdmem {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t rsvd[6];
+	uint32_t read_addr;
+	uint32_t read_data_size;
+};
+
+/* Read ROM */
+struct qla82xx_minidump_entry_rdrom {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t rsvd[6];
+	uint32_t read_addr;
+	uint32_t read_data_size;
+};
+
+/* Mux entry */
+struct qla82xx_minidump_entry_mux {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t select_addr;
+	uint32_t rsvd_0;
+	uint32_t data_size;
+	uint32_t op_count;
+	uint32_t select_value;
+	uint32_t select_value_stride;
+	uint32_t read_addr;
+	uint32_t rsvd_1;
+};
+
+/* Queue entry */
+struct qla82xx_minidump_entry_queue {
+	struct qla82xx_minidump_entry_hdr h;
+	uint32_t select_addr;
+	struct {
+		uint16_t queue_id_stride;
+		uint16_t rsvd_0;
+	} q_strd;
+	uint32_t data_size;
+	uint32_t op_count;
+	uint32_t rsvd_1;
+	uint32_t rsvd_2;
+	uint32_t read_addr;
+	struct {
+		uint8_t read_addr_stride;
+		uint8_t read_addr_cnt;
+		uint16_t rsvd_3;
+	} rd_strd;
+};
+
+#define QLA82XX_MINIDUMP_OCM0_SIZE		(256 * 1024)
+#define QLA82XX_MINIDUMP_L1C_SIZE		(256 * 1024)
+#define QLA82XX_MINIDUMP_L2C_SIZE		1572864
+#define QLA82XX_MINIDUMP_COMMON_STR_SIZE	0
+#define QLA82XX_MINIDUMP_FCOE_STR_SIZE		0
+#define QLA82XX_MINIDUMP_MEM_SIZE		0
+#define QLA82XX_MAX_ENTRY_HDR			4
+
+struct qla82xx_minidump {
+	uint32_t md_ocm0_data[QLA82XX_MINIDUMP_OCM0_SIZE];
+	uint32_t md_l1c_data[QLA82XX_MINIDUMP_L1C_SIZE];
+	uint32_t md_l2c_data[QLA82XX_MINIDUMP_L2C_SIZE];
+	uint32_t md_cs_data[QLA82XX_MINIDUMP_COMMON_STR_SIZE];
+	uint32_t md_fcoes_data[QLA82XX_MINIDUMP_FCOE_STR_SIZE];
+	uint32_t md_mem_data[QLA82XX_MINIDUMP_MEM_SIZE];
+};
+
+#define MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE	0x129
+#define RQST_TMPLT_SIZE				0x0
+#define RQST_TMPLT				0x1
+#define MD_DIRECT_ROM_WINDOW			0x42110030
+#define MD_DIRECT_ROM_READ_BASE			0x42150000
+#define MD_MIU_TEST_AGT_CTRL			0x41000090
+#define MD_MIU_TEST_AGT_ADDR_LO			0x41000094
+#define MD_MIU_TEST_AGT_ADDR_HI			0x41000098
+
+static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8,
+				0x410000AC, 0x410000B8, 0x410000BC };
 #endif
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 613c119..cfa5db4 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -82,6 +82,20 @@ MODULE_PARM_DESC(ql4xsess_recovery_tmo,
 		" Target Session Recovery Timeout.\n"
 		"\t\t  Default: 120 sec.");
 
+int ql4xmdcapmask = 0x1F;
+module_param(ql4xmdcapmask, int, S_IRUGO);
+MODULE_PARM_DESC(ql4xmdcapmask,
+		 " Set the Minidump driver capture mask level.\n"
+		 "\t\t  Default is 0x1F.\n"
+		 "\t\t  Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F");
+
+int ql4xenablemd = 1;
+module_param(ql4xenablemd, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql4xenablemd,
+		 " Set to enable minidump.\n"
+		 "\t\t  0 - disable minidump\n"
+		 "\t\t  1 - enable minidump (Default)");
+
 static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
 /*
  * SCSI host template entry points
@@ -2265,6 +2279,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
 		dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
 				  ha->queues_dma);
 
+	 if (ha->fw_dump)
+		vfree(ha->fw_dump);
+
 	ha->queues_len = 0;
 	ha->queues = NULL;
 	ha->queues_dma = 0;
@@ -2274,6 +2291,8 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
 	ha->response_dma = 0;
 	ha->shadow_regs = NULL;
 	ha->shadow_regs_dma = 0;
+	ha->fw_dump = NULL;
+	ha->fw_dump_size = 0;
 
 	/* Free srb pool. */
 	if (ha->srb_mempool)
@@ -5068,6 +5087,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
 
 	set_bit(AF_INIT_DONE, &ha->flags);
 
+	qla4_8xxx_alloc_sysfs_attr(ha);
+
 	printk(KERN_INFO
 	       " QLogic iSCSI HBA Driver version: %s\n"
 	       "  QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
@@ -5194,6 +5215,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
 		iscsi_boot_destroy_kset(ha->boot_kset);
 
 	qla4xxx_destroy_fw_ddb_session(ha);
+	qla4_8xxx_free_sysfs_attr(ha);
 
 	scsi_remove_host(ha->host);
 
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/6] qla4xxx: Update driver version to 5.02.00-k17
  2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
                   ` (4 preceding siblings ...)
  2012-04-24  5:32 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure vikas.chaudhary
@ 2012-04-24  5:32 ` vikas.chaudhary
  5 siblings, 0 replies; 15+ messages in thread
From: vikas.chaudhary @ 2012-04-24  5:32 UTC (permalink / raw)
  To: jbottomley, michaelc
  Cc: linux-scsi, vikas.chaudhary, lalit.chandivade, ravi.anand

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_version.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 97b30c1..cc1cc35 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.02.00-k16"
+#define QLA4XXX_DRIVER_VERSION	"5.02.00-k17"
-- 
1.7.9.1.265.gb3a76



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/6] qla4xxx: Add change_queue_depth API support
  2012-04-24  5:32 ` [PATCH 4/6] qla4xxx: Add change_queue_depth API support vikas.chaudhary
@ 2012-04-27 15:43   ` Mike Christie
  2012-04-30 11:32     ` Vikas Chaudhary
  0 siblings, 1 reply; 15+ messages in thread
From: Mike Christie @ 2012-04-27 15:43 UTC (permalink / raw)
  To: vikas.chaudhary
  Cc: jbottomley, linux-scsi, lalit.chandivade, ravi.anand, Tej Parkash

On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
>  
> +static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
> +				      int reason)
> +{
> +	int queue_depth;
> +	if (!ql4xqfulltracking)
> +		return -EOPNOTSUPP;
> +
> +	queue_depth = iscsi_change_queue_depth(sdev, qdepth, reason);
> +	return queue_depth;
> +}
> +

No need for queue_depth. Just do

return iscsi_change_queue_depth(sdev, qdepth, reason);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-04-24  5:32 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure vikas.chaudhary
@ 2012-04-27 16:05   ` Mike Christie
  2012-05-17  9:12     ` James Bottomley
  0 siblings, 1 reply; 15+ messages in thread
From: Mike Christie @ 2012-04-27 16:05 UTC (permalink / raw)
  To: vikas.chaudhary
  Cc: jbottomley, linux-scsi, lalit.chandivade, ravi.anand, Tej Parkash,
	Shyam Sundar

On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
> +
> +static ssize_t
> +qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj,
> +			      struct bin_attribute *ba, char *buf, loff_t off,
> +			      size_t count)
> +{
> +	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
> +					       struct device, kobj)));
> +	uint32_t dev_state;
> +	int reading;
> +
> +	if (!is_qla8022(ha))
> +		return -EINVAL;
> +
> +	if (off != 0)
> +		return 0;
> +
> +	reading = simple_strtol(buf, NULL, 10);

I think we are supposed to be using kstrtol now.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/6] qla4xxx: Add change_queue_depth API support
  2012-04-27 15:43   ` Mike Christie
@ 2012-04-30 11:32     ` Vikas Chaudhary
  0 siblings, 0 replies; 15+ messages in thread
From: Vikas Chaudhary @ 2012-04-30 11:32 UTC (permalink / raw)
  To: Mike Christie
  Cc: jbottomley@parallels.com, scsi, Lalit Chandivade, Ravi Anand,
	Tej Parkash



-----Original Message-----
From: Mike Christie <michaelc@cs.wisc.edu>
Date: Fri, 27 Apr 2012 08:43:15 -0700
To: Vikas <vikas.chaudhary@qlogic.com>
Cc: "jbottomley@parallels.com" <jbottomley@parallels.com>, scsi
<linux-scsi@vger.kernel.org>, Lalit Chandivade
<lalit.chandivade@qlogic.com>, Ravi Anand <ravi.anand@qlogic.com>, Tej
Parkash <tej.parkash@qlogic.com>
Subject: Re: [PATCH 4/6] qla4xxx: Add change_queue_depth API support

>On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
>>
>> +static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int
>>qdepth,
>> +                                  int reason)
>> +{
>> +    int queue_depth;
>> +    if (!ql4xqfulltracking)
>> +            return -EOPNOTSUPP;
>> +
>> +    queue_depth = iscsi_change_queue_depth(sdev, qdepth, reason);
>> +    return queue_depth;
>> +}
>> +
>
>No need for queue_depth. Just do
>
>return iscsi_change_queue_depth(sdev, qdepth, reason);

Thanks for the review.
updated patch is posted here:
http://marc.info/?l=linux-scsi&m=133578541226558&w=2



This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
       [not found] <CBC865CB.E843%vikas.chaudhary@qlogic.com>
@ 2012-05-04 10:00 ` Vikas Chaudhary
  2012-05-04 10:17   ` Mike Christie
  0 siblings, 1 reply; 15+ messages in thread
From: Vikas Chaudhary @ 2012-05-04 10:00 UTC (permalink / raw)
  To: Mike Christie, jbottomley@parallels.com
  Cc: scsi, Lalit Chandivade, Ravi Anand, Tej Parkash, Shyam Sundar,
	Vikas Chaudhary


Looks like my earlier email fails to go on scsi-liist. Resending email.

From:  Vikas <vikas.chaudhary@qlogic.com>
Date:  Thu, 3 May 2012 04:30:11 -0700
To:  Mike Christie <michaelc@cs.wisc.edu>
Cc:  "jbottomley@parallels.com" <jbottomley@parallels.com>, scsi
<linux-scsi@vger.kernel.org>, Lalit Chandivade
<lalit.chandivade@qlogic.com>, Ravi Anand <ravi.anand@qlogic.com>, Tej
Parkash <tej.parkash@qlogic.com>, Shyam Sundar <shyam.sundar@qlogic.com>
Subject:  Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on
firmware failure


>
>-----Original Message-----
>From: Mike Christie <michaelc@cs.wisc.edu>
>Date: Fri, 27 Apr 2012 09:05:15 -0700
>To: Vikas <vikas.chaudhary@qlogic.com>
>Cc: "jbottomley@parallels.com" <jbottomley@parallels.com>, scsi
><linux-scsi@vger.kernel.org>, Lalit Chandivade
><lalit.chandivade@qlogic.com>, Ravi Anand <ravi.anand@qlogic.com>, Tej
>Parkash <tej.parkash@qlogic.com>, Shyam Sundar <shyam.sundar@qlogic.com>
>Subject: Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on
>firmware failure
>
>>On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
>>> +
>>> +static ssize_t
>>> +qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject
>>>*kobj,
>>> +                         struct bin_attribute *ba, char *buf, loff_t off,
>>> +                         size_t count)
>>> +{
>>> +   struct scsi_qla_host *ha =
>>>to_qla_host(dev_to_shost(container_of(kobj,
>>> +                                          struct device, kobj)));
>>> +   uint32_t dev_state;
>>> +   int reading;
>>> +
>>> +   if (!is_qla8022(ha))
>>> +           return -EINVAL;
>>> +
>>> +   if (off != 0)
>>> +           return 0;
>>> +
>>> +   reading = simple_strtol(buf, NULL, 10);
>>
>>I think we are supposed to be using kstrtol now.
>
>
>We tried using kstrtol but most of times we found kstrtol return error.
>
>We added following patch to debug this issue:-
>
>--- a/drivers/scsi/qla4xxx/ql4_attr.c
>+++ b/drivers/scsi/qla4xxx/ql4_attr.c
>@@ -35,7 +35,8 @@ qla4_8xxx_sysfs_write_fw_dump(struct file *filep,
>struct kobject *kobj,
>        struct scsi_qla_host *ha =
>to_qla_host(dev_to_shost(container_of(kobj,
>                                               struct device, kobj)));
>        uint32_t dev_state;
>-       int reading;
>+       long reading;
>+       int read, ret;
>
>        if (is_qla40XX(ha))
>                return -EINVAL;
>@@ -43,7 +44,20 @@ qla4_8xxx_sysfs_write_fw_dump(struct file *filep,
>struct kobject *kobj,
>        if (off != 0)
>                return 0;
>
>-       reading = simple_strtol(buf, NULL, 10);
>+       printk("------------------------------------------\n");
>+       ql4_printk(KERN_INFO, ha, "Buf = %s\n", buf);
>+       printk("------------------------------------------\n");
>+       read = simple_strtol(buf, NULL, 10);
>+       ql4_printk(KERN_INFO, ha, "simple strtol val = %d\n", read);
>+       ret = kstrtol(buf, 10, &reading);
>+       if (ret) {
>+               ql4_printk(KERN_INFO, ha, "\nError %d\n", ret);
>+               ql4_printk(KERN_INFO, ha, "Error Converted Val %ld\n",
>reading);
>
>+               return ret;
>+       }
>+       ql4_printk(KERN_INFO, ha, "kstrtol val = %ld\n", reading);
>+       return count;
>+
>        switch (reading) {
>        case 0:
>                /* clear dump collection flags */
>
>
>----
>
>When we do:
># echo 6 > /sys/class/scsi_host/host7/device/fw_dump
>We get following result for this patch:-
>--------------------------------------------------------------------------
>----------------------------------------------------
>May  3 16:45:59 magana kernel: ------------------------------------------
>May  3 16:45:59 magana kernel: qla4xxx 0000:18:00.4: Buf = 6./../../host7
>May  3 16:45:59 magana kernel: ------------------------------------------
>May  3 16:45:59 magana kernel: qla4xxx 0000:18:00.4: simple strtol val = 6
>May  3 16:45:59 magana kernel: qla4xxx 0000:18:00.4:
>May  3 16:45:59 magana kernel: Error -22
>May  3 16:45:59 magana kernel: qla4xxx 0000:18:00.4: Error Converted Val
>-2129482613
>
>--------------------------------------------------------------------------
>----------------------------------------------------
>
>From above logs looks like sysfs attribute reading some extra garbage
>characters because of which
>'kstrtol()' fails but in same case 'simple_strtol()' works fine.
>
>Do you have any idea why we are getting some garbage characters from
>sysfs attribute?
>
>Can you please accept this patch with 'simple_strtol()' till this issue
>get fixed.
>Once it is fix we will update the patch.
>
>Thanks,
>Vikas.
>


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-05-04 10:00 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure Vikas Chaudhary
@ 2012-05-04 10:17   ` Mike Christie
  2012-05-04 10:29     ` Vikas Chaudhary
  0 siblings, 1 reply; 15+ messages in thread
From: Mike Christie @ 2012-05-04 10:17 UTC (permalink / raw)
  To: Vikas Chaudhary
  Cc: jbottomley@parallels.com, scsi, Lalit Chandivade, Ravi Anand,
	Tej Parkash, Shyam Sundar

On 05/04/2012 05:00 AM, Vikas Chaudhary wrote:
>> # echo 6 > /sys/class/scsi_host/host7/device/fw_dump

echo adds a newline by default. If you do echo -n it does not.

Does simple_strtol handle that but kstrol not handle it?

>>From above logs looks like sysfs attribute reading some extra garbage
>> >characters because of which
>> >'kstrtol()' fails but in same case 'simple_strtol()' works fine.
>> >

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-05-04 10:17   ` Mike Christie
@ 2012-05-04 10:29     ` Vikas Chaudhary
  0 siblings, 0 replies; 15+ messages in thread
From: Vikas Chaudhary @ 2012-05-04 10:29 UTC (permalink / raw)
  To: Mike Christie
  Cc: jbottomley@parallels.com, scsi, Lalit Chandivade, Ravi Anand,
	Tej Parkash, Shyam Sundar


-----Original Message-----
From: Mike Christie <michaelc@cs.wisc.edu>
Date: Fri, 4 May 2012 03:17:36 -0700
To: Admin <vikas.chaudhary@qlogic.com>
Cc: "jbottomley@parallels.com" <jbottomley@parallels.com>, scsi
<linux-scsi@vger.kernel.org>, Lalit Chandivade
<lalit.chandivade@qlogic.com>, Ravi Anand <ravi.anand@qlogic.com>, Tej
Parkash <tej.parkash@qlogic.com>, Shyam Sundar <shyam.sundar@qlogic.com>
Subject: Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware
failure

>On 05/04/2012 05:00 AM, Vikas Chaudhary wrote:
>>> # echo 6 > /sys/class/scsi_host/host7/device/fw_dump
>
>echo adds a newline by default. If you do echo -n it does not.

I tried with 'echo -n' I am still getting garbage data from sysfs
attribute.

>
>Does simple_strtol handle that but kstrol not handle it?

Yes, simple_strtol handle this case.


Here are logs:

May  4 16:01:01 magana kernel: ------------------------------------------
May  4 16:01:01 magana kernel: qla4xxx 0000:18:00.5: Buf =
4./../../host12      <-- garbage data from sysfs attribute
May  4 16:01:01 magana kernel: ------------------------------------------
May  4 16:01:01 magana kernel: qla4xxx 0000:18:00.5: simple strtol val =
4            <-- simple_strtol return correct value
May  4 16:01:01 magana kernel: qla4xxx 0000:18:00.5:
May  4 16:01:01 magana kernel: Error -22                                                     <-- error from kstrol
May  4 16:01:01 magana kernel: qla4xxx 0000:18:00.5: Error Converted Val
-2129482613


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-04-27 16:05   ` Mike Christie
@ 2012-05-17  9:12     ` James Bottomley
  2012-05-18  9:29       ` Vikas Chaudhary
  0 siblings, 1 reply; 15+ messages in thread
From: James Bottomley @ 2012-05-17  9:12 UTC (permalink / raw)
  To: Mike Christie
  Cc: vikas.chaudhary, linux-scsi, lalit.chandivade, ravi.anand,
	Tej Parkash, Shyam Sundar

On Fri, 2012-04-27 at 11:05 -0500, Mike Christie wrote:
> On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
> > +
> > +static ssize_t
> > +qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj,
> > +			      struct bin_attribute *ba, char *buf, loff_t off,
> > +			      size_t count)
> > +{
> > +	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
> > +					       struct device, kobj)));
> > +	uint32_t dev_state;
> > +	int reading;
> > +
> > +	if (!is_qla8022(ha))
> > +		return -EINVAL;
> > +
> > +	if (off != 0)
> > +		return 0;
> > +
> > +	reading = simple_strtol(buf, NULL, 10);
> 
> I think we are supposed to be using kstrtol now.

We are.  Checkpatch even warns about this, please fix.

Thanks,

James



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure
  2012-05-17  9:12     ` James Bottomley
@ 2012-05-18  9:29       ` Vikas Chaudhary
  0 siblings, 0 replies; 15+ messages in thread
From: Vikas Chaudhary @ 2012-05-18  9:29 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, linux-kernel
  Cc: linux-scsi@vger.kernel.org, Lalit Chandivade, Ravi Anand,
	Tej Parkash, Shyam Sundar



-----Original Message-----
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Mike Christie <michaelc@cs.wisc.edu>
Cc: Admin <vikas.chaudhary@qlogic.com>, scsi <linux-scsi@vger.kernel.org>,
Lalit Chandivade <lalit.chandivade@qlogic.com>, Ravi Anand
<ravi.anand@qlogic.com>, Tej Parkash <tej.parkash@qlogic.com>, Shyam
Sundar <shyam.sundar@qlogic.com>
Subject: Re: [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware
failure

>On Fri, 2012-04-27 at 11:05 -0500, Mike Christie wrote:
>> On 04/24/2012 12:32 AM, vikas.chaudhary@qlogic.com wrote:
>> > +
>> > +static ssize_t
>> > +qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject
>>*kobj,
>> > +                        struct bin_attribute *ba, char *buf, loff_t off,
>> > +                        size_t count)
>> > +{
>> > +  struct scsi_qla_host *ha =
>>to_qla_host(dev_to_shost(container_of(kobj,
>> > +                                         struct device, kobj)));
>> > +  uint32_t dev_state;
>> > +  int reading;
>> > +
>> > +  if (!is_qla8022(ha))
>> > +          return -EINVAL;
>> > +
>> > +  if (off != 0)
>> > +          return 0;
>> > +
>> > +  reading = simple_strtol(buf, NULL, 10);
>>
>> I think we are supposed to be using kstrtol now.
>
>We are.  Checkpatch even warns about this, please fix.

We have posted updated patch to scsi-list here:-
http://marc.info/?l=linux-scsi&m=133733192809849&w=2

In 1st version of patch we used simple_strtol() as sysfs attribute buffer
is not NULL terminated string and
it include some garbage characters because of this kstrtol() fails.

If I write "5" to sysfs attribute I am getting following string in buf:-

-------------------------------------------
May 18 12:07:54 magana kernel: buf: 5
May 18 12:07:54 magana kernel: ter-|   Receive
                   |  Transmit
May 18 12:07:54 magana kernel: face |bytes    packets errs drop fifo frame
compressed multicast|bytes    packets errs drop fifo colls carrier
compressed
May 18 12:07:54 magana kernel:  eth2:  520166    5418    0    0    0     0
         0       325   393879    1978    0    0    0     0       0
 0
May 18 12:07:54 magana kernel:  eth3:       0       0    0    0    0     0
         0         0        0       0    0    0    0     0       0
 0
May 18 12:07:54 magana kernel:  eth4: 1398425   18696    0    0    0     0
         0         0     7631      39    0    0    0     0       0
 0
May 18 12:07:54 magana kernel:  eth5: 1394451   18678    0    0    0     0
         0         0     6427      30    0    0    0     0       0
 0
May 18 12:07:54 magana kernel:    lo:  361420    1082    0    0    0     0
         0         0   361420    1082    0    0    0     0       0
 0
May 18 12:07:54 magana kernel: virbr0-nic:       0       0    0    0    0
   0          0         0        0       0    0    0    0     0       0
      0
May 18 12:07:54 magana kernel: virbr0:       0       0    0    0    0
0          0         0        0
-------------------------------------------

As we are getting garbage characters after "5", kstrtol() fails but
simple_strtol() works well.

I posted email for same to scsi-list here:-
http://marc.info/?l=linux-scsi&m=133612575603304&w=2

For now in updated patch I am writing "0" at sysfs attribute buf[1] as we
are interested only in buf[0] and after this change kstrtol() works well.

I am interested to know if the behavior of sysfs attribute is correct or
is it an issue?




This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-05-18  9:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-24  5:32 [PATCH 0/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
2012-04-24  5:32 ` [PATCH 1/6] qla4xxx: Correct early completion of pending mbox vikas.chaudhary
2012-04-24  5:32 ` [PATCH 2/6] qla4xxx: Fix kernel panic during discovery logout vikas.chaudhary
2012-04-24  5:32 ` [PATCH 3/6] qla4xxx: Fix clear ddb mbx command failure issue vikas.chaudhary
2012-04-24  5:32 ` [PATCH 4/6] qla4xxx: Add change_queue_depth API support vikas.chaudhary
2012-04-27 15:43   ` Mike Christie
2012-04-30 11:32     ` Vikas Chaudhary
2012-04-24  5:32 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure vikas.chaudhary
2012-04-27 16:05   ` Mike Christie
2012-05-17  9:12     ` James Bottomley
2012-05-18  9:29       ` Vikas Chaudhary
2012-04-24  5:32 ` [PATCH 6/6] qla4xxx: Update driver version to 5.02.00-k17 vikas.chaudhary
     [not found] <CBC865CB.E843%vikas.chaudhary@qlogic.com>
2012-05-04 10:00 ` [PATCH 5/6] qla4xxx: Capture minidump for ISP82XX on firmware failure Vikas Chaudhary
2012-05-04 10:17   ` Mike Christie
2012-05-04 10:29     ` Vikas Chaudhary

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.