Sophie

Sophie

distrib > CentOS > 5 > i386 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 4592

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

From: Chad Dupuis <cdupuis@redhat.com>
Date: Tue, 20 Jul 2010 14:43:39 -0400
Subject: [scsi] qla2xxx: add support for ISP82XX
Message-id: <20100720144246.2739.42585.sendpatchset@localhost.localdomain>
Patchwork-id: 26958
O-Subject: [RHEL 5.6 PATCH v2 3/5] qla2xxx: Add support for ISP82XX.
Bugzilla: 567428

Bugzilla
========

567428

Upstream Status
===============

mainline commit id a9083016a5314b3aeba6e0d2e814872e72168c08

Description
===========

This is a resend of the original patch.

This patch adds the initial support for the QLogic QLA82XX CNA adapter family.
This particular patch is to support the FCoE PCI function.  This patch has been
reworked to look as similar as possible to the upstream code but there is some
functionality that is upstream that won't be backported to RHEL 5.  This
functionality includes:

- Multiple queue support
- CPU affinity dedication
- Asynchronous logins

The other patches in the original patchset will apply cleanly with the new
patch.

Brew Build
==========

2608634

Testing
=======

The reworked patch was tested internally at QLogic and was test built against
the 2.6.18-207.el5 RHEL 5 kernel.

>From aa4005576a04c4781c96cf75a147dc66ec7b303c Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Mon, 12 Jul 2010 12:43:01 +0530
Subject: [PATCH] qla2xxx: Add support for ISP82XX.

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index af8486f..c72f155 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,7 +1,7 @@
 EXTRA_CFLAGS += -DNETLINK_FCTRANSPORT=20
 
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
-		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_nlnk.o ql2100_fw.o \
+		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_nlnk.o qla_nx.o ql2100_fw.o \
 		ql2200_fw.o ql2300_fw.o ql2322_fw.o ql2400_fw.o ql2500_fw.o
 
 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 1bfb503..f99a033 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -40,6 +40,12 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
 	    struct device, kobj)));
 	int reading;
 
+	if (IS_QLA82XX(ha)) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "Firmware dump not supported for ISP82xx\n"));
+		return count;
+	}
+
 	if (off != 0)
 		return (0);
 
@@ -87,6 +93,7 @@ static struct bin_attribute sysfs_fw_dump_attr = {
 
 #define        RESET_FC_FW                     0x2025c
 #define        RESET_MPI                       0x2025d
+#define        RESET_FCOE_CTX                  0x2025e
 
 static ssize_t
 qla2x00_sysfs_write_reset(struct kobject *kobj, char *buf, loff_t off,
@@ -135,7 +142,22 @@ qla2x00_sysfs_write_reset(struct kobject *kobj, char *buf, loff_t off,
 		}		
 		 scsi_unblock_requests(ha->host);
 		break;
+	case RESET_FCOE_CTX:
+		if (!IS_QLA82XX(ha) || ha != pha) {
+			qla_printk(KERN_INFO, ha,
+			    "FCoE ctx reset not supported for host%ld.\n",
+			    ha->host_no);
+			return count;
+		}
+
+		qla_printk(KERN_INFO, ha,
+		    "Issuing FCoE CTX reset on host%ld.\n", ha->host_no);
+		set_bit(FCOE_CTX_RESET_NEEDED, &ha->dpc_flags);
+		qla2xxx_wake_dpc(ha);
+		qla2x00_wait_for_fcoe_ctx_reset(ha);
+		break;
 	}
+
 	return (count);
 }
 
@@ -381,7 +403,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
 		    start == (ha->flt_region_fw * 4))
 			valid = 1;
 		else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
-		    IS_QLA81XX(ha))
+		    IS_QLA8XXX_TYPE(ha))
 			valid = 1;
 		if (!valid) {
 			qla_printk(KERN_WARNING, ha,
@@ -600,8 +622,12 @@ qla2x00_wait_for_passthru_completion(struct scsi_qla_host *ha)
 	    timeout)) {
 		DEBUG2(qla_printk(KERN_WARNING, ha,
 		    "Passthru request timed out.\n"));
-		ha->isp_ops->fw_dump(ha, 0);
-		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+		if (IS_QLA82XX(ha)) {
+			set_bit(FCOE_CTX_RESET_NEEDED, &ha->dpc_flags);
+		} else {
+			ha->isp_ops->fw_dump(ha, 0);
+			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+		}
 		qla2xxx_wake_dpc(ha);
 		ha->pass_thru_cmd_result = 0;
 		ha->pass_thru_cmd_in_process = 0;
@@ -650,6 +676,15 @@ qla2x00_sysfs_write_els(struct kobject *kobj, char *buf, loff_t off,
 	    atomic_read(&ha->loop_state) != LOOP_READY)
 		goto els_error0;
 
+	if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
+	    test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+	    test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
+		DEBUG2_3_11(qla_printk(KERN_INFO, ha,
+		    "%s(%ld): isp reset in progress.\n",
+		    __func__, ha->host_no));
+		goto els_error0;
+	}
+
 	if (count < sizeof(request->ct_iu)) {
 		DEBUG2(qla_printk(KERN_WARNING, ha,
 		    "Passthru ELS buffer insufficient size %zu...\n", count));
@@ -704,7 +739,7 @@ qla2x00_sysfs_write_els(struct kobject *kobj, char *buf, loff_t off,
 	els_iocb->vp_index = ha->vp_idx;
 	els_iocb->sof_type = EST_SOFI3;
 	els_iocb->rx_dsd_count = __constant_cpu_to_le16(1);
-	els_iocb->opcode = 0;
+	els_iocb->opcode = ha->pass_thru[0];
 	els_iocb->port_id[0] = fcport->d_id.b.al_pa;
 	els_iocb->port_id[1] = fcport->d_id.b.area;
 	els_iocb->port_id[2] = fcport->d_id.b.domain;
@@ -778,6 +813,15 @@ qla2x00_sysfs_write_ct(struct kobject *kobj, char *buf, loff_t off,
 	ms_iocb_entry_t *ct_iocb_2G = NULL;
 	unsigned long flags;
 
+	if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
+	    test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+	    test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
+		DEBUG2_3_11(qla_printk(KERN_INFO, ha,
+		    "%s(%ld): isp reset in progress.\n",
+		    __func__, ha->host_no));
+		goto ct_error0;
+	}
+
 	if (atomic_read(&ha->loop_state) != LOOP_READY)
 		goto ct_error0;
 
@@ -1119,7 +1163,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
 			continue;
 		if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha))
 			continue;
-		if (iter->is4GBp_only == 3 && !IS_QLA81XX(ha))
+		if (iter->is4GBp_only == 3 && !(IS_QLA8XXX_TYPE(ha)))
 			continue;
 
 		ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
@@ -1142,7 +1186,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
 			continue;
 		if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha))
 			continue;
-		if (iter->is4GBp_only == 3 && !IS_QLA81XX(ha))
+		if (iter->is4GBp_only == 3 && !(IS_QLA8XXX_TYPE(ha)))
 			continue;
 
 		sysfs_remove_bin_file(&host->shost_gendev.kobj,
@@ -1837,10 +1881,10 @@ qla2x00_vlan_id_show(struct class_device *cdev, char *buf)
 {
 	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
 
-        if (!IS_QLA81XX(ha))
-                return snprintf(buf, PAGE_SIZE, "\n");
+	if (!IS_QLA8XXX_TYPE(ha))
+		return snprintf(buf, PAGE_SIZE, "\n");
 
-        return snprintf(buf, PAGE_SIZE, "%d\n", ha->fcoe_vlan_id);
+	return snprintf(buf, PAGE_SIZE, "%d\n", ha->fcoe_vlan_id);
 }
 
 static ssize_t
@@ -1848,13 +1892,14 @@ qla2x00_vn_port_mac_address_show(struct class_device *cdev, char *buf)
 {
 	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
 
-        if (!IS_QLA81XX(ha))
+	if (!IS_QLA8XXX_TYPE(ha))
                 return snprintf(buf, PAGE_SIZE, "\n");
 
-        return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
-            ha->fcoe_vn_port_mac[5], ha->fcoe_vn_port_mac[4],
-            ha->fcoe_vn_port_mac[3], ha->fcoe_vn_port_mac[2],
-            ha->fcoe_vn_port_mac[1], ha->fcoe_vn_port_mac[0]);
+	return snprintf(buf, PAGE_SIZE,
+	    "%02x:%02x:%02x:%02x:%02x:%02x\n",
+	    ha->fcoe_vn_port_mac[5], ha->fcoe_vn_port_mac[4],
+	    ha->fcoe_vn_port_mac[3], ha->fcoe_vn_port_mac[2],
+	    ha->fcoe_vn_port_mac[1], ha->fcoe_vn_port_mac[0]);
 }
 
 static ssize_t
@@ -1877,7 +1922,7 @@ qla2x00_fw_state_show(struct class_device *cdev, char *buf)
 		test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags))
 		DEBUG2_3_11(qla_printk(KERN_INFO, ha,
 		    "%s(%ld): isp reset in progress.\n",
-			__func__, ha->host_no));
+		    __func__, ha->host_no));
 	else if (!ha->flags.eeh_busy)
 		rval = qla2x00_get_firmware_state(pha, state);
 
@@ -2414,7 +2459,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha)
 	fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
 	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
 
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		speed = FC_PORTSPEED_10GBIT;
 	else if (IS_QLA25XX(ha))
 		speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index de00f3b..86b40ee 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -802,6 +802,9 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 	uint32_t	ext_mem_cnt;
 	void		*nxt;
 
+	if (IS_QLA82XX(ha))
+		return;
+
 	risc_address = ext_mem_cnt = 0;
 	flags = 0;
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 940c140..dc09132 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -33,6 +33,8 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_transport_fc.h>
 
+#include "qla_nx.h"
+
 #define QLA2XXX_DRIVER_NAME  "qla2xxx"
 
 /*
@@ -264,6 +266,22 @@ typedef struct {
 #define REQUEST_ENTRY_CNT_24XX		4096	/* Number of request entries. */
 #define RESPONSE_ENTRY_CNT_2100		64	/* Number of response entries.*/
 #define RESPONSE_ENTRY_CNT_2300		512	/* Number of response entries.*/
+#define REQUEST_ENTRY_CNT_82XX		128	/* Number of request entries. */
+
+struct fcp_cmnd {
+	struct scsi_lun lun;
+	uint8_t crn;
+	uint8_t task_attribute;
+	uint8_t task_managment;
+	uint8_t additional_cdb_len;
+	uint8_t cdb[260]; /* 256 for CDB len and 4 for FCP_DL */
+};
+
+struct dsd_dma {
+	struct list_head list;
+	dma_addr_t dsd_list_dma;
+	void *dsd_addr;
+};
 
 /*
  * SCSI Request Block
@@ -281,6 +299,7 @@ typedef struct srb {
 
 	uint32_t request_sense_length;
 	uint8_t *request_sense_ptr;
+	void *ctx;
 } srb_t;
 
 /*
@@ -300,6 +319,19 @@ typedef struct srb {
 #define SRB_FO_CANCEL		BIT_9	/* Command don't need to do failover */
 #define SRB_IOCTL		BIT_10	/* IOCTL command. */
 #define SRB_TAPE		BIT_11	/* FCP2 (Tape) command. */
+#define SRB_FCP_CMND_DMA_VALID	BIT_12	/* FCP command in IOCB */
+
+
+#define QLA_DSDS_PER_IOCB	37
+#define QLA_DSD_SIZE		12
+struct ct6_dsd {
+	uint16_t fcp_cmnd_len;
+	dma_addr_t fcp_cmnd_dma;
+	struct fcp_cmnd *fcp_cmnd;
+	int dsd_use_cnt;
+	struct list_head dsd_list;
+};
+
 
 /*
  * ISP I/O Register Set structure definitions.
@@ -459,6 +491,7 @@ struct device_reg_2xxx {
 typedef union {
 		struct device_reg_2xxx isp;
 		struct device_reg_24xx isp24;
+		struct device_reg_82xx isp82;
 } device_reg_t;
 
 #define ISP_REQ_Q_IN(ha, reg) \
@@ -715,6 +748,9 @@ typedef struct {
 #define MBC_RESTART_MPI_FW      	0x03d	/* Reset MPI */
 #define MBC_FLASH_ACCESS_CTRL		0x3e    /* Control flash access. */
 
+#define MBC_TOGGLE_INTERRUPT		0x10	/* 82XX specific enable/disable
+						 *  interrupts */
+
 /* Flash access control option field bit definitions */
 #define FAC_OPT_FORCE_SEMAPHORE         BIT_15
 #define FAC_OPT_REQUESTOR_ID            BIT_14
@@ -2207,6 +2243,9 @@ struct isp_operations {
 		uint32_t);
 
 	int (*get_flash_version) (struct scsi_qla_host *, void *);
+	int (*abort_isp) (struct scsi_qla_host *);
+	int (*alloc_sp_pool) (struct scsi_qla_host *);
+	void (*free_sp_pool) (struct scsi_qla_host *);
 };
 
 /* MSI-X Support *************************************************************/
@@ -2349,23 +2388,25 @@ typedef struct scsi_qla_host {
 #define LOOP_DEAD	6
 
 	unsigned long   dpc_flags;
-#define	RESET_MARKER_NEEDED	0	/* Send marker to ISP. */
-#define	RESET_ACTIVE		1
-#define	ISP_ABORT_NEEDED	2	/* Initiate ISP abort. */
-#define	ABORT_ISP_ACTIVE	3	/* ISP abort in progress. */
-#define	LOOP_RESYNC_NEEDED	4	/* Device Resync needed. */
-#define	LOOP_RESYNC_ACTIVE	5
-#define LOCAL_LOOP_UPDATE       6	/* Perform a local loop update. */
-#define RSCN_UPDATE             7	/* Perform an RSCN update. */
-#define RELOGIN_NEEDED	       	8
+#define RESET_MARKER_NEEDED	0	/* Send marker to ISP. */
+#define RESET_ACTIVE		1
+#define ISP_ABORT_NEEDED	2	/* Initiate ISP abort. */
+#define ABORT_ISP_ACTIVE	3	/* ISP abort in progress. */
+#define LOOP_RESYNC_NEEDED	4	/* Device Resync needed. */
+#define LOOP_RESYNC_ACTIVE	5
+#define LOCAL_LOOP_UPDATE	6	/* Perform a local loop update. */
+#define RSCN_UPDATE		7	/* Perform an RSCN update. */
+#define RELOGIN_NEEDED		8
 #define REGISTER_FC4_NEEDED	9	/* SNS FC4 registration required. */
-#define ISP_ABORT_RETRY         10      /* ISP aborted. */
+#define ISP_ABORT_RETRY		10	/* ISP aborted. */
 #define BEACON_BLINK_NEEDED	11
 #define REGISTER_FDMI_NEEDED	12
 #define FCPORT_UPDATE_NEEDED	13
 #define VP_DPC_NEEDED		14	/* wake up for VP dpc handling */
 #define UNLOADING		15
 #define NPIV_CONFIG_NEEDED	16
+#define ISP_UNRECOVERABLE	17
+#define FCOE_CTX_RESET_NEEDED	18	/* Initiate FCoE context reset */
 
 	uint32_t	device_flags;
 #define DFLG_LOCAL_DEVICES		BIT_0
@@ -2373,10 +2414,12 @@ typedef struct scsi_qla_host {
 #define DFLG_FABRIC_DEVICES		BIT_2
 #define	SWITCH_FOUND			BIT_3
 #define	DFLG_NO_CABLE			BIT_4
+#define	DFLG_DEV_FAILED			BIT_5
 
 #define PCI_DEVICE_ID_QLOGIC_ISP2532	0x2532
 #define PCI_DEVICE_ID_QLOGIC_ISP8432	0x8432
 #define PCI_DEVICE_ID_QLOGIC_ISP8001	0x8001
+#define PCI_DEVICE_ID_QLOGIC_ISP8021	0x8021
 	uint32_t	device_type;
 #define DT_ISP2100			BIT_0
 #define DT_ISP2200			BIT_1
@@ -2392,7 +2435,8 @@ typedef struct scsi_qla_host {
 #define DT_ISP2532			BIT_11
 #define DT_ISP8432			BIT_12
 #define DT_ISP8001			BIT_13
-#define DT_ISP_LAST			(DT_ISP8001 << 1)
+#define DT_ISP8021                     	BIT_14
+#define DT_ISP_LAST                    (DT_ISP8021 << 1)
 
 #define DT_IIDMA			BIT_26
 #define DT_FWI2				BIT_27
@@ -2416,6 +2460,7 @@ typedef struct scsi_qla_host {
 #define IS_QLA2532(ha)	(DT_MASK(ha) & DT_ISP2532)
 #define IS_QLA8432(ha)	(DT_MASK(ha) & DT_ISP8432)
 #define IS_QLA8001(ha)	(DT_MASK(ha) & DT_ISP8001)
+#define IS_QLA82XX(ha) 	(DT_MASK(ha) & DT_ISP8021)
 
 #define IS_QLA23XX(ha)	(IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
     			 IS_QLA6312(ha) || IS_QLA6322(ha))
@@ -2426,8 +2471,9 @@ typedef struct scsi_qla_host {
 #define IS_QLA24XX_TYPE(ha)    (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
 				IS_QLA84XX(ha))
 #define IS_QLA81XX(ha)	(IS_QLA8001(ha))
+#define IS_QLA8XXX_TYPE(ha)	(IS_QLA81XX(ha) || IS_QLA82XX(ha))
 #define IS_QLA2XXX_MIDTYPE(ha)  (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
-				IS_QLA25XX(ha) || IS_QLA81XX(ha))
+				IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
 
 #define IS_NOCACHE_VPD_TYPE(ha)	(IS_QLA81XX(ha))
 #define IS_FAC_REQUIRED(ha)     (IS_QLA81XX(ha))
@@ -2593,6 +2639,14 @@ typedef struct scsi_qla_host {
 #define DMA_POOL_SIZE	256
 	struct dma_pool *s_dma_pool;
 
+#define DSD_LIST_DMA_POOL_SIZE	512
+	struct dma_pool *dl_dma_pool;
+
+#define FCP_CMND_DMA_POOL_SIZE	512
+	struct dma_pool *fcp_cmnd_dma_pool;
+
+	mempool_t	*ctx_mempool;
+
 	dma_addr_t	init_cb_dma;
 	init_cb_t	*init_cb;
 	int		init_cb_size;
@@ -2718,6 +2772,7 @@ typedef struct scsi_qla_host {
 	uint32_t        flt_region_nvram;
 	uint32_t	flt_region_npiv_conf;
 	uint32_t	flt_region_gold_fw;
+	uint32_t	flt_region_bootload;
 	uint32_t	flt_region_fcp_prio;
 
 	/* Needed for BEACON */
@@ -2788,6 +2843,30 @@ typedef struct scsi_qla_host {
 	struct qla_statistics qla_stats;
 	struct qlfc_fw fw_buf;
 	struct qla_loopback loopback_buf;
+
+	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 */
+
+	uint32_t crb_win;
+	uint32_t curr_window;
+	uint32_t ddr_mn_window;
+	unsigned long mn_win_crb;
+	unsigned long ms_win_crb;
+	int	qdr_sn_window;
+	uint32_t	nx_dev_init_timeout;
+	uint32_t	nx_reset_timeout;
+	rwlock_t hw_lock;
+	uint16_t portnum; /* port number */
+	int link_width;
+	int fw_heartbeat_counter;
+	int seconds_since_last_heartbeat;
+	struct fw_blob *hablob;
+	struct qla82xx_legacy_intr_set nx_legacy_intr;
+#define	NUM_DSD_CHAIN	4096
+	uint16_t gbl_dsd_inuse;
+	uint16_t gbl_dsd_avail;
+	struct list_head gbl_dsd_list;
 } scsi_qla_host_t;
 
 
@@ -2843,6 +2922,7 @@ typedef struct scsi_qla_host {
 #define OPTROM_SIZE_24XX	0x100000
 #define OPTROM_SIZE_25XX	0x200000
 #define OPTROM_SIZE_81XX	0x400000
+#define OPTROM_SIZE_82XX	0x800000
 
 #include "qla_gbl.h"
 #include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 01da1db..52d7399 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -960,6 +960,29 @@ struct device_reg_24xx {
 	uint32_t iobase_sdata;
 };
 
+/*
+ * ISP 8021 I/O Register Set structure definitions.
+ */
+struct device_reg_82xx {
+	uint32_t req_q_out[64];		/* Request Queue out-Pointer (64 * 4) */
+	uint32_t rsp_q_in[64];		/* Response Queue In-Pointer. */
+	uint32_t rsp_q_out[64];		/* Response Queue Out-Pointer. */
+
+	uint16_t mailbox_in[32];	/* Mail box In registers */
+	uint16_t unused_1[32];
+	uint32_t hint;			/* Host interrupt register */
+#define	HINT_MBX_INT_PENDING	BIT_0
+	uint16_t unused_2[62];
+	uint16_t mailbox_out[32];	/* Mail box Out registers */
+	uint32_t unused_3[48];
+
+	uint32_t host_status;		/* host status */
+#define HSRX_RISC_INT		BIT_15  /* RISC to Host interrupt. */
+#define HSRX_RISC_PAUSED	BIT_8   /* RISC Paused. */
+	uint32_t host_int;		/* Interrupt status. */
+#define ISRX_82XX_RISC_INT	BIT_0	/* RISC interrupt. */
+};
+
 /* MID Support ***************************************************************/
 
 #define MIN_MULTI_ID_FABRIC	64	/* Must be power-of-2. */
@@ -1068,9 +1091,9 @@ struct vp_config_entry_24xx {
 	uint32_t handle;		/* System handle. */
 
 	uint16_t flags;
-#define CS_VF_BIND_VPORTS_TO_VF		BIT_0
-#define CS_VF_SET_QOS_OF_VPORTS		BIT_1
-#define CS_VF_SET_HOPS_OF_VPORTS	BIT_2
+#define CS_VF_BIND_VPORTS_TO_VF         BIT_0
+#define CS_VF_SET_QOS_OF_VPORTS         BIT_1
+#define CS_VF_SET_HOPS_OF_VPORTS        BIT_2
 
 	uint16_t comp_status;		/* Completion status. */
 #define CS_VCT_STS_ERROR	0x01	/* Specified VPs were not disabled. */
@@ -1220,6 +1243,15 @@ struct qla_flt_header {
 #define FLT_REG_FCP_PRIO_0	0x87
 #define FLT_REG_FCP_PRIO_1	0x88
 
+/* 82XX */
+#define FLT_REG_BOOTLOAD_82xx	0x72
+#define FLT_REG_BOOT_CODE_82xx	0x78
+#define FLT_REG_FW_82xx		0x74
+#define FLT_REG_GOLD_FW_82xx	0x75
+#define FLT_REG_VPD_82xx	0x81
+
+#define	FA_VPD_SIZE_82xx	0x400
+
 struct qla_flt_region {
 	uint32_t code;
 	uint32_t size;
@@ -1742,4 +1774,7 @@ struct ex_init_cb_81xx {
 
 /* 81XX Support end **********************************************************/
 
+#define FA_FLASH_LAYOUT_ADDR_82	0xFC400
+
+
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 68622ad..cad79c0 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -46,6 +46,7 @@ extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
 extern void qla2x00_update_fcports(scsi_qla_host_t *);
 
 extern int qla2x00_abort_isp(scsi_qla_host_t *);
+extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *);
 
 extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
 extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
@@ -80,6 +81,9 @@ extern int ql2xenablemsix;
 extern int ql2xetsenable;
 extern int ql2xfwloadbin;
 extern int num_hosts;
+extern int ql2xshiftctondsd;
+extern int ql2xdbwr;
+extern int ql2xdontresethba;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -121,6 +125,7 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
 
 extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
 extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *);
+extern int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *);
 
 extern void qla2xxx_wake_dpc(scsi_qla_host_t *);
 extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *);
@@ -437,4 +442,64 @@ extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t);
  */
 extern fc_port_t *qla2x00_find_port(struct scsi_qla_host *, uint8_t *);
 
+extern int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *);
+/* qla82xx related functions */
+
+/* PCI related functions */
+extern int qla82xx_pci_config(struct scsi_qla_host *);
+extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *);
+extern int qla82xx_iospace_config(scsi_qla_host_t *);
+
+
+/* Initialization related functions */
+extern void qla82xx_reset_chip(struct scsi_qla_host *);
+extern void qla82xx_config_rings(struct scsi_qla_host *);
+extern void qla82xx_reset_adapter(struct scsi_qla_host *);
+extern void qla82xx_watchdog(scsi_qla_host_t *);
+
+/* Firmware and flash related functions */
+extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
+extern uint8_t *qla82xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+    uint32_t, uint32_t);
+extern int qla82xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+    uint32_t, uint32_t);
+extern int qla82xx_erase_sector(scsi_qla_host_t *, int);
+extern int qla82xx_unprotect_flash(scsi_qla_host_t *);
+extern int qla82xx_protect_flash(scsi_qla_host_t *);
+extern int qla82xx_write_flash_dword(scsi_qla_host_t *, uint32_t,
+     uint32_t data);
+
+extern int qla82xx_abort_isp(scsi_qla_host_t *);
+extern int qla82xx_restart_isp(scsi_qla_host_t *);
+
+/* IOCB related functions */
+extern int qla82xx_start_scsi(srb_t *);
+
+/* Interrupt related */
+extern irqreturn_t qla82xx_intr_handler(int, void *, struct pt_regs *);
+extern irqreturn_t qla82xx_msi_handler(int, void *, struct pt_regs *);
+extern irqreturn_t qla82xx_msix_default(int, void *, struct pt_regs *);
+extern irqreturn_t qla82xx_msix_rsp_q(int, void *, struct pt_regs *);
+extern void qla82xx_enable_intrs(struct scsi_qla_host *);
+extern void qla82xx_disable_intrs(struct scsi_qla_host *);
+extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
+extern void qla82xx_poll(int, void *, struct pt_regs *);
+extern void qla82xx_init_flags(struct scsi_qla_host *);
+
+/* ISP 8021 hardware related */
+extern int qla82xx_wr_32(scsi_qla_host_t *, ulong, u32);
+extern int qla82xx_rd_32(scsi_qla_host_t *, ulong);
+extern int qla82xx_rom_fast_read(scsi_qla_host_t *, int , int*);
+
+/* ISP 8021 IDC */
+extern void qla82xx_clear_drv_active(scsi_qla_host_t *);
+extern int qla82xx_idc_lock(scsi_qla_host_t *);
+extern void qla82xx_idc_unlock(scsi_qla_host_t *);
+extern int qla82xx_device_state_handler(scsi_qla_host_t *);
+
+extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *,
+    size_t, char *);
+extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
+extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
+extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
 #endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index b3d50b4..8096228 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1534,7 +1534,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
 	eiter->len = __constant_cpu_to_be16(4 + 4);
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		eiter->a.sup_speed = __constant_cpu_to_be32(
 		    FDMI_PORT_SPEED_10GB);
 	else if (IS_QLA25XX(ha))
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 1365b35..a2691df 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,6 +8,7 @@
 
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
+#include <linux/version.h>
 
 #include "qla_devtbl.h"
 
