Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3597

kernel-2.6.18-194.11.1.el5.src.rpm

From: Marcus Barrow <mbarrow@redhat.com>
Date: Thu, 9 Apr 2009 13:50:51 -0400
Subject: [scsi] qla2xxx : updates and fixes from upstream, part 1
Message-id: 20090409175051.2164.57182.sendpatchset@file.bos.redhat.com
O-Subject: [rhel 5.4 patch] qla2xxx : updates and fixes from upstream, part 1
Bugzilla: 480204
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>
RH-Acked-by: Tomas Henzl <thenzl@redhat.com>

BZ 480204 - qla2xxx - updates and fixes from upstream, part 1

This group of patches if the first part of update for rhel 5.4
found during QLogic and partner testing. These patches apply
and build cleanly to 2.6.18-137.

These changes, where appropriate have been pushed upstream or
are queued for upstream.

They have been tested by QLogic and partners.

 - Ensure fcport obtained from rport->dd_data is not NULL
 - Check QLID signature in FDT.
 - Correct discrepancies during OVERRUN handling on FWI2-capable cards
 - Correct synchronization of software/firmware fcport states.
 - Add supported speed attribute to true.
 - Fix vport abort on main ISP aborts.
 - Use an rport's scsi_target_id member consistently throughout driver.
 - Alert all vports of an aynch event.
 - Correct ISP abort semantics for HBA param  & VPD update.
 - Added 8100 fw, eventaully it will be removed.
 - Correct Kernel Panic with Qlogic 2472 Card.
 - Properly acknowledge IDC notification messages.
 - Fixed IDC handling
 - Added CT Passthru support for 2G HBAs
 - Mask region code
 - Do not retry stop_firmware if the first attemtp timeouts
 - Removed unwanted warning messages

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index c12439c..31fb491 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -141,12 +141,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
 		*iter = chksum;
 	}
 
+	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "HBA not online, failing NVRAM update\n"));
+		return -EINVAL;
+	}
+
 	/* Write NVRAM. */
 	ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
 	ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
 	    count);
 
+	/* Big hammer for NVRAM setting to take effect immediately */
 	set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+	qla2xxx_wake_dpc(ha);
+	qla2x00_wait_for_chip_reset(ha);
 
 	return (count);
 }
@@ -341,6 +350,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
 		if (ha->optrom_state != QLA_SWRITING)
 			break;
 
+		if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "HBA not online, failing OptROM update\n"));
+			return -EINVAL;
+		}
+
 		DEBUG2(qla_printk(KERN_INFO, ha,
 		    "Writing flash region -- 0x%x/0x%x.\n",
 		    ha->optrom_region_start, ha->optrom_region_size));
@@ -396,6 +411,12 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
 	if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
 		return 0;
 
+	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "HBA not online, failing VPD update\n"));
+		return -EINVAL;
+	}
+
 	/* Write NVRAM. */
 	ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
 	ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count);
@@ -476,10 +497,9 @@ qla2x00_find_port(struct scsi_qla_host *ha, uint8_t *pn)
 static void
 qla2x00_wait_for_passthru_completion(struct scsi_qla_host *ha)
 {
-	if (wait_for_completion_timeout(&ha->pass_thru_intr_comp, 10 * HZ))
-		qla_printk(KERN_INFO, ha, "Passthru request completed.\n");
-	else {
-		qla_printk(KERN_WARNING, ha, "Passthru request timed out.\n");
+	if (!wait_for_completion_timeout(&ha->pass_thru_intr_comp, 10 * HZ)) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru request timed out.\n"));
 		ha->isp_ops->fw_dump(ha, 0);
 	}
 }
@@ -491,18 +511,17 @@ qla2x00_sysfs_read_els(struct kobject *kobj, char *buf, loff_t off,
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(
 	    container_of(kobj, struct device, kobj)));
 
+	if (!IS_FWI2_CAPABLE(ha))
+		return 0;
+
 	if (!ha->pass_thru_cmd_in_process || !ha->pass_thru_cmd_result) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru ELS response is not available.\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru ELS response is not available.\n"));
 		return 0;
 	}
 
 	memcpy(buf, ha->pass_thru, count);
 
-	qla_printk(KERN_INFO, ha, "Passthru ELS response %X:\n", 
-	    ((ct_iu_t *)buf)->command);
-	qla2x00_print_byte_buf(buf, min(count, (size_t)64), 16);
-
 	ha->pass_thru_cmd_result = 0;
 	ha->pass_thru_cmd_in_process = 0;
 
@@ -523,30 +542,33 @@ qla2x00_sysfs_write_els(struct kobject *kobj, char *buf, loff_t off,
 
 	count -= sizeof(request->header);
 
+	if (!IS_FWI2_CAPABLE(ha) ||
+	    atomic_read(&ha->loop_state) != LOOP_READY)
+		goto els_error0;
+
 	if (count < sizeof(request->ct_iu)) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru ELS buffer insufficient size %d...\n",
-                    (int)count);
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru ELS buffer insufficient size %ld...\n", count));
 		goto els_error0;
 	}
 
 	if (ha->pass_thru_cmd_in_process || ha->pass_thru_cmd_result) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru ELS request is already progress\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru ELS request is already progress\n"));
 		goto els_error0;
 	}
 
 	fcport = qla2x00_find_port(ha, request->header.WWPN);
 	if (!fcport) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru ELS request failed find port\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru ELS request failed find port\n"));
 		goto els_error0;
 	}
 
 	if (qla2x00_fabric_login(ha, fcport, &nextlid)) {
-		qla_printk(KERN_WARNING, ha,
+		DEBUG2(qla_printk(KERN_WARNING, ha,
 		    "Passthru ELS request failed to login port %06X\n",
-		    fcport->d_id.b24);
+		    fcport->d_id.b24));
 		goto els_error0;
 	}
 
