All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6.
@ 2010-05-04 22:01 giridhar.malavali
  2010-05-04 22:01 ` [PATCH 01/16] qla2xxx: Check for ISP84xx before processing to get 84xx firmware version giridhar.malavali
                   ` (15 more replies)
  0 siblings, 16 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Giridhar Malavali <giridhar.malavali@qlogic.com>

James, 

Please apply these patches.

Andrew Vasquez (5):
  qla2xxx: Check for ISP84xx before processing to get 84xx firmware
    version.
  qla2xxx: Display proper link state for disconnected ports.
  qla2xxx: Further generalization of SRB CTX infrastructure.
  qla2xxx: Limit mailbox command contention for ADISC requests.
  qla2xxx: Cleanup FCP-command-status processing debug statements.

Arun Easi (1):
  qla2xxx: T10 DIF support added.

Giridhar Malavali (3):
  qla2xxx: Optionally disable target reset.
  qla2xxx: Updates to ISP82xx support.
  qla2xxx: Update version number to 8.03.03-k0.

Harish Zunjarrao (1):
  qla2xxx: Add char device to increase driver use count

Lalit Chandivade (2):
  qla2xxx: Clear error status after uncorrectable non-fatal errors.
  qla2xxx: ensure flash operation and host reset via sg_reset are
    mutually exclusive

Madhuranath Iyengar (2):
  qla2xxx: Provide common framework for BSG and IOCB commands.
  qla2xxx: Support for asynchronous TM and Marker IOCBs.

Mike Waychison (1):
  qla2xxx: Silence bogus warning by gcc for wrap and did.

Sarang Radke (1):
  qla2xxx: Add internal loopback support for 81XX

 drivers/scsi/qla2xxx/qla_attr.c    |   33 ++-
 drivers/scsi/qla2xxx/qla_bsg.c     |  206 ++++++++--
 drivers/scsi/qla2xxx/qla_bsg.h     |    7 +
 drivers/scsi/qla2xxx/qla_dbg.c     |   58 +++
 drivers/scsi/qla2xxx/qla_dbg.h     |   10 +
 drivers/scsi/qla2xxx/qla_def.h     |  167 +++++++--
 drivers/scsi/qla2xxx/qla_fw.h      |   47 ++-
 drivers/scsi/qla2xxx/qla_gbl.h     |   29 ++-
 drivers/scsi/qla2xxx/qla_init.c    |  387 ++++++++++++++----
 drivers/scsi/qla2xxx/qla_inline.h  |   16 +
 drivers/scsi/qla2xxx/qla_iocb.c    |  805 +++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_isr.c     |  505 +++++++++++++----------
 drivers/scsi/qla2xxx/qla_mbx.c     |   76 ++++
 drivers/scsi/qla2xxx/qla_nx.c      |  205 +++++-----
 drivers/scsi/qla2xxx/qla_nx.h      |   15 +-
 drivers/scsi/qla2xxx/qla_os.c      |  196 ++++++++-
 drivers/scsi/qla2xxx/qla_version.h |    6 +-
 17 files changed, 2277 insertions(+), 491 deletions(-)


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