@@ -141,6 +142,16 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 	rval = qla2x00_init_rings(ha);
 	ha->flags.chip_reset_done = 1;
 
+	rval = qla2x00_get_fw_version(ha,
+	    &ha->fw_major_version,
+	    &ha->fw_minor_version,
+	    &ha->fw_subminor_version,
+	    &ha->fw_attributes, &ha->fw_memory_size,
+	    ha->mpi_version, &ha->mpi_capabilities,
+	    ha->phy_version);
+	if (rval != QLA_SUCCESS)
+		return QLA_FUNCTION_FAILED;
+
 	if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
 		/* Issue verify 84xx FW IOCB to complete 84xx initialization */
 		rval = qla84xx_init_chip(ha);
@@ -789,16 +800,21 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
 
 	ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
 
-	rval = qla2x00_mbx_reg_test(ha);
-	if (rval) {
-		DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",
-		    ha->host_no));
-		qla_printk(KERN_WARNING, ha,
-		    "Failed mailbox send register test\n");
-	} else {
-		/* Flag a successful rval */
+	/* Avoid for ISP82XX - until firmware intializes */
+	if (!IS_QLA82XX(ha)) {
+		rval = qla2x00_mbx_reg_test(ha);
+		if (rval) {
+			DEBUG(printk(KERN_WARNING
+			    "scsi(%ld): Failed mailbox send register"
+			    "test\n", ha->host_no));
+			qla_printk(KERN_WARNING, ha,
+			    "Failed mailbox send register test\n");
+		} else {
+			/* Flag a successful rval */
+			rval = QLA_SUCCESS;
+		}
+	} else
 		rval = QLA_SUCCESS;
-	}
 
 	return rval;
 }
@@ -927,6 +943,8 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha)
 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 		return;
 
+	if (IS_QLA82XX(ha))
+		request_q_length = REQUEST_ENTRY_CNT_82XX;
 	/* Retrieve IOCB counts available to the firmware. */
 	rval = qla2x00_get_resource_cnts(ha, NULL, &ha->fw_xcb_count, NULL,
 	    &fw_iocb_cnt, &ha->max_npiv_vports);
@@ -1050,21 +1068,26 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
 
 	/* Load firmware sequences */
 	rval = ha->isp_ops->load_risc(ha, &srisc_address);
+	if (IS_QLA82XX(ha))
+		goto enable_82xx_npiv;
+
 	if (rval == QLA_SUCCESS) {
 		DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC "
 		    "code.\n", ha->host_no));
 
 		rval = qla2x00_verify_checksum(ha, srisc_address);
+
 		if (rval == QLA_SUCCESS) {
 			/* Start firmware execution. */
 			DEBUG(printk("scsi(%ld): Checksum OK, start "
 			    "firmware.\n", ha->host_no));
 
 			rval = qla2x00_execute_fw(ha, srisc_address);
+enable_82xx_npiv:
 			/* Retrieve firmware information. */
 			if (rval == QLA_SUCCESS) {
 				fw_major_version = ha->fw_major_version;
-			
+
 				rval = qla2x00_get_fw_version(ha,
 				    &ha->fw_major_version,
 				    &ha->fw_minor_version,
@@ -1077,7 +1100,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
 
 				ha->flags.npiv_supported = 0;
 				if ((IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
-				    IS_QLA84XX(ha) || IS_QLA81XX(ha)) &&
+				    IS_QLA84XX(ha) || IS_QLA8XXX_TYPE(ha)) &&
 				    (ha->fw_attributes & BIT_2)) {
 					ha->flags.npiv_supported = 1;
 					if ((!ha->max_npiv_vports) ||
@@ -1089,8 +1112,8 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
 
 				if (fw_major_version == 0) {
 					qla2x00_resize_request_q(ha);
-
-					if (ql2xallocfwdump)
+					/* TODO: FW Dump support for 82XX */
+					if (!IS_QLA82XX(ha) && ql2xallocfwdump)
 						qla2x00_alloc_fw_dump(ha);
 				}
 			}
@@ -1363,7 +1386,7 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
 		    ha->host_no));
 	}
 
-	return (rval);
+	return rval;
 }
 
 /**
@@ -1605,13 +1628,13 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
 	return(rval);
 }
 
-static inline void
+inline void
 qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def)
 {
 	char *st, *en;
 	uint16_t index;
 	int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
-	    !IS_QLA81XX(ha);
+	    !IS_QLA8XXX_TYPE(ha);
 
 	if (memcmp(model, BINZERO, len) != 0) {
 		strncpy(ha->model_number, model, len);
@@ -2331,7 +2354,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
 	if (fcport->port_type == FCT_TARGET)
 		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
 	fc_remote_port_rolechg(rport, rport_ids.roles);
-
 }
 
 /*
@@ -3444,6 +3466,49 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
 			qla2x00_rport_del(fcport);
 }
 
+void
+qla2x00_abort_isp_cleanup(scsi_qla_host_t *ha)
+{
+
+	scsi_qla_host_t *vha, *tmp_vha;
+	ha->flags.online = 0;
+	ha->flags.chip_reset_done = 0;
+	clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+	ha->qla_stats.total_isp_aborts++;
+
+	qla_printk(KERN_INFO, ha,
+	    "Performing ISP error recovery - ha= %p.\n", ha);
+	/* For ISP82XX reset_chip is not applicable */
+	if (!IS_QLA82XX(ha))
+		ha->isp_ops->reset_chip(ha);
+
+	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+	if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
+		atomic_set(&ha->loop_state, LOOP_DOWN);
+		qla2x00_mark_all_devices_lost(ha, 0);
+		list_for_each_entry_safe(vha, tmp_vha, &ha->vp_list, vp_list)
+			qla2x00_mark_all_devices_lost(vha, 0);
+
+	} else {
+		if (!atomic_read(&ha->loop_down_timer))
+			atomic_set(&ha->loop_down_timer,
+			    LOOP_DOWN_TIME);
+	}
+
+	/* Make sure for ISP 82XX IO DMA is complete */
+	if (IS_QLA82XX(ha)) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "Waiting for pending commands\n"));
+		qla2x00_eh_wait_for_pending_commands(ha);
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "Done wait for pending commands\n"));
+	}
+
+	/* Requeue all commands in outstanding command list. */
+	qla2x00_abort_all_cmds(ha, DID_RESET << 16);
+}
+
+
 /*
 *  qla2x00_abort_isp
 *      Resets ISP and aborts all outstanding commands.
@@ -3462,27 +3527,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 	scsi_qla_host_t *vha;
 
 	if (ha->flags.online) {
-		ha->flags.online = 0;
-		ha->flags.chip_reset_done = 0;
-		clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-		ha->qla_stats.total_isp_aborts++;
-
-		qla_printk(KERN_INFO, ha,
-		    "Performing ISP error recovery - ha= %p.\n", ha);
-		ha->isp_ops->reset_chip(ha);
-
-		atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
-		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
-			atomic_set(&ha->loop_state, LOOP_DOWN);
-			qla2x00_mark_all_devices_lost(ha, 0);
-		} else {
-			if (!atomic_read(&ha->loop_down_timer))
-				atomic_set(&ha->loop_down_timer,
-				    LOOP_DOWN_TIME);
-		}
-
-		/* Requeue all commands in outstanding command list. */
-		qla2x00_abort_all_cmds(ha, DID_RESET << 16);
+		qla2x00_abort_isp_cleanup(ha);
 
 		if (pci_channel_offline(ha->pdev) &&
 		    ha->flags.pci_channel_io_perm_failure) {
@@ -3937,7 +3982,6 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr,
 	uint32_t risc_addr;
 	uint32_t risc_size;
 	uint32_t i;
-
 	rval = QLA_SUCCESS;
 
 	segments = FA_RISC_CODE_SEGMENTS;
@@ -4413,12 +4457,18 @@ qla81xx_nvram_config(scsi_qla_host_t *ha)
 	/* Determine NVRAM starting address. */
 	ha->nvram_size = sizeof(struct nvram_81xx);
 	ha->vpd_size = FA_NVRAM_VPD_SIZE;
+	if (IS_QLA82XX(ha))
+		ha->vpd_size = FA_VPD_SIZE_82xx;
 
 	/* Get VPD data into cache */
 	ha->vpd = ha->nvram + VPD_OFFSET;
 	ha->isp_ops->read_optrom(ha, (uint8_t *)ha->vpd,
 	    ha->flt_region_vpd << 2, ha->vpd_size);
 
+	DEBUG5(qla_printk(KERN_INFO, ha,
+	    "scsi(%ld): Contents of VPD\n", ha->host_no));
+	DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->vpd, ha->vpd_size));
+
 	/* Get NVRAM data into cache and calculate checksum. */
 	ha->isp_ops->read_optrom(ha, ha->nvram, ha->flt_region_nvram << 2,
 	    ha->nvram_size);
@@ -4478,7 +4528,7 @@ qla81xx_nvram_config(scsi_qla_host_t *ha)
 	 * Setup driver NVRAM options.
 	 */
 	qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name),
-	    "QLE81XX");
+	    "QLE8XXX");
 
 	/* Use alternate WWN? */
 	if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
@@ -4613,3 +4663,131 @@ qla81xx_update_fw_options(scsi_qla_host_t *ha)
 	ha->fw_options[2] |= BIT_9;
 	qla2x00_set_fw_options(ha, ha->fw_options);
 }
+
+/*
+*  qla82xx_fcoe_ctx_reset
+*      Perform a quick reset and aborts all outstanding commands.
+*      This will only perform an FCoE context reset and avoids a full blown
+*      chip reset.
+*
+* Input:
+*      ha = adapter block pointer.
+*
+* Returns:
+*      0 = success
+*/
+int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *ha)
+{
+	int rval = QLA_FUNCTION_FAILED;
+
+	if (ha->flags.online) {
+		/* Abort all outstanding commands, so as to be requeued later */
+		qla2x00_abort_isp_cleanup(ha);
+	}
+
+	/* Stop currently executing firmware.
+	 * This will destroy existing FCoE context at the F/W end.
+	 */
+	qla2x00_try_to_stop_firmware(ha);
+
+	/* Restart. Creates a new FCoE context on INIT_FIRMWARE. */
+	rval = qla82xx_restart_isp(ha);
+
+	return rval;
+}
+
+int
+qla82xx_restart_isp(scsi_qla_host_t *ha)
+{
+	int status, rval;
+	uint32_t wait_time;
+	scsi_qla_host_t *vha;
+
+	status = qla2x00_init_rings(ha);
+	if (!status) {
+		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+		ha->flags.chip_reset_done = 1;
+		status = qla2x00_fw_ready(ha);
+		if (!status) {
+			DEBUG(qla_printk(KERN_INFO, ha,
+			    "%s(): Start configure loop, "
+			    "status = %d\n", __func__, status));
+
+			/* Issue a marker after FW becomes ready. */
+			qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
+
+			ha->flags.online = 1;
+			/* Wait at most MAX_TARGET RSCNs for a stable link. */
+			wait_time = 256;
+			do {
+				clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+				qla2x00_configure_loop(ha);
+				wait_time--;
+			} while (!atomic_read(&ha->loop_down_timer) &&
+			    !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) &&
+			    wait_time &&
+			    (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)));
+		}
+
+		/* if no cable then assume it's good */
+		if ((ha->device_flags & DFLG_NO_CABLE))
+			status = 0;
+
+		DEBUG(qla_printk(KERN_INFO, ha,
+		    "%s(): Configure loop done, status = 0x%x\n",
+		    __func__, status));
+	}
+
+	if (!status) {
+		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+
+		if (!atomic_read(&ha->loop_down_timer)) {
+			/*
+			 * Issue marker command only when we are going
+			 * to start the I/O .
+			 */
+			ha->marker_needed = 1;
+		}
+
+		ha->flags.online = 1;
+
+		ha->isp_ops->enable_intrs(ha);
+
+		ha->isp_abort_cnt = 0;
+		clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
+
+		/* Update the FW versions */
+		qla2x00_get_fw_version(ha,
+		    &ha->fw_major_version,
+		    &ha->fw_minor_version,
+		    &ha->fw_subminor_version,
+		    &ha->fw_attributes, &ha->fw_memory_size,
+		    ha->mpi_version, &ha->mpi_capabilities,
+		    ha->phy_version);
+
+		if (ha->eft) {
+			memset(ha->eft, 0, EFT_SIZE);
+			rval = qla2x00_trace_control(ha, TC_ENABLE,
+			    ha->eft_dma, EFT_NUM_BUFFERS);
+			if (rval) {
+				qla_printk(KERN_WARNING, ha,
+				    "Unable to reinitialize EFT "
+				    "(%d).\n", rval);
+			}
+		}
+	}
+
+	if (!status) {
+		DEBUG(printk(KERN_INFO
+		    "qla82xx_restart_isp(%ld): succeeded.\n", ha->host_no));
+		list_for_each_entry(vha, &ha->vp_list, vp_list) {
+			if (vha->vp_idx)
+				qla2x00_vp_abort_isp(vha);
+		}
+	} else {
+		qla_printk(KERN_INFO, ha,
+		    "qla82xx_restart_isp: **** FAILED ****\n");
+	}
+
+	return status;
+}
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index be80aa3..577b1f4 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -104,7 +104,10 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *);
 static inline void
 qla2x00_poll(scsi_qla_host_t *ha)
 {
-	ha->isp_ops->intr_handler(0, ha, NULL);
+	if (IS_QLA82XX(ha))
+		qla82xx_poll(0, ha, NULL);
+	else
+		ha->isp_ops->intr_handler(0, ha, NULL);
 }
 
 static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 355ecca..f16e338 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -31,10 +31,10 @@ qla2x00_get_cmd_direction(srb_t *sp)
 	/* Set transfer direction */
 	if (sp->cmd->sc_data_direction == DMA_TO_DEVICE) {
 		cflags = CF_WRITE;
-		sp->ha->qla_stats.output_bytes += scsi_bufflen(sp->cmd); 
+		sp->ha->qla_stats.output_bytes += scsi_bufflen(sp->cmd);
 	} else if (sp->cmd->sc_data_direction == DMA_FROM_DEVICE) {
 		cflags = CF_READ;
-		sp->ha->qla_stats.input_bytes += scsi_bufflen(sp->cmd); 
+		sp->ha->qla_stats.input_bytes += scsi_bufflen(sp->cmd);
 	}
 	return (cflags);
 }
@@ -43,7 +43,7 @@ qla2x00_get_cmd_direction(srb_t *sp)
  * qla2x00_calc_iocbs_32() - Determine number of Command Type 2 and
  * Continuation Type 0 IOCBs to allocate.
  *
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
  *
  * Returns the number of IOCB entries needed to store @dsds.
  */
@@ -65,7 +65,7 @@ qla2x00_calc_iocbs_32(uint16_t dsds)
  * qla2x00_calc_iocbs_64() - Determine number of Command Type 3 and
  * Continuation Type 1 IOCBs to allocate.
  *
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
  *
  * Returns the number of IOCB entries needed to store @dsds.
  */
@@ -523,7 +523,10 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
 	for (timer = HZ; timer; timer--) {
 		if ((req_cnt + 2) >= ha->req_q_cnt) {
 			/* Calculate number of free request entries. */
-			if (IS_FWI2_CAPABLE(ha))
+			if (IS_QLA82XX(ha))
+				cnt = (uint16_t)RD_REG_DWORD(
+				    &reg->isp82.req_q_out);
+			else if (IS_FWI2_CAPABLE(ha))
 				cnt = (uint16_t)RD_REG_DWORD(
 				    &reg->isp24.req_q_out);
 			else
@@ -597,21 +600,39 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha)
 		ha->request_ring_ptr++;
 
 	/* Set chip new ring index. */
-	if (IS_FWI2_CAPABLE(ha)) {
+	if (IS_QLA82XX(ha)) {
+		uint32_t dbval = 0x04 | (ha->portnum << 5);
+
+		/* write, read and verify logic */
+		/* dbval = dbval | (req->id << 8) | (ha->ring_index << 16); */
+		dbval = dbval | (0 << 8) | (ha->req_ring_index << 16);
+		if (ql2xdbwr)
+			qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval);
+		else {
+			WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr,
+			    dbval);
+			wmb();
+			while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
+				WRT_REG_DWORD(
+				    (unsigned long  __iomem *)ha->nxdb_wr_ptr,
+				    dbval);
+				wmb();
+			}
+		}
+	} else if (IS_FWI2_CAPABLE(ha)) {
 		WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index);
 		RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
 	} else {
 		WRT_REG_WORD(ISP_REQ_Q_IN(ha, &reg->isp), ha->req_ring_index);
 		RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, &reg->isp));
 	}
-
 }
 
 /**
  * qla24xx_calc_iocbs() - Determine number of Command Type 3 and
  * Continuation Type 1 IOCBs to allocate.
  *
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
  *
  * Returns the number of IOCB entries needed to store @dsds.
  */
@@ -872,3 +893,446 @@ queuing_error:
 
 	return QLA_FUNCTION_FAILED;
 }
+
+static inline int
+qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
+    uint16_t tot_dsds)
+{
+	uint32_t	*cur_dsd = NULL;
+	scsi_qla_host_t	*ha;
+	struct scsi_cmnd *cmd;
+	struct	scatterlist *cur_seg;
+	uint32_t *dsd_seg;
+	void *next_dsd;
+	uint8_t avail_dsds;
+	uint8_t first_iocb = 1;
+	uint32_t dsd_list_len;
+	struct dsd_dma *dsd_ptr;
+	struct ct6_dsd *ctx;
+
+	cmd = sp->cmd;
+
+	*((uint32_t *)(&cmd_pkt->entry_type)) =
+	    __constant_cpu_to_le32(COMMAND_TYPE_6);
+
+	/* No data transfer */
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
+		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
+		return 0;
+	}
+
+	ha = sp->ha;
+
+	/* Set transfer direction */
+	if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+		cmd_pkt->control_flags =
+		    __constant_cpu_to_le16(CF_WRITE_DATA);
+		ha->qla_stats.output_bytes += scsi_bufflen(cmd);
+	} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		cmd_pkt->control_flags =
+		    __constant_cpu_to_le16(CF_READ_DATA);
+		ha->qla_stats.input_bytes += scsi_bufflen(cmd);
+	}
+
+	cur_seg = scsi_sglist(cmd);
+	ctx = sp->ctx;
+
+	while (tot_dsds) {
+		avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ?
+		    QLA_DSDS_PER_IOCB : tot_dsds;
+		tot_dsds -= avail_dsds;
+		dsd_list_len = (avail_dsds + 1) * QLA_DSD_SIZE;
+		dsd_ptr = list_first_entry(&ha->gbl_dsd_list,
+		    struct dsd_dma, list);
+		next_dsd = dsd_ptr->dsd_addr;
+		list_del(&dsd_ptr->list);
+		ha->gbl_dsd_avail--;
+		list_add_tail(&dsd_ptr->list, &ctx->dsd_list);
+
+		ctx->dsd_use_cnt++;
+		ha->gbl_dsd_inuse++;
+
+		if (first_iocb) {
+			first_iocb = 0;
+			dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
+			*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+			*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+			*dsd_seg++ = dsd_list_len;
+		} else {
+			*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;
+		while (avail_dsds) {
+			dma_addr_t	sle_dma;
+
+			sle_dma = sg_dma_address(cur_seg);
+			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
+			cur_seg++;
+			avail_dsds--;
+		}
+	}
+
+	/* Null termination */
+	*cur_dsd++ =  0;
+	*cur_dsd++ = 0;
+	*cur_dsd++ = 0;
+	cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE;
+	return 0;
+}
+
+/*
+ * qla82xx_calc_dsd_lists() - Determine number of DSD list required
+ * for Command Type 6.
+ *
+ * @dsds: number of data segment descriptors needed
+ *
+ * Returns the number of dsd list needed to store @dsds.
+ */
+inline uint16_t
+qla82xx_calc_dsd_lists(uint16_t dsds)
+{
+	uint16_t dsd_lists = 0;
+
+	dsd_lists = dsds / QLA_DSDS_PER_IOCB;
+	if (dsds % QLA_DSDS_PER_IOCB)
+		dsd_lists++;
+	return dsd_lists;
+}
+
+
+/**
+ * qla82xx_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
+qla82xx_start_scsi(srb_t *sp)
+{
+	int		ret;
+	unsigned long   flags;
+	scsi_qla_host_t	*ha;
+	struct scsi_cmnd *cmd;
+	uint32_t	*clr_ptr;
+	uint32_t        index;
+	uint32_t	handle;
+	struct scatterlist *sg;
+	uint16_t	cnt;
+	uint16_t	req_cnt;
+	uint16_t	tot_dsds;
+	struct device_reg_82xx __iomem *reg;
+	uint32_t dbval;
+	uint32_t *fcp_dl;
+	uint8_t additional_cdb_len;
+	struct ct6_dsd *ctx;
+
+	/* Setup device pointers. */
+	ret = 0;
+	ha = sp->ha;
+	reg = &ha->iobase->isp82;
+	cmd = sp->cmd;
+	/* So we know we haven't pci_map'ed anything yet */
+	tot_dsds = 0;
+
+	dbval = 0x04 | (ha->portnum << 5);
+
+	/* Send marker if required */
+	if (ha->marker_needed != 0) {
+		if (qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS)
+			return QLA_FUNCTION_FAILED;
+		ha->marker_needed = 0;
+	}
+
+	/* Acquire ring specific lock */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	/* Check for room in outstanding command list. */
+	handle = ha->current_outstanding_cmd;
+	for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+		handle++;
+		if (handle == MAX_OUTSTANDING_COMMANDS)
+			handle = 1;
+		if (!ha->outstanding_cmds[handle])
+			break;
+	}
+	if (index == MAX_OUTSTANDING_COMMANDS)
+		goto queuing_error;
+
+	/* Map the sg table so we have an accurate count of sg entries needed */
+	if (scsi_sg_count(cmd)) {
+		sg = scsi_sglist(cmd);
+		tot_dsds = pci_map_sg(ha->pdev, sg, scsi_sg_count(cmd),
+		    cmd->sc_data_direction);
+		if (tot_dsds == 0)
+			goto queuing_error;
+	} else if (scsi_bufflen(cmd)) {
+		dma_addr_t      req_dma;
+
+		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
+		    scsi_bufflen(cmd), cmd->sc_data_direction);
+		if (dma_mapping_error(req_dma))
+			goto queuing_error;
+
+		sp->dma_handle = req_dma;
+		tot_dsds = 1;
+	}
+
+	if (tot_dsds > ql2xshiftctondsd) {
+		struct cmd_type_6 *cmd_pkt;
+		uint16_t more_dsd_lists = 0;
+		struct dsd_dma *dsd_ptr;
+		uint16_t i;
+
+		more_dsd_lists = qla82xx_calc_dsd_lists(tot_dsds);
+
+		if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN)
+			goto queuing_error;
+
+		if (more_dsd_lists <= ha->gbl_dsd_avail)
+			goto sufficient_dsds;
+		else
+			more_dsd_lists -= ha->gbl_dsd_avail;
+
+		for (i = 0; i < more_dsd_lists; i++) {
+			dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
+			if (!dsd_ptr)
+				goto queuing_error;
+
+			dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool,
+			    GFP_ATOMIC, &dsd_ptr->dsd_list_dma);
+			if (!dsd_ptr->dsd_addr) {
+				kfree(dsd_ptr);
+				goto queuing_error;
+			}
+			list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list);
+			ha->gbl_dsd_avail++;
+		}
+
+sufficient_dsds:
+		req_cnt = 1;
+
+		ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
+		if (!sp->ctx) {
+			DEBUG2_3(qla_printk(KERN_ERR, ha,
+			    "%s(%ld): failed to allocate ctx.\n", __func__,
+			    ha->host_no));
+			goto queuing_error;
+		}
+		memset(ctx, 0, sizeof(struct ct6_dsd));
+		ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool,
+			    GFP_ATOMIC, &ctx->fcp_cmnd_dma);
+		if (!ctx->fcp_cmnd) {
+			DEBUG2_3(qla_printk(KERN_ERR, ha,
+			    "%s(%ld): failed to allocate"
+			    " fcp_cmnd.\n", __func__, ha->host_no));
+			goto queuing_error;
+		}
+
+		/* Initialize the DSD list and dma handle */
+		INIT_LIST_HEAD(&ctx->dsd_list);
+		sp->dma_handle = 0;
+		ctx->dsd_use_cnt = 0;
+
+		if (cmd->cmd_len > 16) {
+			additional_cdb_len = cmd->cmd_len - 16;
+			if ((cmd->cmd_len % 4) != 0) {
+				/* SCSI command bigger than 16 bytes must be
+				 * multiple of 4
+				 */
+				goto queuing_error_fcp_cmnd;
+			}
+			ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;
+		} else {
+			additional_cdb_len = 0;
+			ctx->fcp_cmnd_len = 12 + 16 + 4;
+		}
+
+		cmd_pkt = (struct cmd_type_6 *)ha->request_ring_ptr;
+
+		/* Zero out remaining portion of packet. */
+		/*    tagged queuing modifier -- default is TSK_SIMPLE (0). */
+		clr_ptr = (uint32_t *)cmd_pkt + 2;
+		memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
+		cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
+		cmd_pkt->handle = handle;
+
+		/* Build IOCB segments */
+		if (qla2xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds))
+			goto queuing_error_fcp_cmnd;
+
+		int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+
+		/* build FCP_CMND IU */
+		memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+		int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun);
+		ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
+
+		if (cmd->sc_data_direction == DMA_TO_DEVICE)
+			ctx->fcp_cmnd->additional_cdb_len |= 1;
+		else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+			ctx->fcp_cmnd->additional_cdb_len |= 2;
+
+		memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
+
+		fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 +
+		    additional_cdb_len);
+		*fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));
+
+		cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len);
+		cmd_pkt->fcp_cmnd_dseg_address[0] =
+		    cpu_to_le32(LSD(ctx->fcp_cmnd_dma));
+		cmd_pkt->fcp_cmnd_dseg_address[1] =
+		    cpu_to_le32(MSD(ctx->fcp_cmnd_dma));
+
+		sp->flags |= SRB_FCP_CMND_DMA_VALID;
+		cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
+
+		/* 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;
+		cmd_pkt->vp_index = sp->fcport->vp_idx;
+
+		/* Set total data segment count. */
+		cmd_pkt->entry_count = (uint8_t)req_cnt;
+#ifdef QL_DEBUG_LEVEL_3
+		{
+			int i;
+			uint16_t *ptr = (struct cmd_type_6 *)cmd_pkt;
+			printk(KERN_INFO "Dump Command type 6 IOCB\n");
+			for (i = 0; i < sizeof(struct cmd_type_6)/2; i++) {
+				printk(KERN_INFO
+				    "CT6-IOCB[%x]: 0x%x\n", (i*2), *ptr);
+				ptr++;
+			}
+		}
+#endif
+	} else {
+		struct cmd_type_7 *cmd_pkt;
+		req_cnt = qla24xx_calc_iocbs(tot_dsds);
+		if (ha->req_q_cnt < (req_cnt + 2)) {
+			cnt = (uint16_t)RD_REG_DWORD_RELAXED(
+			    &reg->req_q_out[0]);
+			if (ha->req_ring_index < cnt)
+				ha->req_q_cnt = cnt - ha->req_ring_index;
+			else
+				ha->req_q_cnt = ha->request_q_length -
+					(ha->req_ring_index - cnt);
+		}
+		if (ha->req_q_cnt < (req_cnt + 2))
+			goto queuing_error;
+
+		cmd_pkt = (struct cmd_type_7 *)ha->request_ring_ptr;
+
+		/* Zero out remaining portion of packet. */
+		/* tagged queuing modifier -- default is TSK_SIMPLE (0).*/
+		clr_ptr = (uint32_t *)cmd_pkt + 2;
+		memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
+		cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
+		cmd_pkt->handle = handle;
+
+		int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+		host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
+		    sizeof(cmd_pkt->lun));
+
+		/* Load SCSI command packet. */
+		memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
+		host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
+
+		cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
+
+		/* Build IOCB segments */
+		qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds);
+
+		/* 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;
+		cmd_pkt->vp_index = sp->fcport->vp_idx;
+
+		/* Set total data segment count. */
+		cmd_pkt->entry_count = (uint8_t)req_cnt;
+#ifdef QL_DEBUG_LEVEL_3
+		{
+			int i;
+			uint16_t *ptr = (struct cmd_type_7 *)cmd_pkt;
+			printk(KERN_INFO "Dump Command type 7 IOCB\n");
+			for (i = 0; i < sizeof(struct cmd_type_7)/2; i++) {
+				printk(KERN_INFO
+				    "CT7-IOCB[%x]: 0x%x\n", (i * 2), *ptr);
+				ptr++;
+			}
+		}
+#endif
+	}
+
+	/* Build command packet. */
+	ha->current_outstanding_cmd = handle;
+	ha->outstanding_cmds[handle] = sp;
+	sp->ha = ha;
+	sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
+	ha->req_q_cnt -= req_cnt;
+	wmb();
+
+	/* Adjust ring index. */
+	ha->req_ring_index++;
+	if (ha->req_ring_index == ha->request_q_length) {
+		ha->req_ring_index = 0;
+		ha->request_ring_ptr = ha->request_ring;
+	} else
+		ha->request_ring_ptr++;
+
+	sp->flags |= SRB_DMA_VALID;
+
+	/* Set chip new ring index. */
+	/* write, read and verify logic */
+	/* dbval = dbval | (req->id << 8) | (ha->ring_index << 16); */
+	/* TODO - hardcoded the request queue ID to 0 -
+	 * Need to pass proper value
+	 */
+	dbval = dbval | (0 << 8) | (ha->req_ring_index << 16);
+	if (ql2xdbwr)
+		qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval);
+	else {
+		WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval);
+		wmb();
+		while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
+			WRT_REG_DWORD((unsigned long  __iomem *)ha->nxdb_wr_ptr,
+			    dbval);
+			wmb();
+		}
+	}
+
+	/* Manage unprocessed RIO/ZIO commands in response queue. */
+	if (ha->flags.process_response_queue &&
+	    ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
+		qla24xx_process_response_queue(ha);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	return QLA_SUCCESS;
+
+queuing_error_fcp_cmnd:
+	dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma);
+queuing_error:
+	if (scsi_sg_count(cmd) && tot_dsds) {
+		sg = scsi_sglist(cmd);
+		pci_unmap_sg(ha->pdev, sg, scsi_sg_count(cmd),
+		    cmd->sc_data_direction);
+	} else if (tot_dsds) {
+		pci_unmap_single(ha->pdev, sp->dma_handle,
+		    scsi_bufflen(cmd), cmd->sc_data_direction);
+	}
+	if (sp->ctx) {
+		mempool_free(sp->ctx, ha->ctx_mempool);
+		sp->ctx = NULL;
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return QLA_FUNCTION_FAILED;
+}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 6b9430e..1972fe2 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -322,7 +322,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
 	/* Setup to process RIO completion. */
 	handle_cnt = 0;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		goto skip_rio;
 	switch (mb[0]) {
 	case MBA_SCSI_COMPLETION:
@@ -516,7 +516,7 @@ skip_rio:
 		if (IS_QLA2100(ha))
 			break;
 
-		if (IS_QLA81XX(ha)) {
+		if (IS_QLA8XXX_TYPE(ha)) {
 			DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
 			    "%04x\n", ha->host_no, mb[1], mb[2], mb[3]));
 			if (ha->notify_dcbx_comp)
@@ -1569,7 +1569,11 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
 	}
 
 	/* Adjust ring index */