@@ -555,15 +577,14 @@ qla2x00_sysfs_write_els(struct kobject *kobj, char *buf, loff_t off,
 
 	els_iocb = (void *)qla2x00_req_pkt(ha);
 	if (els_iocb == NULL) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru ELS request failed to get request packet\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru ELS request failed to get request packet\n"));
 		goto els_error1;
 	}
 
 	if (count > PAGE_SIZE) {
-		qla_printk(KERN_INFO, ha,
-		    "Passthru ELS request excessive size %d...\n",
-                    (int)count);
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "Passthru ELS request excessive size %ld...\n", count));
 		count = PAGE_SIZE;
 	}
 
@@ -593,12 +614,6 @@ qla2x00_sysfs_write_els(struct kobject *kobj, char *buf, loff_t off,
 	els_iocb->rx_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
 	els_iocb->rx_len = els_iocb->rx_byte_count;
 
-	qla_printk(KERN_INFO, ha, "Passthru ELS request:\n");
-	qla2x00_print_byte_buf(ha->pass_thru, min(count, (size_t)32), 16);
-
-	qla_printk(KERN_INFO, ha, "Passthru ELS IOCB:\n");
-	qla2x00_print_word_buf(els_iocb, sizeof(*els_iocb), 8);
-
 	wmb();
 	qla2x00_isp_cmd(ha);
 
@@ -611,7 +626,8 @@ els_error1:
 	ha->pass_thru_cmd_in_process = 0;
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 els_error0:
-	qla_printk(KERN_WARNING, ha, "Passthru ELS failed\n");
+	DEBUG2(qla_printk(KERN_WARNING, ha,
+	    "Passthru ELS failed on scsi(%ld)\n", ha->host_no));
 	return 0;
 }
 
@@ -634,17 +650,13 @@ qla2x00_sysfs_read_ct(struct kobject *kobj, char *buf, loff_t off,
 	    container_of(kobj, struct device, kobj)));
 
 	if (!ha->pass_thru_cmd_in_process || !ha->pass_thru_cmd_result) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru CT response is not available.\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru CT response is not available.\n"));
 		return 0;
 	}
 
 	memcpy(buf, ha->pass_thru, count);
 
-	qla_printk(KERN_INFO, ha, "Passthru CT response %X:\n", 
-	    ((ct_iu_t *)buf)->command);
-	qla2x00_print_byte_buf(buf, min(count, (size_t)64), 16);
-
 	ha->pass_thru_cmd_result = 0;
 	ha->pass_thru_cmd_in_process = 0;
 
@@ -658,38 +670,34 @@ qla2x00_sysfs_write_ct(struct kobject *kobj, char *buf, loff_t off,
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(
 	    container_of(kobj, struct device, kobj)));
 	fc_ct_request_t *request = (void *)buf;
-	struct ct_entry_24xx *ct_iocb;
+	struct ct_entry_24xx *ct_iocb = NULL;
+	ms_iocb_entry_t *ct_iocb_2G = NULL;
 	unsigned long flags;
 
+	if (atomic_read(&ha->loop_state) != LOOP_READY)
+		goto ct_error0;
+
 	if (count < sizeof(request->ct_iu)) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru CT buffer insufficient size %d...\n",