* [PATCH 01/16] qla2xxx: Check for ISP84xx before processing to get 84xx firmware version.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 02/16] qla2xxx: Display proper link state for disconnected ports giridhar.malavali
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Andrew Vasquez <andrew.vasquez@qlogic.com>

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_attr.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index c272af4..d416c35 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1198,9 +1198,11 @@ qla24xx_84xx_fw_version_show(struct device *dev,
 	scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
 	struct qla_hw_data *ha = vha->hw;
 
-	if (IS_QLA84XX(ha) && ha->cs84xx)
-		if (ha->cs84xx->op_fw_version == 0)
-			rval = qla84xx_verify_chip(vha, status);
+	if (!IS_QLA84XX(ha))
+		return snprintf(buf, PAGE_SIZE, "\n");
+
+	if (ha->cs84xx && ha->cs84xx->op_fw_version == 0)
+		rval = qla84xx_verify_chip(vha, status);
 
 	if ((rval == QLA_SUCCESS) && (status[0] == 0))
 		return snprintf(buf, PAGE_SIZE, "%u\n",
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 02/16] qla2xxx: Display proper link state for disconnected ports.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
  2010-05-04 22:01 ` [PATCH 01/16] qla2xxx: Check for ISP84xx before processing to get 84xx firmware version giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 03/16] qla2xxx: Clear error status after uncorrectable non-fatal errors giridhar.malavali
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Andrew Vasquez <andrew.vasquez@qlogic.com>

With qla2xxx using mid-layer async-scsi-scanning, the link state for
disconnected port is displayed wrong. Additional check for cable presence
is considered to display proper link state.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_attr.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index d416c35..5c98b09 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -987,7 +987,8 @@ qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
 	int len = 0;
 
 	if (atomic_read(&vha->loop_state) == LOOP_DOWN ||
-	    atomic_read(&vha->loop_state) == LOOP_DEAD)
+	    atomic_read(&vha->loop_state) == LOOP_DEAD ||
+	    vha->device_flags & DFLG_NO_CABLE)
 		len = snprintf(buf, PAGE_SIZE, "Link Down\n");
 	else if (atomic_read(&vha->loop_state) != LOOP_READY ||
 	    test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 03/16] qla2xxx: Clear error status after uncorrectable non-fatal errors.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
  2010-05-04 22:01 ` [PATCH 01/16] qla2xxx: Check for ISP84xx before processing to get 84xx firmware version giridhar.malavali
  2010-05-04 22:01 ` [PATCH 02/16] qla2xxx: Display proper link state for disconnected ports giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 04/16] qla2xxx: Add char device to increase driver use count giridhar.malavali
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Lalit Chandivade

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

Currently error status is cleared only after the uncorrectable fatal errors
in the qla2xxx_pci_slot_reset. This fix is added to clear the error status in
qla2xxx_pci_resume. This way for both fatal and non-fatal errors the error
status gets cleared properly.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=572258

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_os.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index b1adeb7..f2102db 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3697,7 +3697,6 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 		ret =  PCI_ERS_RESULT_RECOVERED;
 	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
-	pci_cleanup_aer_uncorrect_error_status(pdev);
 
 	DEBUG17(qla_printk(KERN_WARNING, ha,
 	    "slot_reset-return:ret=%x\n", ret));
@@ -3721,6 +3720,8 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
 		    "from slot/link_reset");
 	}
 
+	pci_cleanup_aer_uncorrect_error_status(pdev);
+
 	ha->flags.eeh_busy = 0;
 }
 
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 04/16] qla2xxx: Add char device to increase driver use count
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (2 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 03/16] qla2xxx: Clear error status after uncorrectable non-fatal errors giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 05/16] qla2xxx: Further generalization of SRB CTX infrastructure giridhar.malavali
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Harish Zunjarrao

From: Harish Zunjarrao <harish.zunjarrao@qlogic.com>

The driver should not be unloaded if any application is using it.
To disallow driver unload, driver use count must be incremented.
Application uses this char device as handle and increases driver
use count to avoid possible driver unload.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_def.h |    3 ++-
 drivers/scsi/qla2xxx/qla_os.c  |   14 ++++++++++++++
 2 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index edb7a70..d4a53e5 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -35,7 +35,8 @@
 
 #include "qla_bsg.h"
 #include "qla_nx.h"
-#define QLA2XXX_DRIVER_NAME  "qla2xxx"
+#define QLA2XXX_DRIVER_NAME	"qla2xxx"
+#define QLA2XXX_APIDEV		"ql2xapidev"
 
 /*
  * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f2102db..10c14af 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -24,6 +24,8 @@
  */
 char qla2x00_version_str[40];
 
+static int apidev_major;
+
 /*
  * SRB allocation cache
  */
@@ -3763,6 +3765,10 @@ static struct pci_driver qla2xxx_pci_driver = {
 	.err_handler	= &qla2xxx_err_handler,
 };
 
+static struct file_operations apidev_fops = {
+	.owner = THIS_MODULE,
+};
+
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -3791,6 +3797,13 @@ qla2x00_module_init(void)
 		kmem_cache_destroy(srb_cachep);
 		return -ENODEV;
 	}
+
+	apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops);
+	if (apidev_major < 0) {
+		printk(KERN_WARNING "qla2xxx: Unable to register char device "
+		    "%s\n", QLA2XXX_APIDEV);
+	}
+
 	qla2xxx_transport_vport_template =
 	    fc_attach_transport(&qla2xxx_transport_vport_functions);
 	if (!qla2xxx_transport_vport_template) {
@@ -3816,6 +3829,7 @@ qla2x00_module_init(void)
 static void __exit
 qla2x00_module_exit(void)
 {
+	unregister_chrdev(apidev_major, QLA2XXX_APIDEV);
 	pci_unregister_driver(&qla2xxx_pci_driver);
 	qla2x00_release_firmware();
 	kmem_cache_destroy(srb_cachep);
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 05/16] qla2xxx: Further generalization of SRB CTX infrastructure.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (3 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 04/16] qla2xxx: Add char device to increase driver use count giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 06/16] qla2xxx: Limit mailbox command contention for ADISC requests giridhar.malavali
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Andrew Vasquez <andrew.vasquez@qlogic.com>

Prepare CTX infrastructure for additional asynchronous
executions, add generic done() operator, pull CMD definitions.

Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |   17 ++++++---
 drivers/scsi/qla2xxx/qla_init.c |   43 +++++++++++++++++-----
 drivers/scsi/qla2xxx/qla_isr.c  |   74 +++++++++++----------------------------
 3 files changed, 65 insertions(+), 69 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index d4a53e5..b3cf609 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -214,14 +214,21 @@ typedef struct srb {
 /*
  * SRB extensions.
  */
-struct srb_ctx {
 #define SRB_LOGIN_CMD	1
 #define SRB_LOGOUT_CMD	2
+#define SRB_ELS_CMD_RPT 3
+#define SRB_ELS_CMD_HST 4
+#define SRB_CT_CMD 5
+
+struct srb_ctx {
 	uint16_t type;
+	char *name;
+
 	struct timer_list timer;
 
-	void (*free)(srb_t *sp);
-	void (*timeout)(srb_t *sp);
+	void (*done)(srb_t *);
+	void (*free)(srb_t *);
+	void (*timeout)(srb_t *);
 };
 
 struct srb_logio {
@@ -231,12 +238,10 @@ struct srb_logio {
 #define SRB_LOGIN_COND_PLOGI	BIT_1
 #define SRB_LOGIN_SKIP_PRLI	BIT_2
 	uint16_t flags;
+	uint16_t data[2];
 };
 
 struct srb_bsg_ctx {
-#define SRB_ELS_CMD_RPT 3
-#define SRB_ELS_CMD_HST 4
-#define SRB_CT_CMD 5
 	uint16_t type;
 };
 
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 55540d2..c3c2c36 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -117,13 +117,22 @@ qla2x00_async_logio_timeout(srb_t *sp)
 
 	DEBUG2(printk(KERN_WARNING
 	    "scsi(%ld:%x): Async-%s timeout.\n",
-	    fcport->vha->host_no, sp->handle,
-	    lio->ctx.type == SRB_LOGIN_CMD ? "login": "logout"));
+	    fcport->vha->host_no, sp->handle, lio->ctx.name));
 
 	if (lio->ctx.type == SRB_LOGIN_CMD)
 		qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
 }
 
+static void
+qla2x00_async_login_ctx_done(srb_t *sp)
+{
+	struct srb_logio *lio = sp->ctx;
+
+	qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
+	    lio->data);
+	lio->ctx.free(sp);
+}
+
 int
 qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
@@ -141,7 +150,9 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 
 	lio = sp->ctx;
 	lio->ctx.type = SRB_LOGIN_CMD;
+	lio->ctx.name = "login";
 	lio->ctx.timeout = qla2x00_async_logio_timeout;
+	lio->ctx.done = qla2x00_async_login_ctx_done;
 	lio->flags |= SRB_LOGIN_COND_PLOGI;
 	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
 		lio->flags |= SRB_LOGIN_RETRIED;
@@ -163,6 +174,16 @@ done:
 	return rval;
 }
 
+static void
+qla2x00_async_logout_ctx_done(srb_t *sp)
+{
+	struct srb_logio *lio = sp->ctx;
+
+	qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
+	    lio->data);
+	lio->ctx.free(sp);
+}
+
 int
 qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
@@ -179,7 +200,9 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 
 	lio = sp->ctx;
 	lio->ctx.type = SRB_LOGOUT_CMD;
+	lio->ctx.name = "logout";
 	lio->ctx.timeout = qla2x00_async_logio_timeout;
+	lio->ctx.done = qla2x00_async_logout_ctx_done;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
 		goto done_free_sp;
@@ -202,17 +225,17 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
 {
 	int rval;
-	uint8_t opts = 0;
 
 	switch (data[0]) {
 	case MBS_COMMAND_COMPLETE:
-		if (fcport->flags & FCF_FCP2_DEVICE)
-			opts |= BIT_1;
-		rval = qla2x00_get_port_database(vha, fcport, opts);
-		if (rval != QLA_SUCCESS)
-			qla2x00_mark_device_lost(vha, fcport, 1, 0);
-		else
-			qla2x00_update_fcport(vha, fcport);
+		if (fcport->flags & FCF_FCP2_DEVICE) {
+			rval = qla2x00_get_port_database(vha, fcport, BIT_1);
+			if (rval != QLA_SUCCESS) {
+				qla2x00_mark_device_lost(vha, fcport, 1, 0);
+				break;
+			}
+		}
+		qla2x00_update_fcport(vha, fcport);
 		break;
 	case MBS_COMMAND_ERROR:
 		if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f1ac62d..037bc41 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -895,34 +895,20 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 {
 	const char func[] = "MBX-IOCB";
 	const char *type;
-	struct qla_hw_data *ha = vha->hw;
 	fc_port_t *fcport;
 	srb_t *sp;
 	struct srb_logio *lio;
-	uint16_t data[2];
+	uint16_t *data;
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
 	if (!sp)
 		return;
 
-	type = NULL;
 	lio = sp->ctx;
-	switch (lio->ctx.type) {
-	case SRB_LOGIN_CMD:
-		type = "login";
-		break;
-	case SRB_LOGOUT_CMD:
-		type = "logout";
-		break;
-	default:
-		qla_printk(KERN_WARNING, ha,
-		    "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
-		    lio->ctx.type);
-		return;
-	}
-
 	del_timer(&lio->ctx.timer);
+	type = lio->ctx.name;
 	fcport = sp->fcport;
+	data = lio->data;
 
 	data[0] = data[1] = 0;
 	if (mbx->entry_status) {
@@ -938,7 +924,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		data[0] = MBS_COMMAND_ERROR;
 		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
 		    QLA_LOGIO_LOGIN_RETRIED: 0;
-		goto done_post_logio_done_work;
+		goto logio_done;
 	}
 
 	if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
@@ -948,10 +934,14 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    le16_to_cpu(mbx->mb1)));
 
 		data[0] = MBS_COMMAND_COMPLETE;
-		if (lio->ctx.type == SRB_LOGIN_CMD && le16_to_cpu(mbx->mb1) & BIT_1)
-			fcport->flags |= FCF_FCP2_DEVICE;
+		if (lio->ctx.type == SRB_LOGIN_CMD)
+			fcport->port_type = FCT_TARGET;
+			if (le16_to_cpu(mbx->mb1) & BIT_0)
+				fcport->port_type = FCT_INITIATOR;
+			if (le16_to_cpu(mbx->mb1) & BIT_1)
+				fcport->flags |= FCF_FCP2_DEVICE;
 
-		goto done_post_logio_done_work;
+		goto logio_done;
 	}
 
 	data[0] = le16_to_cpu(mbx->mb0);
@@ -976,12 +966,8 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	    le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
 	    le16_to_cpu(mbx->mb7)));
 
-done_post_logio_done_work:
-	lio->ctx.type == SRB_LOGIN_CMD ?
-	    qla2x00_post_async_login_done_work(fcport->vha, fcport, data):
-	    qla2x00_post_async_logout_done_work(fcport->vha, fcport, data);
-
-	lio->ctx.free(sp);
+logio_done:
+	lio->ctx.done(sp);
 }
 
 static void
@@ -1084,35 +1070,21 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 {
 	const char func[] = "LOGIO-IOCB";
 	const char *type;
-	struct qla_hw_data *ha = vha->hw;
 	fc_port_t *fcport;
 	srb_t *sp;
 	struct srb_logio *lio;
-	uint16_t data[2];
+	uint16_t *data;
 	uint32_t iop[2];
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, logio);
 	if (!sp)
 		return;
 
-	type = NULL;
 	lio = sp->ctx;
-	switch (lio->ctx.type) {
-	case SRB_LOGIN_CMD:
-		type = "login";
-		break;
-	case SRB_LOGOUT_CMD:
-		type = "logout";
-		break;
-	default:
-		qla_printk(KERN_WARNING, ha,
-		    "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
-		    lio->ctx.type);
-		return;
-	}
-
 	del_timer(&lio->ctx.timer);
+	type = lio->ctx.name;
 	fcport = sp->fcport;
+	data = lio->data;
 
 	data[0] = data[1] = 0;
 	if (logio->entry_status) {
@@ -1125,7 +1097,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		data[0] = MBS_COMMAND_ERROR;
 		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
 		    QLA_LOGIO_LOGIN_RETRIED: 0;
-		goto done_post_logio_done_work;
+		goto logio_done;
 	}
 
 	if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
@@ -1136,7 +1108,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 		data[0] = MBS_COMMAND_COMPLETE;
 		if (lio->ctx.type == SRB_LOGOUT_CMD)
-			goto done_post_logio_done_work;
+			goto logio_done;
 
 		iop[0] = le32_to_cpu(logio->io_parameter[0]);
 		if (iop[0] & BIT_4) {
@@ -1151,7 +1123,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		if (logio->io_parameter[9] || logio->io_parameter[10])
 			fcport->supported_classes |= FC_COS_CLASS3;
 
-		goto done_post_logio_done_work;
+		goto logio_done;
 	}
 
 	iop[0] = le32_to_cpu(logio->io_parameter[0]);
@@ -1184,12 +1156,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 	    le32_to_cpu(logio->io_parameter[0]),
 	    le32_to_cpu(logio->io_parameter[1])));
 
-done_post_logio_done_work:
-	lio->ctx.type == SRB_LOGIN_CMD ?
-	    qla2x00_post_async_login_done_work(fcport->vha, fcport, data):
-	    qla2x00_post_async_logout_done_work(fcport->vha, fcport, data);
-
-	lio->ctx.free(sp);
+logio_done:
+	lio->ctx.done(sp);
 }
 
 /**
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 06/16] qla2xxx: Limit mailbox command contention for ADISC requests.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (4 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 05/16] qla2xxx: Further generalization of SRB CTX infrastructure giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 07/16] qla2xxx: Cleanup FCP-command-status processing debug statements giridhar.malavali
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Andrew Vasquez <andrew.vasquez@qlogic.com>

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |    7 +++
 drivers/scsi/qla2xxx/qla_gbl.h  |    8 ++++
 drivers/scsi/qla2xxx/qla_init.c |   88 ++++++++++++++++++++++++++++++++++++---
 drivers/scsi/qla2xxx/qla_iocb.c |   39 ++++++++++++++++-
 drivers/scsi/qla2xxx/qla_isr.c  |   33 +++++++-------
 drivers/scsi/qla2xxx/qla_os.c   |   31 ++++++++++++-
 6 files changed, 178 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b3cf609..a491338 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -219,6 +219,7 @@ typedef struct srb {
 #define SRB_ELS_CMD_RPT 3
 #define SRB_ELS_CMD_HST 4
 #define SRB_CT_CMD 5
+#define SRB_ADISC_CMD	6
 
 struct srb_ctx {
 	uint16_t type;
@@ -1623,6 +1624,7 @@ typedef struct fc_port {
 #define FCF_FABRIC_DEVICE	BIT_0
 #define FCF_LOGIN_NEEDED	BIT_1
 #define FCF_FCP2_DEVICE		BIT_2
+#define FCF_ASYNC_SENT		BIT_3
 
 /* No loop ID flag. */
 #define FC_NO_LOOP_ID		0x1000
@@ -2156,6 +2158,8 @@ enum qla_work_type {
 	QLA_EVT_ASYNC_LOGIN_DONE,
 	QLA_EVT_ASYNC_LOGOUT,
 	QLA_EVT_ASYNC_LOGOUT_DONE,
+	QLA_EVT_ASYNC_ADISC,
+	QLA_EVT_ASYNC_ADISC_DONE,
 	QLA_EVT_UEVENT,
 };
 
@@ -2514,6 +2518,9 @@ struct qla_hw_data {
 	dma_addr_t	ex_init_cb_dma;
 	struct ex_init_cb_81xx *ex_init_cb;
 
+	void		*async_pd;
+	dma_addr_t	async_pd_dma;
+
 	/* These are used by mailbox operations. */
 	volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index cff5a4a..03be298 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -56,10 +56,14 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
 extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
+extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
+    uint16_t *);
 extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
+extern int qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
+    uint16_t *);
 
 extern fc_port_t *
 qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -97,6 +101,10 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
     fc_port_t *, uint16_t *);
+extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *,
+    uint16_t *);
+extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *,
+    fc_port_t *, uint16_t *);
 extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
 
 extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index c3c2c36..4e7a3d5 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -119,6 +119,7 @@ qla2x00_async_logio_timeout(srb_t *sp)
 	    "scsi(%ld:%x): Async-%s timeout.\n",
 	    fcport->vha->host_no, sp->handle, lio->ctx.name));
 
+	fcport->flags &= ~FCF_ASYNC_SENT;
 	if (lio->ctx.type == SRB_LOGIN_CMD)
 		qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
 }
@@ -220,6 +221,56 @@ done:
 	return rval;
 }
 
+static void
+qla2x00_async_adisc_ctx_done(srb_t *sp)
+{
+	struct srb_logio *lio = sp->ctx;
+
+	qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
+	    lio->data);
+	lio->ctx.free(sp);
+}
+
+int
+qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
+    uint16_t *data)
+{
+	struct qla_hw_data *ha = vha->hw;
+	srb_t *sp;
+	struct srb_logio *lio;
+	int rval;
+
+	rval = QLA_FUNCTION_FAILED;
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
+	    ELS_TMO_2_RATOV(ha) + 2);
+	if (!sp)
+		goto done;
+
+	lio = sp->ctx;
+	lio->ctx.type = SRB_ADISC_CMD;
+	lio->ctx.name = "adisc";
+	lio->ctx.timeout = qla2x00_async_logio_timeout;
+	lio->ctx.done = qla2x00_async_adisc_ctx_done;
+	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
+		lio->flags |= SRB_LOGIN_RETRIED;
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	DEBUG2(printk(KERN_DEBUG
+	    "scsi(%ld:%x): Async-adisc - loop-id=%x portid=%02x%02x%02x.\n",
+	    fcport->vha->host_no, sp->handle, fcport->loop_id,
+	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
+
+	return rval;
+
+done_free_sp:
+	del_timer_sync(&lio->ctx.timer);
+	lio->ctx.free(sp);
+done:
+	return rval;
+}
+
 int
 qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
@@ -229,15 +280,14 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 	switch (data[0]) {
 	case MBS_COMMAND_COMPLETE:
 		if (fcport->flags & FCF_FCP2_DEVICE) {
-			rval = qla2x00_get_port_database(vha, fcport, BIT_1);
-			if (rval != QLA_SUCCESS) {
-				qla2x00_mark_device_lost(vha, fcport, 1, 0);
-				break;
-			}
+			fcport->flags |= FCF_ASYNC_SENT;
+			qla2x00_post_async_adisc_work(vha, fcport, data);
+			break;
 		}
 		qla2x00_update_fcport(vha, fcport);
 		break;
 	case MBS_COMMAND_ERROR:
+		fcport->flags &= ~FCF_ASYNC_SENT;
 		if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
 			set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 		else
@@ -251,6 +301,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 		fcport->loop_id++;
 		rval = qla2x00_find_new_loop_id(vha, fcport);
 		if (rval != QLA_SUCCESS) {
+			fcport->flags &= ~FCF_ASYNC_SENT;
 			qla2x00_mark_device_lost(vha, fcport, 1, 0);
 			break;
 		}
@@ -268,6 +319,26 @@ qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return QLA_SUCCESS;
 }
 
+int
+qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    uint16_t *data)
+{
+	if (data[0] == MBS_COMMAND_COMPLETE) {
+		qla2x00_update_fcport(vha, fcport);
+
+		return QLA_SUCCESS;
+	}
+
+	/* Retry login. */
+	fcport->flags &= ~FCF_ASYNC_SENT;
+	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
+		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+	else
+		qla2x00_mark_device_lost(vha, fcport, 1, 0);
+
+	return QLA_SUCCESS;
+}
+
 /****************************************************************************/
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
@@ -2062,6 +2133,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
 	if (IS_QLA23XX(ha)) {
 		nv->firmware_options[0] |= BIT_2;
 		nv->firmware_options[0] &= ~BIT_3;
+		nv->firmware_options[0] &= ~BIT_6;
 		nv->add_firmware_options[1] |= BIT_5 | BIT_4;
 
 		if (IS_QLA2300(ha)) {
@@ -2680,7 +2752,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
 	    PORT_RETRY_TIME;
 	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
 	    PORT_RETRY_TIME);
-	fcport->flags &= ~FCF_LOGIN_NEEDED;
+	fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
 
 	qla2x00_iidma_fcport(vha, fcport);
 
@@ -3326,11 +3398,15 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
 	retry = 0;
 
 	if (IS_ALOGIO_CAPABLE(ha)) {
+		if (fcport->flags & FCF_ASYNC_SENT)
+			return rval;
+		fcport->flags |= FCF_ASYNC_SENT;
 		rval = qla2x00_post_async_login_work(vha, fcport, NULL);
 		if (!rval)
 			return rval;
 	}
 
+	fcport->flags &= ~FCF_ASYNC_SENT;
 	rval = qla2x00_fabric_login(vha, fcport, next_loopid);
 	if (rval == QLA_SUCCESS) {
 		/* Send an ADISC to FCP2 devices.*/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d792ae3..8112e41 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1054,6 +1054,36 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
 }
 
 static void
+qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+{
+	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+	logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC);
+	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+	logio->vp_index = sp->fcport->vp_idx;
+}
+
+static void
+qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
+{
+	struct qla_hw_data *ha = sp->fcport->vha->hw;
+
+	mbx->entry_type = MBX_IOCB_TYPE;
+	SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
+	mbx->mb0 = cpu_to_le16(MBC_GET_PORT_DATABASE);
+	if (HAS_EXTENDED_IDS(ha)) {
+		mbx->mb1 = cpu_to_le16(sp->fcport->loop_id);
+		mbx->mb10 = cpu_to_le16(BIT_0);
+	} else {
+		mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | BIT_0);
+	}
+	mbx->mb2 = cpu_to_le16(MSW(ha->async_pd_dma));
+	mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma));
+	mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma)));
+	mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma)));
+	mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx);
+}
+
+static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
 	struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
@@ -1185,12 +1215,12 @@ qla2x00_start_sp(srb_t *sp)
 	switch (ctx->type) {
 	case SRB_LOGIN_CMD:
 		IS_FWI2_CAPABLE(ha) ?
-		    qla24xx_login_iocb(sp, pkt):
+		    qla24xx_login_iocb(sp, pkt) :
 		    qla2x00_login_iocb(sp, pkt);
 		break;
 	case SRB_LOGOUT_CMD:
 		IS_FWI2_CAPABLE(ha) ?
-		    qla24xx_logout_iocb(sp, pkt):
+		    qla24xx_logout_iocb(sp, pkt) :
 		    qla2x00_logout_iocb(sp, pkt);
 		break;
 	case SRB_ELS_CMD_RPT:
@@ -1200,6 +1230,11 @@ qla2x00_start_sp(srb_t *sp)
 	case SRB_CT_CMD:
 		qla24xx_ct_iocb(sp, pkt);
 		break;
+	case SRB_ADISC_CMD:
+		IS_FWI2_CAPABLE(ha) ?
+		    qla24xx_adisc_iocb(sp, pkt) :
+		    qla2x00_adisc_iocb(sp, pkt);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 037bc41..a1968eb 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -899,6 +899,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	srb_t *sp;
 	struct srb_logio *lio;
 	uint16_t *data;
+	uint16_t status;
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
 	if (!sp)
@@ -910,7 +911,9 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	fcport = sp->fcport;
 	data = lio->data;
 
-	data[0] = data[1] = 0;
+	data[0] = MBS_COMMAND_ERROR;
+	data[1] = lio->flags & SRB_LOGIN_RETRIED ?
+	    QLA_LOGIO_LOGIN_RETRIED : 0;
 	if (mbx->entry_status) {
 		DEBUG2(printk(KERN_WARNING
 		    "scsi(%ld:%x): Async-%s error entry - entry-status=%x "
@@ -921,26 +924,27 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    le16_to_cpu(mbx->status_flags)));
 		DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx)));
 
-		data[0] = MBS_COMMAND_ERROR;
-		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
-		    QLA_LOGIO_LOGIN_RETRIED: 0;
 		goto logio_done;
 	}
 
-	if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
+	status = le16_to_cpu(mbx->status);
+	if (status == 0x30 && lio->ctx.type == SRB_LOGIN_CMD &&
+	    le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
+		status = 0;
+	if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
 		DEBUG2(printk(KERN_DEBUG
 		    "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n",
 		    fcport->vha->host_no, sp->handle, type,
 		    le16_to_cpu(mbx->mb1)));
 
 		data[0] = MBS_COMMAND_COMPLETE;
-		if (lio->ctx.type == SRB_LOGIN_CMD)
+		if (lio->ctx.type == SRB_LOGIN_CMD) {
 			fcport->port_type = FCT_TARGET;
 			if (le16_to_cpu(mbx->mb1) & BIT_0)
 				fcport->port_type = FCT_INITIATOR;
 			if (le16_to_cpu(mbx->mb1) & BIT_1)
 				fcport->flags |= FCF_FCP2_DEVICE;
-
+		}
 		goto logio_done;
 	}
 
@@ -953,15 +957,13 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		break;
 	default:
 		data[0] = MBS_COMMAND_ERROR;
-		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
-		    QLA_LOGIO_LOGIN_RETRIED: 0;
 		break;
 	}
 
 	DEBUG2(printk(KERN_WARNING
 	    "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x "
 	    "mb6=%x mb7=%x.\n",
-	    fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status),
+	    fcport->vha->host_no, sp->handle, type, status,
 	    le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
 	    le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
 	    le16_to_cpu(mbx->mb7)));
@@ -1086,7 +1088,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 	fcport = sp->fcport;
 	data = lio->data;
 
-	data[0] = data[1] = 0;
+	data[0] = MBS_COMMAND_ERROR;
+	data[1] = lio->flags & SRB_LOGIN_RETRIED ?
+		QLA_LOGIO_LOGIN_RETRIED : 0;
 	if (logio->entry_status) {
 		DEBUG2(printk(KERN_WARNING
 		    "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
@@ -1094,9 +1098,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    logio->entry_status));
 		DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio)));
 
-		data[0] = MBS_COMMAND_ERROR;
-		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
-		    QLA_LOGIO_LOGIN_RETRIED: 0;
 		goto logio_done;
 	}
 
@@ -1107,7 +1108,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    le32_to_cpu(logio->io_parameter[0])));
 
 		data[0] = MBS_COMMAND_COMPLETE;
-		if (lio->ctx.type == SRB_LOGOUT_CMD)
+		if (lio->ctx.type != SRB_LOGIN_CMD)
 			goto logio_done;
 
 		iop[0] = le32_to_cpu(logio->io_parameter[0]);
@@ -1144,8 +1145,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		/* Fall through. */
 	default:
 		data[0] = MBS_COMMAND_ERROR;
-		data[1] = lio->flags & SRB_LOGIN_RETRIED ?
-		    QLA_LOGIO_LOGIN_RETRIED: 0;
 		break;
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 10c14af..2e083c0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2639,9 +2639,19 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 
 	INIT_LIST_HEAD(&ha->gbl_dsd_list);
 
+	/* Get consistent memory allocated for Async Port-Database. */
+	if (!IS_FWI2_CAPABLE(ha)) {
+		ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+			&ha->async_pd_dma);
+		if (!ha->async_pd)
+			goto fail_async_pd;
+	}
+
 	INIT_LIST_HEAD(&ha->vp_list);
 	return 1;
 
+fail_async_pd:
+	dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
 fail_ex_init_cb:
 	kfree(ha->npiv_info);
 fail_npiv_info:
@@ -2757,6 +2767,9 @@ qla2x00_mem_free(struct qla_hw_data *ha)
 		dma_pool_free(ha->s_dma_pool,
 			ha->ex_init_cb, ha->ex_init_cb_dma);
 
+	if (ha->async_pd)
+		dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
+
 	if (ha->s_dma_pool)
 		dma_pool_destroy(ha->s_dma_pool);
 
@@ -2809,6 +2822,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
 	ha->init_cb_dma = 0;
 	ha->ex_init_cb = NULL;
 	ha->ex_init_cb_dma = 0;
+	ha->async_pd = NULL;
+	ha->async_pd_dma = 0;
 
 	ha->s_dma_pool = NULL;
 	ha->dl_dma_pool = NULL;
@@ -2935,6 +2950,8 @@ qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
 qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
 qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
 qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
+qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
+qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
 
 int
 qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
@@ -3004,6 +3021,14 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 			qla2x00_async_logout_done(vha, e->u.logio.fcport,
 			    e->u.logio.data);
 			break;
+		case QLA_EVT_ASYNC_ADISC:
+			qla2x00_async_adisc(vha, e->u.logio.fcport,
+			    e->u.logio.data);
+			break;
+		case QLA_EVT_ASYNC_ADISC_DONE:
+			qla2x00_async_adisc_done(vha, e->u.logio.fcport,
+			    e->u.logio.data);
+			break;
 		case QLA_EVT_UEVENT:
 			qla2x00_uevent_emit(vha, e->u.uevent.code);
 			break;
@@ -3029,9 +3054,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 	 * If the port is not ONLINE then try to login
 	 * to it if we haven't run out of retries.
 	 */
-		if (atomic_read(&fcport->state) !=
-			FCS_ONLINE && fcport->login_retry) {
-
+		if (atomic_read(&fcport->state) != FCS_ONLINE &&
+		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
 			fcport->login_retry--;
 			if (fcport->flags & FCF_FABRIC_DEVICE) {
 				if (fcport->flags & FCF_FCP2_DEVICE)
@@ -3042,6 +3066,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 							fcport->d_id.b.al_pa);
 
 				if (IS_ALOGIO_CAPABLE(ha)) {
+					fcport->flags |= FCF_ASYNC_SENT;
 					data[0] = 0;
 					data[1] = QLA_LOGIO_LOGIN_RETRIED;
 					status = qla2x00_post_async_login_work(
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 07/16] qla2xxx: Cleanup FCP-command-status processing debug statements.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (5 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 06/16] qla2xxx: Limit mailbox command contention for ADISC requests giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 08/16] qla2xxx: Provide common framework for BSG and IOCB commands giridhar.malavali
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Andrew Vasquez <andrew.vasquez@qlogic.com>

Migrate to a consistent set of debug entries during status-IOCB
handling:

* group CS_TIMEOUT handling with CS_PORT_UNAVAILABLE and the like
  (more regrouping of common behaviour).

* drop CS_DATA_OVERRUN handling as it now falls into the
  'default' case (still returns DID_ERROR).

* consolidate CS_RESET and CS_ABORTED handling, as we the only
  functional difference was a printk() (still returns DID_RESET).

* dropped all the earlier inconsistent [qla_]printk()s sprinkled
  throught the needlessly large case-statement.  Failure case
  I/Os are now logged with a 'standard' format:

	<command failure details>
	<command generic details>

  so, for example a dropped-frame is logged as:

	qla2xxx 0000:13:00.0: scsi(16:0:0) Dropped frame(s) detected (4000 of 4000 bytes).
	qla2xxx 0000:13:00.0: scsi(16:0:0) FCP command status: 0x15-0x18 (70018) \
    oxid=78 ser=76 cdb=280000 len=4000 rsp_info=0 resid=0 fw_resid=4000

  which should now convey all relevant information.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_isr.c |  192 +++++++++++++---------------------------
 1 files changed, 63 insertions(+), 129 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a1968eb..b92f9a6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1283,6 +1283,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 	struct sts_entry_24xx *sts24;
 	uint16_t	comp_status;
 	uint16_t	scsi_status;
+	uint16_t	ox_id;
 	uint8_t		lscsi_status;
 	int32_t		resid;
 	uint32_t	sense_len, rsp_info_len, resid_len, fw_resid_len;
@@ -1291,6 +1292,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 	uint32_t handle;
 	uint16_t que;
 	struct req_que *req;
+	int logit = 1;
 
 	sts = (sts_entry_t *) pkt;
 	sts24 = (struct sts_entry_24xx *) pkt;
@@ -1320,9 +1322,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		sp = NULL;
 
 	if (sp == NULL) {
-		DEBUG2(printk("scsi(%ld): Status Entry invalid handle.\n",
-		    vha->host_no));
-		qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n");
+		qla_printk(KERN_WARNING, ha,
+		    "scsi(%ld): Invalid status handle (0x%x).\n", vha->host_no,
+		    sts->handle);
 
 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 		qla2xxx_wake_dpc(vha);
@@ -1330,10 +1332,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 	}
 	cp = sp->cmd;
 	if (cp == NULL) {
-		DEBUG2(printk("scsi(%ld): Command already returned back to OS "
-		    "pkt->handle=%d sp=%p.\n", vha->host_no, handle, sp));
 		qla_printk(KERN_WARNING, ha,
-		    "Command is NULL: already returned to OS (sp=%p)\n", sp);
+		    "scsi(%ld): Command already returned (0x%x/%p).\n",
+		    vha->host_no, sts->handle, sp);
 
 		return;
 	}
@@ -1342,6 +1343,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 
 	fcport = sp->fcport;
 
+	ox_id = 0;
 	sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
 	if (IS_FWI2_CAPABLE(ha)) {
 		if (scsi_status & SS_SENSE_LEN_VALID)
@@ -1355,6 +1357,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		rsp_info = sts24->data;
 		sense_data = sts24->data;
 		host_to_fcp_swap(sts24->data, sizeof(sts24->data));
+		ox_id = le16_to_cpu(sts24->ox_id);
 	} else {
 		if (scsi_status & SS_SENSE_LEN_VALID)
 			sense_len = le16_to_cpu(sts->req_sense_length);
@@ -1371,17 +1374,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		if (IS_FWI2_CAPABLE(ha))
 			sense_data += rsp_info_len;
 		if (rsp_info_len > 3 && rsp_info[3]) {
-			DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
-			    "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..."
-			    "retrying command\n", vha->host_no,
-			    cp->device->channel, cp->device->id,
-			    cp->device->lun, rsp_info_len, rsp_info[0],
-			    rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4],
-			    rsp_info[5], rsp_info[6], rsp_info[7]));
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "scsi(%ld:%d:%d): FCP I/O protocol failure "
+			    "(0x%x/0x%x).\n", vha->host_no, cp->device->id,
+			    cp->device->lun, rsp_info_len, rsp_info[3]));
 
 			cp->result = DID_BUS_BUSY << 16;
-			qla2x00_sp_compl(ha, sp);
-			return;
+			goto out;
 		}
 	}
 
@@ -1408,12 +1407,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 			    ((unsigned)(scsi_bufflen(cp) - resid) <
 			     cp->underflow)) {
 				qla_printk(KERN_INFO, ha,
-					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-					   "detected (%x of %x bytes)...returning "
-					   "error status.\n", vha->host_no,
-					   cp->device->channel, cp->device->id,
-					   cp->device->lun, resid,
-					   scsi_bufflen(cp));
+				    "scsi(%ld:%d:%d): Mid-layer underflow "
+				    "detected (0x%x of 0x%x bytes).\n",
+				    vha->host_no, cp->device->id,
+				    cp->device->lun, resid, scsi_bufflen(cp));
 
 				cp->result = DID_ERROR << 16;
 				break;
@@ -1422,12 +1419,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		cp->result = DID_OK << 16 | lscsi_status;
 
 		if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
-			DEBUG2(printk(KERN_INFO
-			    "scsi(%ld): QUEUE FULL status detected "
-			    "0x%x-0x%x.\n", vha->host_no, comp_status,
-			    scsi_status));
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
+			    vha->host_no, cp->device->id, cp->device->lun));
 			break;
 		}
+		logit = 0;
 		if (lscsi_status != SS_CHECK_CONDITION)
 			break;
 
@@ -1439,23 +1436,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		break;
 
 	case CS_DATA_UNDERRUN:
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x. "
-		    "resid=0x%x fw_resid=0x%x cdb=0x%x os_underflow=0x%x\n",
-		    vha->host_no, cp->device->id, cp->device->lun, comp_status,
-		    scsi_status, resid_len, fw_resid_len, cp->cmnd[0],
-		    cp->underflow));
-
 		/* Use F/W calculated residual length. */
 		resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len;
 		scsi_set_resid(cp, resid);
 		if (scsi_status & SS_RESIDUAL_UNDER) {
 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
-				DEBUG2(printk(
-				    "scsi(%ld:%d:%d:%d) Dropped frame(s) "
-				    "detected (%x of %x bytes)...residual "
-				    "length mismatch...retrying command.\n",
-				    vha->host_no, cp->device->channel,
+				DEBUG2(qla_printk(KERN_INFO, ha,
+				    "scsi(%ld:%d:%d) Dropped frame(s) detected "
+				    "(0x%x of 0x%x bytes).\n", vha->host_no,
 				    cp->device->id, cp->device->lun, resid,
 				    scsi_bufflen(cp)));
 
@@ -1467,21 +1455,18 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 			    ((unsigned)(scsi_bufflen(cp) - resid) <
 			    cp->underflow)) {
 				qla_printk(KERN_INFO, ha,
-				    "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-				    "detected (%x of %x bytes)...returning "
-				    "error status.\n", vha->host_no,
-				    cp->device->channel, cp->device->id,
+				    "scsi(%ld:%d:%d): Mid-layer underflow "
+				    "detected (0x%x of 0x%x bytes).\n",
+				    vha->host_no, cp->device->id,
 				    cp->device->lun, resid, scsi_bufflen(cp));
 
 				cp->result = DID_ERROR << 16;
 				break;
 			}
 		} else if (!lscsi_status) {
-			DEBUG2(printk(
-			    "scsi(%ld:%d:%d:%d) Dropped frame(s) detected "
-			    "(%x of %x bytes)...firmware reported underrun..."
-			    "retrying command.\n", vha->host_no,
-			    cp->device->channel, cp->device->id,
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x "
+			    "of 0x%x bytes).\n", vha->host_no, cp->device->id,
 			    cp->device->lun, resid, scsi_bufflen(cp)));
 
 			cp->result = DID_ERROR << 16;
@@ -1489,6 +1474,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		}
 
 		cp->result = DID_OK << 16 | lscsi_status;
+		logit = 0;
 
 		/*
 		 * Check to see if SCSI Status is non zero. If so report SCSI
@@ -1496,10 +1482,11 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		 */
 		if (lscsi_status != 0) {
 			if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
-				DEBUG2(printk(KERN_INFO
-				    "scsi(%ld): QUEUE FULL status detected "
-				    "0x%x-0x%x.\n", vha->host_no, comp_status,
-				    scsi_status));
+				DEBUG2(qla_printk(KERN_INFO, ha,
+				    "scsi(%ld:%d:%d) QUEUE FULL detected.\n",
+				    vha->host_no, cp->device->id,
+				    cp->device->lun));
+				logit = 1;
 				break;
 			}
 			if (lscsi_status != SS_CHECK_CONDITION)
@@ -1513,109 +1500,56 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		}
 		break;
 
-	case CS_DATA_OVERRUN:
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n",
-		    vha->host_no, cp->device->id, cp->device->lun, comp_status,
-		    scsi_status));
-		DEBUG2(printk(KERN_INFO
-		    "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
-		    cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3],
-		    cp->cmnd[4], cp->cmnd[5]));
-		DEBUG2(printk(KERN_INFO
-		    "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
-		    "status!\n",
-		    cp->serial_number, scsi_bufflen(cp), resid_len));
-
-		cp->result = DID_ERROR << 16;
-		break;
-
 	case CS_PORT_LOGGED_OUT:
 	case CS_PORT_CONFIG_CHG:
 	case CS_PORT_BUSY:
 	case CS_INCOMPLETE:
 	case CS_PORT_UNAVAILABLE:
-		/*
-		 * If the port is in Target Down state, return all IOs for this
-		 * Target with DID_NO_CONNECT ELSE Queue the IOs in the
-		 * retry_queue.
-		 */
-		DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down "
-		    "pid=%ld, compl status=0x%x, port state=0x%x\n",
-		    vha->host_no, cp->device->id, cp->device->lun,
-		    cp->serial_number, comp_status,
-		    atomic_read(&fcport->state)));
-
+	case CS_TIMEOUT:
 		/*
 		 * We are going to have the fc class block the rport
 		 * while we try to recover so instruct the mid layer
 		 * to requeue until the class decides how to handle this.
 		 */
 		cp->result = DID_TRANSPORT_DISRUPTED << 16;
+
+		if (comp_status == CS_TIMEOUT) {
+			if (IS_FWI2_CAPABLE(ha))
+				break;
+			else if ((le16_to_cpu(sts->status_flags) &
+			    SF_LOGOUT_SENT) == 0)
+				break;
+		}
+
+		DEBUG2(qla_printk(KERN_INFO, ha,
+			"scsi(%ld:%d:%d) Port down status: port-state=0x%x\n",
+			vha->host_no, cp->device->id, cp->device->lun,
+			atomic_read(&fcport->state)));
+
 		if (atomic_read(&fcport->state) == FCS_ONLINE)
 			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
 		break;
 
 	case CS_RESET:
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld): RESET status detected 0x%x-0x%x.\n",
-		    vha->host_no, comp_status, scsi_status));
-
-		cp->result = DID_RESET << 16;
-		break;
-
 	case CS_ABORTED:
-		/*
-		 * hv2.19.12 - DID_ABORT does not retry the request if we
-		 * aborted this request then abort otherwise it must be a
-		 * reset.
-		 */
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld): ABORT status detected 0x%x-0x%x.\n",
-		    vha->host_no, comp_status, scsi_status));
-
 		cp->result = DID_RESET << 16;
 		break;
-
-	case CS_TIMEOUT:
-		/*
-		 * We are going to have the fc class block the rport
-		 * while we try to recover so instruct the mid layer
-		 * to requeue until the class decides how to handle this.
-		 */
-		cp->result = DID_TRANSPORT_DISRUPTED << 16;
-
-		if (IS_FWI2_CAPABLE(ha)) {
-			DEBUG2(printk(KERN_INFO
-			    "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
-			    "0x%x-0x%x\n", vha->host_no, cp->device->channel,
-			    cp->device->id, cp->device->lun, comp_status,
-			    scsi_status));
-			break;
-		}
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x "
-		    "sflags=%x.\n", vha->host_no, cp->device->channel,
-		    cp->device->id, cp->device->lun, comp_status, scsi_status,
-		    le16_to_cpu(sts->status_flags)));
-
-		/* Check to see if logout occurred. */
-		if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
-			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
-		break;
-
 	default:
-		DEBUG3(printk("scsi(%ld): Error detected (unknown status) "
-		    "0x%x-0x%x.\n", vha->host_no, comp_status, scsi_status));
-		qla_printk(KERN_INFO, ha,
-		    "Unknown status detected 0x%x-0x%x.\n",
-		    comp_status, scsi_status);
-
 		cp->result = DID_ERROR << 16;
 		break;
 	}
 
-	/* Place command on done queue. */
+out:
+	if (logit)
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "scsi(%ld:%d:%d) FCP command status: 0x%x-0x%x (0x%x) "
+		    "oxid=0x%x ser=0x%lx cdb=%02x%02x%02x len=0x%x "
+		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x\n", vha->host_no,
+		    cp->device->id, cp->device->lun, comp_status, scsi_status,
+		    cp->result, ox_id, cp->serial_number, cp->cmnd[0],
+		    cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len,
+		    resid_len, fw_resid_len));
+
 	if (rsp->status_srb == NULL)
 		qla2x00_sp_compl(ha, sp);
 }
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 08/16] qla2xxx: Provide common framework for BSG and IOCB commands.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (6 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 07/16] qla2xxx: Cleanup FCP-command-status processing debug statements giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 09/16] qla2xxx: Support for asynchronous TM and Marker IOCBs giridhar.malavali
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Madhuranath Iyengar

From: Madhuranath Iyengar <madhuranath.iyengar@qlogic.com>

Currently, BSG and IOCB/Logio commands have a different
framework (srb structs). The purpose of this effort is to
consolidate them into a generalized framework for these
as well as other asynchronous operations in the future.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c  |   28 ++++----
 drivers/scsi/qla2xxx/qla_def.h  |   48 +++++++-------
 drivers/scsi/qla2xxx/qla_gbl.h  |    6 +-
 drivers/scsi/qla2xxx/qla_init.c |  135 ++++++++++++++++++++++----------------
 drivers/scsi/qla2xxx/qla_iocb.c |   24 ++++---
 drivers/scsi/qla2xxx/qla_isr.c  |   50 ++++++++-------
 drivers/scsi/qla2xxx/qla_os.c   |   13 +---
 7 files changed, 162 insertions(+), 142 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 21e5bcd..951db81 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -16,7 +16,7 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
 {
 	srb_t *sp;
 	struct qla_hw_data *ha = vha->hw;
-	struct srb_bsg_ctx *ctx;
+	struct srb_ctx *ctx;
 
 	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
 	if (!sp)
@@ -208,7 +208,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 	int req_sg_cnt, rsp_sg_cnt;
 	int rval =  (DRIVER_ERROR << 16);
 	uint16_t nextlid = 0;
-	struct srb_bsg *els;
+	struct srb_ctx *els;
 
 	/*  Multiple SG's are not supported for ELS requests */
 	if (bsg_job->request_payload.sg_cnt > 1 ||
@@ -307,17 +307,17 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 	}
 
 	/* Alloc SRB structure */
-	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg));
+	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
 	if (!sp) {
 		rval = -ENOMEM;
 		goto done_unmap_sg;
 	}
 
 	els = sp->ctx;
-	els->ctx.type =
+	els->type =
 		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
 		SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
-	els->bsg_job = bsg_job;
+	els->u.bsg_job = bsg_job;
 
 	DEBUG2(qla_printk(KERN_INFO, ha,
 		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
@@ -361,7 +361,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 	uint16_t loop_id;
 	struct fc_port *fcport;
 	char  *type = "FC_BSG_HST_CT";
-	struct srb_bsg *ct;
+	struct srb_ctx *ct;
 
 	/* pass through is supported only for ISP 4Gb or higher */
 	if (!IS_FWI2_CAPABLE(ha)) {
@@ -442,15 +442,15 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 	fcport->loop_id = loop_id;
 
 	/* Alloc SRB structure */
-	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg));
+	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
 	if (!sp) {
 		rval = -ENOMEM;
 		goto done_free_fcport;
 	}
 
 	ct = sp->ctx;
-	ct->ctx.type = SRB_CT_CMD;
-	ct->bsg_job = bsg_job;
+	ct->type = SRB_CT_CMD;
+	ct->u.bsg_job = bsg_job;
 
 	DEBUG2(qla_printk(KERN_INFO, ha,
 		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
@@ -1155,7 +1155,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
 	int cnt, que;
 	unsigned long flags;
 	struct req_que *req;
-	struct srb_bsg *sp_bsg;
+	struct srb_ctx *sp_bsg;
 
 	/* find the bsg job from the active list of commands */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1167,11 +1167,11 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
 		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
 			sp = req->outstanding_cmds[cnt];
 			if (sp) {
-				sp_bsg = (struct srb_bsg *)sp->ctx;
+				sp_bsg = sp->ctx;
 
-				if (((sp_bsg->ctx.type == SRB_CT_CMD) ||
-					(sp_bsg->ctx.type == SRB_ELS_CMD_HST))
-					&& (sp_bsg->bsg_job == bsg_job)) {
+				if (((sp_bsg->type == SRB_CT_CMD) ||
+					(sp_bsg->type == SRB_ELS_CMD_HST))
+					&& (sp_bsg->u.bsg_job == bsg_job)) {
 					if (ha->isp_ops->abort_command(sp)) {
 						DEBUG2(qla_printk(KERN_INFO, ha,
 						    "scsi(%ld): mbx "
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a491338..08f5fd5 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -214,16 +214,16 @@ typedef struct srb {
 /*
  * SRB extensions.
  */
-#define SRB_LOGIN_CMD	1
-#define SRB_LOGOUT_CMD	2
-#define SRB_ELS_CMD_RPT 3
-#define SRB_ELS_CMD_HST 4
-#define SRB_CT_CMD 5
-#define SRB_ADISC_CMD	6
-
-struct srb_ctx {
-	uint16_t type;
-	char *name;
+struct srb_iocb {
+	union {
+		struct {
+			uint16_t flags;
+#define SRB_LOGIN_RETRIED	BIT_0
+#define SRB_LOGIN_COND_PLOGI	BIT_1
+#define SRB_LOGIN_SKIP_PRLI	BIT_2
+			uint16_t data[2];
+		} logio;
+	} u;
 
 	struct timer_list timer;
 
@@ -232,23 +232,21 @@ struct srb_ctx {
 	void (*timeout)(srb_t *);
 };
 
-struct srb_logio {
-	struct srb_ctx ctx;
-
-#define SRB_LOGIN_RETRIED	BIT_0
-#define SRB_LOGIN_COND_PLOGI	BIT_1
-#define SRB_LOGIN_SKIP_PRLI	BIT_2
-	uint16_t flags;
-	uint16_t data[2];
-};
+/* Values for srb_ctx type */
+#define SRB_LOGIN_CMD	1
+#define SRB_LOGOUT_CMD	2
+#define SRB_ELS_CMD_RPT 3
+#define SRB_ELS_CMD_HST 4
+#define SRB_CT_CMD	5
+#define SRB_ADISC_CMD	6
 
-struct srb_bsg_ctx {
+struct srb_ctx {
 	uint16_t type;
-};
-
-struct srb_bsg {
-	struct srb_bsg_ctx ctx;
-	struct fc_bsg_job *bsg_job;
+	char *name;
+	union {
+		struct srb_iocb *iocb_cmd;
+		struct fc_bsg_job *bsg_job;
+	} u;
 };
 
 struct msg_echo_lb {
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 03be298..408e5f0 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -58,11 +58,11 @@ extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
 extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
-extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
+extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
-extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
+extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
-extern int qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
+extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 
 extern fc_port_t *
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4e7a3d5..72b4ef2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -48,6 +48,7 @@ qla2x00_ctx_sp_timeout(unsigned long __data)
 {
 	srb_t *sp = (srb_t *)__data;
 	struct srb_ctx *ctx;
+	struct srb_iocb *iocb;
 	fc_port_t *fcport = sp->fcport;
 	struct qla_hw_data *ha = fcport->vha->hw;
 	struct req_que *req;
@@ -57,17 +58,21 @@ qla2x00_ctx_sp_timeout(unsigned long __data)
 	req = ha->req_q_map[0];
 	req->outstanding_cmds[sp->handle] = NULL;
 	ctx = sp->ctx;
-	ctx->timeout(sp);
+	iocb = ctx->u.iocb_cmd;
+	iocb->timeout(sp);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-	ctx->free(sp);
+	iocb->free(sp);
 }
 
 void
 qla2x00_ctx_sp_free(srb_t *sp)
 {
 	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *iocb = ctx->u.iocb_cmd;
 
+	del_timer_sync(&iocb->timer);
+	kfree(iocb);
 	kfree(ctx);
 	mempool_free(sp, sp->fcport->vha->hw->srb_mempool);
 }
@@ -79,6 +84,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
 	srb_t *sp;
 	struct qla_hw_data *ha = vha->hw;
 	struct srb_ctx *ctx;
+	struct srb_iocb *iocb;
 
 	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
 	if (!sp)
@@ -86,21 +92,30 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
 	ctx = kzalloc(size, GFP_KERNEL);
 	if (!ctx) {
 		mempool_free(sp, ha->srb_mempool);
+		sp = NULL;
+		goto done;
+	}
+	iocb = kzalloc(sizeof(struct srb_iocb), GFP_KERNEL);
+	if (!iocb) {
+		mempool_free(sp, ha->srb_mempool);
+		sp = NULL;
+		kfree(ctx);
 		goto done;
 	}
 
 	memset(sp, 0, sizeof(*sp));
 	sp->fcport = fcport;
 	sp->ctx = ctx;
-	ctx->free = qla2x00_ctx_sp_free;
+	ctx->u.iocb_cmd = iocb;
+	iocb->free = qla2x00_ctx_sp_free;
 
-	init_timer(&ctx->timer);
+	init_timer(&iocb->timer);
 	if (!tmo)
 		goto done;
-	ctx->timer.expires = jiffies + tmo * HZ;
-	ctx->timer.data = (unsigned long)sp;
-	ctx->timer.function = qla2x00_ctx_sp_timeout;
-	add_timer(&ctx->timer);
+	iocb->timer.expires = jiffies + tmo * HZ;
+	iocb->timer.data = (unsigned long)sp;
+	iocb->timer.function = qla2x00_ctx_sp_timeout;
+	add_timer(&iocb->timer);
 done:
 	return sp;
 }
@@ -113,25 +128,26 @@ static void
 qla2x00_async_logio_timeout(srb_t *sp)
 {
 	fc_port_t *fcport = sp->fcport;
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
 
 	DEBUG2(printk(KERN_WARNING
 	    "scsi(%ld:%x): Async-%s timeout.\n",
-	    fcport->vha->host_no, sp->handle, lio->ctx.name));
+	    fcport->vha->host_no, sp->handle, ctx->name));
 
 	fcport->flags &= ~FCF_ASYNC_SENT;
-	if (lio->ctx.type == SRB_LOGIN_CMD)
+	if (ctx->type == SRB_LOGIN_CMD)
 		qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
 }
 
 static void
 qla2x00_async_login_ctx_done(srb_t *sp)
 {
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *lio = ctx->u.iocb_cmd;
 
 	qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
-	    lio->data);
-	lio->ctx.free(sp);
+		lio->u.logio.data);
+	lio->free(sp);
 }
 
 int
@@ -140,23 +156,25 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 {
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
-	struct srb_logio *lio;
+	struct srb_ctx *ctx;
+	struct srb_iocb *lio;
 	int rval;
 
 	rval = QLA_FUNCTION_FAILED;
-	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
 	    ELS_TMO_2_RATOV(ha) + 2);
 	if (!sp)
 		goto done;
 
-	lio = sp->ctx;
-	lio->ctx.type = SRB_LOGIN_CMD;
-	lio->ctx.name = "login";
-	lio->ctx.timeout = qla2x00_async_logio_timeout;
-	lio->ctx.done = qla2x00_async_login_ctx_done;
-	lio->flags |= SRB_LOGIN_COND_PLOGI;
+	ctx = sp->ctx;
+	ctx->type = SRB_LOGIN_CMD;
+	ctx->name = "login";
+	lio = ctx->u.iocb_cmd;
+	lio->timeout = qla2x00_async_logio_timeout;
+	lio->done = qla2x00_async_login_ctx_done;
+	lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
 	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
-		lio->flags |= SRB_LOGIN_RETRIED;
+		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
 		goto done_free_sp;
@@ -169,8 +187,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return rval;
 
 done_free_sp:
-	del_timer_sync(&lio->ctx.timer);
-	lio->ctx.free(sp);
+	lio->free(sp);
 done:
 	return rval;
 }
@@ -178,11 +195,12 @@ done:
 static void
 qla2x00_async_logout_ctx_done(srb_t *sp)
 {
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *lio = ctx->u.iocb_cmd;
 
 	qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
-	    lio->data);
-	lio->ctx.free(sp);
+	    lio->u.logio.data);
+	lio->free(sp);
 }
 
 int
@@ -190,20 +208,22 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
-	struct srb_logio *lio;
+	struct srb_ctx *ctx;
+	struct srb_iocb *lio;
 	int rval;
 
 	rval = QLA_FUNCTION_FAILED;
-	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
 	    ELS_TMO_2_RATOV(ha) + 2);
 	if (!sp)
 		goto done;
 
-	lio = sp->ctx;
-	lio->ctx.type = SRB_LOGOUT_CMD;
-	lio->ctx.name = "logout";
-	lio->ctx.timeout = qla2x00_async_logio_timeout;
-	lio->ctx.done = qla2x00_async_logout_ctx_done;
+	ctx = sp->ctx;
+	ctx->type = SRB_LOGOUT_CMD;
+	ctx->name = "logout";
+	lio = ctx->u.iocb_cmd;
+	lio->timeout = qla2x00_async_logio_timeout;
+	lio->done = qla2x00_async_logout_ctx_done;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
 		goto done_free_sp;
@@ -215,8 +235,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	return rval;
 
 done_free_sp:
-	del_timer_sync(&lio->ctx.timer);
-	lio->ctx.free(sp);
+	lio->free(sp);
 done:
 	return rval;
 }
@@ -224,11 +243,12 @@ done:
 static void
 qla2x00_async_adisc_ctx_done(srb_t *sp)
 {
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *lio = ctx->u.iocb_cmd;
 
 	qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
-	    lio->data);
-	lio->ctx.free(sp);
+	    lio->u.logio.data);
+	lio->free(sp);
 }
 
 int
@@ -237,22 +257,24 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 {
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
-	struct srb_logio *lio;
+	struct srb_ctx *ctx;
+	struct srb_iocb *lio;
 	int rval;
 
 	rval = QLA_FUNCTION_FAILED;
-	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
 	    ELS_TMO_2_RATOV(ha) + 2);
 	if (!sp)
 		goto done;
 
-	lio = sp->ctx;
-	lio->ctx.type = SRB_ADISC_CMD;
-	lio->ctx.name = "adisc";
-	lio->ctx.timeout = qla2x00_async_logio_timeout;
-	lio->ctx.done = qla2x00_async_adisc_ctx_done;
+	ctx = sp->ctx;
+	ctx->type = SRB_ADISC_CMD;
+	ctx->name = "adisc";
+	lio = ctx->u.iocb_cmd;
+	lio->timeout = qla2x00_async_logio_timeout;
+	lio->done = qla2x00_async_adisc_ctx_done;
 	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
-		lio->flags |= SRB_LOGIN_RETRIED;
+		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
 		goto done_free_sp;
@@ -265,13 +287,12 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return rval;
 
 done_free_sp:
-	del_timer_sync(&lio->ctx.timer);
-	lio->ctx.free(sp);
+	lio->free(sp);
 done:
 	return rval;
 }
 
-int
+void
 qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
 {
@@ -308,25 +329,25 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 		qla2x00_post_async_login_work(vha, fcport, NULL);
 		break;
 	}
-	return QLA_SUCCESS;
+	return;
 }
 
-int
+void
 qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
 {
 	qla2x00_mark_device_lost(vha, fcport, 1, 0);
-	return QLA_SUCCESS;
+	return;
 }
 
-int
+void
 qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
 {
 	if (data[0] == MBS_COMMAND_COMPLETE) {
 		qla2x00_update_fcport(vha, fcport);
 
-		return QLA_SUCCESS;
+		return;
 	}
 
 	/* Retry login. */
@@ -336,7 +357,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 	else
 		qla2x00_mark_device_lost(vha, fcport, 1, 0);
 
-	return QLA_SUCCESS;
+	return;
 }
 
 /****************************************************************************/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8112e41..8861b88 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -983,13 +983,14 @@ qla2x00_start_iocbs(srb_t *sp)
 static void
 qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 {
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *lio = ctx->u.iocb_cmd;
 
 	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
 	logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
-	if (lio->flags & SRB_LOGIN_COND_PLOGI)
+	if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI)
 		logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
-	if (lio->flags & SRB_LOGIN_SKIP_PRLI)
+	if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI)
 		logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI);
 	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
 	logio->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -1002,14 +1003,15 @@ static void
 qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
 {
 	struct qla_hw_data *ha = sp->fcport->vha->hw;
-	struct srb_logio *lio = sp->ctx;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *lio = ctx->u.iocb_cmd;
 	uint16_t opts;
 
 	mbx->entry_type = MBX_IOCB_TYPE;;
 	SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
 	mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
-	opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0;
-	opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0;
+	opts = lio->u.logio.flags & SRB_LOGIN_COND_PLOGI ? BIT_0 : 0;
+	opts |= lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI ? BIT_1 : 0;
 	if (HAS_EXTENDED_IDS(ha)) {
 		mbx->mb1 = cpu_to_le16(sp->fcport->loop_id);
 		mbx->mb10 = cpu_to_le16(opts);
@@ -1086,7 +1088,7 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
 static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
-	struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
+	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
 
         els_iocb->entry_type = ELS_IOCB_TYPE;
         els_iocb->entry_count = 1;
@@ -1099,8 +1101,10 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
         els_iocb->sof_type = EST_SOFI3;
         els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt);
 
-        els_iocb->opcode =(((struct srb_bsg*)sp->ctx)->ctx.type == SRB_ELS_CMD_RPT) ?
-	    bsg_job->request->rqst_data.r_els.els_code : bsg_job->request->rqst_data.h_els.command_code;
+	els_iocb->opcode =
+	    (((struct srb_ctx *)sp->ctx)->type == SRB_ELS_CMD_RPT) ?
+	    bsg_job->request->rqst_data.r_els.els_code :
+	    bsg_job->request->rqst_data.h_els.command_code;
         els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
         els_iocb->port_id[1] = sp->fcport->d_id.b.area;
         els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
@@ -1134,7 +1138,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
 	int index;
 	uint16_t tot_dsds;
         scsi_qla_host_t *vha = sp->fcport->vha;
-	struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
+	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
 	int loop_iterartion = 0;
 	int cont_iocb_prsnt = 0;
 	int entry_count = 1;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index b92f9a6..166bb20 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -897,7 +897,8 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	const char *type;
 	fc_port_t *fcport;
 	srb_t *sp;
-	struct srb_logio *lio;
+	struct srb_iocb *lio;
+	struct srb_ctx *ctx;
 	uint16_t *data;
 	uint16_t status;
 
@@ -905,14 +906,14 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	if (!sp)
 		return;
 
-	lio = sp->ctx;
-	del_timer(&lio->ctx.timer);
-	type = lio->ctx.name;
+	ctx = sp->ctx;
+	lio = ctx->u.iocb_cmd;
+	type = ctx->name;
 	fcport = sp->fcport;
-	data = lio->data;
+	data = lio->u.logio.data;
 
 	data[0] = MBS_COMMAND_ERROR;
-	data[1] = lio->flags & SRB_LOGIN_RETRIED ?
+	data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
 	    QLA_LOGIO_LOGIN_RETRIED : 0;
 	if (mbx->entry_status) {
 		DEBUG2(printk(KERN_WARNING
@@ -928,7 +929,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	}
 
 	status = le16_to_cpu(mbx->status);
-	if (status == 0x30 && lio->ctx.type == SRB_LOGIN_CMD &&
+	if (status == 0x30 && ctx->type == SRB_LOGIN_CMD &&
 	    le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
 		status = 0;
 	if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
@@ -938,7 +939,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    le16_to_cpu(mbx->mb1)));
 
 		data[0] = MBS_COMMAND_COMPLETE;
-		if (lio->ctx.type == SRB_LOGIN_CMD) {
+		if (ctx->type == SRB_LOGIN_CMD) {
 			fcport->port_type = FCT_TARGET;
 			if (le16_to_cpu(mbx->mb1) & BIT_0)
 				fcport->port_type = FCT_INITIATOR;
@@ -969,7 +970,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 	    le16_to_cpu(mbx->mb7)));
 
 logio_done:
-	lio->ctx.done(sp);
+	lio->done(sp);
 }
 
 static void
@@ -980,7 +981,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	const char *type;
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
-	struct srb_bsg *sp_bsg;
+	struct srb_ctx *sp_bsg;
 	struct fc_bsg_job *bsg_job;
 	uint16_t comp_status;
 	uint32_t fw_status[3];
@@ -989,11 +990,11 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 	if (!sp)
 		return;
-	sp_bsg = (struct srb_bsg*)sp->ctx;
-	bsg_job = sp_bsg->bsg_job;
+	sp_bsg = sp->ctx;
+	bsg_job = sp_bsg->u.bsg_job;
 
 	type = NULL;
-	switch (sp_bsg->ctx.type) {
+	switch (sp_bsg->type) {
 	case SRB_ELS_CMD_RPT:
 	case SRB_ELS_CMD_HST:
 		type = "els";
@@ -1004,7 +1005,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	default:
 		qla_printk(KERN_WARNING, ha,
 		    "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
-		    sp_bsg->ctx.type);
+		    sp_bsg->type);
 		return;
 	}
 
@@ -1058,8 +1059,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	dma_unmap_sg(&ha->pdev->dev,
 	    bsg_job->reply_payload.sg_list,
 	    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
-	if ((sp_bsg->ctx.type == SRB_ELS_CMD_HST) ||
-	    (sp_bsg->ctx.type == SRB_CT_CMD))
+	if ((sp_bsg->type == SRB_ELS_CMD_HST) ||
+	    (sp_bsg->type == SRB_CT_CMD))
 		kfree(sp->fcport);
 	kfree(sp->ctx);
 	mempool_free(sp, ha->srb_mempool);
@@ -1074,7 +1075,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 	const char *type;
 	fc_port_t *fcport;
 	srb_t *sp;
-	struct srb_logio *lio;
+	struct srb_iocb *lio;
+	struct srb_ctx *ctx;
 	uint16_t *data;
 	uint32_t iop[2];
 
@@ -1082,14 +1084,14 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 	if (!sp)
 		return;
 
-	lio = sp->ctx;
-	del_timer(&lio->ctx.timer);
-	type = lio->ctx.name;
+	ctx = sp->ctx;
+	lio = ctx->u.iocb_cmd;
+	type = ctx->name;
 	fcport = sp->fcport;
-	data = lio->data;
+	data = lio->u.logio.data;
 
 	data[0] = MBS_COMMAND_ERROR;
-	data[1] = lio->flags & SRB_LOGIN_RETRIED ?
+	data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
 		QLA_LOGIO_LOGIN_RETRIED : 0;
 	if (logio->entry_status) {
 		DEBUG2(printk(KERN_WARNING
@@ -1108,7 +1110,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		    le32_to_cpu(logio->io_parameter[0])));
 
 		data[0] = MBS_COMMAND_COMPLETE;
-		if (lio->ctx.type != SRB_LOGIN_CMD)
+		if (ctx->type != SRB_LOGIN_CMD)
 			goto logio_done;
 
 		iop[0] = le32_to_cpu(logio->io_parameter[0]);
@@ -1156,7 +1158,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 	    le32_to_cpu(logio->io_parameter[1])));
 
 logio_done:
-	lio->ctx.done(sp);
+	lio->done(sp);
 }
 
 /**
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2e083c0..70651f9 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1191,24 +1191,19 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 					ctx = sp->ctx;
 					if (ctx->type == SRB_LOGIN_CMD ||
 					    ctx->type == SRB_LOGOUT_CMD) {
-						del_timer_sync(&ctx->timer);
-						ctx->free(sp);
+						ctx->u.iocb_cmd->free(sp);
 					} else {
-						struct srb_bsg *sp_bsg =
-						    (struct srb_bsg *)sp->ctx;
 						struct fc_bsg_job *bsg_job =
-						    sp_bsg->bsg_job;
-
+						    ctx->u.bsg_job;
 						if (bsg_job->request->msgcode
 						    == FC_BSG_HST_CT)
 							kfree(sp->fcport);
 						bsg_job->req->errors = 0;
 						bsg_job->reply->result = res;
-						bsg_job->job_done(
-						    sp_bsg->bsg_job);
+						bsg_job->job_done(bsg_job);
 						kfree(sp->ctx);
 						mempool_free(sp,
-						    ha->srb_mempool);
+							ha->srb_mempool);
 					}
 				}
 			}
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 09/16] qla2xxx: Support for asynchronous TM and Marker IOCBs.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (7 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 08/16] qla2xxx: Provide common framework for BSG and IOCB commands giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 10/16] qla2xxx: T10 DIF support added giridhar.malavali
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Madhuranath Iyengar

From: Madhuranath Iyengar <madhuranath.iyengar@qlogic.com>

Currently we can only issue the task management (TM)
commands via the mailbox mechanism. This is a limitation,
since only one mailbox command can be issued at a time.
The purpose of this effort is to provide support for
issuing and processing the respose to TM and Marker
IOCBs asynchronously. Towards achieving this, the
consolidated srb architecture that is currently used for
BSG and IOCB/Logio commands has been enhanced and used.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c  |    4 +
 drivers/scsi/qla2xxx/qla_def.h  |   22 ++++++
 drivers/scsi/qla2xxx/qla_gbl.h  |    7 ++
 drivers/scsi/qla2xxx/qla_init.c |  156 ++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_iocb.c |   64 ++++++++++++++++
 drivers/scsi/qla2xxx/qla_isr.c  |  102 +++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_mbx.c  |   10 +++
 drivers/scsi/qla2xxx/qla_os.c   |    5 +
 8 files changed, 366 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 951db81..b905dfe 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -317,6 +317,9 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 	els->type =
 		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
 		SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
+	els->name =
+		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
+		"bsg_els_rpt" : "bsg_els_hst");
 	els->u.bsg_job = bsg_job;
 
 	DEBUG2(qla_printk(KERN_INFO, ha,
@@ -450,6 +453,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 
 	ct = sp->ctx;
 	ct->type = SRB_CT_CMD;
+	ct->name = "bsg_ct";
 	ct->u.bsg_job = bsg_job;
 
 	DEBUG2(qla_printk(KERN_INFO, ha,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 08f5fd5..0d2cecb 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -223,6 +223,26 @@ struct srb_iocb {
 #define SRB_LOGIN_SKIP_PRLI	BIT_2
 			uint16_t data[2];
 		} logio;
+		struct {
+			/*
+			 * Values for flags field below are as
+			 * defined in tsk_mgmt_entry struct
+			 * for control_flags field in qla_fw.h.
+			 */
+			uint32_t flags;
+			uint32_t lun;
+			uint32_t data;
+		} tmf;
+		struct {
+			/*
+			 * values for modif field below are as
+			 * defined in mrk_entry_24xx struct
+			 * for the modifier field in qla_fw.h.
+			 */
+			uint8_t modif;
+			uint16_t lun;
+			uint32_t data;
+		} marker;
 	} u;
 
 	struct timer_list timer;
@@ -239,6 +259,8 @@ struct srb_iocb {
 #define SRB_ELS_CMD_HST 4
 #define SRB_CT_CMD	5
 #define SRB_ADISC_CMD	6
+#define SRB_TM_CMD	7
+#define SRB_MARKER_CMD	8
 
 struct srb_ctx {
 	uint16_t type;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 408e5f0..3dbefe1 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -58,12 +58,18 @@ extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
 extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
+extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
+extern int qla2x00_async_marker(fc_port_t *, uint16_t, uint8_t);
 extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
+extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
+	struct srb_iocb *);
+extern void qla2x00_async_marker_done(struct scsi_qla_host *, fc_port_t *,
+	struct srb_iocb *);
 
 extern fc_port_t *
 qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -87,6 +93,7 @@ extern int ql2xetsenable;
 extern int ql2xshiftctondsd;
 extern int ql2xdbwr;
 extern int ql2xdontresethba;
+extern int ql2xasynctmfenable;
 
 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_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 72b4ef2..e78089d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -125,7 +125,7 @@ done:
 #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2)
 
 static void
-qla2x00_async_logio_timeout(srb_t *sp)
+qla2x00_async_iocb_timeout(srb_t *sp)
 {
 	fc_port_t *fcport = sp->fcport;
 	struct srb_ctx *ctx = sp->ctx;
@@ -170,7 +170,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	ctx->type = SRB_LOGIN_CMD;
 	ctx->name = "login";
 	lio = ctx->u.iocb_cmd;
-	lio->timeout = qla2x00_async_logio_timeout;
+	lio->timeout = qla2x00_async_iocb_timeout;
 	lio->done = qla2x00_async_login_ctx_done;
 	lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
 	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
@@ -222,7 +222,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 	ctx->type = SRB_LOGOUT_CMD;
 	ctx->name = "logout";
 	lio = ctx->u.iocb_cmd;
-	lio->timeout = qla2x00_async_logio_timeout;
+	lio->timeout = qla2x00_async_iocb_timeout;
 	lio->done = qla2x00_async_logout_ctx_done;
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS)
@@ -271,7 +271,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 	ctx->type = SRB_ADISC_CMD;
 	ctx->name = "adisc";
 	lio = ctx->u.iocb_cmd;
-	lio->timeout = qla2x00_async_logio_timeout;
+	lio->timeout = qla2x00_async_iocb_timeout;
 	lio->done = qla2x00_async_adisc_ctx_done;
 	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
 		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
@@ -292,6 +292,112 @@ done:
 	return rval;
 }
 
+static void
+qla2x00_async_tm_cmd_ctx_done(srb_t *sp)
+{
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
+
+	qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb);
+	iocb->free(sp);
+}
+
+int
+qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
+	uint32_t tag)
+{
+	struct scsi_qla_host *vha = fcport->vha;
+	struct qla_hw_data *ha = vha->hw;
+	srb_t *sp;
+	struct srb_ctx *ctx;
+	struct srb_iocb *tcf;
+	int rval;
+
+	rval = QLA_FUNCTION_FAILED;
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
+	    ELS_TMO_2_RATOV(ha) + 2);
+	if (!sp)
+		goto done;
+
+	ctx = sp->ctx;
+	ctx->type = SRB_TM_CMD;
+	ctx->name = "tmf";
+	tcf = ctx->u.iocb_cmd;
+	tcf->u.tmf.flags = flags;
+	tcf->u.tmf.lun = lun;
+	tcf->u.tmf.data = tag;
+	tcf->timeout = qla2x00_async_iocb_timeout;
+	tcf->done = qla2x00_async_tm_cmd_ctx_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	DEBUG2(printk(KERN_DEBUG
+	    "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n",
+	    fcport->vha->host_no, sp->handle, fcport->loop_id,
+	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
+
+	return rval;
+
+done_free_sp:
+	tcf->free(sp);
+done:
+	return rval;
+}
+
+static void
+qla2x00_async_marker_ctx_done(srb_t *sp)
+{
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
+
+	qla2x00_async_marker_done(sp->fcport->vha, sp->fcport, iocb);
+	iocb->free(sp);
+}
+
+int
+qla2x00_async_marker(fc_port_t *fcport, uint16_t lun, uint8_t modif)
+{
+	struct scsi_qla_host *vha = fcport->vha;
+	srb_t *sp;
+	struct srb_ctx *ctx;
+	struct srb_iocb *mrk;
+	int rval;
+
+	rval = QLA_FUNCTION_FAILED;
+	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 0);
+	if (!sp)
+		goto done;
+
+	ctx = sp->ctx;
+	ctx->type = SRB_MARKER_CMD;
+	ctx->name = "marker";
+	mrk = ctx->u.iocb_cmd;
+	mrk->u.marker.lun = lun;
+	mrk->u.marker.modif = modif;
+	mrk->timeout = qla2x00_async_iocb_timeout;
+	mrk->done = qla2x00_async_marker_ctx_done;
+
+	rval = qla2x00_start_sp(sp);
+	if (rval != QLA_SUCCESS)
+		goto done_free_sp;
+
+	DEBUG2(printk(KERN_DEBUG
+	    "scsi(%ld:%x): Async-marker - loop-id=%x "
+	    "portid=%02x%02x%02x.\n",
+	    fcport->vha->host_no, sp->handle, fcport->loop_id,
+	    fcport->d_id.b.domain, fcport->d_id.b.area,
+	    fcport->d_id.b.al_pa));
+
+	return rval;
+
+done_free_sp:
+	mrk->free(sp);
+done:
+	return rval;
+}
+
 void
 qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
@@ -360,6 +466,48 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 	return;
 }
 
+void
+qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    struct srb_iocb *iocb)
+{
+	int rval;
+	uint32_t flags;
+	uint16_t lun;
+
+	flags = iocb->u.tmf.flags;
+	lun = (uint16_t)iocb->u.tmf.lun;
+
+	/* Issue Marker IOCB */
+	rval = qla2x00_async_marker(fcport, lun,
+		flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
+
+	if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
+		DEBUG2_3_11(printk(KERN_WARNING
+			"%s(%ld): TM IOCB failed (%x).\n",
+			__func__, vha->host_no, rval));
+	}
+
+	return;
+}
+
+void
+qla2x00_async_marker_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    struct srb_iocb *iocb)
+{
+	/*
+	 * Currently we dont have any specific post response processing
+	 * for this IOCB. We'll just return success or failed
+	 * depending on whether the IOCB command succeeded or failed.
+	 */
+	if (iocb->u.tmf.data) {
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): Marker IOCB failed (%x).\n",
+		    __func__, vha->host_no, iocb->u.tmf.data));
+	}
+
+	return;
+}
+
 /****************************************************************************/
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8861b88..d7a9fff 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1086,6 +1086,64 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
 }
 
 static void
+qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
+{
+	uint32_t flags;
+	unsigned int lun;
+	struct fc_port *fcport = sp->fcport;
+	scsi_qla_host_t *vha = fcport->vha;
+	struct qla_hw_data *ha = vha->hw;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *iocb = ctx->u.iocb_cmd;
+	struct req_que *req = vha->req;
+
+	flags = iocb->u.tmf.flags;
+	lun = iocb->u.tmf.lun;
+
+	tsk->entry_type = TSK_MGMT_IOCB_TYPE;
+	tsk->entry_count = 1;
+	tsk->handle = MAKE_HANDLE(req->id, tsk->handle);
+	tsk->nport_handle = cpu_to_le16(fcport->loop_id);
+	tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
+	tsk->control_flags = cpu_to_le32(flags);
+	tsk->port_id[0] = fcport->d_id.b.al_pa;
+	tsk->port_id[1] = fcport->d_id.b.area;
+	tsk->port_id[2] = fcport->d_id.b.domain;
+	tsk->vp_index = fcport->vp_idx;
+
+	if (flags == TCF_LUN_RESET) {
+		int_to_scsilun(lun, &tsk->lun);
+		host_to_fcp_swap((uint8_t *)&tsk->lun,
+			sizeof(tsk->lun));
+	}
+}
+
+static void
+qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
+{
+	uint16_t lun;
+	uint8_t modif;
+	struct fc_port *fcport = sp->fcport;
+	scsi_qla_host_t *vha = fcport->vha;
+	struct srb_ctx *ctx = sp->ctx;
+	struct srb_iocb *iocb = ctx->u.iocb_cmd;
+	struct req_que *req = vha->req;
+
+	lun = iocb->u.marker.lun;
+	modif = iocb->u.marker.modif;
+	mrk->entry_type = MARKER_TYPE;
+	mrk->modifier = modif;
+	if (modif !=  MK_SYNC_ALL) {
+		mrk->nport_handle = cpu_to_le16(fcport->loop_id);
+		mrk->lun[1] = LSB(lun);
+		mrk->lun[2] = MSB(lun);
+		host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
+		mrk->vp_index = vha->vp_idx;
+		mrk->handle = MAKE_HANDLE(req->id, mrk->handle);
+	}
+}
+
+static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
 	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
@@ -1239,6 +1297,12 @@ qla2x00_start_sp(srb_t *sp)
 		    qla24xx_adisc_iocb(sp, pkt) :
 		    qla2x00_adisc_iocb(sp, pkt);
 		break;
+	case SRB_TM_CMD:
+		qla24xx_tm_iocb(sp, pkt);
+		break;
+	case SRB_MARKER_CMD:
+		qla24xx_marker_iocb(sp, pkt);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 166bb20..eed71ea 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1161,6 +1161,99 @@ logio_done:
 	lio->done(sp);
 }
 
+static void
+qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+    struct tsk_mgmt_entry *tsk)
+{
+	const char func[] = "TMF-IOCB";
+	const char *type;
+	fc_port_t *fcport;
+	srb_t *sp;
+	struct srb_iocb *iocb;
+	struct srb_ctx *ctx;
+	struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
+	int error = 1;
+
+	sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
+	if (!sp)
+		return;
+
+	ctx = sp->ctx;
+	iocb = ctx->u.iocb_cmd;
+	type = ctx->name;
+	fcport = sp->fcport;
+
+	if (sts->entry_status) {
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error - entry-status(%x).\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->entry_status));
+	} else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error - completion status(%x).\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->comp_status));
+	} else if (!(le16_to_cpu(sts->scsi_status) &
+	    SS_RESPONSE_INFO_LEN_VALID)) {
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error - no response info(%x).\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->scsi_status));
+	} else if (le32_to_cpu(sts->rsp_data_len) < 4) {
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error - not enough response(%d).\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->rsp_data_len));
+	} else if (sts->data[3]) {
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error - response(%x).\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->data[3]));
+	} else {
+		error = 0;
+	}
+
+	if (error) {
+		iocb->u.tmf.data = error;
+		DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts)));
+	}
+
+	iocb->done(sp);
+}
+
+static void
+qla24xx_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+    struct mrk_entry_24xx *mrk)
+{
+	const char func[] = "MRK-IOCB";
+	const char *type;
+	fc_port_t *fcport;
+	srb_t *sp;
+	struct srb_iocb *iocb;
+	struct srb_ctx *ctx;
+	struct sts_entry_24xx *sts = (struct sts_entry_24xx *)mrk;
+
+	sp = qla2x00_get_sp_from_handle(vha, func, req, mrk);
+	if (!sp)
+		return;
+
+	ctx = sp->ctx;
+	iocb = ctx->u.iocb_cmd;
+	type = ctx->name;
+	fcport = sp->fcport;
+
+	if (sts->entry_status) {
+		iocb->u.marker.data = 1;
+		DEBUG2(printk(KERN_WARNING
+		    "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
+		    fcport->vha->host_no, sp->handle, type,
+		    sts->entry_status));
+		DEBUG2(qla2x00_dump_buffer((uint8_t *)mrk, sizeof(*sts)));
+	}
+
+	iocb->done(sp);
+}
+
 /**
  * qla2x00_process_response_queue() - Process response queue entries.
  * @ha: SCSI driver HA context
@@ -1225,6 +1318,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
 		case MBX_IOCB_TYPE:
 			qla2x00_mbx_iocb_entry(vha, rsp->req,
 			    (struct mbx_entry *)pkt);
+			break;
 		default:
 			/* Type Not Supported. */
 			DEBUG4(printk(KERN_WARNING
@@ -1751,6 +1845,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			qla24xx_logio_entry(vha, rsp->req,
 			    (struct logio_entry_24xx *)pkt);
 			break;
+		case TSK_MGMT_IOCB_TYPE:
+			qla24xx_tm_iocb_entry(vha, rsp->req,
+			    (struct tsk_mgmt_entry *)pkt);
+			break;
+		case MARKER_TYPE:
+			qla24xx_marker_iocb_entry(vha, rsp->req,
+			    (struct mrk_entry_24xx *)pkt);
+			break;
                 case CT_IOCB_TYPE:
 			qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
 			clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 2f30332..f3650d0 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2464,12 +2464,22 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
 int
 qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
 {
+	struct qla_hw_data *ha = fcport->vha->hw;
+
+	if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+		return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
+
 	return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
 }
 
 int
 qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
 {
+	struct qla_hw_data *ha = fcport->vha->hw;
+
+	if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+		return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
+
 	return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 70651f9..523d414 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -142,6 +142,11 @@ MODULE_PARM_DESC(ql2xdontresethba,
 	" 1 -- Do not reset on failure.\n");
 
 
+int ql2xasynctmfenable;
+module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xasynctmfenable,
+		"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
+		"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
 /*
  * SCSI host template entry points
  */
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 10/16] qla2xxx: T10 DIF support added.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (8 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 09/16] qla2xxx: Support for asynchronous TM and Marker IOCBs giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 11/16] qla2xxx: Silence bogus warning by gcc for wrap and did giridhar.malavali
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Arun Easi

From: Arun Easi <arun.easi@qlogic.com>

Signed-off-by: Duane Grigsby <duane.grigsby@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_attr.c   |   16 +
 drivers/scsi/qla2xxx/qla_dbg.c    |   58 ++++
 drivers/scsi/qla2xxx/qla_dbg.h    |   10 +
 drivers/scsi/qla2xxx/qla_def.h    |   84 +++++-
 drivers/scsi/qla2xxx/qla_fw.h     |   47 +++-
 drivers/scsi/qla2xxx/qla_gbl.h    |    4 +
 drivers/scsi/qla2xxx/qla_inline.h |   16 +
 drivers/scsi/qla2xxx/qla_iocb.c   |  678 ++++++++++++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_isr.c    |   77 +++++
 drivers/scsi/qla2xxx/qla_os.c     |   75 ++++-
 10 files changed, 1053 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 5c98b09..62a22cf 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1726,6 +1726,22 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 			fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
 	}
 
+	if (IS_QLA25XX(ha) && ql2xenabledif) {
+		if (ha->fw_attributes & BIT_4) {
+			vha->flags.difdix_supported = 1;
+			DEBUG18(qla_printk(KERN_INFO, ha,
+			    "Registering for DIF/DIX type 1 and 3"
+			    " protection.\n"));
+			scsi_host_set_prot(vha->host,
+			    SHOST_DIF_TYPE1_PROTECTION
+			    | SHOST_DIF_TYPE3_PROTECTION
+			    | SHOST_DIX_TYPE1_PROTECTION
+			    | SHOST_DIX_TYPE3_PROTECTION);
+			scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC);
+		} else
+			vha->flags.difdix_supported = 0;
+	}
+
 	if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
 				   &ha->pdev->dev)) {
 		DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 89bfc11..2afc8a3 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1663,4 +1663,62 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
 		printk("\n");
 }
 
+void
+qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
+{
+	uint32_t cnt;
+	uint8_t c;
+	uint8_t  last16[16], cur16[16];
+	uint32_t lc = 0, num_same16 = 0, j;
+
+	printk(KERN_DEBUG " 0   1   2   3   4   5   6   7   8   9  "
+	    "Ah  Bh  Ch  Dh  Eh  Fh\n");
+	printk(KERN_DEBUG "----------------------------------------"
+	    "----------------------\n");
+
+	for (cnt = 0; cnt < size;) {
+		c = *b++;
 
+		cur16[lc++] = c;
+
+		cnt++;
+		if (cnt % 16)
+			continue;
+
+		/* We have 16 now */
+		lc = 0;
+		if (num_same16 == 0) {
+			memcpy(last16, cur16, 16);
+			num_same16++;
+			continue;
+		}
+		if (memcmp(cur16, last16, 16) == 0) {
+			num_same16++;
+			continue;
+		}
+		for (j = 0; j < 16; j++)
+			printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
+		printk(KERN_DEBUG "\n");
+
+		if (num_same16 > 1)
+			printk(KERN_DEBUG "> prev pattern repeats (%u)"
+			    "more times\n", num_same16-1);
+		memcpy(last16, cur16, 16);
+		num_same16 = 1;
+	}
+
+	if (num_same16) {
+		for (j = 0; j < 16; j++)
+			printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
+		printk(KERN_DEBUG "\n");
+
+		if (num_same16 > 1)
+			printk(KERN_DEBUG "> prev pattern repeats (%u)"
+			    "more times\n", num_same16-1);
+	}
+	if (lc) {
+		for (j = 0; j < lc; j++)
+			printk(KERN_DEBUG "%02x  ", (uint32_t)cur16[j]);
+		printk(KERN_DEBUG "\n");
+	}
+}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index d6d9c86..916c81f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -27,6 +27,9 @@
 /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
 /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
 /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
+/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
+
+/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */
 
 /*
 * Macros use for debugging the driver.
@@ -139,6 +142,13 @@
 #define DEBUG17(x)	do {} while (0)
 #endif
 
+#if defined(QL_DEBUG_LEVEL_18)
+#define DEBUG18(x)	do {if (ql2xextended_error_logging) x; } while (0)
+#else
+#define DEBUG18(x)	do {} while (0)
+#endif
+
+
 /*
  * Firmware Dump structure definition
  */
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 0d2cecb..4559f5c 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -189,6 +189,16 @@
 struct req_que;
 
 /*
+ * (sd.h is not exported, hence local inclusion)
+ * Data Integrity Field tuple.
+ */
+struct sd_dif_tuple {
+	__be16 guard_tag;	/* Checksum */
+	__be16 app_tag;		/* Opaque storage */
+	__be32 ref_tag;		/* Target LBA or indirect LBA */
+};
+
+/*
  * SCSI Request Block
  */
 typedef struct srb {
@@ -208,8 +218,14 @@ typedef struct srb {
 /*
  * SRB flag definitions
  */
-#define SRB_DMA_VALID		BIT_0	/* Command sent to ISP */
-#define SRB_FCP_CMND_DMA_VALID	BIT_12  /* FCP command in IOCB */
+#define SRB_DMA_VALID			BIT_0	/* Command sent to ISP */
+#define SRB_FCP_CMND_DMA_VALID		BIT_12	/* DIF: DSD List valid */
+#define SRB_CRC_CTX_DMA_VALID		BIT_2	/* DIF: context DMA valid */
+#define SRB_CRC_PROT_DMA_VALID		BIT_4	/* DIF: prot DMA valid */
+#define SRB_CRC_CTX_DSD_VALID		BIT_5	/* DIF: dsd_list valid */
+
+/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
+#define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)
 
 /*
  * SRB extensions.
@@ -1330,6 +1346,66 @@ typedef struct {
 	uint32_t dseg_4_length;		/* Data segment 4 length. */
 } cont_a64_entry_t;
 
+#define PO_MODE_DIF_INSERT	0
+#define PO_MODE_DIF_REMOVE	BIT_0
+#define PO_MODE_DIF_PASS	BIT_1
+#define PO_MODE_DIF_REPLACE	(BIT_0 + BIT_1)
+#define PO_ENABLE_DIF_BUNDLING	BIT_8
+#define PO_ENABLE_INCR_GUARD_SEED	BIT_3
+#define PO_DISABLE_INCR_REF_TAG	BIT_5
+#define PO_DISABLE_GUARD_CHECK	BIT_4
+/*
+ * ISP queue - 64-Bit addressing, continuation crc entry structure definition.
+ */
+struct crc_context {
+	uint32_t handle;		/* System handle. */
+	uint32_t ref_tag;
+	uint16_t app_tag;
+	uint8_t ref_tag_mask[4];	/* Validation/Replacement Mask*/
+	uint8_t app_tag_mask[2];	/* Validation/Replacement Mask*/
+	uint16_t guard_seed;		/* Initial Guard Seed */
+	uint16_t prot_opts;		/* Requested Data Protection Mode */
+	uint16_t blk_size;		/* Data size in bytes */
+	uint16_t runt_blk_guard;	/* Guard value for runt block (tape
+					 * only) */
+	uint32_t byte_count;		/* Total byte count/ total data
+					 * transfer count */
+	union {
+		struct {
+			uint32_t	reserved_1;
+			uint16_t	reserved_2;
+			uint16_t	reserved_3;
+			uint32_t	reserved_4;
+			uint32_t	data_address[2];
+			uint32_t	data_length;
+			uint32_t	reserved_5[2];
+			uint32_t	reserved_6;
+		} nobundling;
+		struct {
+			uint32_t	dif_byte_count;	/* Total DIF byte
+							 * count */
+			uint16_t	reserved_1;
+			uint16_t	dseg_count;	/* Data segment count */
+			uint32_t	reserved_2;
+			uint32_t	data_address[2];
+			uint32_t	data_length;
+			uint32_t	dif_address[2];
+			uint32_t	dif_length;	/* Data segment 0
+							 * length */
+		} bundling;
+	} u;
+
+	struct fcp_cmnd	fcp_cmnd;
+	dma_addr_t	crc_ctx_dma;
+	/* List of DMA context transfers */
+	struct list_head dsd_list;
+
+	/* This structure should not exceed 512 bytes */
+};
+
+#define CRC_CONTEXT_LEN_FW	(offsetof(struct crc_context, fcp_cmnd.lun))
+#define CRC_CONTEXT_FCPCMND_OFF	(offsetof(struct crc_context, fcp_cmnd.lun))
+
 /*
  * ISP queue - status entry structure definition.
  */
@@ -1390,6 +1466,7 @@ typedef struct {
 #define CS_ABORTED		0x5	/* System aborted command. */
 #define CS_TIMEOUT		0x6	/* Timeout error. */
 #define CS_DATA_OVERRUN		0x7	/* Data overrun. */
+#define CS_DIF_ERROR		0xC	/* DIF error detected  */
 
 #define CS_DATA_UNDERRUN	0x15	/* Data Underrun. */
 #define CS_QUEUE_FULL		0x1C	/* Queue Full. */
@@ -2732,6 +2809,7 @@ typedef struct scsi_qla_host {
 
 		uint32_t	management_server_logged_in :1;
 		uint32_t	process_response_queue	:1;
+		uint32_t	difdix_supported:1;
 	} flags;
 
 	atomic_t	loop_state;
@@ -2883,6 +2961,8 @@ typedef struct scsi_qla_host {
 #define OPTROM_BURST_SIZE	0x1000
 #define OPTROM_BURST_DWORDS	(OPTROM_BURST_SIZE / 4)
 
+#define	QLA_DSDS_PER_IOCB	37
+
 #include "qla_gbl.h"
 #include "qla_dbg.h"
 #include "qla_inline.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index a77a247..93f8339 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -400,6 +400,7 @@ struct cmd_type_6 {
 	struct scsi_lun lun;		/* FCP LUN (BE). */
 
 	uint16_t control_flags;		/* Control flags. */
+#define CF_DIF_SEG_DESCR_ENABLE		BIT_3
 #define CF_DATA_SEG_DESCR_ENABLE	BIT_2
 #define CF_READ_DATA			BIT_1
 #define CF_WRITE_DATA			BIT_0
@@ -466,6 +467,43 @@ struct cmd_type_7 {
 	uint32_t dseg_0_len;		/* Data segment 0 length. */
 };
 
+#define COMMAND_TYPE_CRC_2	0x6A	/* Command Type CRC_2 (Type 6)
+					 * (T10-DIF) */
+struct cmd_type_crc_2 {
+	uint8_t entry_type;		/* Entry type. */
+	uint8_t entry_count;		/* Entry count. */
+	uint8_t sys_define;		/* System defined. */
+	uint8_t entry_status;		/* Entry Status. */
+
+	uint32_t handle;		/* System handle. */
+
+	uint16_t nport_handle;		/* N_PORT handle. */
+	uint16_t timeout;		/* Command timeout. */
+
+	uint16_t dseg_count;		/* Data segment count. */
+
+	uint16_t fcp_rsp_dseg_len;	/* FCP_RSP DSD length. */
+
+	struct scsi_lun lun;		/* FCP LUN (BE). */
+
+	uint16_t control_flags;		/* Control flags. */
+
+	uint16_t fcp_cmnd_dseg_len;		/* Data segment length. */
+	uint32_t fcp_cmnd_dseg_address[2];	/* Data segment address. */
+
+	uint32_t fcp_rsp_dseg_address[2];	/* Data segment address. */
+
+	uint32_t byte_count;		/* Total byte count. */
+
+	uint8_t port_id[3];		/* PortID of destination port. */
+	uint8_t vp_index;
+
+	uint32_t crc_context_address[2];	/* Data segment address. */
+	uint16_t crc_context_len;		/* Data segment length. */
+	uint16_t reserved_1;			/* MUST be set to 0. */
+};
+
+
 /*
  * ISP queue - status entry structure definition.
  */
@@ -496,10 +534,17 @@ struct sts_entry_24xx {
 
 	uint32_t sense_len;		/* FCP SENSE length. */
 	uint32_t rsp_data_len;		/* FCP response data length. */
-
 	uint8_t data[28];		/* FCP response/sense information. */
+	/*
+	 * If DIF Error is set in comp_status, these additional fields are
+	 * defined:
+	 * &data[10] : uint8_t report_runt_bg[2];	- computed guard
+	 * &data[12] : uint8_t actual_dif[8];		- DIF Data recieved
+	 * &data[20] : uint8_t expected_dif[8];		- DIF Data computed
+	*/
 };
 
+
 /*
  * Status entry completion status
  */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3dbefe1..3e946da 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -94,6 +94,8 @@ extern int ql2xshiftctondsd;
 extern int ql2xdbwr;
 extern int ql2xdontresethba;
 extern int ql2xasynctmfenable;
+extern int ql2xenabledif;
+extern int ql2xenablehba_err_chk;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -179,6 +181,7 @@ extern int qla2x00_start_sp(srb_t *);
 extern void qla2x00_ctx_sp_free(srb_t *);
 extern uint16_t qla24xx_calc_iocbs(uint16_t);
 extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
+extern int qla24xx_dif_start_scsi(srb_t *);
 
 
 /*
@@ -423,6 +426,7 @@ extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla2x00_dump_regs(scsi_qla_host_t *);
 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
+extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
 
 /*
  * Global Function Prototypes in qla_gs.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index ad53c64..84c2fea 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -67,3 +67,19 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
 	return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
 	    loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
 }
+
+static inline void
+qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
+{
+	struct dsd_dma *dsd_ptr, *tdsd_ptr;
+
+	/* clean up allocated prev pool */
+	list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
+	    &((struct crc_context *)sp->ctx)->dsd_list, list) {
+		dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
+		    dsd_ptr->dsd_list_dma);
+		list_del(&dsd_ptr->list);
+		kfree(dsd_ptr);
+	}
+	INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list);
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d7a9fff..8ef9453 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -145,7 +145,49 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha)
 	return (cont_pkt);
 }
 
-/**
+static inline int
+qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
+{
+	uint8_t	guard = scsi_host_get_guard(sp->cmd->device->host);
+
+	/* We only support T10 DIF right now */
+	if (guard != SHOST_DIX_GUARD_CRC) {
+		DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard));
+		return 0;
+	}
+
+	/* We always use DIFF Bundling for best performance */
+	*fw_prot_opts = 0;
+
+	/* Translate SCSI opcode to a protection opcode */
+	switch (scsi_get_prot_op(sp->cmd)) {
+	case SCSI_PROT_READ_STRIP:
+		*fw_prot_opts |= PO_MODE_DIF_REMOVE;
+		break;
+	case SCSI_PROT_WRITE_INSERT:
+		*fw_prot_opts |= PO_MODE_DIF_INSERT;
+		break;
+	case SCSI_PROT_READ_INSERT:
+		*fw_prot_opts |= PO_MODE_DIF_INSERT;
+		break;
+	case SCSI_PROT_WRITE_STRIP:
+		*fw_prot_opts |= PO_MODE_DIF_REMOVE;
+		break;
+	case SCSI_PROT_READ_PASS:
+		*fw_prot_opts |= PO_MODE_DIF_PASS;
+		break;
+	case SCSI_PROT_WRITE_PASS:
+		*fw_prot_opts |= PO_MODE_DIF_PASS;
+		break;
+	default:	/* Normal Request */
+		*fw_prot_opts |= PO_MODE_DIF_PASS;
+		break;
+	}
+
+	return scsi_prot_sg_count(sp->cmd);
+}
+
+/*
  * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit
  * capable IOCB types.
  *
@@ -636,6 +678,8 @@ qla24xx_calc_iocbs(uint16_t dsds)
 		if ((dsds - 1) % 5)
 			iocbs++;
 	}
+	DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n",
+	    __func__, iocbs));
 	return iocbs;
 }
 
@@ -716,6 +760,453 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
 	}
 }
 
+struct fw_dif_context {
+	uint32_t ref_tag;
+	uint16_t app_tag;
+	uint8_t ref_tag_mask[4];	/* Validation/Replacement Mask*/
+	uint8_t app_tag_mask[2];	/* Validation/Replacement Mask*/
+};
+
+/*
+ * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command
+ *
+ */
+static inline void
+qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
+    unsigned int protcnt)
+{
+	struct sd_dif_tuple *spt;
+	unsigned char op = scsi_get_prot_op(cmd);
+
+	switch (scsi_get_prot_type(cmd)) {
+	/* For TYPE 0 protection: no checking */
+	case SCSI_PROT_DIF_TYPE0:
+		pkt->ref_tag_mask[0] = 0x00;
+		pkt->ref_tag_mask[1] = 0x00;
+		pkt->ref_tag_mask[2] = 0x00;
+		pkt->ref_tag_mask[3] = 0x00;
+		break;
+
+	/*
+	 * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to
+	 * match LBA in CDB + N
+	 */
+	case SCSI_PROT_DIF_TYPE2:
+		break;
+
+	/* For Type 3 protection: 16 bit GUARD only */
+	case SCSI_PROT_DIF_TYPE3:
+		pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] =
+			pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] =
+								0x00;
+		break;
+
+	/*
+	 * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
+	 * 16 bit app tag.
+	 */
+	case SCSI_PROT_DIF_TYPE1:
+		if (!ql2xenablehba_err_chk)
+			break;
+
+		if (protcnt && (op == SCSI_PROT_WRITE_STRIP ||
+		    op == SCSI_PROT_WRITE_PASS)) {
+			spt = page_address(sg_page(scsi_prot_sglist(cmd))) +
+			    scsi_prot_sglist(cmd)[0].offset;
+			DEBUG18(printk(KERN_DEBUG
+			    "%s(): LBA from user %p, lba = 0x%x\n",
+			    __func__, spt, (int)spt->ref_tag));
+			pkt->ref_tag = swab32(spt->ref_tag);
+			pkt->app_tag_mask[0] = 0x0;
+			pkt->app_tag_mask[1] = 0x0;
+		} else {
+			pkt->ref_tag = cpu_to_le32((uint32_t)
+			    (0xffffffff & scsi_get_lba(cmd)));
+			pkt->app_tag = __constant_cpu_to_le16(0);
+			pkt->app_tag_mask[0] = 0x0;
+			pkt->app_tag_mask[1] = 0x0;
+		}
+		/* enable ALL bytes of the ref tag */
+		pkt->ref_tag_mask[0] = 0xff;
+		pkt->ref_tag_mask[1] = 0xff;
+		pkt->ref_tag_mask[2] = 0xff;
+		pkt->ref_tag_mask[3] = 0xff;
+		break;
+	}
+
+	DEBUG18(printk(KERN_DEBUG
+	    "%s(): Setting protection Tags: (BIG) ref tag = 0x%x,"
+	    " app tag = 0x%x, prot SG count %d , cmd lba 0x%x,"
+	    " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt,
+	    (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd)));
+}
+
+
+static int
+qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
+	uint16_t tot_dsds)
+{
+	void *next_dsd;
+	uint8_t avail_dsds = 0;
+	uint32_t dsd_list_len;
+	struct dsd_dma *dsd_ptr;
+	struct scatterlist *sg;
+	uint32_t *cur_dsd = dsd;
+	int	i;
+	uint16_t	used_dsds = tot_dsds;
+
+	uint8_t		*cp;
+
+	scsi_for_each_sg(sp->cmd, sg, tot_dsds, i) {
+		dma_addr_t	sle_dma;
+
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
+					QLA_DSDS_PER_IOCB : used_dsds;
+			dsd_list_len = (avail_dsds + 1) * 12;
+			used_dsds -= avail_dsds;
+
+			/* allocate tracking DS */
+			dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
+			if (!dsd_ptr)
+				return 1;
+
+			/* allocate new list */
+			dsd_ptr->dsd_addr = next_dsd =
+			    dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
+				&dsd_ptr->dsd_list_dma);
+
+			if (!next_dsd) {
+				/*
+				 * Need to cleanup only this dsd_ptr, rest
+				 * will be done by sp_free_dma()
+				 */
+				kfree(dsd_ptr);
+				return 1;
+			}
+
+			list_add_tail(&dsd_ptr->list,
+			    &((struct crc_context *)sp->ctx)->dsd_list);
+
+			sp->flags |= SRB_CRC_CTX_DSD_VALID;
+
+			/* add new list to cmd iocb or last list */
+			*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+			*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+			*cur_dsd++ = dsd_list_len;
+			cur_dsd = (uint32_t *)next_dsd;
+		}
+		sle_dma = sg_dma_address(sg);
+		DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x,"
+		    " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma),
+		    MSD(sle_dma), sg_dma_len(sg)));
+		*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
+
+		if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
+			cp = page_address(sg_page(sg)) + sg->offset;
+			DEBUG18(printk("%s(): User Data buffer= %p:\n",
+			    __func__ , cp));
+		}
+	}
+	/* Null termination */
+	*cur_dsd++ = 0;
+	*cur_dsd++ = 0;
+	*cur_dsd++ = 0;
+	return 0;
+}
+
+static int
+qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
+							uint32_t *dsd,
+	uint16_t tot_dsds)
+{
+	void *next_dsd;
+	uint8_t avail_dsds = 0;
+	uint32_t dsd_list_len;
+	struct dsd_dma *dsd_ptr;
+	struct scatterlist *sg;
+	int	i;
+	struct scsi_cmnd *cmd;
+	uint32_t *cur_dsd = dsd;
+	uint16_t	used_dsds = tot_dsds;
+
+	uint8_t		*cp;
+
+
+	cmd = sp->cmd;
+	scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) {
+		dma_addr_t	sle_dma;
+
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
+						QLA_DSDS_PER_IOCB : used_dsds;
+			dsd_list_len = (avail_dsds + 1) * 12;
+			used_dsds -= avail_dsds;
+
+			/* allocate tracking DS */
+			dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
+			if (!dsd_ptr)
+				return 1;
+
+			/* allocate new list */
+			dsd_ptr->dsd_addr = next_dsd =
+			    dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
+				&dsd_ptr->dsd_list_dma);
+
+			if (!next_dsd) {
+				/*
+				 * Need to cleanup only this dsd_ptr, rest
+				 * will be done by sp_free_dma()
+				 */
+				kfree(dsd_ptr);
+				return 1;
+			}
+
+			list_add_tail(&dsd_ptr->list,
+			    &((struct crc_context *)sp->ctx)->dsd_list);
+
+			sp->flags |= SRB_CRC_CTX_DSD_VALID;
+
+			/* add new list to cmd iocb or last list */
+			*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+			*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+			*cur_dsd++ = dsd_list_len;
+			cur_dsd = (uint32_t *)next_dsd;
+		}
+		sle_dma = sg_dma_address(sg);
+		if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
+			DEBUG18(printk(KERN_DEBUG
+			    "%s(): %p, sg entry %d - addr =0x%x"
+			    "0x%x, len =%d\n", __func__ , cur_dsd, i,
+			    LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg)));
+		}
+		*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+
+		if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
+			cp = page_address(sg_page(sg)) + sg->offset;
+			DEBUG18(printk("%s(): Protection Data buffer = %p:\n",
+			    __func__ , cp));
+		}
+		avail_dsds--;
+	}
+	/* Null termination */
+	*cur_dsd++ = 0;
+	*cur_dsd++ = 0;
+	*cur_dsd++ = 0;
+	return 0;
+}
+
+/**
+ * qla24xx_build_scsi_crc_2_iocbs() - Build IOCB command utilizing Command
+ *							Type 6 IOCB types.
+ *
+ * @sp: SRB command to process
+ * @cmd_pkt: Command type 3 IOCB
+ * @tot_dsds: Total number of segments to transfer
+ */
+static inline int
+qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
+    uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts)
+{
+	uint32_t		*cur_dsd, *fcp_dl;
+	scsi_qla_host_t		*vha;
+	struct scsi_cmnd	*cmd;
+	struct scatterlist	*cur_seg;
+	int			sgc;
+	uint32_t		total_bytes;
+	uint32_t		data_bytes;
+	uint32_t		dif_bytes;
+	uint8_t			bundling = 1;
+	uint16_t		blk_size;
+	uint8_t			*clr_ptr;
+	struct crc_context	*crc_ctx_pkt = NULL;
+	struct qla_hw_data	*ha;
+	uint8_t			additional_fcpcdb_len;
+	uint16_t		fcp_cmnd_len;
+	struct fcp_cmnd		*fcp_cmnd;
+	dma_addr_t		crc_ctx_dma;
+
+	cmd = sp->cmd;
+
+	sgc = 0;
+	/* Update entry type to indicate Command Type CRC_2 IOCB */
+	*((uint32_t *)(&cmd_pkt->entry_type)) =
+	    __constant_cpu_to_le32(COMMAND_TYPE_CRC_2);
+
+	/* No data transfer */
+	data_bytes = scsi_bufflen(cmd);
+	if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
+		DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
+		    __func__, data_bytes));
+		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
+		return QLA_SUCCESS;
+	}
+
+	vha = sp->fcport->vha;
+	ha = vha->hw;
+
+	DEBUG18(printk(KERN_DEBUG
+	    "%s(%ld): Executing cmd sp %p, pid=%ld, prot_op=%u.\n", __func__,
+	    vha->host_no, sp, cmd->serial_number, scsi_get_prot_op(sp->cmd)));
+
+	cmd_pkt->vp_index = sp->fcport->vp_idx;
+
+	/* Set transfer direction */
+	if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+		cmd_pkt->control_flags =
+		    __constant_cpu_to_le16(CF_WRITE_DATA);
+	} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		cmd_pkt->control_flags =
+		    __constant_cpu_to_le16(CF_READ_DATA);
+	}
+
+	tot_prot_dsds = scsi_prot_sg_count(cmd);
+	if (!tot_prot_dsds)
+		bundling = 0;
+
+	/* Allocate CRC context from global pool */
+	crc_ctx_pkt = sp->ctx = dma_pool_alloc(ha->dl_dma_pool,
+	    GFP_ATOMIC, &crc_ctx_dma);
+
+	if (!crc_ctx_pkt)
+		goto crc_queuing_error;
+
+	/* Zero out CTX area. */
+	clr_ptr = (uint8_t *)crc_ctx_pkt;
+	memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
+
+	crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
+
+	sp->flags |= SRB_CRC_CTX_DMA_VALID;
+
+	/* Set handle */
+	crc_ctx_pkt->handle = cmd_pkt->handle;
+
+	INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list);
+
+	qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *)
+	    &crc_ctx_pkt->ref_tag, tot_prot_dsds);
+
+	cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
+	cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
+	cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
+
+	/* Determine SCSI command length -- align to 4 byte boundary */
+	if (cmd->cmd_len > 16) {
+		DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n",
+		    __func__));
+		additional_fcpcdb_len = cmd->cmd_len - 16;
+		if ((cmd->cmd_len % 4) != 0) {
+			/* SCSI cmd > 16 bytes must be multiple of 4 */
+			goto crc_queuing_error;
+		}
+		fcp_cmnd_len = 12 + cmd->cmd_len + 4;
+	} else {
+		additional_fcpcdb_len = 0;
+		fcp_cmnd_len = 12 + 16 + 4;
+	}
+
+	fcp_cmnd = &crc_ctx_pkt->fcp_cmnd;
+
+	fcp_cmnd->additional_cdb_len = additional_fcpcdb_len;
+	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		fcp_cmnd->additional_cdb_len |= 1;
+	else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+		fcp_cmnd->additional_cdb_len |= 2;
+
+	int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
+	memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
+	cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
+	cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
+	    LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
+	cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
+	    MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
+	fcp_cmnd->task_attribute = 0;
+	fcp_cmnd->task_managment = 0;
+
+	cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
+
+	DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
+	    "entries %d, data bytes %d, Protection entries %d\n",
+	    __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds),
+	    data_bytes, tot_prot_dsds));
+
+	/* Compute dif len and adjust data len to incude protection */
+	total_bytes = data_bytes;
+	dif_bytes = 0;
+	blk_size = cmd->device->sector_size;
+	if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE1) {
+		dif_bytes = (data_bytes / blk_size) * 8;
+		total_bytes += dif_bytes;
+	}
+
+	if (!ql2xenablehba_err_chk)
+		fw_prot_opts |= 0x10; /* Disable Guard tag checking */
+
+	if (!bundling) {
+		cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
+	} else {
+		/*
+		 * Configure Bundling if we need to fetch interlaving
+		 * protection PCI accesses
+		 */
+		fw_prot_opts |= PO_ENABLE_DIF_BUNDLING;
+		crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes);
+		crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds -
+							tot_prot_dsds);
+		cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address;
+	}
+
+	/* Finish the common fields of CRC pkt */
+	crc_ctx_pkt->blk_size = cpu_to_le16(blk_size);
+	crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts);
+	crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
+	crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0);
+	/* Fibre channel byte count */
+	cmd_pkt->byte_count = cpu_to_le32(total_bytes);
+	fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 +
+	    additional_fcpcdb_len);
+	*fcp_dl = htonl(total_bytes);
+
+	DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes"
+	    " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__,
+	    vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes,
+	    crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size));
+
+	/* Walks data segments */
+
+	cmd_pkt->control_flags |=
+	    __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE);
+	if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd,
+	    (tot_dsds - tot_prot_dsds)))
+		goto crc_queuing_error;
+
+	if (bundling && tot_prot_dsds) {
+		/* Walks dif segments */
+		cur_seg = scsi_prot_sglist(cmd);
+		cmd_pkt->control_flags |=
+			__constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE);
+		cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
+		if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd,
+		    tot_prot_dsds))
+			goto crc_queuing_error;
+	}
+	return QLA_SUCCESS;
+
+crc_queuing_error:
+	DEBUG18(qla_printk(KERN_INFO, ha,
+	    "CMD sent FAILED crc_q error:sp = %p\n", sp));
+	/* Cleanup will be performed by the caller */
+
+	return QLA_FUNCTION_FAILED;
+}
 
 /**
  * qla24xx_start_scsi() - Send a SCSI command to the ISP
@@ -869,6 +1360,191 @@ queuing_error:
 	return QLA_FUNCTION_FAILED;
 }
 
+
+/**
+ * qla24xx_dif_start_scsi() - Send a SCSI command to the ISP
+ * @sp: command to send to the ISP
+ *
+ * Returns non-zero if a failure occurred, else zero.
+ */
+int
+qla24xx_dif_start_scsi(srb_t *sp)
+{
+	int			nseg;
+	unsigned long		flags;
+	uint32_t		*clr_ptr;
+	uint32_t		index;
+	uint32_t		handle;
+	uint16_t		cnt;
+	uint16_t		req_cnt = 0;
+	uint16_t		tot_dsds;
+	uint16_t		tot_prot_dsds;
+	uint16_t		fw_prot_opts = 0;
+	struct req_que		*req = NULL;
+	struct rsp_que		*rsp = NULL;
+	struct scsi_cmnd	*cmd = sp->cmd;
+	struct scsi_qla_host	*vha = sp->fcport->vha;
+	struct qla_hw_data	*ha = vha->hw;
+	struct cmd_type_crc_2	*cmd_pkt;
+	uint32_t		status = 0;
+
+#define QDSS_GOT_Q_SPACE	BIT_0
+
+	/* Only process protection in this routine */
+	if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL)
+		return qla24xx_start_scsi(sp);
+
+	/* Setup device pointers. */
+
+	qla25xx_set_que(sp, &rsp);
+	req = vha->req;
+
+	/* So we know we haven't pci_map'ed anything yet */
+	tot_dsds = 0;
+
+	/* Send marker if required */
+	if (vha->marker_needed != 0) {
+		if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+		    QLA_SUCCESS)
+			return QLA_FUNCTION_FAILED;
+		vha->marker_needed = 0;
+	}
+
+	/* Acquire ring specific lock */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	/* Check for room in outstanding command list. */
+	handle = req->current_outstanding_cmd;
+	for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+		handle++;
+		if (handle == MAX_OUTSTANDING_COMMANDS)
+			handle = 1;
+		if (!req->outstanding_cmds[handle])
+			break;
+	}
+
+	if (index == MAX_OUTSTANDING_COMMANDS)
+		goto queuing_error;
+
+	/* Compute number of required data segments */
+	/* Map the sg table so we have an accurate count of sg entries needed */
+	if (scsi_sg_count(cmd)) {
+		nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
+		    scsi_sg_count(cmd), cmd->sc_data_direction);
+		if (unlikely(!nseg))
+			goto queuing_error;
+		else
+			sp->flags |= SRB_DMA_VALID;
+	} else
+		nseg = 0;
+
+	/* number of required data segments */
+	tot_dsds = nseg;
+
+	/* Compute number of required protection segments */
+	if (qla24xx_configure_prot_mode(sp, &fw_prot_opts)) {
+		nseg = dma_map_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
+		    scsi_prot_sg_count(cmd), cmd->sc_data_direction);
+		if (unlikely(!nseg))
+			goto queuing_error;
+		else
+			sp->flags |= SRB_CRC_PROT_DMA_VALID;
+	} else {
+		nseg = 0;
+	}
+
+	req_cnt = 1;
+	/* Total Data and protection sg segment(s) */
+	tot_prot_dsds = nseg;
+	tot_dsds += nseg;
+	if (req->cnt < (req_cnt + 2)) {
+		cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
+
+		if (req->ring_index < cnt)
+			req->cnt = cnt - req->ring_index;
+		else
+			req->cnt = req->length -
+				(req->ring_index - cnt);
+	}
+
+	if (req->cnt < (req_cnt + 2))
+		goto queuing_error;
+
+	status |= QDSS_GOT_Q_SPACE;
+
+	/* Build header part of command packet (excluding the OPCODE). */
+	req->current_outstanding_cmd = handle;
+	req->outstanding_cmds[handle] = sp;
+	sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
+	req->cnt -= req_cnt;
+
+	/* Fill-in common area */
+	cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr;
+	cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+
+	clr_ptr = (uint32_t *)cmd_pkt + 2;
+	memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
+
+	/* Set NPORT-ID and LUN number*/
+	cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+	cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
+	cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
+	cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
+
+	int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+	host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
+
+	/* Total Data and protection segment(s) */
+	cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
+
+	/* Build IOCB segments and adjust for data protection segments */
+	if (qla24xx_build_scsi_crc_2_iocbs(sp, (struct cmd_type_crc_2 *)
+	    req->ring_ptr, tot_dsds, tot_prot_dsds, fw_prot_opts) !=
+		QLA_SUCCESS)
+		goto queuing_error;
+
+	cmd_pkt->entry_count = (uint8_t)req_cnt;
+	/* Specify response queue number where completion should happen */
+	cmd_pkt->entry_status = (uint8_t) rsp->id;
+	cmd_pkt->timeout = __constant_cpu_to_le16(0);
+	wmb();
+
+	/* Adjust ring index. */
+	req->ring_index++;
+	if (req->ring_index == req->length) {
+		req->ring_index = 0;
+		req->ring_ptr = req->ring;
+	} else
+		req->ring_ptr++;
+
+	/* Set chip new ring index. */
+	WRT_REG_DWORD(req->req_q_in, req->ring_index);
+	RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
+
+	/* Manage unprocessed RIO/ZIO commands in response queue. */
+	if (vha->flags.process_response_queue &&
+	    rsp->ring_ptr->signature != RESPONSE_PROCESSED)
+		qla24xx_process_response_queue(vha, rsp);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return QLA_SUCCESS;
+
+queuing_error:
+	if (status & QDSS_GOT_Q_SPACE) {
+		req->outstanding_cmds[handle] = NULL;
+		req->cnt += req_cnt;
+	}
+	/* Cleanup will be performed by the caller (queuecommand) */
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	DEBUG18(qla_printk(KERN_INFO, ha,
+	    "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd)));
+	return QLA_FUNCTION_FAILED;
+}
+
+
 static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp)
 {
 	struct scsi_cmnd *cmd = sp->cmd;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index eed71ea..be3d8be 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_bsg_fc.h>
+#include <scsi/scsi_eh.h>
 
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
 static void qla2x00_process_completed_request(struct scsi_qla_host *,
@@ -1364,6 +1365,78 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
 		DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
 }
 
+struct scsi_dif_tuple {
+	__be16 guard;       /* Checksum */
+	__be16 app_tag;         /* APPL identifer */
+	__be32 ref_tag;         /* Target LBA or indirect LBA */
+};
+
+/*
+ * Checks the guard or meta-data for the type of error
+ * detected by the HBA. In case of errors, we set the
+ * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
+ * to indicate to the kernel that the HBA detected error.
+ */
+static inline void
+qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
+{
+	struct scsi_cmnd *cmd = sp->cmd;
+	struct scsi_dif_tuple	*ep =
+			(struct scsi_dif_tuple *)&sts24->data[20];
+	struct scsi_dif_tuple	*ap =
+			(struct scsi_dif_tuple *)&sts24->data[12];
+	uint32_t	e_ref_tag, a_ref_tag;
+	uint16_t	e_app_tag, a_app_tag;
+	uint16_t	e_guard, a_guard;
+
+	e_ref_tag = be32_to_cpu(ep->ref_tag);
+	a_ref_tag = be32_to_cpu(ap->ref_tag);
+	e_app_tag = be16_to_cpu(ep->app_tag);
+	a_app_tag = be16_to_cpu(ap->app_tag);
+	e_guard = be16_to_cpu(ep->guard);
+	a_guard = be16_to_cpu(ap->guard);
+
+	DEBUG18(printk(KERN_DEBUG
+	    "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
+
+	DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
+	    " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
+	    " tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
+	    cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
+	    a_app_tag, e_app_tag, a_guard, e_guard));
+
+
+	/* check guard */
+	if (e_guard != a_guard) {
+		scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+		    0x10, 0x1);
+		set_driver_byte(cmd, DRIVER_SENSE);
+		set_host_byte(cmd, DID_ABORT);
+		cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+		return;
+	}
+
+	/* check appl tag */
+	if (e_app_tag != a_app_tag) {
+		scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+		    0x10, 0x2);
+		set_driver_byte(cmd, DRIVER_SENSE);
+		set_host_byte(cmd, DID_ABORT);
+		cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+		return;
+	}
+
+	/* check ref tag */
+	if (e_ref_tag != a_ref_tag) {
+		scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+		    0x10, 0x3);
+		set_driver_byte(cmd, DRIVER_SENSE);
+		set_host_byte(cmd, DID_ABORT);
+		cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+		return;
+	}
+}
+
 /**
  * qla2x00_status_entry() - Process a Status IOCB entry.
  * @ha: SCSI driver HA context
@@ -1630,6 +1703,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 	case CS_ABORTED:
 		cp->result = DID_RESET << 16;
 		break;
+
+	case CS_DIF_ERROR:
+		qla2x00_handle_dif_error(sp, sts24);
+		break;
 	default:
 		cp->result = DID_ERROR << 16;
 		break;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 523d414..5104aef 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -92,6 +92,19 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xmaxqdepth,
 		"Maximum queue depth to report for target devices.");
 
+/* Do not change the value of this after module load */
+int ql2xenabledif = 1;
+module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xenabledif,
+		" Enable T10-CRC-DIF "
+		" Default is 0 - No DIF Support. 1 - Enable it");
+
+int ql2xenablehba_err_chk;
+module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xenablehba_err_chk,
+		" Enable T10-CRC-DIF Error isolation by HBA"
+		" Default is 0 - Error isolation disabled, 1 - Enable it");
+
 int ql2xiidmaenable=1;
 module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xiidmaenable,
@@ -537,6 +550,14 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	if (fcport->drport)
 		goto qc24_target_busy;
 
+	if (!vha->flags.difdix_supported &&
+		scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
+			DEBUG2(qla_printk(KERN_ERR, ha,
+			    "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
+			    cmd->cmnd[0]));
+			cmd->result = DID_NO_CONNECT << 16;
+			goto qc24_fail_command;
+	}
 	if (atomic_read(&fcport->state) != FCS_ONLINE) {
 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
 		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
@@ -776,7 +797,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
 		if (sp == NULL)
 			continue;
-		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID))
+		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
+		    !IS_PROT_IO(sp))
 			continue;
 		if (sp->cmd != cmd)
 			continue;
@@ -842,7 +864,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
 		sp = req->outstanding_cmds[cnt];
 		if (!sp)
 			continue;
-		if (sp->ctx)
+		if ((sp->ctx) && !IS_PROT_IO(sp))
 			continue;
 		if (vha->vp_idx != sp->fcport->vha->vp_idx)
 			continue;
@@ -1189,7 +1211,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 			if (sp) {
 				req->outstanding_cmds[cnt] = NULL;
 				if (!sp->ctx ||
-				(sp->flags & SRB_FCP_CMND_DMA_VALID)) {
+					(sp->flags & SRB_FCP_CMND_DMA_VALID) ||
+					IS_PROT_IO(sp)) {
 					sp->cmd->result = res;
 					qla2x00_sp_compl(ha, sp);
 				} else {
@@ -1553,7 +1576,7 @@ static struct isp_operations qla25xx_isp_ops = {
 	.read_optrom		= qla25xx_read_optrom_data,
 	.write_optrom		= qla24xx_write_optrom_data,
 	.get_flash_version	= qla24xx_get_flash_version,
-	.start_scsi		= qla24xx_start_scsi,
+	.start_scsi		= qla24xx_dif_start_scsi,
 	.abort_isp		= qla2x00_abort_isp,
 };
 
@@ -2185,6 +2208,22 @@ skip_dpc:
 	DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
 	    base_vha->host_no, ha));
 
+	if (IS_QLA25XX(ha) && ql2xenabledif) {
+		if (ha->fw_attributes & BIT_4) {
+			base_vha->flags.difdix_supported = 1;
+			DEBUG18(qla_printk(KERN_INFO, ha,
+			    "Registering for DIF/DIX type 1 and 3"
+			    " protection.\n"));
+			scsi_host_set_prot(host,
+			    SHOST_DIF_TYPE1_PROTECTION
+			    | SHOST_DIF_TYPE3_PROTECTION
+			    | SHOST_DIX_TYPE1_PROTECTION
+			    | SHOST_DIX_TYPE3_PROTECTION);
+			scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC);
+		} else
+			base_vha->flags.difdix_supported = 0;
+	}
+
 	ha->isp_ops->enable_intrs(ha);
 
 	ret = scsi_add_host(host, &pdev->dev);
@@ -2546,7 +2585,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 	if (!ha->s_dma_pool)
 		goto fail_free_nvram;
 
-	if (IS_QLA82XX(ha)) {
+	if (IS_QLA82XX(ha) || ql2xenabledif) {
 		ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
 			DSD_LIST_DMA_POOL_SIZE, 8, 0);
 		if (!ha->dl_dma_pool) {
@@ -2678,12 +2717,12 @@ fail_free_ms_iocb:
 	ha->ms_iocb = NULL;
 	ha->ms_iocb_dma = 0;
 fail_dma_pool:
-	if (IS_QLA82XX(ha)) {
+	if (IS_QLA82XX(ha) || ql2xenabledif) {
 		dma_pool_destroy(ha->fcp_cmnd_dma_pool);
 		ha->fcp_cmnd_dma_pool = NULL;
 	}
 fail_dl_dma_pool:
-	if (IS_QLA82XX(ha)) {
+	if (IS_QLA82XX(ha) || ql2xenabledif) {
 		dma_pool_destroy(ha->dl_dma_pool);
 		ha->dl_dma_pool = NULL;
 	}
@@ -3346,11 +3385,31 @@ static void
 qla2x00_sp_free_dma(srb_t *sp)
 {
 	struct scsi_cmnd *cmd = sp->cmd;
+	struct qla_hw_data *ha = sp->fcport->vha->hw;
 
 	if (sp->flags & SRB_DMA_VALID) {
 		scsi_dma_unmap(cmd);
 		sp->flags &= ~SRB_DMA_VALID;
 	}
+
+	if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
+		dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
+		    scsi_prot_sg_count(cmd), cmd->sc_data_direction);
+		sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
+	}
+
+	if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
+		/* List assured to be having elements */
+		qla2x00_clean_dsd_pool(ha, sp);
+		sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
+	}
+
+	if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
+		dma_pool_free(ha->dl_dma_pool, sp->ctx,
+		    ((struct crc_context *)sp->ctx)->crc_ctx_dma);
+		sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
+	}
+
 	CMD_SP(cmd) = NULL;
 }
 
@@ -3464,7 +3523,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
 					sp = req->outstanding_cmds[index];
 					if (!sp)
 						continue;
-					if (sp->ctx)
+					if (sp->ctx && !IS_PROT_IO(sp))
 						continue;
 					sfcp = sp->fcport;
 					if (!(sfcp->flags & FCF_FCP2_DEVICE))
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 11/16] qla2xxx: Silence bogus warning by gcc for wrap and did.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (9 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 10/16] qla2xxx: T10 DIF support added giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 12/16] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive giridhar.malavali
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Mike Waychison

From: Mike Waychison <mikew@google.com>

The qla2xxx driver uses a port_id_t to mark the start of its enumerations.  gcc
is complaining that wrap.b24 may be used uninitialized, but this doesn't look
to be possible.  Silence it.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_init.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e78089d..7fd1344 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3150,7 +3150,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
 	sw_info_t	*swl;
 	int		swl_idx;
 	int		first_dev, last_dev;
-	port_id_t	wrap, nxt_d_id;
+	port_id_t	wrap = {}, nxt_d_id;
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
 	struct scsi_qla_host *tvp;
@@ -3453,7 +3453,7 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
 	uint32_t rscn_entry;
 	uint8_t rscn_out_iter;
 	uint8_t format;
-	port_id_t d_id;
+	port_id_t d_id = {};
 
 	rval = QLA_RSCNS_HANDLED;
 
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 12/16] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (10 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 11/16] qla2xxx: Silence bogus warning by gcc for wrap and did giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 13/16] qla2xxx: Optionally disable target reset giridhar.malavali
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Lalit Chandivade

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

The problem occurring is a hw-race where there's an outstanding read-flash
operation occurring while the chip is being reset (done via an sg_reset script).
After the chip is paused, the read-flash operation never completes and the
DPC thread, while trying to complete the reset, is never able to recover,
as the HW appears to be hung...

The fix is to wait for outstanding flash operation prior to doing a sg_reset -h.
And to wait for reset to complete before any flash operations.

Note, during the wait, if any of the operation (reset/flash) does not complete,
failure is returned to the upper layer. The upper layer either need to
fail or retry.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_attr.c |    6 +++++
 drivers/scsi/qla2xxx/qla_os.c   |   46 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 62a22cf..3b70860 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -281,6 +281,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
 			return count;
 		}
 
+		if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+			qla_printk(KERN_WARNING, ha,
+				"HBA not online, failing NVRAM update.\n");
+			return -EAGAIN;
+		}
+
 		DEBUG2(qla_printk(KERN_INFO, ha,
 		    "Reading flash region -- 0x%x/0x%x.\n",
 		    ha->optrom_region_start, ha->optrom_region_size));
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 5104aef..0de92d3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -676,6 +676,50 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
 	return (return_status);
 }
 
+/*
+ * qla2x00_wait_for_reset_ready
+ *    Wait till the HBA is online after going through
+ *    <= MAX_RETRIES_OF_ISP_ABORT  or
+ *    finally HBA is disabled ie marked offline or flash
+ *    operations are in progress.
+ *
+ * Input:
+ *     ha - pointer to host adapter structure
+ *
+ * Note:
+ *    Does context switching-Release SPIN_LOCK
+ *    (if any) before calling this routine.
+ *
+ * Return:
+ *    Success (Adapter is online/no flash ops) : 0
+ *    Failed  (Adapter is offline/disabled/flash ops in progress) : 1
+ */
+int
+qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
+{
+	int		return_status;
+	unsigned long	wait_online;
+	struct qla_hw_data *ha = vha->hw;
+	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+
+	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
+	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
+	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
+	    ha->optrom_state != QLA_SWAITING ||
+	    ha->dpc_active) && time_before(jiffies, wait_online))
+		msleep(1000);
+
+	if (base_vha->flags.online &&  ha->optrom_state == QLA_SWAITING)
+		return_status = QLA_SUCCESS;
+	else
+		return_status = QLA_FUNCTION_FAILED;
+
+	DEBUG2(printk("%s return_status=%d\n", __func__, return_status));
+
+	return return_status;
+}
+
 int
 qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
 {
@@ -1081,7 +1125,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
 
-	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
+	if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
 		goto eh_host_reset_lock;
 
 	/*
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 13/16] qla2xxx: Optionally disable target reset.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (11 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 12/16] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 14/16] qla2xxx: Updates to ISP82xx support giridhar.malavali
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Giridhar Malavali <giridhar.malavali@qlogic.com>

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_gbl.h |    1 +
 drivers/scsi/qla2xxx/qla_os.c  |    8 +++++++-
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3e946da..8217c3b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -96,6 +96,7 @@ extern int ql2xdontresethba;
 extern int ql2xasynctmfenable;
 extern int ql2xenabledif;
 extern int ql2xenablehba_err_chk;
+extern int ql2xtargetreset;
 
 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_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0de92d3..be1a8fc 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -154,6 +154,12 @@ MODULE_PARM_DESC(ql2xdontresethba,
 	" 0 (Default) -- Reset on failure.\n"
 	" 1 -- Do not reset on failure.\n");
 
+int ql2xtargetreset = 1;
+module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xtargetreset,
+		 "Enable target reset."
+		 "Default is 1 - use hw defaults.");
+
 
 int ql2xasynctmfenable;
 module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
@@ -1193,7 +1199,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 	struct fc_port *fcport;
 	struct qla_hw_data *ha = vha->hw;
 
-	if (ha->flags.enable_target_reset) {
+	if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) {
 		list_for_each_entry(fcport, &vha->vp_fcports, list) {
 			if (fcport->port_type != FCT_TARGET)
 				continue;
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 14/16] qla2xxx: Updates to ISP82xx support.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (12 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 13/16] qla2xxx: Optionally disable target reset giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-04 22:01 ` [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX giridhar.malavali
  2010-05-04 22:01 ` [PATCH 16/16] qla2xxx: Update version number to 8.03.03-k0 giridhar.malavali
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Giridhar Malavali <giridhar.malavali@qlogic.com>

1) Allow transition to NEED RESET state only from READY state for ISP82xx.
2) Avoid infinite ISP aborts when chip reset fails.
3) Code cleanup to remove some of the unused debug code.

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Santosh Vernekar <santosh.vernekar@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |    2 -
 drivers/scsi/qla2xxx/qla_init.c |   33 ------
 drivers/scsi/qla2xxx/qla_nx.c   |  205 ++++++++++++++++++++-------------------
 drivers/scsi/qla2xxx/qla_nx.h   |   15 ++--
 4 files changed, 111 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 4559f5c..8396109 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2764,8 +2764,6 @@ struct qla_hw_data {
 	unsigned long	nx_pcibase;		/* Base I/O address */
 	uint8_t		*nxdb_rd_ptr;		/* Doorbell read pointer */
 	unsigned long	nxdb_wr_ptr;		/* Door bell write pointer */
-	unsigned long	first_page_group_start;
-	unsigned long	first_page_group_end;
 
 	uint32_t	crb_win;
 	uint32_t	curr_window;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7fd1344..ab2cc71 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -5296,39 +5296,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
 				    "(%d).\n", rval);
 			}
 		}
-	} else {	/* failed the ISP abort */
-		vha->flags.online = 1;
-		if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
-			if (ha->isp_abort_cnt == 0) {
-				qla_printk(KERN_WARNING, ha,
-				    "ISP error recovery failed - "
-				    "board disabled\n");
-				/*
-				 * The next call disables the board
-				 * completely.
-				 */
-				ha->isp_ops->reset_adapter(vha);
-				vha->flags.online = 0;
-				clear_bit(ISP_ABORT_RETRY,
-					&vha->dpc_flags);
-				status = 0;
-			} else { /* schedule another ISP abort */
-				ha->isp_abort_cnt--;
-				qla_printk(KERN_INFO, ha,
-					"qla%ld: ISP abort - "
-					"retry remaining %d\n",
-					vha->host_no, ha->isp_abort_cnt);
-				status = 1;
-			}
-		} else {
-			ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
-			qla_printk(KERN_INFO, ha,
-				"(%ld): ISP error recovery "
-				"- retrying (%d) more times\n",
-				vha->host_no, ha->isp_abort_cnt);
-			set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
-			status = 1;
-		}
 	}
 
 	if (!status) {
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 495ff1a..ff562de 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -30,16 +30,6 @@
 #define QLA82XX_PCI_CAMQM_2M_BASE	(0x000ff800UL)
 #define CRB_INDIRECT_2M	(0x1e0000UL)
 
-static inline void *qla82xx_pci_base_offsetfset(struct qla_hw_data *ha,
-    unsigned long off)
-{
-	if ((off < ha->first_page_group_end) &&
-	    (off >= ha->first_page_group_start))
-		return (void *)(ha->nx_pcibase + off);
-
-	return NULL;
-}
-
 #define MAX_CRB_XFORM 60
 static unsigned long crb_addr_xform[MAX_CRB_XFORM];
 int qla82xx_crb_table_initialized;
@@ -335,6 +325,18 @@ unsigned qla82xx_crb_hub_agt[64] = {
 	0,
 };
 
+/* Device states */
+char *qdev_state[] = {
+	 "Unknown",
+	"Cold",
+	"Initializing",
+	"Ready",
+	"Need Reset",
+	"Need Quiescent",
+	"Failed",
+	"Quiescent",
+};
+
 /*
  * In: 'off' is offset from CRB space in 128M pci map
  * Out: 'off' is 2M pci map addr
@@ -661,7 +663,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
 	u64 off, void *data, int size)
 {
 	unsigned long   flags;
-	void           *addr;
+	void           *addr = NULL;
 	int             ret = 0;
 	u64             start;
 	uint8_t         *mem_ptr = NULL;
@@ -684,26 +686,23 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
 		return -1;
 	}
 
-	addr = qla82xx_pci_base_offsetfset(ha, start);
-	if (!addr) {
-		write_unlock_irqrestore(&ha->hw_lock, flags);
-		mem_base = pci_resource_start(ha->pdev, 0);
-		mem_page = start & PAGE_MASK;
-		/* Map two pages whenever user tries to access addresses in two
-		* consecutive pages.
-		*/
-		if (mem_page != ((start + size - 1) & PAGE_MASK))
-			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
-		else
-			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
-		if (mem_ptr == 0UL) {
-			*(u8  *)data = 0;
-			return -1;
-		}
-		addr = mem_ptr;
-		addr += start & (PAGE_SIZE - 1);
-		write_lock_irqsave(&ha->hw_lock, flags);
+	write_unlock_irqrestore(&ha->hw_lock, flags);
+	mem_base = pci_resource_start(ha->pdev, 0);
+	mem_page = start & PAGE_MASK;
+	/* Map two pages whenever user tries to access addresses in two
+	* consecutive pages.
+	*/
+	if (mem_page != ((start + size - 1) & PAGE_MASK))
+		mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+	else
+		mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+	if (mem_ptr == 0UL) {
+		*(u8  *)data = 0;
+		return -1;
 	}
+	addr = mem_ptr;
+	addr += start & (PAGE_SIZE - 1);
+	write_lock_irqsave(&ha->hw_lock, flags);
 
 	switch (size) {
 	case 1:
@@ -734,7 +733,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
 	u64 off, void *data, int size)
 {
 	unsigned long   flags;
-	void           *addr;
+	void           *addr = NULL;
 	int             ret = 0;
 	u64             start;
 	uint8_t         *mem_ptr = NULL;
@@ -757,25 +756,22 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
 		return -1;
 	}
 
-	addr = qla82xx_pci_base_offsetfset(ha, start);
-	if (!addr) {
-		write_unlock_irqrestore(&ha->hw_lock, flags);
-		mem_base = pci_resource_start(ha->pdev, 0);
-		mem_page = start & PAGE_MASK;
-		/* Map two pages whenever user tries to access addresses in two
-		 * consecutive pages.
-		 */
-		if (mem_page != ((start + size - 1) & PAGE_MASK))
-			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
-		else
-			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
-		if (mem_ptr == 0UL)
-			return -1;
+	write_unlock_irqrestore(&ha->hw_lock, flags);
+	mem_base = pci_resource_start(ha->pdev, 0);
+	mem_page = start & PAGE_MASK;
+	/* Map two pages whenever user tries to access addresses in two
+	 * consecutive pages.
+	 */
+	if (mem_page != ((start + size - 1) & PAGE_MASK))
+		mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
+	else
+		mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+	if (mem_ptr == 0UL)
+		return -1;
 
-		addr = mem_ptr;
-		addr += start & (PAGE_SIZE - 1);
-		write_lock_irqsave(&ha->hw_lock, flags);
-	}
+	addr = mem_ptr;
+	addr += start & (PAGE_SIZE - 1);
+	write_lock_irqsave(&ha->hw_lock, flags);
 
 	switch (size) {
 	case 1:
@@ -1866,6 +1862,14 @@ void qla82xx_config_rings(struct scsi_qla_host *vha)
 	WRT_REG_DWORD((unsigned long  __iomem *)&reg->rsp_q_out[0], 0);
 }
 
+void qla82xx_reset_adapter(struct scsi_qla_host *vha)
+{
+	struct qla_hw_data *ha = vha->hw;
+	vha->flags.online = 0;
+	qla2x00_try_to_stop_firmware(vha);
+	ha->isp_ops->disable_intrs(ha);
+}
+
 int qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
 {
 	u64 *ptr64;
@@ -2093,15 +2097,7 @@ qla82xx_intr_handler(int irq, void *dev_id)
 
 		if (RD_REG_DWORD(&reg->host_int)) {
 			stat = RD_REG_DWORD(&reg->host_status);
-			if (stat & HSRX_RISC_PAUSED) {
-				if (pci_channel_offline(ha->pdev))
-					break;
-
-				qla_printk(KERN_INFO, ha, "RISC paused\n");
-				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-				qla2xxx_wake_dpc(vha);
-				break;
-			} else if ((stat & HSRX_RISC_INT) == 0)
+			if ((stat & HSRX_RISC_INT) == 0)
 				break;
 
 			switch (stat & 0xff) {
@@ -2177,15 +2173,7 @@ qla82xx_msix_default(int irq, void *dev_id)
 	do {
 		if (RD_REG_DWORD(&reg->host_int)) {
 			stat = RD_REG_DWORD(&reg->host_status);
-			if (stat & HSRX_RISC_PAUSED) {
-				if (pci_channel_offline(ha->pdev))
-					break;
-
-				qla_printk(KERN_INFO, ha, "RISC paused\n");
-				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-				qla2xxx_wake_dpc(vha);
-				break;
-			} else if ((stat & HSRX_RISC_INT) == 0)
+			if ((stat & HSRX_RISC_INT) == 0)
 				break;
 
 			switch (stat & 0xff) {
@@ -3348,6 +3336,9 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
 	}
 
 	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+	qla_printk(KERN_INFO, ha, "3: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) {
 		qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n");
@@ -3398,7 +3389,6 @@ int
 qla82xx_device_state_handler(scsi_qla_host_t *vha)
 {
 	uint32_t dev_state;
-	uint32_t drv_active;
 	int rval = QLA_SUCCESS;
 	unsigned long dev_init_timeout;
 	struct qla_hw_data *ha = vha->hw;
@@ -3407,38 +3397,9 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
 	if (!vha->flags.init_done)
 		qla82xx_set_drv_active(vha);
 
-	/* Set cold state*/
-	if (!PCI_FUNC(ha->pdev->devfn & 1)) {
-
-		/* Check if other functions alive, else set dev state
-		 * to cold
-		 */
-		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-		drv_active &= ~(1 << (ha->portnum * 4));
-		drv_active &= ~(1 << ((ha->portnum + 1) * 4));
-
-		dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-		if (!drv_active) {
-
-			switch (dev_state) {
-			case QLA82XX_DEV_COLD:
-			case QLA82XX_DEV_READY:
-			case QLA82XX_DEV_INITIALIZING:
-			case QLA82XX_DEV_NEED_RESET:
-			case QLA82XX_DEV_NEED_QUIESCENT:
-			case QLA82XX_DEV_QUIESCENT:
-			case QLA82XX_DEV_FAILED:
-				break;
-			default:
-				qla_printk(KERN_INFO, ha,
-					"No other function exist,"
-					" resetting dev state to COLD\n");
-				qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
-					QLA82XX_DEV_COLD);
-				break;
-			}
-		}
-	}
+	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+	qla_printk(KERN_INFO, ha, "1: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);
@@ -3453,6 +3414,11 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
 			break;
 		}
 		dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		qla_printk(KERN_INFO, ha,
+			"2:Device state is 0x%x = %s\n", dev_state,
+			dev_state < MAX_STATES ?
+			qdev_state[dev_state] : "Unknown");
+
 		switch (dev_state) {
 		case QLA82XX_DEV_READY:
 			goto exit;
@@ -3545,12 +3511,14 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
 
 	qla82xx_idc_lock(ha);
 	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-	if (dev_state != QLA82XX_DEV_INITIALIZING) {
+	if (dev_state == QLA82XX_DEV_READY) {
 		qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n");
 		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 			QLA82XX_DEV_NEED_RESET);
 	} else
-		qla_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n");
+		qla_printk(KERN_INFO, ha, "HW State: %s\n",
+			dev_state < MAX_STATES ?
+			qdev_state[dev_state] : "Unknown");
 	qla82xx_idc_unlock(ha);
 
 	rval = qla82xx_device_state_handler(vha);
@@ -3561,6 +3529,39 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
 
 	if (rval == QLA_SUCCESS)
 		qla82xx_restart_isp(vha);
+
+	if (rval) {
+		vha->flags.online = 1;
+		if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+			if (ha->isp_abort_cnt == 0) {
+				qla_printk(KERN_WARNING, ha,
+				    "ISP error recovery failed - "
+				    "board disabled\n");
+				/*
+				 * The next call disables the board
+				 * completely.
+				 */
+				ha->isp_ops->reset_adapter(vha);
+				vha->flags.online = 0;
+				clear_bit(ISP_ABORT_RETRY,
+				    &vha->dpc_flags);
+				rval = QLA_SUCCESS;
+			} else { /* schedule another ISP abort */
+				ha->isp_abort_cnt--;
+				DEBUG(qla_printk(KERN_INFO, ha,
+				    "qla%ld: ISP abort - retry remaining %d\n",
+				    vha->host_no, ha->isp_abort_cnt));
+				rval = QLA_FUNCTION_FAILED;
+			}
+		} else {
+			ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
+			DEBUG(qla_printk(KERN_INFO, ha,
+			    "(%ld): ISP error recovery - retrying (%d) "
+			    "more times\n", vha->host_no, ha->isp_abort_cnt));
+			set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
+			rval = QLA_FUNCTION_FAILED;
+		}
+	}
 	return rval;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 7804bbb..f8f99a5 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -545,13 +545,14 @@
 #define QLA82XX_CRB_DEV_PART_INFO    (QLA82XX_CAM_RAM(0x14c))
 
 /* Every driver should use these Device State */
-#define QLA82XX_DEV_COLD	    1
-#define QLA82XX_DEV_INITIALIZING    2
-#define QLA82XX_DEV_READY	    3
-#define QLA82XX_DEV_NEED_RESET	    4
-#define QLA82XX_DEV_NEED_QUIESCENT  5
-#define QLA82XX_DEV_FAILED	    6
-#define QLA82XX_DEV_QUIESCENT	    7
+#define QLA82XX_DEV_COLD		1
+#define QLA82XX_DEV_INITIALIZING	2
+#define QLA82XX_DEV_READY		3
+#define QLA82XX_DEV_NEED_RESET		4
+#define QLA82XX_DEV_NEED_QUIESCENT	5
+#define QLA82XX_DEV_FAILED		6
+#define QLA82XX_DEV_QUIESCENT		7
+#define	MAX_STATES			8 /* Increment if new state added */
 
 #define QLA82XX_IDC_VERSION			1
 #define QLA82XX_ROM_DEV_INIT_TIMEOUT		30
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (13 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 14/16] qla2xxx: Updates to ISP82xx support giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  2010-05-16 22:30   ` James Bottomley
  2010-05-04 22:01 ` [PATCH 16/16] qla2xxx: Update version number to 8.03.03-k0 giridhar.malavali
  15 siblings, 1 reply; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley
  Cc: giridhar.malavali, andrew.vasquez, linux-scsi, Sarang Radke

From: Sarang Radke <sarang.radke@qlogic.com>

Signed-off-by: Sarang Radke <sarang.radke@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c |  174 +++++++++++++++++++++++++++++++++++++---
 drivers/scsi/qla2xxx/qla_bsg.h |    7 ++
 drivers/scsi/qla2xxx/qla_def.h |    4 +
 drivers/scsi/qla2xxx/qla_gbl.h |    5 +
 drivers/scsi/qla2xxx/qla_isr.c |    7 +-
 drivers/scsi/qla2xxx/qla_mbx.c |   66 +++++++++++++++
 drivers/scsi/qla2xxx/qla_os.c  |    1 +
 7 files changed, 252 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index b905dfe..980ddca 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -483,17 +483,110 @@ done:
 	return rval;
 }
 
+/* Set the port configuration to enable the
+ * internal loopback on ISP81XX
+ */
+static inline int
+qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
+    uint16_t *new_config)
+{
+	int ret = 0;
+	int rval = 0;
+	struct qla_hw_data *ha = vha->hw;
+
+	if (!IS_QLA81XX(ha))
+		goto done_set_internal;
+
+	new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
+	memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
+
+	ha->notify_dcbx_comp = 1;
+	ret = qla81xx_set_port_config(vha, new_config);
+	if (ret != QLA_SUCCESS) {
+		DEBUG2(printk(KERN_ERR
+		    "%s(%lu): Set port config failed\n",
+		    __func__, vha->host_no));
+		ha->notify_dcbx_comp = 0;
+		rval = -EINVAL;
+		goto done_set_internal;
+	}
+
+	/* Wait for DCBX complete event */
+	if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "State change notificaition not received.\n"));
+	} else
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "State change RECEIVED\n"));
+
+	ha->notify_dcbx_comp = 0;
+
+done_set_internal:
+	return rval;
+}
+
+/* Set the port configuration to disable the
+ * internal loopback on ISP81XX
+ */
+static inline int
+qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
+    int wait)
+{
+	int ret = 0;
+	int rval = 0;
+	uint16_t new_config[4];
+	struct qla_hw_data *ha = vha->hw;
+
+	if (!IS_QLA81XX(ha))
+		goto done_reset_internal;
+
+	memset(new_config, 0 , sizeof(new_config));
+	if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
+			ENABLE_INTERNAL_LOOPBACK) {
+		new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
+		memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
+
+		ha->notify_dcbx_comp = wait;
+		ret = qla81xx_set_port_config(vha, new_config);
+		if (ret != QLA_SUCCESS) {
+			DEBUG2(printk(KERN_ERR
+			    "%s(%lu): Set port config failed\n",
+			     __func__, vha->host_no));
+			ha->notify_dcbx_comp = 0;
+			rval = -EINVAL;
+			goto done_reset_internal;
+		}
+
+		/* Wait for DCBX complete event */
+		if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
+			(20 * HZ))) {
+			DEBUG2(qla_printk(KERN_WARNING, ha,
+			    "State change notificaition not received.\n"));
+			ha->notify_dcbx_comp = 0;
+			rval = -EINVAL;
+			goto done_reset_internal;
+		} else
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "State change RECEIVED\n"));
+
+		ha->notify_dcbx_comp = 0;
+	}
+done_reset_internal:
+	return rval;
+}
+
 static int
 qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 {
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
-	int rval;
+	int rval, ret;
 	uint8_t command_sent;
 	char *type;
 	struct msg_echo_lb elreq;
 	uint16_t response[MAILBOX_REGISTER_COUNT];
+	uint16_t config[4], new_config[4];
 	uint8_t *fw_sts_ptr;
 	uint8_t *req_data = NULL;
 	dma_addr_t req_data_dma;
@@ -568,7 +661,54 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 
 	elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 
-	if (ha->current_topology != ISP_CFG_F) {
+	if ((ha->current_topology == ISP_CFG_F ||
+	    (IS_QLA81XX(ha) &&
+	    le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
+	    && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
+		elreq.options == EXTERNAL_LOOPBACK) {
+		type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
+		DEBUG2(qla_printk(KERN_INFO, ha,
+			"scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
+		command_sent = INT_DEF_LB_ECHO_CMD;
+		rval = qla2x00_echo_test(vha, &elreq, response);
+
+	} else {
+		if (IS_QLA81XX(ha)) {
+			memset(config, 0, sizeof(config));
+			memset(new_config, 0, sizeof(new_config));
+			ret = qla81xx_get_port_config(vha, config);
+			if (ret != QLA_SUCCESS) {
+				DEBUG2(printk(KERN_ERR
+				    "%s(%lu): Get port config failed\n",
+				    __func__, vha->host_no));
+				bsg_job->reply->reply_payload_rcv_len = 0;
+				bsg_job->reply->result = (DID_ERROR << 16);
+				goto done_free_dma_req;
+			}
+		}
+
+		if (elreq.options != EXTERNAL_LOOPBACK && IS_QLA81XX(ha)) {
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "Internal: current port config = %x\n", config[0]));
+			ret = qla81xx_set_internal_loopback(vha, config,
+			    new_config);
+			if (ret) {
+				bsg_job->reply->reply_payload_rcv_len = 0;
+				bsg_job->reply->result = (DID_ERROR << 16);
+				goto done_free_dma_req;
+			}
+		} else {
+			/* For external loopback to work
+			 * ensure internal loopback is disabled
+			 */
+			ret = qla81xx_reset_internal_loopback(vha, config, 1);
+			if (ret) {
+				bsg_job->reply->reply_payload_rcv_len = 0;
+				bsg_job->reply->result = (DID_ERROR << 16);
+				goto done_free_dma_req;
+			}
+		}
+
 		type = "FC_BSG_HST_VENDOR_LOOPBACK";
 		DEBUG2(qla_printk(KERN_INFO, ha,
 			"scsi(%ld) bsg rqst type: %s\n",
@@ -577,20 +717,34 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 		command_sent = INT_DEF_LB_LOOPBACK_CMD;
 		rval = qla2x00_loopback_test(vha, &elreq, response);
 		if (IS_QLA81XX(ha)) {
+			if (new_config[1]) {
+				/* Revert back to original port config
+				 * Also clear internal loopback
+				 */
+				qla81xx_reset_internal_loopback(vha,
+				    new_config, 0);
+			}
+
 			if (response[0] == MBS_COMMAND_ERROR &&
-				response[1] == MBS_LB_RESET) {
+					response[1] == MBS_LB_RESET) {
 				DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
-				"ISP\n", __func__, vha->host_no));
+					"ISP\n", __func__, vha->host_no));
 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 				qla2xxx_wake_dpc(vha);
+				qla2x00_wait_for_chip_reset(vha);
+				/* Also reset the MPI */
+				if (qla81xx_restart_mpi_firmware(vha) !=
+				    QLA_SUCCESS) {
+					qla_printk(KERN_INFO, ha,
+					    "MPI reset failed for host%ld.\n",
+					    vha->host_no);
+				}
+
+				bsg_job->reply->reply_payload_rcv_len = 0;
+				bsg_job->reply->result = (DID_ERROR << 16);
+				goto done_free_dma_req;
 			}
 		}
-	} else {
-		type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
-		DEBUG2(qla_printk(KERN_INFO, ha,
-		    "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
-		command_sent = INT_DEF_LB_ECHO_CMD;
-		rval = qla2x00_echo_test(vha, &elreq, response);
 	}
 
 	if (rval) {
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 76ed92d..1f096da 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -19,6 +19,13 @@
 #define INT_DEF_LB_LOOPBACK_CMD         0
 #define INT_DEF_LB_ECHO_CMD             1
 
+/* Loopback related definations */
+#define EXTERNAL_LOOPBACK		0xF2
+#define ENABLE_INTERNAL_LOOPBACK	0x02
+#define INTERNAL_LOOPBACK_MASK		0x000E
+#define MAX_ELS_FRAME_PAYLOAD		252
+#define ELS_OPCODE_BYTE			0x10
+
 /* BSG Vendor specific definations */
 #define A84_ISSUE_WRITE_TYPE_CMD        0
 #define A84_ISSUE_READ_TYPE_CMD         1
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8396109..4d8a7b9 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -713,6 +713,8 @@ typedef struct {
 #define MBC_SEND_RNFT_ELS		0x5e	/* Send RNFT ELS request */
 #define MBC_GET_LINK_PRIV_STATS		0x6d	/* Get link & private data. */
 #define MBC_SET_VENDOR_ID		0x76	/* Set Vendor ID. */
+#define MBC_SET_PORT_CONFIG		0x122	/* Set port configuration */
+#define MBC_GET_PORT_CONFIG		0x123	/* Get port configuration */
 
 /* Firmware return data sizes */
 #define FCAL_MAP_SIZE	128
@@ -2630,6 +2632,8 @@ struct qla_hw_data {
 	struct mutex vport_lock;        /* Virtual port synchronization */
 	struct completion mbx_cmd_comp; /* Serialize mbx access */
 	struct completion mbx_intr_comp;  /* Used for completion notification */
+	struct completion dcbx_comp;	/* For set port config notification */
+	int notify_dcbx_comp;
 
 	/* Basic firmware related information. */
 	uint16_t	fw_major_version;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 8217c3b..6ff36f1 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -357,6 +357,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
 extern int qla2x00_get_data_rate(scsi_qla_host_t *);
 extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
 	uint16_t *);
+extern int
+qla81xx_get_port_config(scsi_qla_host_t *, uint16_t *);
+
+extern int
+qla81xx_set_port_config(scsi_qla_host_t *, uint16_t *);
 
 /*
  * Global Function Prototypes in qla_isr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index be3d8be..2fe0250 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -545,10 +545,13 @@ skip_rio:
 		if (IS_QLA2100(ha))
 			break;
 
-		if (IS_QLA8XXX_TYPE(ha))
+		if (IS_QLA8XXX_TYPE(ha)) {
 			DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
 			    "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
-		else
+			if (ha->notify_dcbx_comp)
+				complete(&ha->dcbx_comp);
+
+		} else
 			DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
 			    "received.\n", vha->host_no));
 
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f3650d0..f593afa 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3950,6 +3950,72 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
 }
 
 int
+qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+	struct qla_hw_data *ha = vha->hw;
+
+	DEBUG11(printk(KERN_INFO
+	    "%s(%ld): entered.\n", __func__, vha->host_no));
+
+	if (!IS_QLA81XX(ha))
+		return QLA_FUNCTION_FAILED;
+	mcp->mb[0] = MBC_GET_PORT_CONFIG;
+	mcp->out_mb = MBX_0;
+	mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+
+	rval = qla2x00_mailbox_command(vha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): failed=%x (%x).\n", __func__,
+		    vha->host_no, rval, mcp->mb[0]));
+	} else {
+		/* Copy all bits to preserve original value */
+		memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
+
+		DEBUG11(printk(KERN_INFO
+		    "%s(%ld): done.\n", __func__, vha->host_no));
+	}
+	return rval;
+}
+
+int
+qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	DEBUG11(printk(KERN_INFO
+	    "%s(%ld): entered.\n", __func__, vha->host_no));
+
+	mcp->mb[0] = MBC_SET_PORT_CONFIG;
+	/* Copy all bits to preserve original setting */
+	memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
+	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(vha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): failed=%x (%x).\n", __func__,
+		    vha->host_no, rval, mcp->mb[0]));
+	} else
+		DEBUG11(printk(KERN_INFO
+		    "%s(%ld): done.\n", __func__, vha->host_no));
+
+	return rval;
+}
+
+
+int
 qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
 		uint16_t *mb)
 {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index be1a8fc..58e6102 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2113,6 +2113,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	init_completion(&ha->mbx_cmd_comp);
 	complete(&ha->mbx_cmd_comp);
 	init_completion(&ha->mbx_intr_comp);
+	init_completion(&ha->dcbx_comp);
 
 	set_bit(0, (unsigned long *) ha->vp_idx_map);
 
-- 
1.6.2.rc1.30.gd43c


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

* [PATCH 16/16] qla2xxx: Update version number to 8.03.03-k0.
  2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
                   ` (14 preceding siblings ...)
  2010-05-04 22:01 ` [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX giridhar.malavali
@ 2010-05-04 22:01 ` giridhar.malavali
  15 siblings, 0 replies; 19+ messages in thread
From: giridhar.malavali @ 2010-05-04 22:01 UTC (permalink / raw)
  To: James.Bottomley; +Cc: giridhar.malavali, andrew.vasquez, linux-scsi

From: Giridhar Malavali <giridhar.malavali@qlogic.com>

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_version.h |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 109068d..9b49b08 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.02-k2"
+#define QLA2XXX_VERSION      "8.03.03-k0"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	3
-#define QLA_DRIVER_PATCH_VER	2
-#define QLA_DRIVER_BETA_VER	2
+#define QLA_DRIVER_PATCH_VER	3
+#define QLA_DRIVER_BETA_VER	0
-- 
1.6.2.rc1.30.gd43c


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

* Re: [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX
  2010-05-04 22:01 ` [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX giridhar.malavali
@ 2010-05-16 22:30   ` James Bottomley
  2010-05-17 21:50     ` Giridhar Malavali
  0 siblings, 1 reply; 19+ messages in thread
From: James Bottomley @ 2010-05-16 22:30 UTC (permalink / raw)
  To: giridhar.malavali; +Cc: andrew.vasquez, linux-scsi, Sarang Radke

I'm getting this error from this patch:

  CC [M]  drivers/scsi/qla2xxx/qla_bsg.o
drivers/scsi/qla2xxx/qla_bsg.c: In function ‘qla2x00_process_loopback’:
drivers/scsi/qla2xxx/qla_bsg.c:584: warning: ‘rval’ may be used
uninitialized in this function

It looks like this hunk of code.

On Tue, 2010-05-04 at 15:01 -0700, giridhar.malavali@qlogic.com wrote:
>  static int
>  qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>  {
>  	struct Scsi_Host *host = bsg_job->shost;
>  	scsi_qla_host_t *vha = shost_priv(host);
>  	struct qla_hw_data *ha = vha->hw;
> -	int rval;
> +	int rval, ret;
>  	uint8_t command_sent;
>  	char *type;
>  	struct msg_echo_lb elreq;
>  	uint16_t response[MAILBOX_REGISTER_COUNT];
> +	uint16_t config[4], new_config[4];
>  	uint8_t *fw_sts_ptr;
>  	uint8_t *req_data = NULL;
>  	dma_addr_t req_data_dma;
> @@ -568,7 +661,54 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>  
>  	elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
>  
> -	if (ha->current_topology != ISP_CFG_F) {
> +	if ((ha->current_topology == ISP_CFG_F ||
> +	    (IS_QLA81XX(ha) &&
> +	    le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
> +	    && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
> +		elreq.options == EXTERNAL_LOOPBACK) {
> +		type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
> +		DEBUG2(qla_printk(KERN_INFO, ha,
> +			"scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
> +		command_sent = INT_DEF_LB_ECHO_CMD;
> +		rval = qla2x00_echo_test(vha, &elreq, response);
> +
> +	} else {
> +		if (IS_QLA81XX(ha)) {
> +			memset(config, 0, sizeof(config));
> +			memset(new_config, 0, sizeof(new_config));
> +			ret = qla81xx_get_port_config(vha, config);
> +			if (ret != QLA_SUCCESS) {
> +				DEBUG2(printk(KERN_ERR
> +				    "%s(%lu): Get port config failed\n",
> +				    __func__, vha->host_no));
> +				bsg_job->reply->reply_payload_rcv_len = 0;
> +				bsg_job->reply->result = (DID_ERROR << 16);
> +				goto done_free_dma_req;

Specifically, here and a few others below.  If ret indicates the command
failed, shouldn't we be setting rval to pass the error upwards ... it's
currently uninitialised, I think?

James

> +			}
> +		}
> +
> +		if (elreq.options != EXTERNAL_LOOPBACK && IS_QLA81XX(ha)) {
> +			DEBUG2(qla_printk(KERN_INFO, ha,
> +			    "Internal: current port config = %x\n", config[0]));
> +			ret = qla81xx_set_internal_loopback(vha, config,
> +			    new_config);
> +			if (ret) {
> +				bsg_job->reply->reply_payload_rcv_len = 0;
> +				bsg_job->reply->result = (DID_ERROR << 16);
> +				goto done_free_dma_req;
> +			}
> +		} else {
> +			/* For external loopback to work
> +			 * ensure internal loopback is disabled
> +			 */
> +			ret = qla81xx_reset_internal_loopback(vha, config, 1);
> +			if (ret) {
> +				bsg_job->reply->reply_payload_rcv_len = 0;
> +				bsg_job->reply->result = (DID_ERROR << 16);
> +				goto done_free_dma_req;
> +			}
> +		}
> +
>  		type = "FC_BSG_HST_VENDOR_LOOPBACK";
>  		DEBUG2(qla_printk(KERN_INFO, ha,
>  			"scsi(%ld) bsg rqst type: %s\n",
> @@ -577,20 +717,34 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>  		command_sent = INT_DEF_LB_LOOPBACK_CMD;
>  		rval = qla2x00_loopback_test(vha, &elreq, response);
>  		if (IS_QLA81XX(ha)) {
> +			if (new_config[1]) {
> +				/* Revert back to original port config
> +				 * Also clear internal loopback
> +				 */
> +				qla81xx_reset_internal_loopback(vha,
> +				    new_config, 0);
> +			}
> +
>  			if (response[0] == MBS_COMMAND_ERROR &&
> -				response[1] == MBS_LB_RESET) {
> +					response[1] == MBS_LB_RESET) {
>  				DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
> -				"ISP\n", __func__, vha->host_no));
> +					"ISP\n", __func__, vha->host_no));
>  				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
>  				qla2xxx_wake_dpc(vha);
> +				qla2x00_wait_for_chip_reset(vha);
> +				/* Also reset the MPI */
> +				if (qla81xx_restart_mpi_firmware(vha) !=
> +				    QLA_SUCCESS) {
> +					qla_printk(KERN_INFO, ha,
> +					    "MPI reset failed for host%ld.\n",
> +					    vha->host_no);
> +				}
> +
> +				bsg_job->reply->reply_payload_rcv_len = 0;
> +				bsg_job->reply->result = (DID_ERROR << 16);
> +				goto done_free_dma_req;
>  			}
>  		}
> -	} else {
> -		type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
> -		DEBUG2(qla_printk(KERN_INFO, ha,
> -		    "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
> -		command_sent = INT_DEF_LB_ECHO_CMD;
> -		rval = qla2x00_echo_test(vha, &elreq, response);
>  	}
>  
>  	if (rval) {
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> index 76ed92d..1f096da 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.h
> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> @@ -19,6 +19,13 @@
>  #define INT_DEF_LB_LOOPBACK_CMD         0
>  #define INT_DEF_LB_ECHO_CMD             1
>  
> +/* Loopback related definations */
> +#define EXTERNAL_LOOPBACK		0xF2
> +#define ENABLE_INTERNAL_LOOPBACK	0x02
> +#define INTERNAL_LOOPBACK_MASK		0x000E
> +#define MAX_ELS_FRAME_PAYLOAD		252
> +#define ELS_OPCODE_BYTE			0x10
> +
>  /* BSG Vendor specific definations */
>  #define A84_ISSUE_WRITE_TYPE_CMD        0
>  #define A84_ISSUE_READ_TYPE_CMD         1
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 8396109..4d8a7b9 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -713,6 +713,8 @@ typedef struct {
>  #define MBC_SEND_RNFT_ELS		0x5e	/* Send RNFT ELS request */
>  #define MBC_GET_LINK_PRIV_STATS		0x6d	/* Get link & private data. */
>  #define MBC_SET_VENDOR_ID		0x76	/* Set Vendor ID. */
> +#define MBC_SET_PORT_CONFIG		0x122	/* Set port configuration */
> +#define MBC_GET_PORT_CONFIG		0x123	/* Get port configuration */
>  
>  /* Firmware return data sizes */
>  #define FCAL_MAP_SIZE	128
> @@ -2630,6 +2632,8 @@ struct qla_hw_data {
>  	struct mutex vport_lock;        /* Virtual port synchronization */
>  	struct completion mbx_cmd_comp; /* Serialize mbx access */
>  	struct completion mbx_intr_comp;  /* Used for completion notification */
> +	struct completion dcbx_comp;	/* For set port config notification */
> +	int notify_dcbx_comp;
>  
>  	/* Basic firmware related information. */
>  	uint16_t	fw_major_version;
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 8217c3b..6ff36f1 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -357,6 +357,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
>  extern int qla2x00_get_data_rate(scsi_qla_host_t *);
>  extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
>  	uint16_t *);
> +extern int
> +qla81xx_get_port_config(scsi_qla_host_t *, uint16_t *);
> +
> +extern int
> +qla81xx_set_port_config(scsi_qla_host_t *, uint16_t *);
>  
>  /*
>   * Global Function Prototypes in qla_isr.c source file.
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index be3d8be..2fe0250 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -545,10 +545,13 @@ skip_rio:
>  		if (IS_QLA2100(ha))
>  			break;
>  
> -		if (IS_QLA8XXX_TYPE(ha))
> +		if (IS_QLA8XXX_TYPE(ha)) {
>  			DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
>  			    "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
> -		else
> +			if (ha->notify_dcbx_comp)
> +				complete(&ha->dcbx_comp);
> +
> +		} else
>  			DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
>  			    "received.\n", vha->host_no));
>  
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index f3650d0..f593afa 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -3950,6 +3950,72 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
>  }
>  
>  int
> +qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
> +{
> +	int rval;
> +	mbx_cmd_t mc;
> +	mbx_cmd_t *mcp = &mc;
> +	struct qla_hw_data *ha = vha->hw;
> +
> +	DEBUG11(printk(KERN_INFO
> +	    "%s(%ld): entered.\n", __func__, vha->host_no));
> +
> +	if (!IS_QLA81XX(ha))
> +		return QLA_FUNCTION_FAILED;
> +	mcp->mb[0] = MBC_GET_PORT_CONFIG;
> +	mcp->out_mb = MBX_0;
> +	mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
> +	mcp->tov = MBX_TOV_SECONDS;
> +	mcp->flags = 0;
> +
> +	rval = qla2x00_mailbox_command(vha, mcp);
> +
> +	if (rval != QLA_SUCCESS) {
> +		DEBUG2_3_11(printk(KERN_WARNING
> +		    "%s(%ld): failed=%x (%x).\n", __func__,
> +		    vha->host_no, rval, mcp->mb[0]));
> +	} else {
> +		/* Copy all bits to preserve original value */
> +		memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
> +
> +		DEBUG11(printk(KERN_INFO
> +		    "%s(%ld): done.\n", __func__, vha->host_no));
> +	}
> +	return rval;
> +}
> +
> +int
> +qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
> +{
> +	int rval;
> +	mbx_cmd_t mc;
> +	mbx_cmd_t *mcp = &mc;
> +
> +	DEBUG11(printk(KERN_INFO
> +	    "%s(%ld): entered.\n", __func__, vha->host_no));
> +
> +	mcp->mb[0] = MBC_SET_PORT_CONFIG;
> +	/* Copy all bits to preserve original setting */
> +	memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
> +	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
> +	mcp->in_mb = MBX_0;
> +	mcp->tov = MBX_TOV_SECONDS;
> +	mcp->flags = 0;
> +	rval = qla2x00_mailbox_command(vha, mcp);
> +
> +	if (rval != QLA_SUCCESS) {
> +		DEBUG2_3_11(printk(KERN_WARNING
> +		    "%s(%ld): failed=%x (%x).\n", __func__,
> +		    vha->host_no, rval, mcp->mb[0]));
> +	} else
> +		DEBUG11(printk(KERN_INFO
> +		    "%s(%ld): done.\n", __func__, vha->host_no));
> +
> +	return rval;
> +}
> +
> +
> +int
>  qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
>  		uint16_t *mb)
>  {
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index be1a8fc..58e6102 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -2113,6 +2113,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
>  	init_completion(&ha->mbx_cmd_comp);
>  	complete(&ha->mbx_cmd_comp);
>  	init_completion(&ha->mbx_intr_comp);
> +	init_completion(&ha->dcbx_comp);
>  
>  	set_bit(0, (unsigned long *) ha->vp_idx_map);
>  
> -- 
> 1.6.2.rc1.30.gd43c
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

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

* Re: [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX
  2010-05-16 22:30   ` James Bottomley
@ 2010-05-17 21:50     ` Giridhar Malavali
  0 siblings, 0 replies; 19+ messages in thread
From: Giridhar Malavali @ 2010-05-17 21:50 UTC (permalink / raw)
  To: James Bottomley; +Cc: Andrew Vasquez, LinuxSCSI, Sarang Radke




On 5/16/10 3:30 PM, "James Bottomley" <James.Bottomley@suse.de> wrote:

> I'm getting this error from this patch:
> 
>   CC [M]  drivers/scsi/qla2xxx/qla_bsg.o
> drivers/scsi/qla2xxx/qla_bsg.c: In function Oqla2x00_process_loopback¹:
> drivers/scsi/qla2xxx/qla_bsg.c:584: warning: Orval¹ may be used
> uninitialized in this function
> 
> It looks like this hunk of code.
> 
> On Tue, 2010-05-04 at 15:01 -0700, giridhar.malavali@qlogic.com wrote:
>>  static int
>>  qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>>  {
>>       struct Scsi_Host *host = bsg_job->shost;
>>       scsi_qla_host_t *vha = shost_priv(host);
>>       struct qla_hw_data *ha = vha->hw;
>> -     int rval;
>> +     int rval, ret;
>>       uint8_t command_sent;
>>       char *type;
>>       struct msg_echo_lb elreq;
>>       uint16_t response[MAILBOX_REGISTER_COUNT];
>> +     uint16_t config[4], new_config[4];
>>       uint8_t *fw_sts_ptr;
>>       uint8_t *req_data = NULL;
>>       dma_addr_t req_data_dma;
>> @@ -568,7 +661,54 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>> 
>>       elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
>> 
>> -     if (ha->current_topology != ISP_CFG_F) {
>> +     if ((ha->current_topology == ISP_CFG_F ||
>> +         (IS_QLA81XX(ha) &&
>> +         le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
>> +         && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
>> +             elreq.options == EXTERNAL_LOOPBACK) {
>> +             type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
>> +             DEBUG2(qla_printk(KERN_INFO, ha,
>> +                     "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
>> +             command_sent = INT_DEF_LB_ECHO_CMD;
>> +             rval = qla2x00_echo_test(vha, &elreq, response);
>> +
>> +     } else {
>> +             if (IS_QLA81XX(ha)) {
>> +                     memset(config, 0, sizeof(config));
>> +                     memset(new_config, 0, sizeof(new_config));
>> +                     ret = qla81xx_get_port_config(vha, config);
>> +                     if (ret != QLA_SUCCESS) {
>> +                             DEBUG2(printk(KERN_ERR
>> +                                 "%s(%lu): Get port config failed\n",
>> +                                 __func__, vha->host_no));
>> +                             bsg_job->reply->reply_payload_rcv_len = 0;
>> +                             bsg_job->reply->result = (DID_ERROR << 16);
>> +                             goto done_free_dma_req;
> 
> Specifically, here and a few others below.  If ret indicates the command
> failed, shouldn't we be setting rval to pass the error upwards ... it's
> currently uninitialised, I think?
> 
> James

Yes. I will correct this patch and send it again.

> 
>> +                     }
>> +             }
>> +
>> +             if (elreq.options != EXTERNAL_LOOPBACK && IS_QLA81XX(ha)) {
>> +                     DEBUG2(qla_printk(KERN_INFO, ha,
>> +                         "Internal: current port config = %x\n",
>> config[0]));
>> +                     ret = qla81xx_set_internal_loopback(vha, config,
>> +                         new_config);
>> +                     if (ret) {
>> +                             bsg_job->reply->reply_payload_rcv_len = 0;
>> +                             bsg_job->reply->result = (DID_ERROR << 16);
>> +                             goto done_free_dma_req;
>> +                     }
>> +             } else {
>> +                     /* For external loopback to work
>> +                      * ensure internal loopback is disabled
>> +                      */
>> +                     ret = qla81xx_reset_internal_loopback(vha, config, 1);
>> +                     if (ret) {
>> +                             bsg_job->reply->reply_payload_rcv_len = 0;
>> +                             bsg_job->reply->result = (DID_ERROR << 16);
>> +                             goto done_free_dma_req;
>> +                     }
>> +             }
>> +
>>               type = "FC_BSG_HST_VENDOR_LOOPBACK";
>>               DEBUG2(qla_printk(KERN_INFO, ha,
>>                       "scsi(%ld) bsg rqst type: %s\n",
>> @@ -577,20 +717,34 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
>>               command_sent = INT_DEF_LB_LOOPBACK_CMD;
>>               rval = qla2x00_loopback_test(vha, &elreq, response);
>>               if (IS_QLA81XX(ha)) {
>> +                     if (new_config[1]) {
>> +                             /* Revert back to original port config
>> +                              * Also clear internal loopback
>> +                              */
>> +                             qla81xx_reset_internal_loopback(vha,
>> +                                 new_config, 0);
>> +                     }
>> +
>>                       if (response[0] == MBS_COMMAND_ERROR &&
>> -                             response[1] == MBS_LB_RESET) {
>> +                                     response[1] == MBS_LB_RESET) {
>>                               DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
>> -                             "ISP\n", __func__, vha->host_no));
>> +                                     "ISP\n", __func__, vha->host_no));
>>                               set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
>>                               qla2xxx_wake_dpc(vha);
>> +                             qla2x00_wait_for_chip_reset(vha);
>> +                             /* Also reset the MPI */
>> +                             if (qla81xx_restart_mpi_firmware(vha) !=
>> +                                 QLA_SUCCESS) {
>> +                                     qla_printk(KERN_INFO, ha,
>> +                                         "MPI reset failed for host%ld.\n",
>> +                                         vha->host_no);
>> +                             }
>> +
>> +                             bsg_job->reply->reply_payload_rcv_len = 0;
>> +                             bsg_job->reply->result = (DID_ERROR << 16);
>> +                             goto done_free_dma_req;
>>                       }
>>               }
>> -     } else {
>> -             type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
>> -             DEBUG2(qla_printk(KERN_INFO, ha,
>> -                 "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
>> -             command_sent = INT_DEF_LB_ECHO_CMD;
>> -             rval = qla2x00_echo_test(vha, &elreq, response);
>>       }
>> 
>>       if (rval) {
>> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
>> index 76ed92d..1f096da 100644
>> --- a/drivers/scsi/qla2xxx/qla_bsg.h
>> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
>> @@ -19,6 +19,13 @@
>>  #define INT_DEF_LB_LOOPBACK_CMD         0
>>  #define INT_DEF_LB_ECHO_CMD             1
>> 
>> +/* Loopback related definations */
>> +#define EXTERNAL_LOOPBACK            0xF2
>> +#define ENABLE_INTERNAL_LOOPBACK     0x02
>> +#define INTERNAL_LOOPBACK_MASK               0x000E
>> +#define MAX_ELS_FRAME_PAYLOAD                252
>> +#define ELS_OPCODE_BYTE                      0x10
>> +
>>  /* BSG Vendor specific definations */
>>  #define A84_ISSUE_WRITE_TYPE_CMD        0
>>  #define A84_ISSUE_READ_TYPE_CMD         1
>> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
>> index 8396109..4d8a7b9 100644
>> --- a/drivers/scsi/qla2xxx/qla_def.h
>> +++ b/drivers/scsi/qla2xxx/qla_def.h
>> @@ -713,6 +713,8 @@ typedef struct {
>>  #define MBC_SEND_RNFT_ELS            0x5e    /* Send RNFT ELS request */
>>  #define MBC_GET_LINK_PRIV_STATS              0x6d    /* Get link & private
>> data. */
>>  #define MBC_SET_VENDOR_ID            0x76    /* Set Vendor ID. */
>> +#define MBC_SET_PORT_CONFIG          0x122   /* Set port configuration */
>> +#define MBC_GET_PORT_CONFIG          0x123   /* Get port configuration */
>> 
>>  /* Firmware return data sizes */
>>  #define FCAL_MAP_SIZE        128
>> @@ -2630,6 +2632,8 @@ struct qla_hw_data {
>>       struct mutex vport_lock;        /* Virtual port synchronization */
>>       struct completion mbx_cmd_comp; /* Serialize mbx access */
>>       struct completion mbx_intr_comp;  /* Used for completion notification
>> */
>> +     struct completion dcbx_comp;    /* For set port config notification */
>> +     int notify_dcbx_comp;
>> 
>>       /* Basic firmware related information. */
>>       uint16_t        fw_major_version;
>> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
>> index 8217c3b..6ff36f1 100644
>> --- a/drivers/scsi/qla2xxx/qla_gbl.h
>> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
>> @@ -357,6 +357,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t,
>> uint32_t);
>>  extern int qla2x00_get_data_rate(scsi_qla_host_t *);
>>  extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
>>       uint16_t *);
>> +extern int
>> +qla81xx_get_port_config(scsi_qla_host_t *, uint16_t *);
>> +
>> +extern int
>> +qla81xx_set_port_config(scsi_qla_host_t *, uint16_t *);
>> 
>>  /*
>>   * Global Function Prototypes in qla_isr.c source file.
>> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
>> index be3d8be..2fe0250 100644
>> --- a/drivers/scsi/qla2xxx/qla_isr.c
>> +++ b/drivers/scsi/qla2xxx/qla_isr.c
>> @@ -545,10 +545,13 @@ skip_rio:
>>               if (IS_QLA2100(ha))
>>                       break;
>> 
>> -             if (IS_QLA8XXX_TYPE(ha))
>> +             if (IS_QLA8XXX_TYPE(ha)) {
>>                       DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
>>                           "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
>> -             else
>> +                     if (ha->notify_dcbx_comp)
>> +                             complete(&ha->dcbx_comp);
>> +
>> +             } else
>>                       DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
>>                           "received.\n", vha->host_no));
>> 
>> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
>> index f3650d0..f593afa 100644
>> --- a/drivers/scsi/qla2xxx/qla_mbx.c
>> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
>> @@ -3950,6 +3950,72 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
>>  }
>> 
>>  int
>> +qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
>> +{
>> +     int rval;
>> +     mbx_cmd_t mc;
>> +     mbx_cmd_t *mcp = &mc;
>> +     struct qla_hw_data *ha = vha->hw;
>> +
>> +     DEBUG11(printk(KERN_INFO
>> +         "%s(%ld): entered.\n", __func__, vha->host_no));
>> +
>> +     if (!IS_QLA81XX(ha))
>> +             return QLA_FUNCTION_FAILED;
>> +     mcp->mb[0] = MBC_GET_PORT_CONFIG;
>> +     mcp->out_mb = MBX_0;
>> +     mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
>> +     mcp->tov = MBX_TOV_SECONDS;
>> +     mcp->flags = 0;
>> +
>> +     rval = qla2x00_mailbox_command(vha, mcp);
>> +
>> +     if (rval != QLA_SUCCESS) {
>> +             DEBUG2_3_11(printk(KERN_WARNING
>> +                 "%s(%ld): failed=%x (%x).\n", __func__,
>> +                 vha->host_no, rval, mcp->mb[0]));
>> +     } else {
>> +             /* Copy all bits to preserve original value */
>> +             memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
>> +
>> +             DEBUG11(printk(KERN_INFO
>> +                 "%s(%ld): done.\n", __func__, vha->host_no));
>> +     }
>> +     return rval;
>> +}
>> +
>> +int
>> +qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
>> +{
>> +     int rval;
>> +     mbx_cmd_t mc;
>> +     mbx_cmd_t *mcp = &mc;
>> +
>> +     DEBUG11(printk(KERN_INFO
>> +         "%s(%ld): entered.\n", __func__, vha->host_no));
>> +
>> +     mcp->mb[0] = MBC_SET_PORT_CONFIG;
>> +     /* Copy all bits to preserve original setting */
>> +     memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
>> +     mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
>> +     mcp->in_mb = MBX_0;
>> +     mcp->tov = MBX_TOV_SECONDS;
>> +     mcp->flags = 0;
>> +     rval = qla2x00_mailbox_command(vha, mcp);
>> +
>> +     if (rval != QLA_SUCCESS) {
>> +             DEBUG2_3_11(printk(KERN_WARNING
>> +                 "%s(%ld): failed=%x (%x).\n", __func__,
>> +                 vha->host_no, rval, mcp->mb[0]));
>> +     } else
>> +             DEBUG11(printk(KERN_INFO
>> +                 "%s(%ld): done.\n", __func__, vha->host_no));
>> +
>> +     return rval;
>> +}
>> +
>> +
>> +int
>>  qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t
>> priority,
>>               uint16_t *mb)
>>  {
>> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
>> index be1a8fc..58e6102 100644
>> --- a/drivers/scsi/qla2xxx/qla_os.c
>> +++ b/drivers/scsi/qla2xxx/qla_os.c
>> @@ -2113,6 +2113,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct
>> pci_device_id *id)
>>       init_completion(&ha->mbx_cmd_comp);
>>       complete(&ha->mbx_cmd_comp);
>>       init_completion(&ha->mbx_intr_comp);
>> +     init_completion(&ha->dcbx_comp);
>> 
>>       set_bit(0, (unsigned long *) ha->vp_idx_map);
>> 
>> --
>> 1.6.2.rc1.30.gd43c
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

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

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

end of thread, other threads:[~2010-05-17 21:51 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-04 22:01 [PATCH 00/16] qla2xxx: Updates for scsi-misc-2.6 giridhar.malavali
2010-05-04 22:01 ` [PATCH 01/16] qla2xxx: Check for ISP84xx before processing to get 84xx firmware version giridhar.malavali
2010-05-04 22:01 ` [PATCH 02/16] qla2xxx: Display proper link state for disconnected ports giridhar.malavali
2010-05-04 22:01 ` [PATCH 03/16] qla2xxx: Clear error status after uncorrectable non-fatal errors giridhar.malavali
2010-05-04 22:01 ` [PATCH 04/16] qla2xxx: Add char device to increase driver use count giridhar.malavali
2010-05-04 22:01 ` [PATCH 05/16] qla2xxx: Further generalization of SRB CTX infrastructure giridhar.malavali
2010-05-04 22:01 ` [PATCH 06/16] qla2xxx: Limit mailbox command contention for ADISC requests giridhar.malavali
2010-05-04 22:01 ` [PATCH 07/16] qla2xxx: Cleanup FCP-command-status processing debug statements giridhar.malavali
2010-05-04 22:01 ` [PATCH 08/16] qla2xxx: Provide common framework for BSG and IOCB commands giridhar.malavali
2010-05-04 22:01 ` [PATCH 09/16] qla2xxx: Support for asynchronous TM and Marker IOCBs giridhar.malavali
2010-05-04 22:01 ` [PATCH 10/16] qla2xxx: T10 DIF support added giridhar.malavali
2010-05-04 22:01 ` [PATCH 11/16] qla2xxx: Silence bogus warning by gcc for wrap and did giridhar.malavali
2010-05-04 22:01 ` [PATCH 12/16] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive giridhar.malavali
2010-05-04 22:01 ` [PATCH 13/16] qla2xxx: Optionally disable target reset giridhar.malavali
2010-05-04 22:01 ` [PATCH 14/16] qla2xxx: Updates to ISP82xx support giridhar.malavali
2010-05-04 22:01 ` [PATCH 15/16] qla2xxx: Add internal loopback support for 81XX giridhar.malavali
2010-05-16 22:30   ` James Bottomley
2010-05-17 21:50     ` Giridhar Malavali
2010-05-04 22:01 ` [PATCH 16/16] qla2xxx: Update version number to 8.03.03-k0 giridhar.malavali

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.