-	WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
+	if (IS_QLA82XX(ha)) {
+		struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
+		WRT_REG_DWORD(&reg->rsp_q_out[0], ha->rsp_ring_index);
+	} else
+		WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
 }
 
 static void
@@ -1865,7 +1869,7 @@ struct qla_init_msix_entry {
 	irq_handler_t handler;
 };
 
-static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
+static struct qla_init_msix_entry qla24xx_msix_entries[QLA_MSIX_ENTRIES] = {
 	{ QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
 		"qla2xxx (default)", qla24xx_msix_default },
 
@@ -1873,6 +1877,14 @@ static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
 		"qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
 };
 
+static struct qla_init_msix_entry qla82xx_msix_entries[QLA_MSIX_ENTRIES] = {
+	{ QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
+		"qla2xxx (default)", qla82xx_msix_default },
+
+	{ QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q,
+		"qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
+};
+
 static void
 qla24xx_disable_msix(scsi_qla_host_t *ha)
 {
@@ -1880,7 +1892,13 @@ qla24xx_disable_msix(scsi_qla_host_t *ha)
 	struct qla_msix_entry *qentry;
 
 	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
-		qentry = &ha->msix_entries[imsix_entries[i].index];
+		if (IS_QLA82XX(ha))
+			qentry =
+			    &ha->msix_entries[qla82xx_msix_entries[i].index];
+		else
+			qentry =
+			    &ha->msix_entries[qla24xx_msix_entries[i].index];
+
 		if (qentry->have_irq)
 			free_irq(qentry->msix_vector, ha);
 	}
@@ -1894,8 +1912,12 @@ qla24xx_enable_msix(scsi_qla_host_t *ha)
 	struct msix_entry entries[QLA_MSIX_ENTRIES];
 	struct qla_msix_entry *qentry;
 
-	for (i = 0; i < QLA_MSIX_ENTRIES; i++)
-		entries[i].entry = imsix_entries[i].entry;
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
+		if (IS_QLA82XX(ha))
+			entries[i].entry = qla82xx_msix_entries[i].entry;
+		else
+			entries[i].entry = qla24xx_msix_entries[i].entry;
+	}
 
 	ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
 	if (ret) {
@@ -1907,16 +1929,28 @@ qla24xx_enable_msix(scsi_qla_host_t *ha)
 	ha->flags.msix_enabled = 1;
 
 	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
-		qentry = &ha->msix_entries[imsix_entries[i].index];
+		if (IS_QLA82XX(ha))
+			qentry =
+			    &ha->msix_entries[qla82xx_msix_entries[i].index];
+		else
+			qentry =
+			    &ha->msix_entries[qla24xx_msix_entries[i].index];
 		qentry->msix_vector = entries[i].vector;
 		qentry->msix_entry = entries[i].entry;
 		qentry->have_irq = 0;
-		ret = request_irq(qentry->msix_vector,
-		    imsix_entries[i].handler, 0, imsix_entries[i].name, ha);
+		if (IS_QLA82XX(ha)) {
+			ret = request_irq(qentry->msix_vector,
+			    qla82xx_msix_entries[i].handler, 0,
+			    qla82xx_msix_entries[i].name, ha);
+		} else {
+			ret = request_irq(qentry->msix_vector,
+			    qla24xx_msix_entries[i].handler, 0,
+			    qla24xx_msix_entries[i].name, ha);
+		}
 		if (ret) {
 			qla_printk(KERN_WARNING, ha,
 			    "MSI-X: Unable to register handler -- %x/%d.\n",
-			    imsix_entries[i].index, ret);
+			    qla24xx_msix_entries[i].index, ret);
 			qla24xx_disable_msix(ha);
 			goto msix_out;
 		}
@@ -1934,7 +1968,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
 
 	/* If possible, enable MSI-X, MSI. */
 	if ( ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha)
-	    && !IS_QLA8432(ha) && !IS_QLA8001(ha)))
+	    && !IS_QLA8432(ha) && !IS_QLA8XXX_TYPE(ha)))
 		goto skip_msi;
 
 	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
@@ -1995,7 +2029,6 @@ skip_msi:
 void
 qla2x00_free_irqs(scsi_qla_host_t *ha)
 {
-
 	if (ha->flags.msix_enabled)
 		qla24xx_disable_msix(ha);
 	else if (ha->flags.msi_enabled) {
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 8c88b04..17560a8 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -57,6 +57,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 			     "Exiting.\n", __func__, ha->host_no));
 		return QLA_FUNCTION_TIMEOUT;
 	}
+
+	if (ha->device_flags & DFLG_DEV_FAILED) {
+		DEBUG(qla_printk(KERN_ERR, ha,
+		    "%s(%ld): Device in failed state, timeout MBX "
+		     "Exiting.\n", __func__, ha->host_no));
+		return QLA_FUNCTION_TIMEOUT;
+	}
+
 	/*
 	 * Wait for active mailbox commands to finish by waiting at most tov
 	 * seconds. This is to serialize actual issuing of mailbox cmds during
@@ -80,7 +88,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
 	/* Load mailbox registers. */
-	if (IS_FWI2_CAPABLE(ha))
+	if (IS_QLA82XX(ha))
+		optr = (uint16_t __iomem *)&reg->isp82.mailbox_in[0];
+	else if (IS_FWI2_CAPABLE(ha) && !IS_QLA82XX(ha))
 		optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
 	else
 		optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
@@ -125,10 +135,20 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 	/* Wait for mbx cmd completion until timeout */
 
 	if (!abort_active && io_lock_on) {
-
 		set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
-		if (IS_FWI2_CAPABLE(ha))
+		if (IS_QLA82XX(ha)) {
+			if (RD_REG_DWORD(&reg->isp82.hint) &
+			    HINT_MBX_INT_PENDING) {
+				spin_unlock_irqrestore(
+				    &ha->hardware_lock, flags);
+				DEBUG2_3_11(printk(KERN_INFO
+				    "%s(%ld): Pending Mailbox timeout. "
+				    "Exiting.\n", __func__, ha->host_no));
+				return QLA_FUNCTION_TIMEOUT;
+			}
+			WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
+		} else if (IS_FWI2_CAPABLE(ha))
 			WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
 		else
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@@ -141,8 +161,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 	} else {
 		DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
 		    ha->host_no, command));
-
-		if (IS_FWI2_CAPABLE(ha))
+		if (IS_QLA82XX(ha)) {
+			if (RD_REG_DWORD(&reg->isp82.hint) &
+			    HINT_MBX_INT_PENDING) {
+				spin_unlock_irqrestore(
+				    &ha->hardware_lock, flags);
+				DEBUG2_3_11(printk(KERN_INFO
+				    "%s(%ld): Pending Mailbox timeout. "
+				    "Exiting.\n", __func__, ha->host_no));
+				return QLA_FUNCTION_TIMEOUT;
+			}
+			WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
+		} else if (IS_FWI2_CAPABLE(ha))
 			WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
 		else
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@@ -173,7 +203,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 
 		DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__,
 		    ha->host_no, command));
-
 		/* Got interrupt. Clear the flag. */
 		ha->flags.mbox_int = 0;
 		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
@@ -258,7 +287,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 
 			set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
 			clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-			if (qla2x00_abort_isp(ha)) {
+			if (ha->isp_ops->abort_isp(ha)) {
 				/* Failed. retry later. */
 				set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
 			}
@@ -294,7 +323,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
 
 	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
-	if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
+	if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha) || IS_QLA82XX(ha)) {
 		mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
 		mcp->mb[8] = MSW(risc_addr);
 		mcp->out_mb = MBX_8|MBX_0;
@@ -912,7 +941,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
 	mcp->mb[9] = ha->vp_idx;
 	mcp->out_mb = MBX_9|MBX_0;
 	mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
 
 	mcp->tov = 30;
@@ -937,7 +966,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
 		/*EMPTY*/
 		DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
 		    ha->host_no));
-		if (IS_QLA81XX(ha)) {
+		if (IS_QLA8XXX_TYPE(ha)) {
                         ha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
                         ha->fcoe_fcf_idx = mcp->mb[10];
                         ha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8;
@@ -947,7 +976,6 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
                         ha->fcoe_vn_port_mac[1] = mcp->mb[13] >> 8;
                         ha->fcoe_vn_port_mac[0] = mcp->mb[13] & 0xff;
                 }
-
 	}
 
 	return rval;
@@ -1035,6 +1063,10 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
 	DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
 	    ha->host_no));
 
+	if (IS_QLA82XX(ha) && ql2xdbwr)
+		qla82xx_wr_32(ha, ha->nxdb_wr_ptr,
+		    (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16)));
+
 	if (ha->flags.npiv_supported)
 		mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
 	else
@@ -1370,7 +1402,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
 
 	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
-	if (IS_QLA81XX(ha)) {
+	if (IS_QLA8XXX_TYPE(ha)) {
 		/* Logout across all FCFs. */
 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
 		mcp->mb[1] = BIT_1;
@@ -1863,7 +1895,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
 	mbx_cmd_t mc;
 	mbx_cmd_t *mcp = &mc;
 
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		return QLA_SUCCESS;
 
 	DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
@@ -2572,7 +2604,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
 	mcp->mb[0] = MBC_PORT_PARAMS;
 	mcp->mb[1] = loop_id;
 	mcp->mb[2] = BIT_0;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0);
 	else
 		mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0);
@@ -3156,7 +3188,7 @@ qla81xx_get_xgmac_stats(scsi_qla_host_t *ha, uint32_t len,
 	mbx_cmd_t mc;
 	mbx_cmd_t *mcp = &mc;
 
-	if (!IS_QLA81XX(ha))
+	if (!IS_QLA8XXX_TYPE(ha))
 		return QLA_FUNCTION_FAILED;
 
 	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
@@ -3371,8 +3403,8 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *ha, dma_addr_t tlv_dma,
         mbx_cmd_t mc;
         mbx_cmd_t *mcp = &mc;
 
-        if (!IS_QLA81XX(ha))
-                return QLA_FUNCTION_FAILED;
+	if (!IS_QLA8XXX_TYPE(ha))
+		return QLA_FUNCTION_FAILED;
 
         DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
@@ -3416,7 +3448,7 @@ qla2x00_loopback_test(scsi_qla_host_t *ha, struct msg_loopback *req,
 
 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
 	mcp->mb[1] = req->options | BIT_6;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->mb[2] = 0;
 	mcp->mb[10] = LSW(req->tx_cnt);
 	mcp->mb[11] = MSW(req->tx_cnt);
@@ -3432,7 +3464,7 @@ qla2x00_loopback_test(scsi_qla_host_t *ha, struct msg_loopback *req,
 	mcp->mb[19] = MSW(req->iter_cnt);
 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->out_mb |= MBX_2;
 
 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
@@ -3466,9 +3498,9 @@ qla2x00_echo_test(scsi_qla_host_t *ha, struct msg_loopback *req,
 
 	mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
 	mcp->mb[1] = BIT_6;
-	if (IS_QLA81XX(ha)) {
+	if (IS_QLA8XXX_TYPE(ha)) {
 		mcp->mb[1] |= BIT_15;
-		mcp->mb[2] |= 0;
+		mcp->mb[2] |= ha->fcoe_fcf_idx;
 	}
 	mcp->mb[10] = req->tx_cnt;
 	mcp->mb[14] = LSW(ha->loopback_buf.loopback_dma);
@@ -3481,13 +3513,13 @@ qla2x00_echo_test(scsi_qla_host_t *ha, struct msg_loopback *req,
 	mcp->mb[7] = MSW(MSD(ha->loopback_buf.loopback_dma));
 	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
 	   MBX_7|MBX_6|MBX_1|MBX_0;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->out_mb |= MBX_2;
 
 	mcp->in_mb = MBX_0;
-	if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
+	if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
 		mcp->in_mb |= MBX_1;
-	if (IS_QLA81XX(ha))
+	if (IS_QLA8XXX_TYPE(ha))
 		mcp->in_mb |= MBX_3;
 
 	mcp->buf_size = req->tx_cnt;
@@ -3540,7 +3572,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *ha, uint32_t risc_addr, uint32_t *data)
 	return rval;
 }
 
-	int
+int
 qla2x00_write_ram_word(scsi_qla_host_t *ha, uint32_t risc_addr, uint32_t data)
 {
 	int rval;
@@ -3573,6 +3605,76 @@ qla2x00_write_ram_word(scsi_qla_host_t *ha, uint32_t risc_addr, uint32_t data)
 }
 
 int
+qla82xx_mbx_intr_enable(scsi_qla_host_t *ha)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	if (!IS_FWI2_CAPABLE(ha))
+		return QLA_FUNCTION_FAILED;
+
+	DEBUG11(qla_printk(KERN_INFO, ha,
+	    "%s(%ld): entered.\n", __func__, ha->host_no));
+
+	memset(mcp, 0, sizeof(mbx_cmd_t));
+	mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
+	mcp->mb[1] = 1; /* enable interrupt */
+
+	mcp->out_mb = MBX_1|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+
+	rval = qla2x00_mailbox_command(ha, mcp);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(qla_printk(KERN_ERR, ha,
+		    "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
+		    ha->host_no, rval, mcp->mb[0]));
+	} else {
+		DEBUG11(qla_printk(KERN_INFO, ha,
+		    "%s(%ld): done.\n", __func__, ha->host_no));
+	}
+
+	return rval;
+}
+
+int
+qla82xx_mbx_intr_disable(scsi_qla_host_t *ha)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	if (!IS_FWI2_CAPABLE(ha))
+		return QLA_FUNCTION_FAILED;
+
+	DEBUG11(qla_printk(KERN_INFO, ha,
+	    "%s(%ld): entered.\n", __func__, ha->host_no));
+
+	memset(mcp, 0, sizeof(mbx_cmd_t));
+	mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
+	mcp->mb[1] = 0; /* disable interrupt */
+
+	mcp->out_mb = MBX_1|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+
+	rval = qla2x00_mailbox_command(ha, mcp);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(qla_printk(KERN_ERR, ha,
+		    "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
+		    ha->host_no, rval, mcp->mb[0]));
+	} else {
+		DEBUG11(qla_printk(KERN_INFO, ha,
+		    "%s(%ld): done.\n", __func__, ha->host_no));
+	}
+
+	return rval;
+}
+
+int
 qla2x00_get_data_rate(scsi_qla_host_t *ha)
 {
 	int rval;
diff --git a/drivers/scsi/qla2xxx/qla_nlnk.c b/drivers/scsi/qla2xxx/qla_nlnk.c
index 4429a71..a25665a 100644
--- a/drivers/scsi/qla2xxx/qla_nlnk.c
+++ b/drivers/scsi/qla2xxx/qla_nlnk.c
@@ -941,8 +941,8 @@ ql_fc_proc_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int rcvlen)
 	/* Use existing 84xx interface to get MPI XGMAC statistics for
 	 * 81xx via FC interface
 	 */
-	if ((!IS_QLA81XX(ha) && !IS_QLA84XX(ha)) ||
-	    (IS_QLA81XX(ha) && (ql_cmd->cmd != QLA84_MGMT_CMD))) {
+	if ((!IS_QLA8XXX_TYPE(ha) && !IS_QLA84XX(ha)) ||
+	    (IS_QLA8XXX_TYPE(ha) && (ql_cmd->cmd != QLA84_MGMT_CMD))) {
 		DEBUG16(printk(KERN_ERR "%s: invalid host ha = %p"
 		    "dtype = 0x%x\n", __func__, ha, (ha ? DT_MASK(ha): ~0)));
 		err = -ENODEV;
@@ -977,7 +977,7 @@ ql_fc_proc_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int rcvlen)
 				(rcvlen - sizeof(struct scsi_nl_hdr)),
 				NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
 				(uint32_t)nlh->nlmsg_type);