-                    (int)count);
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru CT buffer insufficient size %ld...\n", count));
 		goto ct_error0;
 	}
 
 	if (ha->pass_thru_cmd_in_process || ha->pass_thru_cmd_result) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru CT request is already progress\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru CT request is already progress\n"));
 		goto ct_error0;
 	}
 
 	if (qla2x00_mgmt_svr_login(ha)) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru CT request failed to login management server\n");
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "Passthru CT request failed to login management server\n"));
 		goto ct_error0;
 	}
 
 	ha->pass_thru_cmd_in_process = 1;
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
-	ct_iocb = (void *)qla2x00_req_pkt(ha);
-	if (ct_iocb == NULL) {
-		qla_printk(KERN_WARNING, ha,
-		    "Passthru CT request failed to get request packet\n");
-		goto ct_error1;
-	}
-
 	if (count > PAGE_SIZE) {
 		qla_printk(KERN_INFO, ha,
 		    "Passthru CT request excessive size %d...\n",
@@ -700,29 +708,71 @@ qla2x00_sysfs_write_ct(struct kobject *kobj, char *buf, loff_t off,
 	memset(ha->pass_thru, 0, PAGE_SIZE);
 	memcpy(ha->pass_thru, &request->ct_iu, count);
 
-	ct_iocb->entry_type = CT_IOCB_TYPE;
-	ct_iocb->entry_count = 1;
-	ct_iocb->entry_status = 0;
-	ct_iocb->comp_status = __constant_cpu_to_le16(0);
-	ct_iocb->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
-	ct_iocb->cmd_dsd_count = __constant_cpu_to_le16(1);
-	ct_iocb->vp_index = ha->vp_idx;
-	ct_iocb->timeout = __constant_cpu_to_le16(25);
-	ct_iocb->rsp_dsd_count = __constant_cpu_to_le16(1);
-	ct_iocb->rsp_byte_count = cpu_to_le32(PAGE_SIZE);
-	ct_iocb->cmd_byte_count = cpu_to_le32(count);
-	ct_iocb->dseg_0_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
-	ct_iocb->dseg_0_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
-	ct_iocb->dseg_0_len = ct_iocb->cmd_byte_count;
-	ct_iocb->dseg_1_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
-	ct_iocb->dseg_1_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
-	ct_iocb->dseg_1_len = ct_iocb->rsp_byte_count;
-
-	qla_printk(KERN_INFO, ha, "Passthru CT request:\n");
-	qla2x00_print_byte_buf(ha->pass_thru, min(count, (size_t)32), 16);
-
-	qla_printk(KERN_INFO, ha, "Passthru CT IOCB:\n");
-	qla2x00_print_word_buf(ct_iocb, sizeof(*ct_iocb), 8);
+	if (IS_FWI2_CAPABLE(ha)) {
+		ct_iocb = (void *)qla2x00_req_pkt(ha);
+
+		if (ct_iocb == NULL) {
+			qla_printk(KERN_WARNING, ha, "Passthru CT request "
+			    "failed to get request packet\n");
+			goto ct_error1;
+		}
+
+		ct_iocb->entry_type = CT_IOCB_TYPE;
+		ct_iocb->entry_count = 1;
+		ct_iocb->entry_status = 0;
+		ct_iocb->comp_status = __constant_cpu_to_le16(0);
+		ct_iocb->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
+		ct_iocb->cmd_dsd_count = __constant_cpu_to_le16(1);
+		ct_iocb->vp_index = ha->vp_idx;
+		ct_iocb->timeout = __constant_cpu_to_le16(25);
+		ct_iocb->rsp_dsd_count = __constant_cpu_to_le16(1);
+		ct_iocb->rsp_byte_count = cpu_to_le32(PAGE_SIZE);
+		ct_iocb->cmd_byte_count = cpu_to_le32(count);
+
+		ct_iocb->dseg_0_address[0] =
+		    cpu_to_le32(LSD(ha->pass_thru_dma));
+		ct_iocb->dseg_0_address[1] =
+		    cpu_to_le32(MSD(ha->pass_thru_dma));
+		ct_iocb->dseg_0_len = ct_iocb->cmd_byte_count;
+
+		ct_iocb->dseg_1_address[0] =
+		    cpu_to_le32(LSD(ha->pass_thru_dma));
+		ct_iocb->dseg_1_address[1] =
+		    cpu_to_le32(MSD(ha->pass_thru_dma));
+		ct_iocb->dseg_1_len = ct_iocb->rsp_byte_count;
+	} else {
+		ct_iocb_2G = (void *)qla2x00_req_pkt(ha);
+
+		if (ct_iocb_2G == NULL) {
+			qla_printk(KERN_WARNING, ha, "Passthru CT request "
+			    "failed to get request packet\n");
+			goto ct_error1;
+		}
+
+		ct_iocb_2G->entry_type = CT_IOCB_TYPE;
+		ct_iocb_2G->entry_count = 1;
+		ct_iocb_2G->entry_status = 0;
+		SET_TARGET_ID(ha, ct_iocb_2G->loop_id, ha->mgmt_svr_loop_id);
+		ct_iocb_2G->status = __constant_cpu_to_le16(0);
+		ct_iocb_2G->control_flags = __constant_cpu_to_le16(0);
+		ct_iocb_2G->timeout = __constant_cpu_to_le16(25);
+		ct_iocb_2G->cmd_dsd_count = __constant_cpu_to_le16(1);
+		ct_iocb_2G->total_dsd_count = __constant_cpu_to_le16(2);
+		ct_iocb_2G->rsp_bytecount = cpu_to_le32(PAGE_SIZE);
+		ct_iocb_2G->req_bytecount = cpu_to_le32(count);
+
+		ct_iocb_2G->dseg_req_address[0] =
+		    cpu_to_le32(LSD(ha->pass_thru_dma));
+		ct_iocb_2G->dseg_req_address[1] =
+		    cpu_to_le32(MSD(ha->pass_thru_dma));
+		ct_iocb_2G->dseg_req_length = ct_iocb_2G->req_bytecount;
+
+		ct_iocb_2G->dseg_rsp_address[0] =
+		    cpu_to_le32(LSD(ha->pass_thru_dma));
+		ct_iocb_2G->dseg_rsp_address[1] =
+		    cpu_to_le32(MSD(ha->pass_thru_dma));
+		ct_iocb_2G->dseg_rsp_length = ct_iocb_2G->rsp_bytecount;
+	}
 
 	wmb();
 	qla2x00_isp_cmd(ha);
@@ -736,7 +786,8 @@ ct_error1:
 	ha->pass_thru_cmd_in_process = 0;
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 ct_error0:
-	qla_printk(KERN_WARNING, ha, "Passthru CT failed\n");
+	DEBUG2(qla_printk(KERN_WARNING, ha,
+	    "Passthru CT failed on scsi(%ld)\n", ha->host_no));
 	return 0;
 }
 
@@ -763,7 +814,7 @@ static struct sysfs_entry {
 	{ "vpd", &sysfs_vpd_attr, 1 },
 	{ "sfp", &sysfs_sfp_attr, 1 },
 	{ "els", &sysfs_els_attr, 1 },
-	{ "ct", &sysfs_ct_attr, 1 },
+	{ "ct", &sysfs_ct_attr, },
 	{ NULL },
 };
 
@@ -1657,7 +1708,8 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
 	u64 node_name = 0;
 
 	list_for_each_entry(fcport, &ha->fcports, list) {
-		if (starget->id == fcport->os_target_id) {
+		if (fcport->rport &&
+		    starget->id == fcport->rport->scsi_target_id) {
 			node_name = wwn_to_u64(fcport->node_name);
 			break;
 		}
@@ -1675,7 +1727,8 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
 	u64 port_name = 0;
 
 	list_for_each_entry(fcport, &ha->fcports, list) {
-		if (starget->id == fcport->os_target_id) {
+		if (fcport->rport &&
+		    starget->id == fcport->rport->scsi_target_id) {
 			port_name = wwn_to_u64(fcport->port_name);
 			break;
 		}
@@ -1693,7 +1746,8 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
 	uint32_t port_id = ~0U;
 
 	list_for_each_entry(fcport, &ha->fcports, list) {
-		if (starget->id == fcport->os_target_id) {
+		if (fcport->rport &&
+		    starget->id == fcport->rport->scsi_target_id) {
 			port_id = fcport->d_id.b.domain << 16 |
 			    fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
 			break;
@@ -1718,6 +1772,19 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
 	struct Scsi_Host *host = rport_to_shost(rport);
 	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
 
+	if (!fcport)
+		return;
+	/*
+	 * At this point all fcport's software-states are cleared.  Perform any
+	 * final cleanup of firmware resources (PCBs and XCBs).
+	 */
+	if (fcport->loop_id != FC_NO_LOOP_ID) {
+		fcport->ha->isp_ops->fabric_logout(fcport->ha,
+			fcport->loop_id, fcport->d_id.b.domain,
+			fcport->d_id.b.area, fcport->d_id.b.al_pa);
+		fcport->loop_id = FC_NO_LOOP_ID;
+	}
+
 	qla2x00_abort_fcport_cmds(fcport);
 
 	/*
@@ -1735,6 +1802,19 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
 {
 	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
 
+	if (!fcport)
+		return;
+	/*
+	 * At this point all fcport's software-states are cleared.  Perform any
+	 * final cleanup of firmware resources (PCBs and XCBs).
+	 */
+	if (fcport->loop_id != FC_NO_LOOP_ID) {
+		fcport->ha->isp_ops->fabric_logout(fcport->ha,
+			fcport->loop_id, fcport->d_id.b.domain,
+			fcport->d_id.b.area, fcport->d_id.b.al_pa);
+		fcport->loop_id = FC_NO_LOOP_ID;
+	}
+
 	qla2x00_abort_fcport_cmds(fcport);
 	scsi_target_unblock(&rport->dev);
 }
@@ -1851,6 +1931,7 @@ struct fc_function_template qla2xxx_transport_functions = {
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_supported_classes = 1,
+	.show_host_supported_speeds = 1,
 
 	.get_host_port_id = qla2x00_get_host_port_id,
 	.show_host_port_id = 1,
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index af163b1..b1dec9e 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1740,36 +1740,6 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
 	printk("  sp flags=0x%x\n", sp->flags);
 }
 
-void
-qla2x00_print_byte_buf(void *buffer, size_t count, size_t per_line)
-{
-	uint8_t *p = buffer;
-	size_t i;
-
-	for (i = 0; i < count; i++){
-		if (i && per_line && !(i % per_line))
-			printk("\n");
-		printk(" %02X", *p++);
-	}
-	printk("\n");
-}
-
-void
-qla2x00_print_word_buf(void *buffer, size_t count, size_t per_line)
-{
-	uint16_t *p = buffer;
-	size_t i;
-
-	count /= sizeof(*p);
-
-	for (i = 0; i < count; i++) {
-		if (i && per_line && !(i % per_line))
-			printk("\n");
-		printk(" %04X", *p++);
-	}
-	printk("\n");
-}
-
 #if defined(QL_DEBUG_ROUTINES)
 /*
  * qla2x00_formatted_dump_buffer
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 04bb84b..38d5029 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -705,6 +705,7 @@ typedef struct {
 #define MBC_SEND_RNFT_ELS		0x5e	/* Send RNFT ELS request */
 #define MBC_GET_LINK_PRIV_STATS		0x6d	/* Get link & private data. */
 #define MBC_SET_VENDOR_ID		0x76	/* Set Vendor ID. */
+#define MBC_IDC_ACK			0x101   /* Ack IDC */
 
 #define TC_ENABLE			4
 #define TC_DISABLE			5
@@ -1629,8 +1630,6 @@ typedef struct fc_port {
 	atomic_t state;
 	uint32_t flags;
 
-	unsigned int os_target_id;
-
 	int port_login_retry_count;
 	int login_retry;
 	atomic_t port_down_timer;
@@ -2234,11 +2233,31 @@ struct qlfc_fw {
         uint32_t len;
 };
 
+/* Work events.  */
+enum qla_work_type {
+       QLA_EVT_IDC_ACK,
+};
+
+struct qla_work_evt {
+       struct list_head        list;
+       enum qla_work_type      type;
+       u32                     flags;
+#define QLA_EVT_FLAG_FREE       0x1
+
+       union {
+               struct {
+#define QLA_IDC_ACK_REGS        7
+                       uint16_t mb[QLA_IDC_ACK_REGS];
+               } idc_ack;
+       } u;
+};
+
 /*
  * Linux Host Adapter structure
  */
 typedef struct scsi_qla_host {
 	struct list_head list;
+	struct list_head work_list;
 
 	/* Commonly used flags and state information. */
 	struct Scsi_Host *host;
@@ -2272,6 +2291,7 @@ typedef struct scsi_qla_host {
 		uint32_t        vsan_enabled            :1;
 		uint32_t        npiv_supported          :1;
 		uint32_t        pci_channel_io_perm_failure          :1;
+		uint32_t        chip_reset_done         :1;
 	} flags;
 
 	atomic_t	loop_state;
@@ -2554,7 +2574,7 @@ typedef struct scsi_qla_host {
 #define  MBX_TIMEDOUT		BIT_5
 #define  MBX_ACCESS_TIMEDOUT	BIT_6
 
-	mbx_cmd_t 	mc;
+	mbx_cmd_t       mc;
 
 	/* Basic firmware related information. */
 	uint16_t	fw_major_version;
diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h
index d78d35e..d6ea69d 100644
--- a/drivers/scsi/qla2xxx/qla_devtbl.h
+++ b/drivers/scsi/qla2xxx/qla_devtbl.h
@@ -72,7 +72,7 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
 	"QLA2462",	"Sun PCI-X 2.0 to 4Gb FC, Dual Channel",	/* 0x141 */
 	"QLE2460",	"Sun PCI-Express to 2Gb FC, Single Channel",	/* 0x142 */
 	"QLE2462",	"Sun PCI-Express to 4Gb FC, Single Channel",	/* 0x143 */
-	"QEM2462"	"Server I/O Module 4Gb FC, Dual Channel",	/* 0x144 */
+	"QEM2462",	"Server I/O Module 4Gb FC, Dual Channel",	/* 0x144 */
 	"QLE2440",	"PCI-Express to 4Gb FC, Single Channel",	/* 0x145 */
 	"QLE2464",	"PCI-Express to 4Gb FC, Quad Channel",		/* 0x146 */
 	"QLA2440",	"PCI-X 2.0 to 4Gb FC, Single Channel",		/* 0x147 */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1d3100e..22cee28 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -54,6 +54,8 @@ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
 
 extern void qla84xx_put_chip(struct scsi_qla_host *);
 
+extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
+
 /*
  * Global Data in qla_os.c source file.
  */
@@ -109,11 +111,12 @@ extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
 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 void qla2xxx_wake_dpc(scsi_qla_host_t *);
 extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *);
 extern void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
-extern void qla2x00_vp_abort_isp(scsi_qla_host_t *);
+extern int qla2x00_vp_abort_isp(scsi_qla_host_t *);
 extern void fc_convert_hex_char(uint8_t *, char *, int);
 extern int fc_parse_wwn(const char *, u64 *);
 
@@ -262,6 +265,9 @@ extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
 extern int
 qla84xx_reset(struct scsi_qla_host *, uint32_t);
 
+extern int
+qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -329,8 +335,6 @@ extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla2x00_dump_regs(scsi_qla_host_t *);
 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
 extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
-extern void qla2x00_print_byte_buf(void *, size_t, size_t);
-extern void qla2x00_print_word_buf(void *, size_t, size_t);
 
 /*
  * Global Function Prototypes in qla_gs.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 6bbd2bb..404d31e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -65,6 +65,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 
 	/* Clear adapter flags. */
 	ha->flags.online = 0;
+	ha->flags.chip_reset_done = 0;
 	ha->flags.reset_active = 0;
 	ha->flags.pci_channel_io_perm_failure = 0;
 	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
@@ -138,6 +139,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 	}
 
 	rval = qla2x00_init_rings(ha);
+	ha->flags.chip_reset_done = 1;
 
 	if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
 		/* Issue verify 84xx FW IOCB to complete 84xx initialization */
@@ -2183,9 +2185,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
 		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
 	fc_remote_port_rolechg(rport, rport_ids.roles);
 
-	if (rport->scsi_target_id != -1 &&
-	    rport->scsi_target_id < ha->host->max_id)
-		fcport->os_target_id = rport->scsi_target_id;
 }
 
 /*
@@ -3172,9 +3171,11 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 	uint16_t       cnt;
 	srb_t          *sp;
 	uint8_t        status = 0;
+	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++;
 
@@ -3287,6 +3288,12 @@ isp_return:
 		qla_printk(KERN_INFO, ha,
 			"qla2x00_abort_isp: **** FAILED ****\n");
 	} else {
+
+		list_for_each_entry(vha, &ha->vp_list, vp_list) {
+			if (vha->vp_idx)
+				qla2x00_vp_abort_isp(vha);
+		}
+
 		DEBUG(printk(KERN_INFO
 				"qla2x00_abort_isp(%ld): exiting.\n",
 				ha->host_no));
@@ -3364,6 +3371,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
  done:
 	if (!status && !(status = qla2x00_init_rings(ha))) {
 		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+		ha->flags.chip_reset_done = 1;
 		if (!(status = qla2x00_fw_ready(ha))) {
 			DEBUG(printk("%s(): Start configure loop, "
 			    "status = %d\n", __func__, status));
@@ -3938,7 +3946,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
 		return;
 
 	ret = qla2x00_stop_firmware(ha);
-	for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) {
+	for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
+	    retries ; retries--) {
 		qla2x00_reset_chip(ha);
 		if (qla2x00_chip_diag(ha) != QLA_SUCCESS)
 			continue;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 554d77f..069d3a6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -261,6 +261,43 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
 	}
 }
 
+static void
+qla81xx_idc_event(scsi_qla_host_t *ha, uint16_t aen, uint16_t descr)
+{
+
+	int rval = 0;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
+
+	static char *event[] =
+	    { "Complete", "Request Notification", "Time Extension" };
+	struct device_reg_24xx __iomem *reg24 = &pha->iobase->isp24;
+	uint16_t __iomem *wptr;
+	uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
+
+	/* Seed data -- mailbox1 -> mailbox7. */
+	wptr = (uint16_t __iomem *)&reg24->mailbox1;
+	for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
+		mb[cnt] = RD_REG_WORD(wptr);
+
+	DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+	    "%04x %04x %04x %04x %04x %04x %04x.\n", ha->host_no,
+	    event[aen & 0xff],
+	    mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+
+	/* Acknowledgement needed? [Notify && non-zero timeout]. */
+	timeout = (descr >> 8) & 0xf;
+	if (aen != MBA_IDC_NOTIFY || !timeout)
+		return;
+
+	DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+	     "ACK timeout=%d.\n", ha->host_no, event[aen & 0xff], timeout));
+
+	rval = qla2x00_post_idc_ack_work(ha, mb);
+	if (rval != QLA_SUCCESS)
+		qla_printk(KERN_WARNING, ha,
+				"IDC failed to post ACK.\n");
+}
+
 /**
  * qla2x00_async_event() - Process aynchronous events.
  * @ha: SCSI driver HA context
@@ -716,23 +753,14 @@ skip_rio:
 		    "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
 		break;
 	case MBA_IDC_COMPLETE:
-		DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-		    "Complete -- %04x %04x %04x\n", ha->host_no, mb[1], mb[2],
-		    mb[3]));
-		break;
 	case MBA_IDC_NOTIFY:
-		DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-		    "Request Notification -- %04x %04x %04x\n", ha->host_no,
-		    mb[1], mb[2], mb[3]));
-		/**** Mailbox registers 4 - 7 valid!!! */
-		break;
 	case MBA_IDC_TIME_EXT:
-		DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-		    "Time Extension -- %04x %04x %04x\n", ha->host_no, mb[1],
-		    mb[2], mb[3]));
-		/**** Mailbox registers 4 - 7 valid!!! */
+		 qla81xx_idc_event(ha, mb[0], mb[1]);
 		break;
 	}
+
+	if (!ha->vp_idx && ha->num_vhosts)
+                qla2x00_alert_all_vps(ha, mb);
 }
 
 static void
@@ -896,7 +924,19 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
 			qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
 			break;
 		case MS_IOCB_TYPE:
-			qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
+			if (ha->outstanding_cmds[pkt->handle])
+				qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
+			else {
+				if (ha->pass_thru_cmd_result)
+					qla_printk(KERN_INFO, ha,
+					    "Passthru cmd result on.\n");
+				if (!ha->pass_thru_cmd_in_process)
+					qla_printk(KERN_INFO, ha,
+					    "Passthru in process off.\n");
+
+				ha->pass_thru_cmd_result = 1;
+				complete(&ha->pass_thru_intr_comp);
+			}
 			break;
 		default:
 			/* Type Not Supported. */
@@ -1050,6 +1090,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
 		}
 	}
 