-		else if (IS_QLA81XX(ha))
+		else if (IS_QLA8XXX_TYPE(ha))
 			err = qla81xx_mgmt_cmd(ha, ql_cmd,
 				(rcvlen - sizeof(struct scsi_nl_hdr)),
 				NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
new file mode 100644
index 0000000..d4aadd6
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -0,0 +1,2708 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include "qla_def.h"
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#define MASK(n)			((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define MS_WIN(addr) (addr & 0x0ffc0000)
+#define QLA82XX_PCI_MN_2M   (0)
+#define QLA82XX_PCI_MS_2M   (0x80000)
+#define QLA82XX_PCI_OCM0_2M (0xc0000)
+#define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800)
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+
+/* CRB window related */
+#define CRB_BLK(off)	((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off)	((off >> 16) & 0xf)
+#define CRB_WINDOW_2M	(0x130060)
+#define QLA82XX_PCI_CAMQM_2M_END	(0x04800800UL)
+#define CRB_HI(off)	((qla82xx_crb_hub_agt[CRB_BLK(off)] << 20) | \
+			((off) & 0xf0000))
+#define QLA82XX_PCI_CAMQM_2M_BASE	(0x000ff800UL)
+#define CRB_INDIRECT_2M	(0x1e0000UL)
+
+#define MAX_CRB_XFORM 60
+static unsigned long crb_addr_xform[MAX_CRB_XFORM];
+int qla82xx_crb_table_initialized;
+
+#define qla82xx_crb_addr_transform(name) \
+		(crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \
+		QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20)
+
+static void qla82xx_crb_addr_transform_setup(void)
+{
+	qla82xx_crb_addr_transform(XDMA);
+	qla82xx_crb_addr_transform(TIMR);
+	qla82xx_crb_addr_transform(SRE);
+	qla82xx_crb_addr_transform(SQN3);
+	qla82xx_crb_addr_transform(SQN2);
+	qla82xx_crb_addr_transform(SQN1);
+	qla82xx_crb_addr_transform(SQN0);
+	qla82xx_crb_addr_transform(SQS3);
+	qla82xx_crb_addr_transform(SQS2);
+	qla82xx_crb_addr_transform(SQS1);
+	qla82xx_crb_addr_transform(SQS0);
+	qla82xx_crb_addr_transform(RPMX7);
+	qla82xx_crb_addr_transform(RPMX6);
+	qla82xx_crb_addr_transform(RPMX5);
+	qla82xx_crb_addr_transform(RPMX4);
+	qla82xx_crb_addr_transform(RPMX3);
+	qla82xx_crb_addr_transform(RPMX2);
+	qla82xx_crb_addr_transform(RPMX1);
+	qla82xx_crb_addr_transform(RPMX0);
+	qla82xx_crb_addr_transform(ROMUSB);
+	qla82xx_crb_addr_transform(SN);
+	qla82xx_crb_addr_transform(QMN);
+	qla82xx_crb_addr_transform(QMS);
+	qla82xx_crb_addr_transform(PGNI);
+	qla82xx_crb_addr_transform(PGND);
+	qla82xx_crb_addr_transform(PGN3);
+	qla82xx_crb_addr_transform(PGN2);
+	qla82xx_crb_addr_transform(PGN1);
+	qla82xx_crb_addr_transform(PGN0);
+	qla82xx_crb_addr_transform(PGSI);
+	qla82xx_crb_addr_transform(PGSD);
+	qla82xx_crb_addr_transform(PGS3);
+	qla82xx_crb_addr_transform(PGS2);
+	qla82xx_crb_addr_transform(PGS1);
+	qla82xx_crb_addr_transform(PGS0);
+	qla82xx_crb_addr_transform(PS);
+	qla82xx_crb_addr_transform(PH);
+	qla82xx_crb_addr_transform(NIU);
+	qla82xx_crb_addr_transform(I2Q);
+	qla82xx_crb_addr_transform(EG);
+	qla82xx_crb_addr_transform(MN);
+	qla82xx_crb_addr_transform(MS);
+	qla82xx_crb_addr_transform(CAS2);
+	qla82xx_crb_addr_transform(CAS1);
+	qla82xx_crb_addr_transform(CAS0);
+	qla82xx_crb_addr_transform(CAM);
+	qla82xx_crb_addr_transform(C2C1);
+	qla82xx_crb_addr_transform(C2C0);
+	qla82xx_crb_addr_transform(SMB);
+	qla82xx_crb_addr_transform(OCM0);
+	/*
+	 * Used only in P3 just define it for P2 also.
+	 */
+	qla82xx_crb_addr_transform(I2C0);
+
+	qla82xx_crb_table_initialized = 1;
+}
+
+struct crb_128M_2M_block_map crb_128M_2M_map[64] = {
+    {{{0, 0,         0,         0} } },		/* 0: PCI */
+    {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */
+	  {1, 0x0110000, 0x0120000, 0x130000},
+	  {1, 0x0120000, 0x0122000, 0x124000},
+	  {1, 0x0130000, 0x0132000, 0x126000},
+	  {1, 0x0140000, 0x0142000, 0x128000},
+	  {1, 0x0150000, 0x0152000, 0x12a000},
+	  {1, 0x0160000, 0x0170000, 0x110000},
+	  {1, 0x0170000, 0x0172000, 0x12e000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {1, 0x01e0000, 0x01e0800, 0x122000},
+	  {0, 0x0000000, 0x0000000, 0x000000} } },
+	{{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+    {{{0, 0,         0,         0} } },	    /* 3: */
+    {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+    {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE   */
+    {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU   */
+    {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM    */
+    {{{1, 0x0800000, 0x0802000, 0x170000},  /* 8: SQM0  */
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x08f0000, 0x08f2000, 0x172000} } },
+    {{{1, 0x0900000, 0x0902000, 0x174000},	/* 9: SQM1*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x09f0000, 0x09f2000, 0x176000} } },
+    {{{0, 0x0a00000, 0x0a02000, 0x178000},	/* 10: SQM2*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+    {{{0, 0x0b00000, 0x0b02000, 0x17c000},	/* 11: SQM3*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+	{{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+	{{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+	{{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+	{{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+	{{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+	{{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+	{{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+	{{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+	{{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+	{{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+	{{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+	{{{0, 0,         0,         0} } },	/* 23: */
+	{{{0, 0,         0,         0} } },	/* 24: */
+	{{{0, 0,         0,         0} } },	/* 25: */
+	{{{0, 0,         0,         0} } },	/* 26: */
+	{{{0, 0,         0,         0} } },	/* 27: */
+	{{{0, 0,         0,         0} } },	/* 28: */
+	{{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+    {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+    {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+	{{{0} } },				/* 32: PCI */
+	{{{1, 0x2100000, 0x2102000, 0x120000},	/* 33: PCIE */
+	  {1, 0x2110000, 0x2120000, 0x130000},
+	  {1, 0x2120000, 0x2122000, 0x124000},
+	  {1, 0x2130000, 0x2132000, 0x126000},
+	  {1, 0x2140000, 0x2142000, 0x128000},
+	  {1, 0x2150000, 0x2152000, 0x12a000},
+	  {1, 0x2160000, 0x2170000, 0x110000},
+	  {1, 0x2170000, 0x2172000, 0x12e000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000} } },
+	{{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+	{{{0} } },				/* 35: */
+	{{{0} } },				/* 36: */
+	{{{0} } },				/* 37: */
+	{{{0} } },				/* 38: */
+	{{{0} } },				/* 39: */
+	{{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+	{{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+	{{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+	{{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+	{{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+	{{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+	{{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+	{{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+	{{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+	{{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+	{{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+	{{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+	{{{0} } },				/* 52: */
+	{{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+	{{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+	{{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+	{{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+	{{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+	{{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+	{{{0} } },				/* 59: I2C0 */
+	{{{0} } },				/* 60: I2C1 */
+	{{{1, 0x3d00000, 0x3d04000, 0x1dc000} } },/* 61: LPC */
+	{{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+	{{{1, 0x3f00000, 0x3f01000, 0x168000} } }	/* 63: P2NR0 */
+};
+
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+unsigned qla82xx_crb_hub_agt[64] =
+{
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PS,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_MN,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_MS,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SRE,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_NIU,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_QMN,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGND,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SN,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_EG,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PS,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_CAM,
+	0,
+	0,
+	0,
+	0,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_SMB,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1,
+	0,
+	QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC,
+	0,
+};
+
+/* Device states */
+char *qdev_state[] = {
+	 "Unknown",
+	"Cold",
+	"Initializing",
+	"Ready",
+	"Need Reset",
+	"Need Quiescent",
+	"Failed",
+	"Quiescent",
+};
+
+/*
+ * Set the CRB window based on the offset.
+ * Return 0 if successful; 1 otherwise
+*/
+void qla82xx_pci_change_crbwindow_128M(scsi_qla_host_t *ha, int wndw)
+{
+	WARN_ON(1);
+}
+
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+qla82xx_pci_set_crbwindow_2M(scsi_qla_host_t *ha, ulong *off)
+{
+	u32 win_read;
+
+	ha->crb_win = CRB_HI(*off);
+	writel(ha->crb_win,
+		(void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+
+	/* Read back value to make sure write has gone through before trying
+	* to use it. */
+	win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+	if (win_read != ha->crb_win) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "%s: Written crbwin (0x%x) != Read crbwin (0x%x), "
+		    "off=0x%lx\n", __func__, ha->crb_win, win_read, *off));
+	}
+	*off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
+}
+
+static inline unsigned long
+qla82xx_pci_set_crbwindow(scsi_qla_host_t *ha, u64 off)
+{
+	/*
+	* See if we are currently pointing to the region we want to use next.
+	*/
+	if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_DDR_NET)) {
+		/*
+		* No need to change window. PCIX and PCIE regs are in both
+		* windows.
+		*/
+		return off;
+	}
+
+	if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_PCIX_HOST2)) {
+		/* We are in first CRB window */
+		if (ha->curr_window != 0)
+			qla82xx_pci_change_crbwindow_128M(ha, 0);
+
+		return off;
+	}
+
+	if ((off > QLA82XX_CRB_PCIX_HOST2) && (off < QLA82XX_CRB_MAX)) {
+		/* We are in second CRB window */
+		off = off - QLA82XX_CRB_PCIX_HOST2 + QLA82XX_CRB_PCIX_HOST;
+
+		if (ha->curr_window != 1) {
+			qla82xx_pci_change_crbwindow_128M(ha, 1);
+			return off;
+		}
+
+		if ((off >= QLA82XX_PCI_DIRECT_CRB) &&
+		    (off < QLA82XX_PCI_CAMQM_MAX)) {
+			/*
+			* We are in the QM or direct access register region - do
+			* nothing
+			*/
+			return off;
+		}
+	}
+	/* strange address given */
+	dump_stack();
+	qla_printk(KERN_WARNING, ha,
+		"Warning: qla82xx_pci_set_crbwindow called with"
+		" an unknown address(0x%llx)\n", (unsigned long long)off);
+	return off;
+}
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+
+int qla82xx_crb_win_lock(scsi_qla_host_t *ha)
+{
+	int i;
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore3 from PCI HW block */
+		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
+		if (done == 1)
+			break;
+		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+			return -1;
+		timeout++;
+
+		/* Yield CPU */
+		if (!in_atomic())
+			schedule();
+		else {
+			for (i = 0; i < 20; i++)
+				cpu_relax();    /*This a nop instr on i386*/
+		}
+	}
+	qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum);
+	return 0;
+}
+
+void qla82xx_crb_win_unlock(scsi_qla_host_t *ha)
+{
+	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));
+}
+
+int
+qla82xx_pci_get_crb_addr_2M(scsi_qla_host_t *ha, ulong *off)
+{
+	struct crb_128M_2M_sub_block_map *m;
+
+	if (*off >= QLA82XX_CRB_MAX)
+		return -1;
+
+	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
+		*off = (*off - QLA82XX_PCI_CAMQM) +
+		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
+		return 0;
+	}
+
+	if (*off < QLA82XX_PCI_CRBSPACE)
+		return -1;
+
+	*off -= QLA82XX_PCI_CRBSPACE;
+	/*
+	 * Try direct map
+	 */
+
+	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
+		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;
+		return 0;
+	}
+
+	/*
+	 * Not in direct map, use crb window
+	 */
+	return 1;
+}
+
+int
+qla82xx_wr_32(scsi_qla_host_t *ha, ulong off, u32 data)
+{
+	unsigned long flags = 0;
+	int rv;
+
+	rv = qla82xx_pci_get_crb_addr_2M(ha, &off);
+
+	BUG_ON(rv == -1);
+
+	if (rv == 1) {
+		write_lock_irqsave(&ha->hw_lock, flags);
+		qla82xx_crb_win_lock(ha);
+		qla82xx_pci_set_crbwindow_2M(ha, &off);
+	}
+
+	writel(data, (void __iomem *)off);
+
+	if (rv == 1) {
+		qla82xx_crb_win_unlock(ha);
+		write_unlock_irqrestore(&ha->hw_lock, flags);
+	}
+	return 0;
+}
+
+int
+qla82xx_rd_32(scsi_qla_host_t *ha, ulong off)
+{
+	unsigned long flags = 0;
+	int rv;
+	u32 data;
+
+	rv = qla82xx_pci_get_crb_addr_2M(ha, &off);
+
+	BUG_ON(rv == -1);
+
+	if (rv == 1) {
+		write_lock_irqsave(&ha->hw_lock, flags);
+		qla82xx_crb_win_lock(ha);
+		qla82xx_pci_set_crbwindow_2M(ha, &off);
+	}
+	data = RD_REG_DWORD((void __iomem *)off);
+
+	if (rv == 1) {
+		qla82xx_crb_win_unlock(ha);
+		write_unlock_irqrestore(&ha->hw_lock, flags);
+	}
+	return data;
+}
+
+#define IDC_LOCK_TIMEOUT 100000000
+
+int qla82xx_idc_lock(scsi_qla_host_t *ha)
+{
+	int i;
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore5 from PCI HW block */
+		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK));
+		if (done == 1)
+			break;
+		if (timeout >= IDC_LOCK_TIMEOUT)
+			return -1;
+
+		timeout++;
+
+		/* Yield CPU */
+		if (!in_interrupt())
+			schedule();
+		else {
+			for (i = 0; i < 20; i++)
+				cpu_relax();    /*This a nop instr on i386*/
+		}
+	}
+
+	return 0;
+}
+
+void qla82xx_idc_unlock(scsi_qla_host_t *ha)
+{
+	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK));
+}
+
+/*  PCI Windowing for DDR regions.  */
+#define QLA82XX_ADDR_IN_RANGE(addr, low, high) \
+	(((addr) <= (high)) && ((addr) >= (low)))
+
+/*
+* check memory access boundary.
+* used by test agent. Support ddr access only for now
+*/
+static unsigned long
+qla82xx_pci_mem_bound_check(scsi_qla_host_t *ha,
+    unsigned long long addr, int size)
+{
+	if (!QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET,
+	    QLA82XX_ADDR_DDR_NET_MAX) ||
+	    !QLA82XX_ADDR_IN_RANGE(addr + size - 1, QLA82XX_ADDR_DDR_NET,
+	    QLA82XX_ADDR_DDR_NET_MAX) ||
+	    ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
+		return 0;
+	}
+	return 1;
+}
+
+int qla82xx_pci_set_window_warning_count;
+
+unsigned long
+qla82xx_pci_set_window(scsi_qla_host_t *ha, unsigned long long addr)
+{
+	int window;
+	u32 win_read;
+
+	if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET,
+	    QLA82XX_ADDR_DDR_NET_MAX)) {
+		/* DDR network side */
+		window = MN_WIN(addr);
+		ha->ddr_mn_window = window;
+		qla82xx_wr_32(ha, ha->mn_win_crb | QLA82XX_PCI_CRBSPACE, window);
+		win_read = qla82xx_rd_32(ha, ha->mn_win_crb | QLA82XX_PCI_CRBSPACE);
+		if ((win_read << 17) != window) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
+			    __func__, window, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET;
+	} else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0,
+	    QLA82XX_ADDR_OCM0_MAX)) {
+		unsigned int temp1;
+		if ((addr & 0x00ff800) == 0xff800) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: QM access not handled.\n", __func__);
+			addr = -1UL;
+		}
+
+		window = OCM_WIN(addr);
+		ha->ddr_mn_window = window;
+		qla82xx_wr_32(ha, ha->mn_win_crb | QLA82XX_PCI_CRBSPACE, window);
+		win_read = qla82xx_rd_32(ha, ha->mn_win_crb | QLA82XX_PCI_CRBSPACE);
+		temp1 = ((window & 0x1FF) << 7) |
+		    ((window & 0x0FFFE0000) >> 17);
+		if (win_read != temp1) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
+			    __func__, temp1, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M;
+
+	} else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET,
+	    QLA82XX_P3_ADDR_QDR_NET_MAX)) {
+		/* QDR network side */
+		window = MS_WIN(addr);
+		ha->qdr_sn_window = window;
+		qla82xx_wr_32(ha, ha->ms_win_crb | QLA82XX_PCI_CRBSPACE, window);
+		win_read = qla82xx_rd_32(ha, ha->ms_win_crb | QLA82XX_PCI_CRBSPACE);
+		if (win_read != window) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
+			    __func__, window, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET;
+	} else {
+		/*
+		* peg gdb frequently accesses memory that doesn't exist,
+		* this limits the chit chat so debugging isn't slowed down.
+		*/
+		if ((qla82xx_pci_set_window_warning_count++ < 8) ||
+		    (qla82xx_pci_set_window_warning_count%64 == 0)) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: Warning:%s Unknown address range!\n", __func__,
+			    QLA2XXX_DRIVER_NAME);
+		}
+		addr = -1UL;
+	}
+
+	return addr;
+}
+
+/* check if address is in the same windows as the previous access */
+static int qla82xx_pci_is_same_window(scsi_qla_host_t *ha,
+				      unsigned long long addr)
+{
+	int			window;
+	unsigned long long	qdr_max;
+
+	qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX;
+
+	if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET,
+	    QLA82XX_ADDR_DDR_NET_MAX)) {
+		/* DDR network side */
+		BUG();	/* MN access can not come here */
+	} else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0,
+	    QLA82XX_ADDR_OCM0_MAX)) {
+		return 1;
+	} else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM1,
+	    QLA82XX_ADDR_OCM1_MAX)) {
+		return 1;
+	} else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, qdr_max)) {
+		/* QDR network side */
+		window = ((addr - QLA82XX_ADDR_QDR_NET) >> 22) & 0x3f;
+		if (ha->qdr_sn_window == window)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int qla82xx_pci_mem_read_direct(scsi_qla_host_t *ha,
+	u64 off, void *data, int size)
+{
+	unsigned long   flags;
+	void           *addr = NULL;
+	int             ret = 0;
+	u64             start;
+	uint8_t         *mem_ptr = NULL;
+	unsigned long   mem_base;
+	unsigned long   mem_page;
+
+	write_lock_irqsave(&ha->hw_lock, flags);
+
+	/*
+	 * If attempting to access unknown address or straddle hw windows,
+	 * do not access.
+	 */
+	start = qla82xx_pci_set_window(ha, off);
+	if ((start == -1UL) ||
+	    (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
+		write_unlock_irqrestore(&ha->hw_lock, flags);
+		qla_printk(KERN_ERR, ha, "Out of bound PCI memory access. "
+		    "offset is 0x%llx\n", (unsigned long long)off);
+		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) {
+		*(u8  *)data = 0;
+		return -1;
+	}
+	addr = mem_ptr;
+	addr += start & (PAGE_SIZE - 1);
+	write_lock_irqsave(&ha->hw_lock, flags);
+
+	switch (size) {
+	case 1:
+		*(u8  *)data = readb(addr);
+		break;
+	case 2:
+		*(u16 *)data = readw(addr);
+		break;
+	case 4:
+		*(u32 *)data = readl(addr);
+		break;
+	case 8:
+		*(u64 *)data = readq(addr);
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	write_unlock_irqrestore(&ha->hw_lock, flags);
+
+	if (mem_ptr)
+		iounmap(mem_ptr);
+	return ret;
+}
+
+static int
+qla82xx_pci_mem_write_direct(scsi_qla_host_t *ha, u64 off, void *data, int size)
+{
+	unsigned long   flags;
+	void           *addr = NULL;
+	int             ret = 0;
+	u64             start;
+	uint8_t         *mem_ptr = NULL;
+	unsigned long   mem_base;
+	unsigned long   mem_page;
+
+	write_lock_irqsave(&ha->hw_lock, flags);
+
+	/*
+	 * If attempting to access unknown address or straddle hw windows,
+	 * do not access.
+	 */
+	start = qla82xx_pci_set_window(ha, off);
+	if ((start == -1UL) ||
+	    (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
+		write_unlock_irqrestore(&ha->hw_lock, flags);
+		qla_printk(KERN_ERR, ha,
+		    "Out of bound PCI memory access. Offset is 0x%llx\n",
+		    (unsigned long long)off);
+		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);
+
+	switch (size) {
+	case 1:
+		writeb(*(u8  *)data, addr);
+		break;
+	case 2:
+		writew(*(u16 *)data, addr);
+		break;
+	case 4:
+		writel(*(u32 *)data, addr);
+		break;
+	case 8:
+		writeq(*(u64 *)data, addr);
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	write_unlock_irqrestore(&ha->hw_lock, flags);
+	if (mem_ptr)
+		iounmap(mem_ptr);
+	return ret;
+}
+
+unsigned long qla82xx_decode_crb_addr(unsigned long addr)
+{
+	int i;
+	unsigned long base_addr, offset, pci_base;
+
+	if (!qla82xx_crb_table_initialized)
+		qla82xx_crb_addr_transform_setup();
+
+	pci_base = ADDR_ERROR;
+	base_addr = addr & 0xfff00000;
+	offset = addr & 0x000fffff;
+
+	for (i = 0; i < MAX_CRB_XFORM; i++) {
+		if (crb_addr_xform[i] == base_addr) {
+			pci_base = i << 20;
+			break;
+		}
+	}
+
+	if (pci_base == ADDR_ERROR)
+		return pci_base;
+
+	return pci_base + offset;
+}
+
+static long rom_max_timeout = 100;
+static long qla82xx_rom_lock_timeout = 100;
+
+int
+qla82xx_rom_lock(scsi_qla_host_t *ha)
+{
+	int i;
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore2 from PCI HW block */
+
+		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK));
+		if (done == 1)
+			break;
+		if (timeout >= qla82xx_rom_lock_timeout)
+			return -1;
+		timeout++;
+
+		/*
+		 * Yield CPU
+		 */
+		if (!in_atomic())
+			schedule();
+		else {
+			for (i = 0; i < 20; i++)
+				cpu_relax(); /*This a nop instr on i386*/
+		}
+	}
+	qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+	return 0;
+}
+
+void
+qla82xx_rom_unlock(scsi_qla_host_t *ha)
+{
+	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
+}
+
+int
+qla82xx_wait_rom_busy(scsi_qla_host_t *ha)
+{
+	long timeout = 0;
+	long done = 0 ;
+
+	while (done == 0) {
+		done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
+		done &= 4;
+		timeout++;
+		if (timeout >= rom_max_timeout) {
+			qla_printk(KERN_WARNING, ha,
+			    "Timeout reached  waiting for rom busy\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int
+qla82xx_wait_rom_done(scsi_qla_host_t *ha)
+{
+	long timeout = 0;
+	long done = 0 ;
+
+	while (done == 0) {
+		done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS);
+		done &= 2;
+		timeout++;
+		if (timeout >= rom_max_timeout) {
+			qla_printk(KERN_ERR, ha,
+			    "Timeout reached  waiting for rom done");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int
+qla82xx_do_rom_fast_read(scsi_qla_host_t *ha, int addr, int *valp)
+{
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+	qla82xx_wait_rom_busy(ha);
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_ERR, ha,
+		    "Error waiting for rom done\n");
+		return -1;
+	}
+	/* reset abyte_cnt and dummy_byte_cnt */
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	udelay(10);
+	cond_resched();
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
+
+	*valp = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA);
+	return 0;
+}
+
+int
+qla82xx_rom_fast_read(scsi_qla_host_t *ha, int addr, int *valp)
+{
+	int ret, loops = 0;
+
+	while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
+		udelay(100);
+		schedule();
+		loops++;
+	}
+	if (loops >= 50000) {
+		qla_printk(KERN_ERR, ha,
+		    "%s() qla82xx_rom_lock failed\n", __func__);
+		return -1;
+	}
+	ret = qla82xx_do_rom_fast_read(ha, addr, valp);
+	qla82xx_rom_unlock(ha);
+	return ret;
+}
+
+int
+qla82xx_read_status_reg(scsi_qla_host_t *ha, uint32_t *val)
+{
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
+	qla82xx_wait_rom_busy(ha);
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Error waiting for rom done\n");
+		return -1;
+	}
+
+	*val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA);
+	return 0;
+}
+
+int
+qla82xx_flash_wait_write_finish(scsi_qla_host_t *ha)
+{
+	long timeout = 0;
+	uint32_t done = 1 ;
+	uint32_t val;
+	int ret = 0;
+
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
+	while ((done != 0) && (ret == 0)) {
+		ret = qla82xx_read_status_reg(ha, &val);
+		done = val & 1;
+		timeout++;
+		udelay(10);
+		cond_resched();
+		if (timeout >= 50000) {
+			qla_printk(KERN_WARNING, ha,
+			    "Timeout reached  waiting for write finish");
+			return -1;
+		}
+	}
+	return ret;
+}
+
+int
+qla82xx_flash_set_write_enable(scsi_qla_host_t *ha)
+{
+	uint32_t val;
+	qla82xx_wait_rom_busy(ha);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WREN);
+	qla82xx_wait_rom_busy(ha);
+	if (qla82xx_wait_rom_done(ha))
+		return -1;
+	if (qla82xx_read_status_reg(ha, &val) != 0)
+		return -1;
+	if ((val & 2) != 2)
+		return -1;
+	return 0;
+}
+
+int
+qla82xx_write_status_reg(scsi_qla_host_t *ha, uint32_t val)
+{
+	if (qla82xx_flash_set_write_enable(ha))
+			return -1;
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0x1);
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Error waiting for rom done\n");
+		return -1;
+	}
+
+	return qla82xx_flash_wait_write_finish(ha);
+}
+
+
+int
+qla82xx_write_disable_flash(scsi_qla_host_t *ha)
+{
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Error waiting for rom done\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int ql82xx_rom_lock_d(scsi_qla_host_t *ha)
+{
+	int loops = 0;
+	while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) {
+		udelay(100);
+		cond_resched();
+		loops++;
+	}
+	if (loops >= 50000) {
+		qla_printk(KERN_WARNING, ha, "ROM lock failed\n");
+		return -1;
+	}
+	return 0;;
+}
+
+int
+qla82xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t flashaddr,
+     uint32_t data)
+{
+	int ret = 0;
+
+	ret = ql82xx_rom_lock_d(ha);
+	if (ret < 0) {
+		qla_printk(KERN_INFO, ha,
+		    "%s(%ld): ROM Lock failed\n", __func__, ha->host_no);
+		return ret;
+	}
+
+	if (qla82xx_flash_set_write_enable(ha))
+		goto done_write;
+
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, data);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, flashaddr);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_PP);
+	qla82xx_wait_rom_busy(ha);
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Error waiting for rom done\n");
+		ret = -1;
+		goto done_write;
+	}
+
+	ret = qla82xx_flash_wait_write_finish(ha);
+
+done_write:
+	qla82xx_rom_unlock(ha);
+	return ret;
+}
+
+/*
+ * Reset all block protect bits
+ */
+int
+qla82xx_unprotect_flash(scsi_qla_host_t *ha)
+{
+	int ret;
+	uint32_t val;
+
+	ret = ql82xx_rom_lock_d(ha);
+	if (ret < 0) {
+		qla_printk(KERN_ERR, ha,
+		    "%s(%ld): ROM Lock failed\n", __func__, ha->host_no);
+		return ret;
+	}
+	ret = qla82xx_read_status_reg(ha, &val);
+	if (ret < 0)
+		goto done_unprotect;
+
+	val &= ~(0x7 << 2);
+	ret = qla82xx_write_status_reg(ha, val);
+	if (ret < 0) {
+		val |= (0x7 << 2);
+		qla82xx_write_status_reg(ha, val);
+	}
+
+	if (qla82xx_write_disable_flash(ha) != 0)
+		qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+done_unprotect:
+	qla82xx_rom_unlock(ha);
+	return ret;
+}
+
+int
+qla82xx_protect_flash(scsi_qla_host_t *ha)
+{
+	int ret;
+	uint32_t val;
+
+	ret = ql82xx_rom_lock_d(ha);
+	if (ret < 0) {
+		qla_printk(KERN_INFO, ha,
+		    "%s(%ld): ROM Lock failed\n", __func__, ha->host_no);
+		return ret;
+	}
+	ret = qla82xx_read_status_reg(ha, &val);
+	if (ret < 0)
+		goto done_protect;
+
+	val |= (0x7 << 2);
+	/* LOCK all sectors */
+	ret = qla82xx_write_status_reg(ha, val);
+	if (ret < 0)
+		qla_printk(KERN_WARNING, ha, "Write status register failed\n");
+
+	if (qla82xx_write_disable_flash(ha) != 0)
+		qla_printk(KERN_WARNING, ha, "Write disable failed\n");
+
+done_protect:
+	qla82xx_rom_unlock(ha);
+	return ret;
+}
+
+int
+qla82xx_erase_sector(scsi_qla_host_t *ha, int addr)
+{
+	int ret = 0;
+
+	ret = ql82xx_rom_lock_d(ha);
+	if (ret < 0) {
+		qla_printk(KERN_INFO, ha,
+		    "%s(%ld): ROM Lock failed\n", __func__, ha->host_no);
+		return ret;
+	}
+
+
+	qla82xx_flash_set_write_enable(ha);
+
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_SE);
+
+	if (qla82xx_wait_rom_done(ha)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Error waiting for rom done\n");
+		ret = -1;
+		goto done;
+	}
+
+	ret = qla82xx_flash_wait_write_finish(ha);
+
+done:
+	qla82xx_rom_unlock(ha);
+	return ret;
+}
+
+
+/* This routine does CRB initialize sequence
+ *  to put the ISP into operational state
+ */
+int qla82xx_pinit_from_rom(scsi_qla_host_t *ha, int verbose)
+{
+	int addr, val;
+	int i ;
+	struct crb_addr_pair *buf;
+	unsigned long off;
+	unsigned offset, n;
+
+	/* Halt all the indiviual PEGs and other blocks of the ISP */
+	qla82xx_rom_lock(ha);
+	if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))
+		/* don't reset CAM block on reset */
+		qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);
+	else
+		qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);
+
+	qla82xx_rom_unlock(ha);
+
+	/* Read the signature value from the flash.
+	 * Offset 0: Contain signature (0xcafecafe)
+	 * Offset 4: Offset and number of addr/value pairs
+	 * that present in CRB initialize sequence
+	 */
+	if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL ||
+	    qla82xx_rom_fast_read(ha, 4, &n) != 0) {
+		qla_printk(KERN_WARNING, ha,
+		    "[ERROR] Reading crb_init area: n: %08x\n", n);
+		return -1;
+	}
+
+	/* Offset in flash = lower 16 bits
+	 * Number of entries = upper 16 bits
+	 */
+	offset = n & 0xffffU;
+	n = (n >> 16) & 0xffffU;
+
+	/* number of addr/value pair should not exceed 1024 entries */
+	if (n  >= 1024) {
+		qla_printk(KERN_WARNING, ha,
+		    "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n",
+		    QLA2XXX_DRIVER_NAME, __func__, n);
+		return -1;
+	}
+
+	qla_printk(KERN_INFO, ha,
+	    "%s: %d CRB init values found in ROM.\n", QLA2XXX_DRIVER_NAME, n);
+
+	buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL);
+	if (buf == NULL) {
+		qla_printk(KERN_WARNING, ha,
+		    "%s: [ERROR] Unable to malloc memory.\n",
+		    QLA2XXX_DRIVER_NAME);
+		return -1;
+	}
+
+	for (i = 0; i < n; i++) {
+		if (qla82xx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 ||
+		    qla82xx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) != 0) {
+			kfree(buf);
+			return -1;
+		}
+
+		buf[i].addr = addr;
+		buf[i].data = val;
+	}
+
+	for (i = 0; i < n; i++) {
+		/* Translate internal CRB initialization
+		 * address to PCI bus address
+		 */
+		off = qla82xx_decode_crb_addr((unsigned long)buf[i].addr) +
+		    QLA82XX_PCI_CRBSPACE;
+		/* Not all CRB  addr/value pair to be written,
+		 * some of them are skipped
+		 */
+
+		/* skipping cold reboot MAGIC */
+		if (off == QLA82XX_CAM_RAM(0x1fc))
+			continue;
+
+		/* do not reset PCI */
+		if (off == (ROMUSB_GLB + 0xbc))
+			continue;
+
+		/* skip core clock, so that firmware can increase the clock */
+		if (off == (ROMUSB_GLB + 0xc8))
+			continue;
+
+		/* skip the function enable register */
+		if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION))
+			continue;
+
+		if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2))
+			continue;
+
+		if ((off & 0x0ff00000) == QLA82XX_CRB_SMB)
+			continue;
+
+		if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET)
+			continue;
+
+		if (off == ADDR_ERROR) {
+			qla_printk(KERN_WARNING, ha,
+			    "%s: [ERROR] Unknown addr: 0x%08lx\n",
+			    QLA2XXX_DRIVER_NAME, buf[i].addr);
+			continue;
+		}
+
+		qla82xx_wr_32(ha, off, buf[i].data);
+
+		/* ISP requires much bigger delay to settle down,
+		 * else crb_window returns 0xffffffff
+		 */
+		if (off == QLA82XX_ROMUSB_GLB_SW_RESET)
+			msleep(1000);
+
+		/* ISP requires millisec delay between
+		 * successive CRB register updates
+		 */
+		msleep(1);
+	}
+
+	kfree(buf);
+
+	/* Resetting the data and instruction cache */
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8);
+
+	/* Clear all protocol processing engines */
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0);
+
+	return 0;
+}
+
+int qla82xx_check_for_bad_spd(scsi_qla_host_t *ha)
+{
+	u32 val = 0;
+	val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS);
+	val &= QLA82XX_BOOT_LOADER_MN_ISSUE;
+	if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) {
+		qla_printk(KERN_INFO, ha,
+		    "Memory DIMM SPD not programmed.  Assumed valid.\n");
+		return 1;
+	} else if (val) {
+		qla_printk(KERN_INFO, ha,
+		    "Memory DIMM type incorrect.  Info:%08X.\n", val);
+		return 2;
+	}
+	return 0;
+}
+
+int
+qla82xx_pci_mem_read_2M(scsi_qla_host_t *ha,
+		u64 off, void *data, int size)
+{
+	int i, j = 0, k, start, end, loop, sz[2], off0[2];
+	int	      shift_amount;
+	uint32_t      temp;
+	uint64_t      off8, val, mem_crb, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+
+	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
+		mem_crb = QLA82XX_CRB_QDR_NET;
+	else {
+		mem_crb = QLA82XX_CRB_DDR_NET;
+		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
+			return qla82xx_pci_mem_read_direct(ha,
+			    off, data, size);
+	}
+
+	off8 = off & 0xfffffff0;
+	off0[0] = off & 0xf;
+	sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]);
+	shift_amount = 4;
+
+	loop = ((off0[0] + size - 1) >> shift_amount) + 1;
+	off0[1] = 0;
+	sz[1] = size - sz[0];
+
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << shift_amount);
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
+		temp = 0;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
+		temp = MIU_TA_CTL_ENABLE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			if (printk_ratelimit())
+				dev_err(&ha->pdev->dev,
+				    "failed to read through agent\n");
+			break;
+		}
+
+		start = off0[i] >> 2;
+		end   = (off0[i] + sz[i] - 1) >> 2;
+		for (k = start; k <= end; k++) {
+			temp = qla82xx_rd_32(ha,
+					mem_crb + MIU_TEST_AGT_RDDATA(k));
+			word[i] |= ((uint64_t)temp << (32 * (k & 1)));
+		}
+	}
+
+	if (j >= MAX_CTL_CHECK)
+		return -1;
+
+	if ((off0[0] & 7) == 0) {
+		val = word[0];
+	} else {
+		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+			((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+	}
+
+	switch (size) {
+	case 1:
+		*(uint8_t  *)data = val;
+		break;
+	case 2:
+		*(uint16_t *)data = val;
+		break;
+	case 4:
+		*(uint32_t *)data = val;
+		break;
+	case 8:
+		*(uint64_t *)data = val;
+		break;
+	}
+	return 0;
+}
+
+int
+qla82xx_pci_mem_write_2M(scsi_qla_host_t *ha,
+		u64 off, void *data, int size)
+{
+	int i, j, ret = 0, loop, sz[2], off0;
+	int scale, shift_amount, startword;
+	uint32_t temp;
+	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
+		mem_crb = QLA82XX_CRB_QDR_NET;
+	else {
+		mem_crb = QLA82XX_CRB_DDR_NET;
+		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
+			return qla82xx_pci_mem_write_direct(ha,
+			    off, data, size);
+	}
+
+	off0 = off & 0x7;
+	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+	sz[1] = size - sz[0];
+
+	off8 = off & 0xfffffff0;
+	loop = (((off & 0xf) + size - 1) >> 4) + 1;
+	shift_amount = 4;
+	scale = 2;
+	startword = (off & 0xf)/8;
+
+	for (i = 0; i < loop; i++) {
+		if (qla82xx_pci_mem_read_2M(ha, off8 +
+		    (i << shift_amount), &word[i * scale], 8))
+			return -1;
+	}
+
+	switch (size) {
+	case 1:
+		tmpw = *((uint8_t *)data);
+		break;
+	case 2:
+		tmpw = *((uint16_t *)data);
+		break;
+	case 4:
+		tmpw = *((uint32_t *)data);
+		break;
+	case 8:
+	default:
+		tmpw = *((uint64_t *)data);
+		break;
+	}
+
+	if (sz[0] == 8) {
+		word[startword] = tmpw;
+	} else {
+		word[startword] &=
+		    ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+		word[startword] |= tmpw << (off0 * 8);
+	}
+	if (sz[1] != 0) {
+		word[startword+1] &= ~(~0ULL << (sz[1] * 8));
+		word[startword+1] |= tmpw >> (sz[0] * 8);
+	}
+
+
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << shift_amount);
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
+		temp = 0;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
+		temp = word[i * scale] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
+		temp = (word[i * scale] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
+		temp = word[i*scale + 1] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
+		temp = (word[i*scale + 1] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
+
+		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			if (printk_ratelimit())
+				dev_err(&ha->pdev->dev,
+				    "failed to write through agent\n");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+
+int
+qla82xx_fw_load_from_flash(scsi_qla_host_t *ha)
+{
+	int  i;
+	long size = 0;
+	long flashaddr = BOOTLD_START, memaddr = BOOTLD_START;
+	u64 data;
+	u32 high, low;
+	size = (IMAGE_START - BOOTLD_START) / 8;
+
+	for (i = 0; i < size; i++) {
+		if ((qla82xx_rom_fast_read(ha, flashaddr, (int *)&low)) ||
+		    (qla82xx_rom_fast_read(ha, flashaddr + 4, (int *)&high))) {
+			return -1;
+		}
+		data = ((u64)high << 32) | low ;
+		qla82xx_pci_mem_write_2M(ha, memaddr, &data, 8);
+		flashaddr += 8;
+		memaddr += 8;
+
+		if (i % 0x1000 == 0)
+			msleep(1);
+	}
+
+	udelay(100);
+
+	read_lock(&ha->hw_lock);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020);
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e);
+	read_unlock(&ha->hw_lock);
+	return 0;
+}
+
+/* PCI related functions */
+char *
+qla82xx_pci_info_str(struct scsi_qla_host *ha, char *str)
+{
+	int pcie_reg;
+	char lwstr[6];
+	uint16_t lnk;
+
+	pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
+	pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk);
+	ha->link_width = (lnk >> 4) & 0x3f;
+
+	strcpy(str, "PCIe (");
+	strcat(str, "2.5Gb/s ");
+	snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width);
+	strcat(str, lwstr);
+	return str;
+}
+
+int
+qla82xx_iospace_config(scsi_qla_host_t *ha)
+{
+	uint32_t len = 0;
+	pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME);
+
+	len = pci_resource_len(ha->pdev, 0);
+	ha->nx_pcibase = (unsigned long)ioremap(pci_resource_start(ha->pdev, 0),
+	    len);
+	if (!ha->nx_pcibase) {
+		qla_printk(KERN_ERR, ha,
+		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
+		pci_release_regions(ha->pdev);
+		goto iospace_error_exit;
+	}
+
+	/* mapping of IO base pointer */
+	ha->iobase = (device_reg_t __iomem *)((uint8_t *)ha->nx_pcibase +
+	    0xbc000 + (ha->pdev->devfn << 11));
+
+	if (!ql2xdbwr) {
+		ha->nxdb_wr_ptr = (unsigned long)ioremap((pci_resource_start(
+		    ha->pdev, 4) + (ha->pdev->devfn << 12)), 4);
+		if (!ha->nxdb_wr_ptr) {
+			qla_printk(KERN_ERR, ha,
+			    "cannot remap MMIO (%s), aborting\n",
+			    pci_name(ha->pdev));
+			pci_release_regions(ha->pdev);
+			goto iospace_error_exit;
+		}
+
+		/* Mapping of IO base pointer,
+		 * door bell read and write pointer
+		 */
+		ha->nxdb_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) +
+		    (ha->pdev->devfn * 8);
+	} else {
+		ha->nxdb_wr_ptr = (ha->pdev->devfn == 6 ? QLA82XX_CAMRAM_DB1 :
+		     QLA82XX_CAMRAM_DB2);
+	}
+
+	/* Nx - TODO - Multi queue initialization */
+	return 0;
+iospace_error_exit:
+	return -ENOMEM;
+}
+
+/* GS related functions */
+
+/* Initialization related functions */
+
+/**
+ * qla82xx_pci_config() - Setup ISP82xx PCI configuration registers.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+*/
+int
+qla82xx_pci_config(scsi_qla_host_t *ha)
+{
+	pci_set_master(ha->pdev);
+
+	/* TODO - Check for memory write invalidate setting
+	 * Any parity settings
+	 * Adjust Max Read Request size
+	 * PCI disable ROM
+	 */
+	ha->chip_revision = ha->pdev->revision;
+
+	return 0;
+}
+
+/**
+ * qla82xx_reset_chip() - Setup ISP82xx PCI configuration registers.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+void
+qla82xx_reset_chip(scsi_qla_host_t *ha)
+{
+	ha->isp_ops->disable_intrs(ha);
+	/* Reset logic code */
+}
+
+void qla82xx_config_rings(struct scsi_qla_host *ha)
+{
+	struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
+	struct init_cb_81xx *icb;
+
+	/* Setup ring parameters in initialization control block. */
+	icb = (struct init_cb_81xx *)ha->init_cb;
+	icb->request_q_outpointer = __constant_cpu_to_le16(0);
+	icb->response_q_inpointer = __constant_cpu_to_le16(0);
+	icb->request_q_length = cpu_to_le16(ha->request_q_length);
+	icb->response_q_length = cpu_to_le16(ha->response_q_length);
+	icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma));
+	icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma));
+	icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma));
+	icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma));
+
+	WRT_REG_DWORD((unsigned long  __iomem *)&reg->req_q_out[0], 0);
+	WRT_REG_DWORD((unsigned long  __iomem *)&reg->rsp_q_in[0], 0);
+	WRT_REG_DWORD((unsigned long  __iomem *)&reg->rsp_q_out[0], 0);
+}
+
+void qla82xx_reset_adapter(struct scsi_qla_host *ha)
+{
+	ha->flags.online = 0;
+
+	qla2x00_try_to_stop_firmware(ha);
+
+	ha->isp_ops->disable_intrs(ha);
+}
+
+int qla82xx_check_cmdpeg_state(struct scsi_qla_host *ha)
+{
+	u32 val = 0;
+	int retries = 60;
+
+	do {
+		read_lock(&ha->hw_lock);
+		val = qla82xx_rd_32(ha, CRB_CMDPEG_STATE);
+		read_unlock(&ha->hw_lock);
+
+		switch (val) {
+		case PHAN_INITIALIZE_COMPLETE:
+		case PHAN_INITIALIZE_ACK:
+			return QLA_SUCCESS;
+		case PHAN_INITIALIZE_FAILED:
+			break;
+		default:
+			break;
+		}
+		DEBUG3(printk(KERN_INFO
+		    "CRB_CMDPEG_STATE: 0x%x and retries: 0x%x\n",
+		    val, retries));
+
+		msleep(500);
+
+	} while (--retries);
+
+	qla_printk(KERN_INFO, ha,
+	    "Cmd Peg initialization failed: 0x%x.\n", val);
+
+	qla82xx_check_for_bad_spd(ha);
+	val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);
+
+	read_lock(&ha->hw_lock);
+	qla82xx_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+	read_unlock(&ha->hw_lock);
+	return QLA_FUNCTION_FAILED;
+}
+
+int qla82xx_check_rcvpeg_state(struct scsi_qla_host *ha)
+{
+	u32 val = 0;
+	int retries = 60;
+
+	do {
+		read_lock(&ha->hw_lock);
+		val = qla82xx_rd_32(ha, CRB_RCVPEG_STATE);
+		read_unlock(&ha->hw_lock);
+
+		switch (val) {
+		case PHAN_INITIALIZE_COMPLETE:
+		case PHAN_INITIALIZE_ACK:
+			return QLA_SUCCESS;
+		case PHAN_INITIALIZE_FAILED:
+			break;
+		default:
+			break;
+		}
+
+		DEBUG3(printk(KERN_INFO
+		    "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x\n",
+		    val, retries));
+
+		msleep(500);
+
+	} while (--retries);
+
+	qla_printk(KERN_INFO, ha,
+	    "Rcv Peg initialization failed: 0x%x.\n", val);
+
+	read_lock(&ha->hw_lock);
+	qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED);
+	read_unlock(&ha->hw_lock);
+	return QLA_FUNCTION_FAILED;
+}
+
+
+
+/* ISR related functions */
+uint32_t qla82xx_isr_int_target_mask_enable[8] = {
+	ISR_INT_TARGET_MASK, ISR_INT_TARGET_MASK_F1,
+	ISR_INT_TARGET_MASK_F2, ISR_INT_TARGET_MASK_F3,
+	ISR_INT_TARGET_MASK_F4, ISR_INT_TARGET_MASK_F5,
+	ISR_INT_TARGET_MASK_F7, ISR_INT_TARGET_MASK_F7
+};
+
+uint32_t qla82xx_isr_int_target_status[8] = {
+	ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+	ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+	ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+	ISR_INT_TARGET_STATUS_F7, ISR_INT_TARGET_STATUS_F7
+};
+
+static struct qla82xx_legacy_intr_set legacy_intr[] = {
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F0,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(0) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F1,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F1,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F1,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(1) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F2,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F2,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F2,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(2) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F3,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F3,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F3,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(3) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F4,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F4,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F4,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(4) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F5,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F5,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F5,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(5) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F6,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F6,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F6,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(6) },
+	{
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F7,
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F7,
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F7,
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(7) },
+};
+
+/**
+ * qla82xx_mbx_completion() - Process mailbox command completions.
+ * @ha: SCSI driver HA context
+ * @mb0: Mailbox0 register
+ */
+void
+qla82xx_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
+{
+	uint16_t	cnt;
+	uint16_t __iomem *wptr;
+	struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
+	wptr = (uint16_t __iomem *)&reg->mailbox_out[1];
+
+	/* Load return mailbox registers. */
+	ha->flags.mbox_int = 1;
+	ha->mailbox_out[0] = mb0;
+
+	for (cnt = 1; cnt < ha->mbx_count; cnt++) {
+		ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
+		wptr++;
+	}
+
+	if (ha->mcp) {
+		DEBUG3(qla_printk(KERN_INFO, ha,
+		    "%s(%ld): Got mailbox completion. cmd=%x.\n",
+		    __func__, ha->host_no, ha->mcp->mb[0]));
+	} else {
+		DEBUG2_3(qla_printk(KERN_ERR, ha,
+		    "%s(%ld): MBX pointer ERROR!\n", __func__, ha->host_no));
+	}
+}
+
+/**
+ * qla82xx_intr_handler() - Process interrupts for the ISP82XX
+ * @irq:
+ * @dev_id: SCSI driver HA context
+ * @regs:
+ *
+ * Called by system whenever the host adapter generates an interrupt.
+ *
+ * Returns handled flag.
+ */
+irqreturn_t
+qla82xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_82xx __iomem *reg;
+	int		status = 0, status1 = 0;
+	unsigned long	flags;
+	unsigned long	iter;
+	uint32_t	stat;
+	uint16_t	mb[4];
+
+	ha = (scsi_qla_host_t *) dev_id;
+	if (!ha) {
+		printk(KERN_INFO
+		    "%s(): NULL host pointer\n", __func__);
+		return IRQ_NONE;
+	}
+
+	if (unlikely(pci_channel_offline(ha->pdev)))
+		return IRQ_HANDLED;
+
+	/* Check for valid INTa */
+	if (!ha->flags.msi_enabled) {
+		status = qla82xx_rd_32(ha, ISR_INT_VECTOR);
+		if (!(status & ha->nx_legacy_intr.int_vec_bit))
+			return IRQ_NONE;
+
+		status1 = qla82xx_rd_32(ha, ISR_INT_STATE_REG);
+		if (!ISR_IS_LEGACY_INTR_TRIGGERED(status1))
+			return IRQ_NONE;
+	}
+
+	/* clear the interrupt */
+	qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
+
+	/* read twice to ensure write is flushed */
+	qla82xx_rd_32(ha, ISR_INT_VECTOR);
+	qla82xx_rd_32(ha, ISR_INT_VECTOR);
+
+	reg = &ha->iobase->isp82;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (iter = 1; iter--; ) {
+
+		if (RD_REG_DWORD(&reg->host_int)) {
+			stat = RD_REG_DWORD(&reg->host_status);
+			if ((stat & HSRX_RISC_INT) == 0)
+				break;
+
+			switch (stat & 0xff) {
+			case 0x1:
+			case 0x2:
+			case 0x10:
+			case 0x11:
+				qla82xx_mbx_completion(ha, MSW(stat));
+				status |= MBX_INTERRUPT;
+				break;
+			case 0x12:
+				mb[0] = MSW(stat);
+				mb[1] = RD_REG_WORD(&reg->mailbox_out[1]);
+				mb[2] = RD_REG_WORD(&reg->mailbox_out[2]);
+				mb[3] = RD_REG_WORD(&reg->mailbox_out[3]);
+				qla2x00_async_event(ha, mb);
+				break;
+			case 0x13:
+				qla24xx_process_response_queue(ha);
+				break;
+			default:
+				DEBUG2(printk(KERN_WARNING
+				    "scsi(%ld): Unrecognized interrupt type "
+				    "(%d).\n", ha->host_no, stat & 0xff));
+				break;
+			}
+		}
+		WRT_REG_DWORD(&reg->host_int, 0);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	if (!ha->flags.msi_enabled)
+		qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
+
+#ifdef QL_DEBUG_LEVEL_17
+	if (!irq && ha->flags.eeh_busy)
+		qla_printk(KERN_WARNING, ha,
+		    "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
+		    status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
+#endif
+
+	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+		complete(&ha->mbx_intr_comp);
+	}
+	return IRQ_HANDLED;
+}
+
+irqreturn_t
+qla82xx_msix_default(int irq, void *dev_id, struct pt_regs *regs)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_82xx __iomem *reg;
+	int		status = 0;
+	unsigned long	flags;
+	uint32_t	stat;
+	uint16_t	mb[4];
+
+	ha = dev_id;
+	reg = &ha->iobase->isp82;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	do {
+		if (RD_REG_DWORD(&reg->host_int)) {
+			stat = RD_REG_DWORD(&reg->host_status);
+			if ((stat & HSRX_RISC_INT) == 0)
+				break;
+
+			switch (stat & 0xff) {
+			case 0x1:
+			case 0x2:
+			case 0x10:
+			case 0x11:
+				qla82xx_mbx_completion(ha, MSW(stat));
+				status |= MBX_INTERRUPT;
+				break;
+			case 0x12:
+				mb[0] = MSW(stat);
+				mb[1] =
+				    RD_REG_WORD(&reg->mailbox_out[1]);
+				mb[2] =
+				    RD_REG_WORD(&reg->mailbox_out[2]);
+				mb[3] =
+				    RD_REG_WORD(&reg->mailbox_out[3]);
+				qla2x00_async_event(ha, mb);
+				break;
+			case 0x13:
+				qla24xx_process_response_queue(ha);
+				break;
+			default:
+				DEBUG2(printk(KERN_WARNING
+				    "scsi(%ld): Unrecognized interrupt"
+				    " type (%d).\n",
+				    ha->host_no, stat & 0xff));
+				break;
+			}
+		}
+		WRT_REG_DWORD(&reg->host_int, 0);
+	} while (0);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+#ifdef QL_DEBUG_LEVEL_17
+	if (!irq && ha->flags.eeh_busy)
+		qla_printk(KERN_WARNING, ha,
+		    "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n",
+		    status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
+#endif
+
+	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+		complete(&ha->mbx_intr_comp);
+	}
+	return IRQ_HANDLED;
+}
+
+irqreturn_t
+qla82xx_msix_rsp_q(int irq, void *dev_id, struct pt_regs *regs)
+{
+	scsi_qla_host_t *ha;
+	struct device_reg_82xx __iomem *reg;
+	unsigned long flags;
+
+	ha = dev_id;
+	reg = &ha->iobase->isp82;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	qla24xx_process_response_queue(ha);
+
+	WRT_REG_DWORD(&reg->host_int, 0);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+void
+qla82xx_poll(int irq, void *dev_id, struct pt_regs *regs)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_82xx __iomem *reg;
+	int		status = 0;
+	unsigned long	flags;
+	uint32_t	stat;
+	uint16_t	mb[4];
+
+	ha = (scsi_qla_host_t *) dev_id;
+	if (!ha) {
+		printk(KERN_INFO
+		    "%s(): NULL host pointer\n", __func__);
+		return;
+	}
+
+	reg = &ha->iobase->isp82;
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	if (RD_REG_DWORD(&reg->host_int)) {
+		stat = RD_REG_DWORD(&reg->host_status);
+		switch (stat & 0xff) {
+		case 0x1:
+		case 0x2:
+		case 0x10:
+		case 0x11:
+			qla82xx_mbx_completion(ha, MSW(stat));
+			status |= MBX_INTERRUPT;
+			break;
+		case 0x12:
+			mb[0] = MSW(stat);
+			mb[1] = RD_REG_WORD(&reg->mailbox_out[1]);
+			mb[2] = RD_REG_WORD(&reg->mailbox_out[2]);
+			mb[3] = RD_REG_WORD(&reg->mailbox_out[3]);
+			qla2x00_async_event(ha, mb);
+			break;
+		case 0x13:
+			qla24xx_process_response_queue(ha);
+			break;
+		default:
+			qla_printk(KERN_ERR, ha,
+			    "scsi(%ld): Unrecognized completion type "
+			    "(%d).\n", ha->host_no, stat & 0xff);
+			break;
+		}
+	}
+	WRT_REG_DWORD(&reg->host_int, 0);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+void
+qla82xx_enable_intrs(struct scsi_qla_host *ha)
+{
+	qla82xx_mbx_intr_enable(ha);
+	spin_lock_irq(&ha->hardware_lock);
+	qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,
+	    0xfbff); /* BIT 10 - set */
+	spin_unlock_irq(&ha->hardware_lock);
+	ha->interrupts_on = 1;
+}
+
+void
+qla82xx_disable_intrs(struct scsi_qla_host *ha)
+{
+	if (ha->interrupts_on)
+		qla82xx_mbx_intr_disable(ha);
+	spin_lock_irq(&ha->hardware_lock);
+	qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,
+	    0x0400); /* BIT 10 - set */
+	spin_unlock_irq(&ha->hardware_lock);
+	ha->interrupts_on = 0;
+}
+
+void qla82xx_init_flags(struct scsi_qla_host *ha)
+{
+	struct qla82xx_legacy_intr_set *nx_legacy_intr;
+
+	/* ISP 8021 initializations */
+	rwlock_init(&ha->hw_lock);
+	ha->qdr_sn_window = -1;
+	ha->ddr_mn_window = -1;
+	ha->curr_window = 255;
+	ha->portnum = PCI_FUNC(ha->pdev->devfn);
+	nx_legacy_intr = &legacy_intr[ha->portnum];
+	ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
+	ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg;
+	ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
+	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
+}
+
+static inline void
+qla82xx_set_drv_active(scsi_qla_host_t *ha)
+{
+	uint32_t drv_active;
+
+	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+
+	qla_printk(KERN_INFO, ha,
+	    "%s(%ld): drv_active = 0x%x\n", __func__,
+	    ha->host_no, drv_active);
+
+	/* reset value if all FF's */
+	if (drv_active == 0xffffffff) {
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, 0);
+		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+	}
+
+	drv_active |= (1 << (ha->portnum * 4));
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
+}
+
+inline void
+qla82xx_clear_drv_active(scsi_qla_host_t *ha)
+{
+	uint32_t drv_active;
+
+	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+	drv_active &= ~(1 << (ha->portnum * 4));
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
+}
+
+static inline int
+qla82xx_need_reset(scsi_qla_host_t *ha)
+{
+	uint32_t drv_state;
+	int rval;
+
+	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	rval = drv_state & (1 << (ha->portnum * 4));
+	return rval;
+}
+
+static inline void
+qla82xx_set_rst_ready(scsi_qla_host_t *ha)
+{
+	uint32_t drv_state;
+
+	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+
+	/* reset value if all FF's */
+	if (drv_state == 0xffffffff) {
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
+		drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	}
+
+	drv_state |= (1 << (ha->portnum * 4));
+	qla_printk(KERN_INFO, ha,
+	    "%s(%ld):drv_state = 0x%x\n", __func__, ha->host_no, drv_state);
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
+}
+
+static inline void
+qla82xx_clear_rst_ready(scsi_qla_host_t *ha)
+{
+	uint32_t drv_state;
+
+	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	drv_state &= ~(QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
+}
+
+static inline void
+qla82xx_set_qsnt_ready(scsi_qla_host_t *ha)
+{
+	uint32_t qsnt_state;
+
+	qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	qsnt_state |= (QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4));
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
+}
+
+int qla82xx_load_fw(scsi_qla_host_t *ha)
+{
+
+	int rst;
+
+	/* Put both the PEG CMD and RCV PEG to default state
+	 * of 0 before resetting the hardware
+	 */
+	qla82xx_wr_32(ha, CRB_CMDPEG_STATE, 0);
+	qla82xx_wr_32(ha, CRB_RCVPEG_STATE, 0);
+
+	if (qla82xx_pinit_from_rom(ha, 0) != QLA_SUCCESS) {
+		qla_printk(KERN_ERR, ha,
+			"%s: Error during CRB Initialization\n", __func__);
+		return QLA_FUNCTION_FAILED;
+	}
+	udelay(500);
+
+	/* Bring QM and CAMRAM out of reset */
+	rst = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET);
+	rst &= ~((1 << 28) | (1 << 24));
+	qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst);
+
+	/*
+	 * FW Load priority:
+	 * 1) Operational firmware residing in flash.
+	 */
+	qla_printk(KERN_INFO, ha,
+	    "Attempting to load firmware from flash\n");
+
+	if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) {
+		qla_printk(KERN_ERR, ha,
+		    "Firmware loaded successfully from flash\n");
+		return QLA_SUCCESS;
+	}
+
+	return QLA_FUNCTION_FAILED;
+}
+
+static int
+qla82xx_start_firmware(scsi_qla_host_t *ha)
+{
+	int           pcie_cap;
+	uint16_t      lnk;
+
+	/* scrub dma mask expansion register */
+	qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
+
+	/* Overwrite stale initialization register values */
+	qla82xx_wr_32(ha, CRB_CMDPEG_STATE, 0);
+	qla82xx_wr_32(ha, CRB_RCVPEG_STATE, 0);
+	qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0);
+	qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0);
+
+
+	if (qla82xx_load_fw(ha) != QLA_SUCCESS) {
+		qla_printk(KERN_ERR, ha,
+		    "%s: Error trying to start fw!\n", __func__);
+		return QLA_FUNCTION_FAILED;
+	}
+
+	/* Handshake with the card before we register the devices. */
+	if (qla82xx_check_cmdpeg_state(ha) != QLA_SUCCESS) {
+		qla_printk(KERN_ERR, ha,
+		    "%s: Error during card handshake!\n", __func__);
+		return QLA_FUNCTION_FAILED;
+	}
+
+	/* Negotiated Link width */
+	pcie_cap = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
+	pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk);
+	ha->link_width = (lnk >> 4) & 0x3f;
+
+	/* Synchronize with Receive peg */
+	return qla82xx_check_rcvpeg_state(ha);
+}
+
+/*
+ * qla82xx_device_bootstrap
+ *    Initialize device, set DEV_READY, start fw
+ *
+ * Note:
+ *      IDC lock must be held upon entry
+ *
+ * Return:
+ *    Success : 0
+ *    Failed  : 1
+ */
+static int
+qla82xx_device_bootstrap(scsi_qla_host_t *ha)
+{
+	int rval, i, timeout;
+	uint32_t old_count, count;
+
+	if (qla82xx_need_reset(ha))
+		goto dev_initialize;
+
+	old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+
+	for (i = 0; i < 10; i++) {
+		timeout = msleep_interruptible(200);
+		if (timeout) {
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_FAILED);
+			return QLA_FUNCTION_FAILED;
+		}
+
+		count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+		if (count != old_count)
+			goto dev_ready;
+	}
+
+dev_initialize:
+	/* set to DEV_INITIALIZING */
+	qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");
+	qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING);
+
+	/* Driver that sets device state to initializating sets IDC version */
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION);
+
+	qla82xx_idc_unlock(ha);
+	rval = qla82xx_start_firmware(ha);
+	qla82xx_idc_lock(ha);
+
+	if (rval != QLA_SUCCESS) {
+		qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+		qla82xx_clear_drv_active(ha);
+		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED);
+		return rval;
+	}
+
+dev_ready:
+	qla_printk(KERN_INFO, ha, "HW State: READY\n");
+	qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY);
+
+	return QLA_SUCCESS;
+}
+
+static void
+qla82xx_dev_failed_handler(scsi_qla_host_t *ha)
+{
+
+	/* Disable the board */
+	qla_printk(KERN_INFO, ha,
+	    "Disabling the board\n");
+	/* Set DEV_FAILED flag to disable timer */
+	ha->device_flags |= DFLG_DEV_FAILED;
+
+	qla2x00_abort_all_cmds(ha, DID_NO_CONNECT << 16);
+
+	qla2x00_mark_all_devices_lost(ha, 0);
+
+	ha->flags.online = 0;
+	ha->flags.init_done = 0;
+}
+
+/*
+ * qla82xx_need_reset_handler
+ *    Code to start reset sequence
+ *
+ * Note:
+ *      IDC lock must be held upon entry
+ *
+ * Return:
+ *    Success : 0
+ *    Failed  : 1
+ */
+static void
+qla82xx_need_reset_handler(scsi_qla_host_t *ha)
+{
+	uint32_t dev_state, drv_state, drv_active;
+	unsigned long reset_timeout;
+
+
+	if (ha->flags.online) {
+		qla82xx_idc_unlock(ha);
+		qla2x00_abort_isp_cleanup(ha);
+		ha->isp_ops->get_flash_version(ha, ha->request_ring);
+		ha->isp_ops->nvram_config(ha);
+		qla82xx_idc_lock(ha);
+	}
+
+	qla82xx_set_rst_ready(ha);
+
+	/* wait for 10 seconds for reset ack from all functions */
+	reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
+
+	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+
+	qla_printk(KERN_INFO, ha,
+	    "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n",
+	    __func__, ha->host_no, drv_state, drv_active);
+	while (drv_state != drv_active) {
+
+		if (time_after_eq(jiffies, reset_timeout)) {
+			qla_printk(KERN_INFO, ha, "RESET TIMEOUT!\n");
+			break;
+		}
+
+		qla82xx_idc_unlock(ha);
+		msleep(1000);
+		qla82xx_idc_lock(ha);
+
+		drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+	}
+
+	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");
+		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
+	}
+}
+
+static void
+qla82xx_check_fw_alive(scsi_qla_host_t *ha)
+{
+	uint32_t fw_heartbeat_counter, halt_status;
+
+	fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+	if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
+		ha->seconds_since_last_heartbeat++;
+		/* FW not alive after 2 seconds */
+		if (ha->seconds_since_last_heartbeat == 2) {
+			ha->seconds_since_last_heartbeat = 0;
+			halt_status =
+			    qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1);
+			if (halt_status & HALT_STATUS_UNRECOVERABLE) {
+				/* Unrecoverable error. Disable the device. */
+				set_bit(ISP_UNRECOVERABLE, &ha->dpc_flags);
+			} else {
+				/* Recoverable error detected. Reset device. */
+				qla_printk(KERN_INFO, ha,
+				    "scsi(%ld): %s - detect abort needed!\n",
+				    ha->host_no, __func__);
+				set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+			}
+			qla2xxx_wake_dpc(ha);
+		}
+	}
+
+	ha->fw_heartbeat_counter = fw_heartbeat_counter;
+}
+
+/*
+ * qla82xx_device_state_handler
+ *	Main state handler
+ *
+ * Note:
+ *      IDC lock must be held upon entry
+ *
+ * Return:
+ *    Success : 0
+ *    Failed  : 1
+ */
+int
+qla82xx_device_state_handler(scsi_qla_host_t *ha)
+{
+	uint32_t dev_state;
+	int rval = QLA_SUCCESS;
+	unsigned long dev_init_timeout;
+
+	qla82xx_idc_lock(ha);
+
+	if (!ha->flags.init_done)
+		qla82xx_set_drv_active(ha);
+
+	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);
+
+	while (1) {
+
+		if (time_after_eq(jiffies, dev_init_timeout)) {
+			qla_printk(KERN_ERR, ha, "Device init failed!\n");
+			rval = QLA_FUNCTION_FAILED;
+			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;
+		case QLA82XX_DEV_COLD:
+			rval = qla82xx_device_bootstrap(ha);
+			goto exit;
+		case QLA82XX_DEV_INITIALIZING:
+			qla82xx_idc_unlock(ha);
+			msleep(1000);
+			qla82xx_idc_lock(ha);
+			break;
+		case QLA82XX_DEV_NEED_RESET:
+			if (!ql2xdontresethba) {
+				qla82xx_need_reset_handler(ha);
+				dev_init_timeout = jiffies +
+				    (ha->nx_dev_init_timeout * HZ);
+			}
+			break;
+		case QLA82XX_DEV_NEED_QUIESCENT:
+			qla82xx_set_qsnt_ready(ha);
+		case QLA82XX_DEV_QUIESCENT:
+			qla82xx_idc_unlock(ha);
+			msleep(1000);
+			qla82xx_idc_lock(ha);
+			break;
+		case QLA82XX_DEV_FAILED:
+			qla82xx_dev_failed_handler(ha);
+			rval = QLA_FUNCTION_FAILED;
+			goto exit;
+		default:
+			qla82xx_dev_failed_handler(ha);
+			rval = QLA_FUNCTION_FAILED;
+			goto exit;
+		}
+	}
+exit:
+	qla82xx_idc_unlock(ha);
+	return rval;
+}
+
+void qla82xx_watchdog(scsi_qla_host_t *ha)
+{
+	uint32_t dev_state;
+
+	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+
+	/* don't poll if reset is going on */
+	if (!(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
+	    test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+	    test_bit(ISP_ABORT_RETRY, &ha->dpc_flags))) {
+		if (dev_state == QLA82XX_DEV_NEED_RESET) {
+			qla_printk(KERN_WARNING, ha,
+			     "%s(): Adapter reset needed!\n", __func__);
+			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+			qla2xxx_wake_dpc(ha);
+		} else {
+			qla82xx_check_fw_alive(ha);
+		}
+	}
+}
+
+int qla82xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+
+	int rval;
+
+	rval = qla82xx_device_state_handler(ha);
+
+	return rval;
+}
+
+/*
+*  qla82xx_abort_isp
+*      Resets ISP and aborts all outstanding commands.
+*
+* Input:
+*      ha           = adapter block pointer.
+*
+* Returns:
+*      0 = success
+*/
+int
+qla82xx_abort_isp(scsi_qla_host_t *ha)
+{
+	int rval;
+	uint32_t dev_state;
+
+	if (ha->device_flags & DFLG_DEV_FAILED) {
+		DEBUG(printk("%s(%ld): Device in failed state. "
+			     "Exiting.\n", __func__, ha->host_no));
+		return QLA_SUCCESS;
+	}
+
+	qla82xx_idc_lock(ha);
+	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+	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: %s\n",
+		dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+	qla82xx_idc_unlock(ha);
+
+	rval = qla82xx_device_state_handler(ha);
+
+	qla82xx_idc_lock(ha);
+	qla82xx_clear_rst_ready(ha);
+	qla82xx_idc_unlock(ha);
+
+	if (rval == QLA_SUCCESS)
+		rval = qla82xx_restart_isp(ha);
+
+	if (rval) {
+		ha->flags.online = 1;
+		if (test_bit(ISP_ABORT_RETRY, &ha->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(ha);
+				clear_bit(ISP_ABORT_RETRY,
+				    &ha->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",
+				    ha->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", ha->host_no, ha->isp_abort_cnt));
+			set_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
+			rval = QLA_FUNCTION_FAILED;
+		}
+	}
+
+	return rval;
+}
+
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
new file mode 100644
index 0000000..a6205b3
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -0,0 +1,700 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#ifndef __QLA_NX_H
+#define __QLA_NX_H
+
+/*
+ * Following are the states of the Phantom. Phantom will set them and
+ * Host will read to check if the fields are correct.
+*/
+#define PHAN_INITIALIZE_FAILED		0xffff
+#define PHAN_INITIALIZE_COMPLETE	0xff01
+
+/* Host writes the following to notify that it has done the init-handshake */
+#define PHAN_INITIALIZE_ACK		0xf00f
+#define PHAN_PEG_RCV_INITIALIZED	0xff01
+
+/*CRB_RELATED*/
+#define QLA82XX_CRB_BASE	QLA82XX_CAM_RAM(0x200)
+#define QLA82XX_REG(X)		(QLA82XX_CRB_BASE+(X))
+
+#define CRB_CMDPEG_STATE	QLA82XX_REG(0x50)
+#define CRB_RCVPEG_STATE	QLA82XX_REG(0x13c)
+#define BOOT_LOADER_DIMM_STATUS	QLA82XX_REG(0x54)
+#define CRB_DMA_SHIFT		QLA82XX_REG(0xcc)
+
+#define QLA82XX_HW_H0_CH_HUB_ADR	0x05
+#define QLA82XX_HW_H1_CH_HUB_ADR	0x0E
+#define QLA82XX_HW_H2_CH_HUB_ADR	0x03
+#define QLA82XX_HW_H3_CH_HUB_ADR	0x01
+#define QLA82XX_HW_H4_CH_HUB_ADR	0x06
+#define QLA82XX_HW_H5_CH_HUB_ADR	0x07
+#define QLA82XX_HW_H6_CH_HUB_ADR	0x08
+
+/*  Hub 0 */
+#define QLA82XX_HW_MN_CRB_AGT_ADR	0x15
+#define QLA82XX_HW_MS_CRB_AGT_ADR	0x25
+
+/*  Hub 1 */
+#define QLA82XX_HW_PS_CRB_AGT_ADR	0x73
+#define QLA82XX_HW_QMS_CRB_AGT_ADR	0x00
+#define QLA82XX_HW_RPMX3_CRB_AGT_ADR	0x0b
+#define QLA82XX_HW_SQGS0_CRB_AGT_ADR	0x01
+#define QLA82XX_HW_SQGS1_CRB_AGT_ADR	0x02
+#define QLA82XX_HW_SQGS2_CRB_AGT_ADR	0x03
+#define QLA82XX_HW_SQGS3_CRB_AGT_ADR	0x04
+#define QLA82XX_HW_C2C0_CRB_AGT_ADR	0x58
+#define QLA82XX_HW_C2C1_CRB_AGT_ADR	0x59
+#define QLA82XX_HW_C2C2_CRB_AGT_ADR	0x5a
+#define QLA82XX_HW_RPMX2_CRB_AGT_ADR	0x0a
+#define QLA82XX_HW_RPMX4_CRB_AGT_ADR	0x0c
+#define QLA82XX_HW_RPMX7_CRB_AGT_ADR	0x0f
+#define QLA82XX_HW_RPMX9_CRB_AGT_ADR	0x12
+#define QLA82XX_HW_SMB_CRB_AGT_ADR	0x18
+
+/*  Hub 2 */
+#define QLA82XX_HW_NIU_CRB_AGT_ADR	0x31
+#define QLA82XX_HW_I2C0_CRB_AGT_ADR	0x19
+#define QLA82XX_HW_I2C1_CRB_AGT_ADR	0x29
+
+#define QLA82XX_HW_SN_CRB_AGT_ADR	0x10
+#define QLA82XX_HW_I2Q_CRB_AGT_ADR	0x20
+#define QLA82XX_HW_LPC_CRB_AGT_ADR	0x22
+#define QLA82XX_HW_ROMUSB_CRB_AGT_ADR	0x21
+#define QLA82XX_HW_QM_CRB_AGT_ADR	0x66
+#define QLA82XX_HW_SQG0_CRB_AGT_ADR	0x60
+#define QLA82XX_HW_SQG1_CRB_AGT_ADR	0x61
+#define QLA82XX_HW_SQG2_CRB_AGT_ADR	0x62
+#define QLA82XX_HW_SQG3_CRB_AGT_ADR	0x63
+#define QLA82XX_HW_RPMX1_CRB_AGT_ADR	0x09
+#define QLA82XX_HW_RPMX5_CRB_AGT_ADR	0x0d
+#define QLA82XX_HW_RPMX6_CRB_AGT_ADR	0x0e
+#define QLA82XX_HW_RPMX8_CRB_AGT_ADR	0x11
+
+/*  Hub 3 */
+#define QLA82XX_HW_PH_CRB_AGT_ADR	0x1A
+#define QLA82XX_HW_SRE_CRB_AGT_ADR	0x50
+#define QLA82XX_HW_EG_CRB_AGT_ADR	0x51
+#define QLA82XX_HW_RPMX0_CRB_AGT_ADR	0x08
+
+/*  Hub 4 */
+#define QLA82XX_HW_PEGN0_CRB_AGT_ADR	0x40
+#define QLA82XX_HW_PEGN1_CRB_AGT_ADR	0x41
+#define QLA82XX_HW_PEGN2_CRB_AGT_ADR	0x42
+#define QLA82XX_HW_PEGN3_CRB_AGT_ADR	0x43
+#define QLA82XX_HW_PEGNI_CRB_AGT_ADR	0x44
+#define QLA82XX_HW_PEGND_CRB_AGT_ADR	0x45
+#define QLA82XX_HW_PEGNC_CRB_AGT_ADR	0x46
+#define QLA82XX_HW_PEGR0_CRB_AGT_ADR	0x47
+#define QLA82XX_HW_PEGR1_CRB_AGT_ADR	0x48
+#define QLA82XX_HW_PEGR2_CRB_AGT_ADR	0x49
+#define QLA82XX_HW_PEGR3_CRB_AGT_ADR	0x4a
+#define QLA82XX_HW_PEGN4_CRB_AGT_ADR	0x4b
+
+/*  Hub 5 */
+#define QLA82XX_HW_PEGS0_CRB_AGT_ADR	0x40
+#define QLA82XX_HW_PEGS1_CRB_AGT_ADR	0x41
+#define QLA82XX_HW_PEGS2_CRB_AGT_ADR	0x42
+#define QLA82XX_HW_PEGS3_CRB_AGT_ADR	0x43
+
+#define QLA82XX_HW_PEGSI_CRB_AGT_ADR	0x44
+#define QLA82XX_HW_PEGSD_CRB_AGT_ADR	0x45
+#define QLA82XX_HW_PEGSC_CRB_AGT_ADR	0x46
+
+/*  Hub 6 */
+#define QLA82XX_HW_CAS0_CRB_AGT_ADR	0x46
+#define QLA82XX_HW_CAS1_CRB_AGT_ADR	0x47
+#define QLA82XX_HW_CAS2_CRB_AGT_ADR	0x48
+#define QLA82XX_HW_CAS3_CRB_AGT_ADR	0x49
+#define QLA82XX_HW_NCM_CRB_AGT_ADR	0x16
+#define QLA82XX_HW_TMR_CRB_AGT_ADR	0x17
+#define QLA82XX_HW_XDMA_CRB_AGT_ADR	0x05
+#define QLA82XX_HW_OCM0_CRB_AGT_ADR	0x06
+#define QLA82XX_HW_OCM1_CRB_AGT_ADR	0x07
+
+/*  This field defines PCI/X adr [25:20] of agents on the CRB */
+/*  */
+#define QLA82XX_HW_PX_MAP_CRB_PH	0
+#define QLA82XX_HW_PX_MAP_CRB_PS	1
+#define QLA82XX_HW_PX_MAP_CRB_MN	2
+#define QLA82XX_HW_PX_MAP_CRB_MS	3
+#define QLA82XX_HW_PX_MAP_CRB_SRE	5
+#define QLA82XX_HW_PX_MAP_CRB_NIU	6
+#define QLA82XX_HW_PX_MAP_CRB_QMN	7
+#define QLA82XX_HW_PX_MAP_CRB_SQN0	8
+#define QLA82XX_HW_PX_MAP_CRB_SQN1	9
+#define QLA82XX_HW_PX_MAP_CRB_SQN2	10
+#define QLA82XX_HW_PX_MAP_CRB_SQN3	11
+#define QLA82XX_HW_PX_MAP_CRB_QMS	12
+#define QLA82XX_HW_PX_MAP_CRB_SQS0	13
+#define QLA82XX_HW_PX_MAP_CRB_SQS1	14
+#define QLA82XX_HW_PX_MAP_CRB_SQS2	15
+#define QLA82XX_HW_PX_MAP_CRB_SQS3	16
+#define QLA82XX_HW_PX_MAP_CRB_PGN0	17
+#define QLA82XX_HW_PX_MAP_CRB_PGN1	18
+#define QLA82XX_HW_PX_MAP_CRB_PGN2	19
+#define QLA82XX_HW_PX_MAP_CRB_PGN3	20
+#define QLA82XX_HW_PX_MAP_CRB_PGN4	QLA82XX_HW_PX_MAP_CRB_SQS2
+#define QLA82XX_HW_PX_MAP_CRB_PGND	21
+#define QLA82XX_HW_PX_MAP_CRB_PGNI	22
+#define QLA82XX_HW_PX_MAP_CRB_PGS0	23
+#define QLA82XX_HW_PX_MAP_CRB_PGS1	24
+#define QLA82XX_HW_PX_MAP_CRB_PGS2	25
+#define QLA82XX_HW_PX_MAP_CRB_PGS3	26
+#define QLA82XX_HW_PX_MAP_CRB_PGSD	27
+#define QLA82XX_HW_PX_MAP_CRB_PGSI	28
+#define QLA82XX_HW_PX_MAP_CRB_SN	29
+#define QLA82XX_HW_PX_MAP_CRB_EG	31
+#define QLA82XX_HW_PX_MAP_CRB_PH2	32
+#define QLA82XX_HW_PX_MAP_CRB_PS2	33
+#define QLA82XX_HW_PX_MAP_CRB_CAM	34
+#define QLA82XX_HW_PX_MAP_CRB_CAS0	35
+#define QLA82XX_HW_PX_MAP_CRB_CAS1	36
+#define QLA82XX_HW_PX_MAP_CRB_CAS2	37
+#define QLA82XX_HW_PX_MAP_CRB_C2C0	38
+#define QLA82XX_HW_PX_MAP_CRB_C2C1	39
+#define QLA82XX_HW_PX_MAP_CRB_TIMR	40
+#define QLA82XX_HW_PX_MAP_CRB_RPMX1	42
+#define QLA82XX_HW_PX_MAP_CRB_RPMX2	43
+#define QLA82XX_HW_PX_MAP_CRB_RPMX3	44
+#define QLA82XX_HW_PX_MAP_CRB_RPMX4	45
+#define QLA82XX_HW_PX_MAP_CRB_RPMX5	46
+#define QLA82XX_HW_PX_MAP_CRB_RPMX6	47
+#define QLA82XX_HW_PX_MAP_CRB_RPMX7	48
+#define QLA82XX_HW_PX_MAP_CRB_XDMA	49
+#define QLA82XX_HW_PX_MAP_CRB_I2Q	50
+#define QLA82XX_HW_PX_MAP_CRB_ROMUSB	51
+#define QLA82XX_HW_PX_MAP_CRB_CAS3	52
+#define QLA82XX_HW_PX_MAP_CRB_RPMX0	53
+#define QLA82XX_HW_PX_MAP_CRB_RPMX8	54
+#define QLA82XX_HW_PX_MAP_CRB_RPMX9	55
+#define QLA82XX_HW_PX_MAP_CRB_OCM0	56
+#define QLA82XX_HW_PX_MAP_CRB_OCM1	57
+#define QLA82XX_HW_PX_MAP_CRB_SMB	58
+#define QLA82XX_HW_PX_MAP_CRB_I2C0	59
+#define QLA82XX_HW_PX_MAP_CRB_I2C1	60
+#define QLA82XX_HW_PX_MAP_CRB_LPC	61
+#define QLA82XX_HW_PX_MAP_CRB_PGNC	62
+#define QLA82XX_HW_PX_MAP_CRB_PGR0	63
+#define QLA82XX_HW_PX_MAP_CRB_PGR1	4
+#define QLA82XX_HW_PX_MAP_CRB_PGR2	30
+#define QLA82XX_HW_PX_MAP_CRB_PGR3	41
+
+/*  This field defines CRB adr [31:20] of the agents */
+/*  */
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_MN       ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_MN_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PH       ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PH_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_MS       ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_MS_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PS       ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PS_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SS       ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SS_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3    ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX3_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_QMS      ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_QMS_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS0     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQGS0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS1     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQGS1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS2     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQGS2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS3     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQGS3_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C0     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_C2C0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C1     ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_C2C1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2    ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4    ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX4_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7    ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX7_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9    ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX9_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SMB      ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SMB_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_NIU      ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_NIU_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0     ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_I2C0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1     ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_I2C1_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SRE      ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SRE_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_EG       ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_EG_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0    ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_QMN      ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_QM_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQG0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQG1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQG2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SQG3_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1    ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5    ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX5_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6    ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX6_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8    ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_RPMX8_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS0     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_CAS0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS1     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_CAS1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS2     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_CAS2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS3     ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_CAS3_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGNI_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGND     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGND_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGN0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGN1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGN2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGN3_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4	((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGN4_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGNC_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR0     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGR0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR1     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGR1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR2     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGR2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR3     ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGR3_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGSI_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSD     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGSD_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGS0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGS1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGS2_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGS3_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSC     ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_PEGSC_CRB_AGT_ADR)
+
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAM      ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_NCM_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR     ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_TMR_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA     ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_XDMA_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_SN       ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_SN_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q      ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_I2Q_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB   ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_ROMUSB_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0     ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_OCM0_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM1     ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_OCM1_CRB_AGT_ADR)
+#define QLA82XX_HW_CRB_HUB_AGT_ADR_LPC      ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \
+					    QLA82XX_HW_LPC_CRB_AGT_ADR)
+
+#define ROMUSB_GLB				(QLA82XX_CRB_ROMUSB + 0x00000)
+#define QLA82XX_ROMUSB_GLB_PEGTUNE_DONE		(ROMUSB_GLB + 0x005c)
+#define QLA82XX_ROMUSB_GLB_STATUS		(ROMUSB_GLB + 0x0004)
+#define QLA82XX_ROMUSB_GLB_SW_RESET		(ROMUSB_GLB + 0x0008)
+#define QLA82XX_ROMUSB_ROM_ADDRESS		(ROMUSB_ROM + 0x0008)
+#define QLA82XX_ROMUSB_ROM_WDATA		(ROMUSB_ROM + 0x000c)
+#define QLA82XX_ROMUSB_ROM_ABYTE_CNT		(ROMUSB_ROM + 0x0010)
+#define QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT	(ROMUSB_ROM + 0x0014)
+#define QLA82XX_ROMUSB_ROM_RDATA		(ROMUSB_ROM + 0x0018)
+
+#define ROMUSB_ROM			(QLA82XX_CRB_ROMUSB + 0x10000)
+#define QLA82XX_ROMUSB_ROM_INSTR_OPCODE	(ROMUSB_ROM + 0x0004)
+#define QLA82XX_ROMUSB_GLB_CAS_RST	(ROMUSB_GLB + 0x0038)
+
+/* Lock IDs for ROM lock */
+#define ROM_LOCK_DRIVER	0x0d417340
+
+#define QLA82XX_PCI_CRB_WINDOWSIZE	0x00100000    /* all are 1MB windows */
+#define QLA82XX_PCI_CRB_WINDOW(A)	(QLA82XX_PCI_CRBSPACE + (A)*QLA82XX_PCI_CRB_WINDOWSIZE)
+#define QLA82XX_CRB_C2C_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C0)
+#define QLA82XX_CRB_C2C_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C1)
+#define QLA82XX_CRB_C2C_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C2)
+#define QLA82XX_CRB_CAM		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAM)
+#define QLA82XX_CRB_CASPER	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS)
+#define QLA82XX_CRB_CASPER_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS0)
+#define QLA82XX_CRB_CASPER_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS1)
+#define QLA82XX_CRB_CASPER_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS2)
+#define QLA82XX_CRB_DDR_MD	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MS)
+#define QLA82XX_CRB_DDR_NET	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MN)
+#define QLA82XX_CRB_EPG		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_EG)
+#define QLA82XX_CRB_I2Q		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2Q)
+#define QLA82XX_CRB_NIU		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_NIU)
+/* HACK upon HACK upon HACK (for PCIE builds) */
+#define QLA82XX_CRB_PCIX_HOST	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH)
+#define QLA82XX_CRB_PCIX_HOST2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH2)
+#define QLA82XX_CRB_PCIX_MD	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS)
+#define QLA82XX_CRB_PCIE	QLA82XX_CRB_PCIX_MD
+/* window 1 pcie slot */
+#define QLA82XX_CRB_PCIE2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS2)
+
+#define QLA82XX_CRB_PEG_MD_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS0)
+#define QLA82XX_CRB_PEG_MD_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS1)
+#define QLA82XX_CRB_PEG_MD_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS2)
+#define QLA82XX_CRB_PEG_MD_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3)
+#define QLA82XX_CRB_PEG_MD_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3)
+#define QLA82XX_CRB_PEG_MD_D	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSD)
+#define QLA82XX_CRB_PEG_MD_I	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSI)
+#define QLA82XX_CRB_PEG_NET_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN0)
+#define QLA82XX_CRB_PEG_NET_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN1)
+#define QLA82XX_CRB_PEG_NET_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN2)
+#define QLA82XX_CRB_PEG_NET_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN3)
+#define QLA82XX_CRB_PEG_NET_4	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN4)
+#define QLA82XX_CRB_PEG_NET_D	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGND)
+#define QLA82XX_CRB_PEG_NET_I	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGNI)
+#define QLA82XX_CRB_PQM_MD	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMS)
+#define QLA82XX_CRB_PQM_NET	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMN)
+#define QLA82XX_CRB_QDR_MD	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SS)
+#define QLA82XX_CRB_QDR_NET	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SN)
+#define QLA82XX_CRB_ROMUSB	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_ROMUSB)
+#define QLA82XX_CRB_RPMX_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX0)
+#define QLA82XX_CRB_RPMX_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX1)
+#define QLA82XX_CRB_RPMX_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX2)
+#define QLA82XX_CRB_RPMX_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX3)
+#define QLA82XX_CRB_RPMX_4	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX4)
+#define QLA82XX_CRB_RPMX_5	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX5)
+#define QLA82XX_CRB_RPMX_6	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX6)
+#define QLA82XX_CRB_RPMX_7	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX7)
+#define QLA82XX_CRB_SQM_MD_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS0)
+#define QLA82XX_CRB_SQM_MD_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS1)
+#define QLA82XX_CRB_SQM_MD_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS2)
+#define QLA82XX_CRB_SQM_MD_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS3)
+#define QLA82XX_CRB_SQM_NET_0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN0)
+#define QLA82XX_CRB_SQM_NET_1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN1)
+#define QLA82XX_CRB_SQM_NET_2	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN2)
+#define QLA82XX_CRB_SQM_NET_3	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN3)
+#define QLA82XX_CRB_SRE		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SRE)
+#define QLA82XX_CRB_TIMER	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_TIMR)
+#define QLA82XX_CRB_XDMA	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_XDMA)
+#define QLA82XX_CRB_I2C0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C0)
+#define QLA82XX_CRB_I2C1	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C1)
+#define QLA82XX_CRB_OCM0	QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_OCM0)
+#define QLA82XX_CRB_SMB		QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SMB)
+
+#define QLA82XX_CRB_MAX		QLA82XX_PCI_CRB_WINDOW(64)
+
+/*
+ * ====================== BASE ADDRESSES ON-CHIP ======================
+ * Base addresses of major components on-chip.
+ * ====================== BASE ADDRESSES ON-CHIP ======================
+ */
+#define QLA82XX_ADDR_DDR_NET		(0x0000000000000000ULL)
+#define QLA82XX_ADDR_DDR_NET_MAX	(0x000000000fffffffULL)
+
+/* Imbus address bit used to indicate a host address. This bit is
+ * eliminated by the pcie bar and bar select before presentation
+ * over pcie. */
+/* host memory via IMBUS */
+#define QLA82XX_P2_ADDR_PCIE	(0x0000000800000000ULL)
+#define QLA82XX_P3_ADDR_PCIE	(0x0000008000000000ULL)
+#define QLA82XX_ADDR_PCIE_MAX	(0x0000000FFFFFFFFFULL)
+#define QLA82XX_ADDR_OCM0	(0x0000000200000000ULL)
+#define QLA82XX_ADDR_OCM0_MAX	(0x00000002000fffffULL)
+#define QLA82XX_ADDR_OCM1	(0x0000000200400000ULL)
+#define QLA82XX_ADDR_OCM1_MAX	(0x00000002004fffffULL)
+#define QLA82XX_ADDR_QDR_NET	(0x0000000300000000ULL)
+
+#define QLA82XX_P2_ADDR_QDR_NET_MAX	(0x00000003001fffffULL)
+#define QLA82XX_P3_ADDR_QDR_NET_MAX	(0x0000000303ffffffULL)
+
+#define QLA82XX_PCI_CRBSPACE	(unsigned long)0x06000000
+#define QLA82XX_PCI_DIRECT_CRB	(unsigned long)0x04400000
+#define QLA82XX_PCI_CAMQM	(unsigned long)0x04800000
+#define QLA82XX_PCI_CAMQM_MAX	(unsigned long)0x04ffffff
+#define QLA82XX_PCI_DDR_NET	(unsigned long)0x00000000
+#define QLA82XX_PCI_QDR_NET	(unsigned long)0x04000000
+#define QLA82XX_PCI_QDR_NET_MAX	(unsigned long)0x043fffff
+
+/*
+ *   Register offsets for MN
+ */
+#define MIU_CONTROL		(0x000)
+#define MIU_TAG			(0x004)
+#define MIU_TEST_AGT_CTRL	(0x090)
+#define MIU_TEST_AGT_ADDR_LO	(0x094)
+#define MIU_TEST_AGT_ADDR_HI	(0x098)
+#define MIU_TEST_AGT_WRDATA_LO	(0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI	(0x0a4)
+#define MIU_TEST_AGT_WRDATA(i)	(0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO	(0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI	(0x0ac)
+#define MIU_TEST_AGT_RDDATA(i)	(0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK	0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off)	(0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START	1
+#define MIU_TA_CTL_ENABLE	2
+#define MIU_TA_CTL_WRITE	4
+#define MIU_TA_CTL_BUSY		8
+
+/*CAM RAM */
+# define QLA82XX_CAM_RAM_BASE	(QLA82XX_CRB_CAM + 0x02000)
+# define QLA82XX_CAM_RAM(reg)	(QLA82XX_CAM_RAM_BASE + (reg))
+
+#define QLA82XX_PEG_TUNE_MN_SPD_ZEROED	0x80000000
+#define QLA82XX_BOOT_LOADER_MN_ISSUE	0xff00ffff
+#define QLA82XX_PORT_MODE_ADDR		(QLA82XX_CAM_RAM(0x24))
+#define QLA82XX_PEG_HALT_STATUS1	(QLA82XX_CAM_RAM(0xa8))
+#define QLA82XX_PEG_HALT_STATUS2	(QLA82XX_CAM_RAM(0xac))
+#define QLA82XX_PEG_ALIVE_COUNTER	(QLA82XX_CAM_RAM(0xb0))
+#define QLA82XX_CAMRAM_DB1		(QLA82XX_CAM_RAM(0x1b8))
+#define QLA82XX_CAMRAM_DB2		(QLA82XX_CAM_RAM(0x1bc))
+
+#define HALT_STATUS_UNRECOVERABLE	0x80000000
+#define HALT_STATUS_RECOVERABLE		0x40000000
+
+/* Driver Coexistence Defines */
+#define QLA82XX_CRB_DRV_ACTIVE		(QLA82XX_CAM_RAM(0x138))
+#define QLA82XX_CRB_DEV_STATE		(QLA82XX_CAM_RAM(0x140))
+#define QLA82XX_CRB_DEV_PART_INFO	(QLA82XX_CAM_RAM(0x14c))
+#define QLA82XX_CRB_DRV_IDC_VERSION	(QLA82XX_CAM_RAM(0x174))
+#define QLA82XX_CRB_DRV_STATE		(QLA82XX_CAM_RAM(0x144))
+#define QLA82XX_CRB_DRV_SCRATCH		(QLA82XX_CAM_RAM(0x148))
+#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 MAX_STATES			8 /* Increment if new state added */
+
+#define QLA82XX_IDC_VERSION		0x1
+#define ROM_DEV_INIT_TIMEOUT		30
+#define ROM_DRV_RESET_ACK_TIMEOUT	10
+
+#define QLA82XX_ROM_LOCK_ID		(QLA82XX_CAM_RAM(0x100))
+#define QLA82XX_CRB_WIN_LOCK_ID		(QLA82XX_CAM_RAM(0x124))
+#define QLA82XX_FW_VERSION_MAJOR	(QLA82XX_CAM_RAM(0x150))
+#define QLA82XX_FW_VERSION_MINOR	(QLA82XX_CAM_RAM(0x154))
+#define QLA82XX_FW_VERSION_SUB		(QLA82XX_CAM_RAM(0x158))
+#define QLA82XX_PCIE_REG(reg)		(QLA82XX_CRB_PCIE + (reg))
+
+#define PCIE_SETUP_FUNCTION	(0x12040)
+#define PCIE_SETUP_FUNCTION2	(0x12048)
+
+#define QLA82XX_PCIX_PS_REG(reg)	(QLA82XX_CRB_PCIX_MD + (reg))
+#define QLA82XX_PCIX_PS2_REG(reg)	(QLA82XX_CRB_PCIE2 + (reg))
+
+#define PCIE_SEM2_LOCK		(0x1c010)  /* Flash lock   */
+#define PCIE_SEM2_UNLOCK	(0x1c014)  /* Flash unlock */
+#define PCIE_SEM5_LOCK		(0x1c028)  /* Coexistence lock   */
+#define PCIE_SEM5_UNLOCK	(0x1c02c)  /* Coexistence unlock */
+#define PCIE_SEM7_LOCK		(0x1c038)  /* crb win lock */
+#define PCIE_SEM7_UNLOCK	(0x1c03c)  /* crbwin unlock*/
+
+/* Different drive state */
+#define QLA82XX_DRVST_NOT_RDY           0
+#define QLA82XX_DRVST_RST_RDY           1
+#define QLA82XX_DRVST_QSNT_RDY          2
+
+
+#define QLA82XX_MSIX_TBL_SPACE		8192
+#define QLA82XX_PCI_REG_MSIX_TBL	0x44
+#define QLA82XX_PCI_MSIX_CONTROL	0x40
+
+struct crb_128M_2M_sub_block_map {
+	unsigned valid;
+	unsigned start_128M;
+	unsigned end_128M;
+	unsigned start_2M;
+};
+
+struct crb_128M_2M_block_map {
+	struct crb_128M_2M_sub_block_map sub_block[16];
+};
+
+struct crb_addr_pair {
+	long addr;
+	long data;
+};
+
+#define ADDR_ERROR ((unsigned long)0xffffffff)
+#define MAX_CTL_CHECK   1000
+
+/***************************************************************************
+ *		PCI related defines.
+ **************************************************************************/
+
+/*
+ * Interrupt related defines.
+ */
+#define PCIX_TARGET_STATUS	(0x10118)
+#define PCIX_TARGET_STATUS_F1	(0x10160)
+#define PCIX_TARGET_STATUS_F2	(0x10164)
+#define PCIX_TARGET_STATUS_F3	(0x10168)
+#define PCIX_TARGET_STATUS_F4	(0x10360)
+#define PCIX_TARGET_STATUS_F5	(0x10364)
+#define PCIX_TARGET_STATUS_F6	(0x10368)
+#define PCIX_TARGET_STATUS_F7	(0x1036c)
+
+#define PCIX_TARGET_MASK	(0x10128)
+#define PCIX_TARGET_MASK_F1	(0x10170)
+#define PCIX_TARGET_MASK_F2	(0x10174)
+#define PCIX_TARGET_MASK_F3	(0x10178)
+#define PCIX_TARGET_MASK_F4	(0x10370)
+#define PCIX_TARGET_MASK_F5	(0x10374)
+#define PCIX_TARGET_MASK_F6	(0x10378)
+#define PCIX_TARGET_MASK_F7	(0x1037c)
+
+/*
+ * Message Signaled Interrupts
+ */
+#define PCIX_MSI_F0		(0x13000)
+#define PCIX_MSI_F1		(0x13004)
+#define PCIX_MSI_F2		(0x13008)
+#define PCIX_MSI_F3		(0x1300c)
+#define PCIX_MSI_F4		(0x13010)
+#define PCIX_MSI_F5		(0x13014)
+#define PCIX_MSI_F6		(0x13018)
+#define PCIX_MSI_F7		(0x1301c)
+#define PCIX_MSI_F(FUNC)	(0x13000 + ((FUNC) * 4))
+
+/*
+ *
+ */
+#define PCIX_INT_VECTOR		(0x10100)
+#define PCIX_INT_MASK		(0x10104)
+
+/*
+ * Interrupt state machine and other bits.
+ */
+#define PCIE_MISCCFG_RC		(0x1206c)
+
+
+#define ISR_INT_TARGET_STATUS		(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS))
+#define ISR_INT_TARGET_STATUS_F1	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F1))
+#define ISR_INT_TARGET_STATUS_F2	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F2))
+#define ISR_INT_TARGET_STATUS_F3	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
+#define ISR_INT_TARGET_STATUS_F4	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_STATUS_F5	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_STATUS_F6	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_STATUS_F7	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+
+#define ISR_INT_TARGET_MASK	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK))
+#define ISR_INT_TARGET_MASK_F1	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F1))
+#define ISR_INT_TARGET_MASK_F2	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
+#define ISR_INT_TARGET_MASK_F3	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_MASK_F4	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_MASK_F5	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_MASK_F6	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_MASK_F7	(QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
+
+#define ISR_INT_VECTOR		(QLA82XX_PCIX_PS_REG(PCIX_INT_VECTOR))
+#define ISR_INT_MASK		(QLA82XX_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_STATE_REG	(QLA82XX_PCIX_PS_REG(PCIE_MISCCFG_RC))
+
+#define	ISR_MSI_INT_TRIGGER(FUNC)	(QLA82XX_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+
+#define	ISR_IS_LEGACY_INTR_IDLE(VAL)		(((VAL) & 0x300) == 0)
+#define	ISR_IS_LEGACY_INTR_TRIGGERED(VAL)	(((VAL) & 0x300) == 0x200)
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define	PCIX_INT_VECTOR_BIT_F0	0x0080
+#define	PCIX_INT_VECTOR_BIT_F1	0x0100
+#define	PCIX_INT_VECTOR_BIT_F2	0x0200
+#define	PCIX_INT_VECTOR_BIT_F3	0x0400
+#define	PCIX_INT_VECTOR_BIT_F4	0x0800
+#define	PCIX_INT_VECTOR_BIT_F5	0x1000
+#define	PCIX_INT_VECTOR_BIT_F6	0x2000
+#define	PCIX_INT_VECTOR_BIT_F7	0x4000
+
+struct qla82xx_legacy_intr_set {
+	uint32_t	int_vec_bit;
+	uint32_t	tgt_status_reg;
+	uint32_t	tgt_mask_reg;
+	uint32_t	pci_int_reg;
+};
+
+#define BOOTLD_START	0x10000
+#define	IMAGE_START	0x43000
+#define	IMAGE_START_MS	0x100000
+
+/* Magic number to let user know flash is programmed */
+#define   QLA82XX_BDINFO_MAGIC	0x12345678
+#define FW_SIZE_OFFSET		(0x3e840c)
+
+#define MIU_TEST_AGT_WRDATA_UPPER_LO	(0x0b0)
+#define	MIU_TEST_AGT_WRDATA_UPPER_HI	(0x0b4)
+
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem *addr)
+{
+	writel(((u32) (val)), (addr));
+	writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+/******************************************************************************
+*
+*    Definitions specific to M25P flash
+*
+*******************************************************************************
+*   Instructions
+*/
+#define M25P_INSTR_WREN	0x06
+#define M25P_INSTR_WRDI	0x04
+#define M25P_INSTR_RDID	0x9f
+#define M25P_INSTR_RDSR	0x05
+#define M25P_INSTR_WRSR	0x01
+#define M25P_INSTR_READ	0x03
+#define M25P_INSTR_FAST_READ	0x0b
+#define M25P_INSTR_PP	0x02
+#define M25P_INSTR_SE	0xd8
+#define M25P_INSTR_BE	0xc7
+#define M25P_INSTR_DP	0xb9
+#define M25P_INSTR_RES	0xab
+
+
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 8df8769..07ca7f8 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -28,6 +28,11 @@ char qla2x00_version_str[40];
 static kmem_cache_t *srb_cachep;
 
 /*
+ * CT6 CTX allocation cache
+ */
+static kmem_cache_t *ctx_cachep;
+
+/*
  * Ioctl related information.
  */
 int num_hosts;
@@ -115,19 +120,39 @@ MODULE_PARM_DESC(ql2xenablemsix,
                 " 1 = enable MSI-X interrupt mechanism."
                 " 2 = enable MSI interrupt mechanism.");
 
+int ql2xshiftctondsd = 6;
+module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xshiftctondsd,
+		"Set to control shifting of command type processing "
+		"based on total number of DSD.");
+
+
+int ql2xfwloadbin;
+module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfwloadbin,
+		"Option to specify location from which to load ISP firmware:"
+		" 1 -- load firmware from flash."
+		" 0 -- use default semantics.");
+
+int ql2xdbwr = 1;
+module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xdbwr,
+		"Option to specify scheme for request queue posting"
+		" 0 -- Regular doorbell."
+		" 1 -- (Default) CAMRAM doorbell (faster).");
+
+int ql2xdontresethba;
+module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xdontresethba,
+		"1: Do not reset on failure, 0(Default): Reset on failure.");
+
 int ql2xetsenable;
 module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xetsenable,
 		"Enables firmware ETS burst."
 		"Default is 0 - skip ETS enablement.");
 
-int ql2xfwloadbin;
-module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xfwloadbin,
-		"Option to specify location from which to load ISP firmware:\n"
-		"      interface, ISP82XX and above.\n"
-		" 1 -- load firmware from flash.\n"
-		" 0 -- use default semantics.\n");
+
 
 int ql2xtargetreset = 1;
 module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR);
@@ -260,6 +285,9 @@ qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval)
 static inline void
 qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval)
 {
+	/* Currently used for 82XX only. */
+	if (ha->device_flags & DFLG_DEV_FAILED)
+		return;
 	mod_timer(&ha->timer, jiffies + interval * HZ);
 }
 
@@ -278,6 +306,8 @@ static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
 static void qla2x00_mem_free(scsi_qla_host_t *ha);
 static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
 static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
+static int qla2x00_allocate_sp_ctx_pool(scsi_qla_host_t *ha);
+static void qla2x00_free_sp_ctx_pool(scsi_qla_host_t *ha);
 static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
 
 /* -------------------------------------------------------------------------- */
@@ -417,7 +447,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport,
 	sp->flags = 0;
 	CMD_SP(cmd) = (void *)sp;
 	cmd->scsi_done = done;
-
+	sp->ctx = NULL;
 	return sp;
 }
 
@@ -531,12 +561,15 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	}
 
 	spin_unlock_irq(ha->host->host_lock);