+	/* Check for overrun. */
+	if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE &&
+	    scsi_status & SS_RESIDUAL_OVER)
+		comp_status = CS_DATA_OVERRUN;
+
 	/*
 	 * Based on Host and scsi status generate status code for Linux
 	 */
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index ef86059..a007cce 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2939,3 +2939,30 @@ verify_done:
 
 	return rval;
 }
+
+int
+qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+	mcp->mb[0] = MBC_IDC_ACK;
+	memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(vha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+		    vha->host_no, rval, mcp->mb[0]));
+	} else {
+		DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+	}
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 290deca..601c72a 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -218,43 +218,35 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
 void
 qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb)
 {
-	int i, vp_idx_matched;
+	int i = 0;
 	scsi_qla_host_t *vha;
 
 	if (ha->parent)
 		return;
 
-	for_each_mapped_vp_idx(ha, i) {
-		vp_idx_matched = 0;
-
-		list_for_each_entry(vha, &ha->vp_list, vp_list) {
-			if (i == vha->vp_idx) {
-				vp_idx_matched = 1;
-				break;
-			}
-		}
-
-		if (vp_idx_matched) {
-			switch (mb[0]) {
-			case MBA_LIP_OCCURRED:
-			case MBA_LOOP_UP:
-			case MBA_LOOP_DOWN:
-			case MBA_LIP_RESET:
-			case MBA_POINT_TO_POINT:
-			case MBA_CHG_IN_CONNECTION:
-			case MBA_PORT_UPDATE:
-			case MBA_RSCN_UPDATE:
-				DEBUG15(printk("scsi(%ld)%s: Async_event for"
-				    " VP[%d], mb = 0x%x, vha=%p\n",
-				    vha->host_no, __func__,i, *mb, vha));
-				qla2x00_async_event(vha, mb);
-				break;
-			}
-		}
-	}
+        list_for_each_entry(vha, &ha->vp_list, vp_list) {
+                if (vha->vp_idx) {
+                        switch (mb[0]) {
+                        case MBA_LIP_OCCURRED:
+                        case MBA_LOOP_UP:
+                        case MBA_LOOP_DOWN:
+                        case MBA_LIP_RESET:
+                        case MBA_POINT_TO_POINT:
+                        case MBA_CHG_IN_CONNECTION:
+                        case MBA_PORT_UPDATE:
+                        case MBA_RSCN_UPDATE:
+                                DEBUG15(printk("scsi(%ld)%s: Async_event for"
+                                " VP[%d], mb = 0x%x, vha=%p\n",
+                                vha->host_no, __func__, i, *mb, vha));
+                                qla2x00_async_event(vha, mb);
+                                break;
+                        }
+                }
+                i++;
+        }
 }
 
-void
+int
 qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
 {
 	/*
@@ -269,9 +261,16 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
 			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 	}
 
+        /* To exclusively reset vport, we need to log it out first.
+	 * Note: this control_vp can fail if ISP reset is already issued, this
+	 * is expected, as the vp would be already logged out due to ISP reset.
+	 */
+        if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
+                qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
+
 	DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
 	    vha->host_no, vha->vp_idx));
-	qla24xx_enable_vp(vha);
+	return qla24xx_enable_vp(vha);
 }
 
 static int
@@ -444,6 +443,11 @@ qla24xx_create_vhost(scsi_qla_host_t *ha, uint64_t fc_wwpn, uint64_t fc_wwnn)
 	u64_to_wwn(fc_wwpn, vha->port_name);
 	u64_to_wwn(fc_wwnn, vha->node_name);
 
+	INIT_LIST_HEAD(&vha->list);
+	INIT_LIST_HEAD(&vha->vp_list);
+	INIT_LIST_HEAD(&vha->fcports);
+	INIT_LIST_HEAD(&vha->vp_fcports);
+
 	vha->host = host;
 	vha->host_no = host->host_no;
 	vha->parent = ha;
@@ -461,10 +465,6 @@ qla24xx_create_vhost(scsi_qla_host_t *ha, uint64_t fc_wwpn, uint64_t fc_wwnn)
 	complete(&vha->mbx_cmd_comp);
 	init_completion(&vha->mbx_intr_comp);
 