-
 	sp = qla2x00_get_new_sp(pha, fcport, cmd, done);
 	if (!sp)
 		goto qc24_host_busy_lock;
 
-	rval = qla24xx_start_scsi(sp);
+	if (IS_QLA82XX(ha))
+		rval = qla82xx_start_scsi(sp);
+	else
+		rval = qla24xx_start_scsi(sp);
+
 	if (rval != QLA_SUCCESS)
 		goto qc24_host_busy_free_sp;
 
@@ -560,7 +593,6 @@ qc24_fail_command:
 	return 0;
 }
 
-
 /*
  * qla2x00_eh_wait_on_command
  *    Waits for the command to be returned by the Firmware for some
@@ -599,6 +631,44 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
 }
 
 /*
+ * qla2x00_wait_for_fcoe_ctx_reset
+ *    Wait till the FCoE context is reset.
+ *
+ * Note:
+ *    Does context switching here.
+ *    Release SPIN_LOCK (if any) before calling this routine.
+ *
+ * Return:
+ *    Success (fcoe_ctx reset is done) : 0
+ *    Failed  (fcoe_ctx reset not completed within max loop timout ) : 1
+ */
+int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *ha)
+{
+	int status = QLA_FUNCTION_FAILED;
+	unsigned long wait_reset;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
+
+	wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+	while ((test_bit(FCOE_CTX_RESET_NEEDED, &pha->dpc_flags) ||
+	    test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags))
+	    && time_before(jiffies, wait_reset)) {
+
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ);
+
+		if (!test_bit(FCOE_CTX_RESET_NEEDED, &pha->dpc_flags) &&
+		    !test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags)) {
+			status = QLA_SUCCESS;
+			break;
+		}
+	}
+	DEBUG2(printk(KERN_INFO
+	    "%s status=%d\n", __func__, status));
+
+	return status;
+}
+
+/*
  * qla2x00_wait_for_reset_ready
  *    Wait till the HBA is online after going through
  *    <= MAX_RETRIES_OF_ISP_ABORT  or
@@ -765,6 +835,8 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
 			break;
 		}
 	}
+	DEBUG2(qla_printk(KERN_INFO, ha,
+	    "%s return_status=%d\n", __func__, return_status));
 	return (return_status);
 }
 
@@ -1036,7 +1108,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 *
 * Note:
 **************************************************************************/