-	INIT_LIST_HEAD(&vha->list);
-	INIT_LIST_HEAD(&vha->fcports);
-	INIT_LIST_HEAD(&vha->vp_fcports);
-
 	vha->dpc_flags = 0L;
 	set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
 	set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index abb57eb..e006599 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -551,6 +551,48 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
 }
 
 /*
+ * qla2x00_wait_for_chip_reset
+ *    Wait till the HBA chip is reset.
+ *
+ * Note:
+ *    Does context switching-Release SPIN_LOCK
+ *    (if any) before calling this routine.
+ *
+ * Return:
+ *    Success (Chip reset is done) : 0
+ *    Failed  (Chip reset not completed within max loop timoue ) : 1
+ */
+int
+qla2x00_wait_for_chip_reset(scsi_qla_host_t *ha)
+{
+       int             return_status;
+       unsigned long   wait_reset;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
+
+       wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+       while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) ||
+           test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) ||
+           test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) ||
+           pha->dpc_active) && time_before(jiffies, wait_reset)) {
+
+               msleep(1000);
+
+               if (!test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags) &&
+                   pha->flags.chip_reset_done)
+                       break;
+       }
+       if (pha->flags.chip_reset_done)
+               return_status = QLA_SUCCESS;
+       else
+               return_status = QLA_FUNCTION_FAILED;
+
+       DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
+
+       return return_status;
+}
+
+
+/*
  * qla2x00_wait_for_hba_online
  *    Wait till the HBA is online after going through
  *    <= MAX_RETRIES_OF_ISP_ABORT  or
@@ -1012,7 +1054,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 
 eh_bus_reset_done:
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
-	    (ret == FAILED) ? "failed" : "succeded");
+	    (ret == FAILED) ? "failed" : "succeeded");
 
 	return ret;
 }
@@ -1068,27 +1110,29 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 	 * while dpc is stuck for the mailbox to complete.
 	 */
 	qla2x00_wait_for_loop_ready(ha);