-static int
+int
 qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
 {
 	int	cnt;
@@ -1192,12 +1264,22 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 			goto eh_host_reset_lock;
 	} else {
 		set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
-		if (qla2x00_abort_isp(pha)) {
+		if (IS_QLA82XX(pha)) {
+			if (!qla82xx_fcoe_ctx_reset(pha)) {
+				/* Ctx reset success */
+				clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+				ret = SUCCESS;
+				goto eh_host_reset_lock;
+			}
+			/* fall thru if ctx reset failed */
+		}
+		if (ha->isp_ops->abort_isp(pha)) {
 			clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
 			/* failed. schedule dpc to try */
 			set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags);
+			qla2xxx_wake_dpc(pha);
 
-			if (qla2x00_wait_for_reset_ready(ha) !=
+			if (qla2x00_wait_for_hba_online(pha) !=
 			    QLA_SUCCESS)
 				goto eh_host_reset_lock;
 		}
@@ -1246,7 +1328,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
 		}
 	}
 
-	if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) {
+	if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) {
 		ret = qla2x00_full_login_lip(ha);
 		if (ret != QLA_SUCCESS) {
 			DEBUG2_3(printk("%s(%ld): bus_reset failed: "
@@ -1268,7 +1350,6 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
 		qla2x00_wait_for_loop_ready(ha);
 	}
 
-
 	/* Issue marker command only when we are going to start the I/O */
 	ha->marker_needed = 1;
 
@@ -1488,6 +1569,9 @@ static struct isp_operations qla2100_isp_ops = {
 	.read_optrom		= qla2x00_read_optrom_data,
 	.write_optrom		= qla2x00_write_optrom_data,
 	.get_flash_version	= qla2x00_get_flash_version,
+	.abort_isp		= qla2x00_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_pool,
+	.free_sp_pool		= qla2x00_free_sp_pool,
 };
 
 static struct isp_operations qla2300_isp_ops = {
@@ -1521,6 +1605,9 @@ static struct isp_operations qla2300_isp_ops = {
 	.read_optrom		= qla2x00_read_optrom_data,
 	.write_optrom		= qla2x00_write_optrom_data,
 	.get_flash_version	= qla2x00_get_flash_version,
+	.abort_isp		= qla2x00_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_pool,
+	.free_sp_pool		= qla2x00_free_sp_pool,
 };
 
 static struct isp_operations qla24xx_isp_ops = {
@@ -1554,6 +1641,9 @@ static struct isp_operations qla24xx_isp_ops = {
 	.read_optrom		= qla24xx_read_optrom_data,
 	.write_optrom		= qla24xx_write_optrom_data,
 	.get_flash_version	= qla24xx_get_flash_version,
+	.abort_isp		= qla2x00_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_pool,
+	.free_sp_pool		= qla2x00_free_sp_pool,
 };
 
 static struct isp_operations qla25xx_isp_ops = {
@@ -1587,6 +1677,9 @@ 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,
+	.abort_isp		= qla2x00_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_pool,
+	.free_sp_pool		= qla2x00_free_sp_pool,
 };
 
 static struct isp_operations qla81xx_isp_ops = {
@@ -1622,8 +1715,46 @@ static struct isp_operations qla81xx_isp_ops = {
 	.write_optrom		= qla24xx_write_optrom_data,
 /* ------------------------------------------------ */
 	.get_flash_version	= qla24xx_get_flash_version,
+	.abort_isp		= qla2x00_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_pool,
+	.free_sp_pool		= qla2x00_free_sp_pool,
 };
 
+static struct isp_operations qla82xx_isp_ops = {
+	.pci_config		= qla82xx_pci_config,
+	.reset_chip		= qla82xx_reset_chip,
+	.chip_diag		= qla24xx_chip_diag,
+	.config_rings		= qla82xx_config_rings,
+	.reset_adapter		= qla82xx_reset_adapter,
+	.nvram_config		= qla81xx_nvram_config,
+	.update_fw_options	= qla24xx_update_fw_options,
+	.load_risc		= qla82xx_load_risc,
+	.pci_info_str		= qla82xx_pci_info_str,
+	.fw_version_str		= qla24xx_fw_version_str,
+	.intr_handler		= qla82xx_intr_handler,
+	.enable_intrs		= qla82xx_enable_intrs,
+	.disable_intrs		= qla82xx_disable_intrs,
+	.abort_command		= qla24xx_abort_command,
+	.abort_target		= qla24xx_abort_target,
+	.fabric_login		= qla24xx_login_fabric,
+	.fabric_logout		= qla24xx_fabric_logout,
+	.calc_req_entries	= NULL,
+	.build_iocbs		= NULL,
+	.prep_ms_iocb		= qla24xx_prep_ms_iocb,
+	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb,
+	.read_nvram		= NULL,
+	.write_nvram		= NULL,
+	.fw_dump		= qla24xx_fw_dump,
+	.beacon_on		= qla24xx_beacon_on,
+	.beacon_off		= qla24xx_beacon_off,
+	.beacon_blink		= qla24xx_beacon_blink,
+	.read_optrom		= qla82xx_read_optrom_data,
+	.write_optrom		= qla82xx_write_optrom_data,
+	.get_flash_version	= qla24xx_get_flash_version,
+	.abort_isp		= qla82xx_abort_isp,
+	.alloc_sp_pool		= qla2x00_allocate_sp_ctx_pool,
+	.free_sp_pool		= qla2x00_free_sp_ctx_pool,
+};
 
 static inline void
 qla2x00_set_isp_flags(scsi_qla_host_t *ha)
@@ -1711,6 +1842,12 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
 		ha->device_type |= DT_IIDMA;
 		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
 		break;
+	case PCI_DEVICE_ID_QLOGIC_ISP8021:
+		ha->device_type |= DT_ISP8021;
+		ha->device_type |= DT_ZIO_SUPPORTED;
+		ha->device_type |= DT_FWI2;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+		break;
 	}
 }
 
@@ -1719,6 +1856,9 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
 {
 	resource_size_t pio;
 
+	if (IS_QLA82XX(ha))
+		return qla82xx_iospace_config(ha);
+
 	/* We only need PIO for Flash operations on ISP2312 v2 chips. */
 	pio = pci_resource_start(ha->pdev, 0);
 	if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
@@ -1822,8 +1962,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
-	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001)
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021)
 		sht = &qla24xx_driver_template;
+
 	host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
 	if (host == NULL) {
 		printk(KERN_WARNING
@@ -1846,9 +1988,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
 
+#ifdef QL_FNDMTL_REST_RQD
 	/* Set EEH reset type to fundamental if required by hba  */
-	if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
+	if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
 		pdev->fndmntl_rst_rqd = 1;
+#endif
+
+	/* 82xx Initialize */
+	qla82xx_init_flags(ha);
 
 	/* Configure PCI I/O space */
 	ret = qla2x00_iospace_config(ha);
@@ -1933,7 +2080,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
 		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
-		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
+		ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
 		ha->mgmt_svr_loop_id = 10 + ha->vp_idx;    /* xxx marcus */
 		ha->gid_list_info_size = 8;
 		ha->optrom_size = OPTROM_SIZE_25XX;
@@ -1957,7 +2104,23 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		ha->nvram_conf_off = ~0;
 		ha->nvram_data_off = ~0;
 		ha->isp_ops = &qla81xx_isp_ops;
-        }
+	} else if (IS_QLA82XX(ha)) {
+		/* TODO - Need to revisit these initialization codes */
+		host->max_id = MAX_TARGETS_2200;
+		ha->mbx_count = MAILBOX_REGISTER_COUNT;
+		ha->request_q_length = REQUEST_ENTRY_CNT_82XX;
+		ha->response_q_length = 128;
+		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
+		ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
+		ha->mgmt_svr_loop_id = 10 + ha->vp_idx;
+		ha->gid_list_info_size = 8;
+		ha->optrom_size = OPTROM_SIZE_82XX;
+		ha->isp_ops = &qla82xx_isp_ops;
+		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
+		ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
+		ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
+		ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
+	}
 	host->can_queue = ha->request_q_length + 128;
 
 	/* load the F/W, read paramaters, and init the H/W */
@@ -1987,6 +2150,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto probe_failed;
 	}
 
+	ret = qla2x00_request_irqs(ha);
+	if (ret)
+		goto probe_failed;
+
 	if (qla2x00_initialize_adapter(ha)) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to initialize adapter\n");
@@ -1994,6 +2161,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
 		    "Adapter flags %x.\n",
 		    ha->host_no, ha->device_flags));