-	set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
-	if (qla2x00_abort_isp(pha)) {
-		clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
-		/* failed. schedule dpc to try */
-		set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags);
-
-		if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
+	if (ha != pha) {
+		if (qla2x00_vp_abort_isp(ha))
 			goto eh_host_reset_lock;
+	} else {
+		set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+		if (qla2x00_abort_isp(pha)) {
+			clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+			/* failed. schedule dpc to try */
+			set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags);
+
+			if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
+				goto eh_host_reset_lock;
+		}
+		clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
 	}
-	clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
 
 	/* Waiting for our command in done_queue to be returned to OS.*/
 	if (qla2x00_eh_wait_for_pending_commands(pha))
 		ret = SUCCESS;
 
-	if (ha->parent)
-		qla2x00_vp_abort_isp(ha);
-
 eh_host_reset_lock:
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
-	    (ret == FAILED) ? "failed" : "succeded");
+	    (ret == FAILED) ? "failed" : "succeeded");
 
 	return ret;
 }
@@ -1816,6 +1860,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	init_completion(&ha->mbx_intr_comp);
 
 	INIT_LIST_HEAD(&ha->list);
+	INIT_LIST_HEAD(&ha->work_list);
 	INIT_LIST_HEAD(&ha->fcports);
 	INIT_LIST_HEAD(&ha->vp_list);
 
@@ -2531,6 +2576,74 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha)
 	}
 }
 
+static struct qla_work_evt *
+qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
+    int locked)
+{
+       struct qla_work_evt *e;
+
+       e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
+           GFP_KERNEL);
+       if (!e)
+               return NULL;
+
+       INIT_LIST_HEAD(&e->list);
+       e->type = type;
+       e->flags = QLA_EVT_FLAG_FREE;
+       return e;
+}
+
+static int
+qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
+{
+	unsigned long flags = 0;
+
+	if (!locked)
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+	list_add_tail(&e->list, &ha->work_list);
+	qla2xxx_wake_dpc(ha);
+	if (!locked)
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	return QLA_SUCCESS;
+}
+
+int
+qla2x00_post_idc_ack_work(struct scsi_qla_host *ha, uint16_t *mb)
+{
+	struct qla_work_evt *e;
+
+	e = qla2x00_alloc_work(ha, QLA_EVT_IDC_ACK, 1);
+	if (!e)
+		return QLA_FUNCTION_FAILED;
+
+	memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+	return qla2x00_post_work(ha, e, 1);
+}
+
+static void
+qla2x00_do_work(struct scsi_qla_host *ha)
+{
+	struct qla_work_evt *e;
+
+	spin_lock_irq(&ha->hardware_lock);
+	while (!list_empty(&ha->work_list)) {
+		e = list_entry(ha->work_list.next, struct qla_work_evt, list);
+		list_del_init(&e->list);
+		spin_unlock_irq(&ha->hardware_lock);
+
+		switch (e->type) {
+			case QLA_EVT_IDC_ACK:
+				qla81xx_idc_ack(ha, e->u.idc_ack.mb);
+				break;
+		}
+		if (e->flags & QLA_EVT_FLAG_FREE)
+			kfree(e);
+		spin_lock_irq(&ha->hardware_lock);
+	}
+	spin_unlock_irq(&ha->hardware_lock);
+}
+
+
 /**************************************************************************
 * qla2x00_do_dpc
 *   This kernel thread is a task that is schedule by the interrupt handler
@@ -2579,6 +2692,8 @@ qla2x00_do_dpc(void *data)
 			continue;
 		}
 
+		qla2x00_do_work(ha);
+
 		if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
 
 			DEBUG(printk("scsi(%ld): dpc: sched "
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 6c8349a..fb8f4a7 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -686,7 +686,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr)
 		    "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
 		    le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
 
-		switch (le32_to_cpu(region->code)) {
+		switch (le32_to_cpu(region->code) & 0xff) {
 		case FLT_REG_FW:
 			ha->flt_region_fw = start;
 			break;
@@ -756,6 +756,9 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
 	    ha->flt_region_fdt << 2, OPTROM_BURST_SIZE);
 	if (*wptr == __constant_cpu_to_le16(0xffff))
 		goto no_flash_data;
+	if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
+	    fdt->sig[3] != 'D')
+		goto no_flash_data;
 
 	for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;
 	    cnt++)
@@ -1878,7 +1881,7 @@ qla2x00_resume_hba(struct scsi_qla_host *ha)
 	clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
 	set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
 	qla2xxx_wake_dpc(ha);
-	qla2x00_wait_for_hba_online(ha);
+	qla2x00_wait_for_chip_reset(ha);
 	scsi_unblock_requests(ha->host);
 }