+		if (IS_QLA82XX(ha)) {
+			qla82xx_idc_lock(ha);
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_FAILED);
+			qla82xx_idc_unlock(ha);
+			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+		}
 
 		ret = -ENODEV;
 		goto probe_failed;
@@ -2021,9 +2195,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	host->max_lun = MAX_LUNS;
 	host->transportt = qla2xxx_transport_template;
 
+#if 0
 	ret = qla2x00_request_irqs(ha);
 	if (ret)
 		goto probe_failed;
+#endif
 
 	pci_save_state(ha->pdev);
 
@@ -2037,7 +2213,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	reg = ha->iobase;
-	if (!IS_QLA81XX(ha)) {
+	if (IS_QLA82XX(ha)) {
+		/* Need to understand the logic here */
+	} else if (!IS_QLA81XX(ha)) {
 		if (IS_FWI2_CAPABLE(ha)) {
 			WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
 			WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
@@ -2093,7 +2271,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	    ha->isp_ops->fw_version_str(ha, fw_str));
 
 	set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags);
-
 	return 0;
 
 probe_failed:
@@ -2141,7 +2318,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
 			}
 
 			fc_remove_host(vha->host);
-		
+
 			scsi_remove_host(vha->host);
 
 			scsi_host_put(vha->host);
@@ -2171,7 +2348,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
 	qla84xx_put_chip(ha);
 
 	qla2x00_free_sysfs_attr(ha);
-	
+
 	qla_free_nlnk_dmabuf(ha);
 
 	fc_remove_host(ha->host);
@@ -2183,7 +2360,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
 	scsi_host_put(ha->host);
 
 	pci_disable_pcie_error_reporting(pdev);
-
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 }
@@ -2218,16 +2394,28 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 	qla2x00_try_to_stop_firmware(ha);
 
 	/* turn-off interrupts on the card */
-	if (ha->interrupts_on)
+	if (ha->interrupts_on) {
+		ha->flags.init_done = 0;
 		ha->isp_ops->disable_intrs(ha);
+	}
 
 	qla2x00_mem_free(ha);
 
 	qla2x00_free_irqs(ha);
 
 	/* release io space registers  */
-	if (ha->iobase)
+	if (ha->iobase && !IS_QLA82XX(ha))
 		iounmap(ha->iobase);
+
+	if (IS_QLA82XX(ha)) {
+		qla82xx_idc_lock(ha);
+		qla82xx_clear_drv_active(ha);
+		qla82xx_idc_unlock(ha);
+		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
+		if (!ql2xdbwr)
+			iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
+	}
+
 	pci_release_regions(ha->pdev);
 }
 
@@ -2451,7 +2639,40 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
 			continue;
 		}
 
-		if (qla2x00_allocate_sp_pool(ha)) {
+		if (IS_QLA82XX(ha)) {
+			snprintf(name, sizeof(name), "%s_dl_%ld",
+					QLA2XXX_DRIVER_NAME, ha->host_no);
+			ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
+					DSD_LIST_DMA_POOL_SIZE, 8, 0);
+			if (ha->dl_dma_pool == NULL) {
+				qla_printk(KERN_WARNING, ha,
+				"Memory Allocation failed - dl_dma_pool\n");
+
+				qla2x00_mem_free(ha);
+				msleep(100);
+
+				continue;
+			}
+
+			snprintf(name, sizeof(name), "%s_fcp_%ld",
+				QLA2XXX_DRIVER_NAME, ha->host_no);
+			ha->fcp_cmnd_dma_pool = dma_pool_create(name,
+				&ha->pdev->dev,	FCP_CMND_DMA_POOL_SIZE, 8, 0);
+			if (ha->fcp_cmnd_dma_pool == NULL) {
+				qla_printk(KERN_WARNING, ha,
+				"Memory Allocation failed -"
+					"fcp_cmnd_dma_pool\n");
+
+				qla2x00_mem_free(ha);
+				msleep(100);
+
+				continue;
+			}
+		}
+
+		INIT_LIST_HEAD(&ha->gbl_dsd_list);
+
+		if (ha->isp_ops->alloc_sp_pool(ha)) {
 			qla_printk(KERN_WARNING, ha,
 			    "Memory Allocation failed - "
 			    "qla2x00_allocate_sp_pool()\n");
@@ -2550,7 +2771,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
 			}
 
 			/* Get consistent memory allocated for EX-INIT-CB. */
-			if (IS_QLA81XX(ha)) {
+			if (IS_QLA8XXX_TYPE(ha)) {
 				ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
 						&ha->ex_init_cb_dma);
 				if (ha->ex_init_cb == NULL) {
@@ -2612,7 +2833,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 	}
 
 	/* free sp pool */
-	qla2x00_free_sp_pool(ha);
+	ha->isp_ops->free_sp_pool(ha);
 
 	if (ha->fw_dump) {
 		if (ha->eft)
@@ -2648,8 +2869,27 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 	if (ha->s_dma_pool)
 		dma_pool_destroy(ha->s_dma_pool);
 
+	if (!list_empty(&ha->gbl_dsd_list)) {
+		struct dsd_dma *dsd_ptr, *tdsd_ptr;
+
+		/* clean up allocated prev pool */
+		list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
+		    &ha->gbl_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);
+		}
+	}
+
+	if (ha->dl_dma_pool)
+		dma_pool_destroy(ha->dl_dma_pool);
+
+	if (ha->fcp_cmnd_dma_pool)
+		dma_pool_destroy(ha->fcp_cmnd_dma_pool);
+
 	if (ha->init_cb)
-		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, 
+		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
 		    ha->init_cb, ha->init_cb_dma);
 
 	if (ha->gid_list)
@@ -2693,6 +2933,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 	ha->dcbx_tlv_dma = 0;
 
 	ha->s_dma_pool = NULL;
+	ha->dl_dma_pool = NULL;
+	ha->fcp_cmnd_dma_pool = NULL;
 
 	ha->gid_list = NULL;
 	ha->gid_list_dma = 0;
@@ -2757,6 +2999,61 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha)
 	}
 }
 
+/*
+ * qla2x00_allocate_sp_ctx_pool
+ * 	 This routine is called during initialization to allocate
+ *  	 memory for local srb_t and ct6 ctx.
+ *
+ * Input:
+ *	 ha   = adapter block pointer.
+ *
+ * Context:
+ *      Kernel context.
+ */
+static int
+qla2x00_allocate_sp_ctx_pool(scsi_qla_host_t *ha)
+{
+	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
+	if (ha->srb_mempool == NULL) {
+		qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n");
+		return QLA_FUNCTION_FAILED;
+	}
+
+	/* First time allocation of CT6-CTX cache */
+	if (!ctx_cachep) {
+		ctx_cachep = kmem_cache_create("qla2xxx_ctx",
+		    sizeof(struct ct6_dsd), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+		if (!ctx_cachep) {
+			qla_printk(KERN_INFO, ha,
+			    "Unable to allocate CTX cache.\n");
+			return QLA_FUNCTION_FAILED;
+		}
+	}
+
+	ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ, ctx_cachep);
+	if (ha->ctx_mempool == NULL) {
+		qla_printk(KERN_INFO, ha, "Unable to allocate CTX mempool.\n");
+		return QLA_FUNCTION_FAILED;
+	}
+
+	return QLA_SUCCESS;
+}
+
+static void
+qla2x00_free_sp_ctx_pool(scsi_qla_host_t *ha)
+{
+	if (ha->srb_mempool) {
+		mempool_destroy(ha->srb_mempool);
+		ha->srb_mempool = NULL;
+	}
+
+	if (ha->ctx_mempool) {
+		mempool_destroy(ha->ctx_mempool);
+		ha->ctx_mempool = NULL;
+	}
+}
+
+
 static struct qla_work_evt *
 qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type)
 {
@@ -2911,6 +3208,44 @@ qla2x00_do_dpc(void *data)
 		}
 
 		qla2x00_do_work(ha);
+		if (IS_QLA82XX(ha)) {
+			if (test_and_clear_bit(ISP_UNRECOVERABLE,
+			    &ha->dpc_flags)) {
+				qla82xx_idc_lock(ha);
+				qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+				    QLA82XX_DEV_FAILED);
+				qla82xx_idc_unlock(ha);
+				qla_printk(KERN_INFO, ha,
+				     "HW State: FAILED\n");
+				qla82xx_device_state_handler(ha);
+				continue;
+			}
+
+			if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED,
+			    &ha->dpc_flags)) {
+
+				DEBUG(printk(KERN_INFO
+				    "scsi(%ld): dpc: sched "
+				    "qla82xx_fcoe_ctx_reset ha = %p\n",
+				    ha->host_no, ha));
+				if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
+				    &ha->dpc_flags))) {
+					if (qla82xx_fcoe_ctx_reset(ha)) {
+						/* FCoE-ctx reset failed.
+						 * Escalate to chip-reset
+						 */
+						set_bit(ISP_ABORT_NEEDED,
+						    &ha->dpc_flags);
+					}
+					clear_bit(ABORT_ISP_ACTIVE,
+					    &ha->dpc_flags);
+				}
+
+				DEBUG(printk("scsi(%ld): dpc:"
+				    " qla82xx_fcoe_ctx_reset end\n",
+				    ha->host_no));
+			}
+		}
 
 		if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
 
@@ -2920,7 +3255,7 @@ qla2x00_do_dpc(void *data)
 			if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
 			    &ha->dpc_flags))) {
 
-				if (qla2x00_abort_isp(ha)) {
+				if (ha->isp_ops->abort_isp(ha)) {
 					/* failed. retry later */
 					set_bit(ISP_ABORT_NEEDED,
 					    &ha->dpc_flags);
@@ -3108,8 +3443,20 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp)
 
 	qla2x00_sp_free_dma(ha, sp);
 
-	mempool_free(sp, ha->srb_mempool);
+	if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
+		struct ct6_dsd *ctx = sp->ctx;
 
+		dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd,
+		    ctx->fcp_cmnd_dma);
+		list_splice(&ctx->dsd_list, &ha->gbl_dsd_list);
+		ha->gbl_dsd_inuse -= ctx->dsd_use_cnt;
+		ha->gbl_dsd_avail += ctx->dsd_use_cnt;
+
+		mempool_free(sp->ctx, ha->ctx_mempool);
+		sp->ctx = NULL;
+	}
+
+	mempool_free(sp, ha->srb_mempool);
 	cmd->scsi_done(cmd);
 }
 
@@ -3137,6 +3484,9 @@ qla2x00_timer(scsi_qla_host_t *ha)
 	if (!pci_channel_offline(pha->pdev))
 		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
 
+	if (!ha->parent && IS_QLA82XX(ha))
+		qla82xx_watchdog(ha);
+
 	/*
 	 * Ports - Port down timer.
 	 *
@@ -3245,6 +3595,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
 	    start_dpc ||
 	    test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
 	    test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
+	    test_bit(ISP_UNRECOVERABLE, &ha->dpc_flags) ||
+	    test_bit(FCOE_CTX_RESET_NEEDED, &ha->dpc_flags) ||
 	    test_bit(VP_DPC_NEEDED, &ha->dpc_flags) ||
 	    test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
 		qla2xxx_wake_dpc(pha);
@@ -3420,7 +3772,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 #endif
 
 	set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
-	if (qla2x00_abort_isp(ha)== QLA_SUCCESS)
+	if (ha->isp_ops->abort_isp(ha) == QLA_SUCCESS)
 		ret =  PCI_ERS_RESULT_RECOVERED;
 	clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
 
@@ -3471,6 +3823,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@ -3541,6 +3894,8 @@ qla2x00_module_exit(void)
 	/* qla2x00_release_firmware(); */
 	ql_nl_unregister();
 	kmem_cache_destroy(srb_cachep);
+	if (ctx_cachep)
+		kmem_cache_destroy(ctx_cachep);
 	fc_release_transport(qla2xxx_transport_template);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 19d07ee..7a74973 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -566,6 +566,10 @@ qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start)
 		*start = FA_FLASH_LAYOUT_ADDR;
 	else if (IS_QLA81XX(ha))
 		*start = FA_FLASH_LAYOUT_ADDR_81;
+	else if (IS_QLA82XX(ha)) {
+		*start = FA_FLASH_LAYOUT_ADDR_82;
+		goto end;
+	}
 
 	/* Begin with first PCI expansion ROM header. */
 	buf = (uint8_t *)ha->request_ring;
@@ -707,10 +711,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr)
 			break;
 		case FLT_REG_VPD_0:
 			ha->flt_region_vpd_nvram = start;
+			if (IS_QLA82XX(ha))
+				break;
                         if (!(PCI_FUNC(ha->pdev->devfn) & 1))
                                 ha->flt_region_vpd = start;
                         break;
                 case FLT_REG_VPD_1:
+			if (IS_QLA82XX(ha))
+				break;
 			if (PCI_FUNC(ha->pdev->devfn) & 1)
 				ha->flt_region_vpd = start;
 			break;
@@ -736,6 +744,21 @@ qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr)
 		case FLT_REG_GOLD_FW:
 			ha->flt_region_gold_fw = start;
 			break;
+		case FLT_REG_BOOT_CODE_82xx:
+			ha->flt_region_boot = start;
+			break;
+		case FLT_REG_FW_82xx:
+			ha->flt_region_fw = start;
+			break;
+		case FLT_REG_GOLD_FW_82xx:
+			ha->flt_region_gold_fw = start;
+			break;
+		case FLT_REG_BOOTLOAD_82xx:
+			ha->flt_region_bootload = start;
+			break;
+		case FLT_REG_VPD_82xx:
+			ha->flt_region_vpd = start;
+			break;
 		case FLT_REG_FCP_PRIO_0:
 			if (!(PCI_FUNC(ha->pdev->devfn) & 1))
 				ha->flt_region_fcp_prio = start;
@@ -790,9 +813,9 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
 	uint16_t *wptr;
 	struct qla_fdt_layout *fdt;
 	uint8_t	man_id, flash_id;
-	uint16_t mid, fid;
+	uint16_t mid = 0, fid = 0;
 
-	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
+	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha))
 		return;
 
 	wptr = (uint16_t *)ha->request_ring;
@@ -833,6 +856,10 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
 
 no_flash_data:
 	loc = locations[0];
+	if (IS_QLA82XX(ha)) {
+		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+		goto done;
+	}
 	qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
 	ha->fdt_wrt_disable = 0x9c;
 	mid = man_id;
@@ -870,13 +897,40 @@ done:
 	    ha->fdt_block_size));
 }
 
+static void
+qla2xxx_get_idc_param(scsi_qla_host_t *ha)
+{
+#define QLA82XX_IDC_PARAM_ADDR	0x003e885c
+	uint32_t *wptr;
+
+	if (!IS_QLA82XX(ha))
+		return;
+	wptr = (uint32_t *)ha->request_ring;
+	ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
+	    QLA82XX_IDC_PARAM_ADDR , 8);
+
+	if (*wptr == __constant_cpu_to_le32(0xffffffff)) {
+		ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT;
+		ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT;
+	} else {
+		ha->nx_dev_init_timeout = le32_to_cpu(*wptr++);
+		ha->nx_reset_timeout = le32_to_cpu(*wptr);
+	}
+
+	DEBUG2(qla_printk(KERN_DEBUG, ha,
+	    "ha->nx_dev_init_timeout = %d\n", ha->nx_dev_init_timeout));
+	DEBUG2(qla_printk(KERN_DEBUG, ha,
+	    "ha->nx_reset_timeout = %d\n", ha->nx_reset_timeout));
+	return;
+}
+
 int
 qla2xxx_get_flash_info(scsi_qla_host_t *ha)
 {
 	int ret;
 	uint32_t flt_addr;
 
-	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
+	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha))
 		return QLA_SUCCESS;
 
 	ret = qla2xxx_find_flt_start(ha, &flt_addr);
@@ -885,6 +939,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha)
 
 	qla2xxx_get_flt_info(ha, flt_addr);
 	qla2xxx_get_fdt_info(ha);
+	qla2xxx_get_idc_param(ha);
 
 	return QLA_SUCCESS;
 }
@@ -899,7 +954,7 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha)
 	struct qla_npiv_header hdr;
 	struct qla_npiv_entry *entry;
 
-	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
+	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha))
 		return;
 
 	ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr,
@@ -1127,7 +1182,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
 
 		/* Do sector protect. */
 		if (ha->fdt_unprotect_sec_cmd &&
-		    ((faddr & rest_addr) == rest_addr))
+			((faddr & rest_addr) == rest_addr))
 			qla24xx_write_flash_dword(ha,
 			    ha->fdt_protect_sec_cmd,
 			    (fdata & 0xff00) | ((fdata << 16) &
@@ -1485,6 +1540,9 @@ qla24xx_beacon_blink(struct scsi_qla_host *ha)
 	unsigned long flags;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
+	if (IS_QLA82XX(ha))
+		return;
+
 	/* Save the Original GPIOD. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	gpio_data = RD_REG_DWORD(&reg->gpiod);
@@ -1517,6 +1575,9 @@ qla24xx_beacon_on(struct scsi_qla_host *ha)
 	unsigned long flags;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
+	if (IS_QLA82XX(ha))
+		return QLA_SUCCESS;
+
 	if (ha->beacon_blink_led == 0) {
 		/* Enable firmware for update */
 		ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
@@ -1558,6 +1619,9 @@ qla24xx_beacon_off(struct scsi_qla_host *ha)
 	unsigned long flags;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
+	if (IS_QLA82XX(ha))
+		return QLA_SUCCESS;
+
 	ha->beacon_blink_led = 0;
 	ha->beacon_color_state = QLA_LED_ALL_ON;
 
@@ -2333,6 +2397,167 @@ slow_read:
     return qla24xx_read_optrom_data(ha, buf, offset, length);
 }
 
+uint32_t *
+qla82xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+    uint32_t length)
+{
+	uint32_t i;
+	uint32_t val;
+
+	/* Dword reads to flash. */
+	for (i = 0; i < length/4; i++, faddr += 4) {
+		if (qla82xx_rom_fast_read(ha, faddr, &val)) {
+			qla_printk(KERN_WARNING, ha,
+			    "Do ROM fast read failed\n");
+			goto done_read;
+		}
+		dwptr[i] = __constant_cpu_to_le32(val);
+	}
+
+done_read:
+	return dwptr;
+}
+
+/*
+Address and length are byte address
+*/
+uint8_t *
+qla82xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+    uint32_t offset, uint32_t length)
+{
+	scsi_block_requests(ha->host);
+
+	qla82xx_read_flash_data(ha, (uint32_t *)buf, offset, length);
+
+	scsi_unblock_requests(ha->host);
+
+	return buf;
+}
+
+static int
+qla82xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+    uint32_t dwords)
+{
+	int ret;
+	uint32_t liter;
+	uint32_t sec_mask, rest_addr;
+	dma_addr_t optrom_dma;
+	void *optrom = NULL;
+	int page_mode = 0;
+
+	ret = -1;
+
+	/* Prepare burst-capable write on supported ISPs. */
+	if (page_mode && !(faddr & 0xfff) &&
+	    dwords > OPTROM_BURST_DWORDS) {
+		optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+		    &optrom_dma, GFP_KERNEL);
+		if (!optrom) {
+			qla_printk(KERN_DEBUG, ha,
+			    "Unable to allocate memory for optrom burst write "
+			    "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+		}
+	}
+
+	rest_addr = ha->fdt_block_size - 1;
+	sec_mask = ~rest_addr;
+
+	ret = qla82xx_unprotect_flash(ha);
+	if (ret) {
+		qla_printk(KERN_WARNING, ha,
+		    "Unable to unprotect flash for update.\n");
+		goto write_done;
+	}
+
+	for (liter = 0; liter < dwords; liter++, faddr += 4, dwptr++) {
+		/* Are we at the beginning of a sector? */
+		if ((faddr & rest_addr) == 0) {
+
+			ret = qla82xx_erase_sector(ha, faddr);
+			if (ret) {
+				DEBUG9(qla_printk(KERN_ERR, ha,
+				    "Unable to erase sector: "
+				    "address=%x.\n", faddr));
+				break;
+			}
+		}
+
+		/* Go with burst-write. */
+		if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) {
+			/* Copy data to DMA'ble buffer. */
+			memcpy(optrom, dwptr, OPTROM_BURST_SIZE);
+
+			ret = qla2x00_load_ram(ha, optrom_dma,
+			    flash_data_to_access_addr(ha, faddr),
+			    OPTROM_BURST_DWORDS);
+			if (ret != QLA_SUCCESS) {
+				qla_printk(KERN_WARNING, ha,
+				    "Unable to burst-write optrom segment "
+				    "(%x/%x/%llx).\n", ret,
+				    flash_data_to_access_addr(ha, faddr),
+				    (unsigned long long)optrom_dma);
+				qla_printk(KERN_WARNING, ha,
+				    "Reverting to slow-write.\n");
+
+				dma_free_coherent(&ha->pdev->dev,
+				    OPTROM_BURST_SIZE, optrom, optrom_dma);
+				optrom = NULL;
+			} else {
+				liter += OPTROM_BURST_DWORDS - 1;
+				faddr += OPTROM_BURST_DWORDS - 1;
+				dwptr += OPTROM_BURST_DWORDS - 1;
+				continue;
+			}
+		}
+
+		ret = qla82xx_write_flash_dword(ha, faddr,
+		    cpu_to_le32(*dwptr));
+		if (ret) {
+			DEBUG9(printk(KERN_DEBUG "%s(%ld) Unable to program"
+			    "flash address=%x data=%x.\n", __func__,
+			    ha->host_no, faddr, *dwptr));
+			break;
+		}
+
+	}
+
+	ret = qla82xx_protect_flash(ha);
+	if (ret)
+		qla_printk(KERN_WARNING, ha,
+		    "Unable to protect flash after update.\n");
+write_done:
+	if (optrom)
+		dma_free_coherent(&ha->pdev->dev,
+		    OPTROM_BURST_SIZE, optrom, optrom_dma);
+
+	return ret;
+}
+
+
+int
+qla82xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+    uint32_t offset, uint32_t length)
+{
+	int rval;
+
+	/* Suspend HBA. */
+	scsi_block_requests(ha->host);
+
+	/* Go with write. */
+	rval = qla82xx_write_flash_data(ha, (uint32_t *)buf, offset,
+	    length >> 2);
+
+	scsi_unblock_requests(ha->host);
+
+	/* Convert return ISP82xx to generic */
+	if (rval)
+		rval = QLA_FUNCTION_FAILED;
+	else
+		rval = QLA_SUCCESS;
+
+	return rval;
+}
+
 /**
  * qla2x00_get_fcode_version() - Determine an FCODE image's version.
  * @ha: HA context