changeset 10736:d831c82c5d2c

6866510 Mismatched Metis FC-Qlogic Fcode level reported by 'fcinfo' and '.properties' 6867260 ssd_io_time to setting does not take effect in qlc driver while shorter than 25 6875471 fix failed for 6856545: ssertion failed: !MUTEX_HELD(&ha->mutex), file: ... 6876303 qlc driver fails to suspend during suspend/resume DR operation on an M5000 6883190 Failed SunVTS diagnostic 'HBA component stress' test. 6885119 qlc driver fails to initialize CNA cards on the M5000, but initializes OK on other platforms
author Daniel Beauregard <Daniel.Beauregard@Sun.COM>
date Wed, 07 Oct 2009 16:02:38 -0700
parents 336fb268ea6f
children c6d4bb2a188c
files usr/src/cmd/mdb/common/modules/qlc/qlc.c usr/src/uts/common/io/fibre-channel/fca/qlc/ql_api.c usr/src/uts/common/io/fibre-channel/fca/qlc/ql_init.c usr/src/uts/common/io/fibre-channel/fca/qlc/ql_isr.c usr/src/uts/common/io/fibre-channel/fca/qlc/ql_mbx.c usr/src/uts/common/io/fibre-channel/fca/qlc/ql_xioctl.c usr/src/uts/common/sys/fibre-channel/fca/qlc/exioct.h usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_init.h usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_mbx.h usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_open.h
diffstat 10 files changed, 1200 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/qlc/qlc.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/cmd/mdb/common/modules/qlc/qlc.c	Wed Oct 07 16:02:38 2009 -0700
@@ -72,6 +72,8 @@
     const mdb_arg_t *);
 static int ql_25xx_dump_dcmd(ql_adapter_state_t *, uint_t, int,
     const mdb_arg_t *);
+static int ql_81xx_dump_dcmd(ql_adapter_state_t *, uint_t, int,
+    const mdb_arg_t *);
 static void ql_elog_common(ql_adapter_state_t *, boolean_t);
 
 /*
@@ -1814,8 +1816,10 @@
 
 	if (CFG_IST(ha, CFG_CTRL_2422)) {
 		(void) ql_24xx_dump_dcmd(ha, flags, argc, argv);
-	} else if (CFG_IST(ha, CFG_CTRL_2581))  {
+	} else if (CFG_IST(ha, CFG_CTRL_25XX))  {
 		(void) ql_25xx_dump_dcmd(ha, flags, argc, argv);
+	} else if (CFG_IST(ha, CFG_CTRL_81XX))  {
+		(void) ql_81xx_dump_dcmd(ha, flags, argc, argv);
 	} else {
 		(void) ql_23xx_dump_dcmd(ha, flags, argc, argv);
 	}
@@ -2776,6 +2780,382 @@
 }
 
 /*
+ * ql_81xx_dump_dcmd
+ *	prints out a firmware dump buffer
+ *
+ * Input:
+ *	addr  = User supplied address. (NB: nust be an ha)
+ *	flags = mdb flags.
+ *	argc  = Number of user supplied args.
+ *	argv  = Arg array.
+ *
+ * Returns:
+ *	DCMD_OK or DCMD_ERR
+ *
+ * Context:
+ *	User context.
+ *
+ */
+/*ARGSUSED*/
+static int
+ql_81xx_dump_dcmd(ql_adapter_state_t *ha, uint_t flags, int argc,
+    const mdb_arg_t *argv)
+{
+	ql_81xx_fw_dump_t	*fw;
+	uint32_t		cnt = 0;
+
+	fw = (ql_81xx_fw_dump_t *)mdb_alloc(ha->ql_dump_size, UM_SLEEP);
+
+	if (mdb_vread(fw, ha->ql_dump_size,
+	    (uintptr_t)ha->ql_dump_ptr) == -1) {
+		mdb_warn("failed to read ql_dump_ptr (no f/w dump active?)");
+		mdb_free(fw, ha->ql_dump_size);
+		return (DCMD_OK);
+	}
+
+	mdb_printf("\nISP FW Version %d.%02d.%02d Attributes %X\n",
+	    ha->fw_major_version, ha->fw_minor_version,
+	    ha->fw_subminor_version, ha->fw_attributes);
+
+	mdb_printf("\nR2H Register\n%08x\n", fw->r2h_status);
+
+	mdb_printf("\n\nHostRisc Registers");
+	for (cnt = 0; cnt < sizeof (fw->hostrisc_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->hostrisc_reg[cnt]);
+	}
+
+	mdb_printf("\n\nPCIe Registers");
+	for (cnt = 0; cnt < sizeof (fw->pcie_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->pcie_reg[cnt]);
+	}
+
+	mdb_printf("\n\nHost Interface Registers");
+	for (cnt = 0; cnt < sizeof (fw->host_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->host_reg[cnt]);
+	}
+
+	mdb_printf("\n\nShadow Registers");
+	for (cnt = 0; cnt < sizeof (fw->shadow_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+
+		mdb_printf("%08x ", fw->shadow_reg[cnt]);
+	}
+
+	mdb_printf("\n\nMailbox Registers");
+	for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
+		if (cnt % 16 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%04x ", fw->mailbox_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXSEQ GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->xseq_gp_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xseq_gp_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXSEQ-0 Registers");
+	for (cnt = 0; cnt < sizeof (fw->xseq_0_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xseq_0_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXSEQ-1 Registers");
+	for (cnt = 0; cnt < sizeof (fw->xseq_1_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xseq_1_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRSEQ GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->rseq_gp_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rseq_gp_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRSEQ-0 Registers");
+	for (cnt = 0; cnt < sizeof (fw->rseq_0_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rseq_0_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRSEQ-1 Registers");
+	for (cnt = 0; cnt < sizeof (fw->rseq_1_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rseq_1_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRSEQ-2 Registers");
+	for (cnt = 0; cnt < sizeof (fw->rseq_2_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rseq_2_reg[cnt]);
+	}
+
+	mdb_printf("\n\nASEQ GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->aseq_gp_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->aseq_gp_reg[cnt]);
+	}
+
+	mdb_printf("\n\nASEQ-0 GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->aseq_0_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+
+		mdb_printf("%08x ", fw->aseq_0_reg[cnt]);
+	}
+
+	mdb_printf("\n\nASEQ-1 GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->aseq_1_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+
+		mdb_printf("%08x ", fw->aseq_1_reg[cnt]);
+	}
+
+	mdb_printf("\n\nASEQ-2 GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->aseq_2_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->aseq_2_reg[cnt]);
+	}
+
+	mdb_printf("\n\nCommand DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->cmd_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->cmd_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRequest0 Queue DMA Channel Registers");
+	for (cnt = 0; cnt < sizeof (fw->req0_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->req0_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nResponse0 Queue DMA Channel Registers");
+	for (cnt = 0; cnt < sizeof (fw->resp0_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->resp0_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRequest1 Queue DMA Channel Registers");
+	for (cnt = 0; cnt < sizeof (fw->req1_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->req1_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT0 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt0_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt0_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT1 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt1_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt1_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT2 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt2_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt2_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT3 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt3_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt3_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT4 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt4_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt4_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nXMT Data DMA Common Registers");
+	for (cnt = 0; cnt < sizeof (fw->xmt_data_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->xmt_data_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRCV Thread 0 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->rcvt0_data_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rcvt0_data_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRCV Thread 1 Data DMA Registers");
+	for (cnt = 0; cnt < sizeof (fw->rcvt1_data_dma_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->rcvt1_data_dma_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRISC GP Registers");
+	for (cnt = 0; cnt < sizeof (fw->risc_gp_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->risc_gp_reg[cnt]);
+	}
+
+	mdb_printf("\n\nRISC IO Register\n%08x", fw->risc_io);
+
+	mdb_printf("\n\nLMC Registers");
+	for (cnt = 0; cnt < sizeof (fw->lmc_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->lmc_reg[cnt]);
+	}
+
+	mdb_printf("\n\nFPM Hardware Registers");
+	for (cnt = 0; cnt < sizeof (fw->fpm_hdw_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->fpm_hdw_reg[cnt]);
+	}
+
+	mdb_printf("\n\nFB Hardware Registers");
+	for (cnt = 0; cnt < sizeof (fw->fb_hdw_reg) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n");
+		}
+		mdb_printf("%08x ", fw->fb_hdw_reg[cnt]);
+	}
+
+	mdb_printf("\n\nCode RAM");
+	for (cnt = 0; cnt < sizeof (fw->code_ram) / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n%08x: ", cnt + 0x20000);
+		}
+		mdb_printf("%08x ", fw->code_ram[cnt]);
+	}
+
+	mdb_printf("\n\nExternal Memory");
+	for (cnt = 0; cnt < ha->fw_ext_memory_size / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n%08x: ", cnt + 0x100000);
+		}
+		mdb_printf("%08x ", fw->ext_mem[cnt]);
+	}
+
+	mdb_printf("\n[<==END] ISP Debug Dump");
+
+	mdb_printf("\n\nRequest Queue");
+
+	for (cnt = 0; cnt < REQUEST_QUEUE_SIZE / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n%08x: ", cnt);
+		}
+		mdb_printf("%08x ", fw->req_q[cnt]);
+	}
+
+	mdb_printf("\n\nResponse Queue");
+
+	for (cnt = 0; cnt < RESPONSE_QUEUE_SIZE / 4; cnt++) {
+		if (cnt % 8 == 0) {
+			mdb_printf("\n%08x: ", cnt);
+		}
+		mdb_printf("%08x ", fw->rsp_q[cnt]);
+	}
+
+	if ((ha->cfg_flags & CFG_ENABLE_FWEXTTRACE) &&
+	    (ha->fwexttracebuf.bp != NULL)) {
+		uint32_t cnt_b = 0;
+		uint32_t *w32 = ha->fwexttracebuf.bp;
+
+		mdb_printf("\n\nExtended Trace Buffer Memory");
+		/* show data address as a byte address, data as long words */
+		for (cnt = 0; cnt < FWEXTSIZE / 4; cnt++) {
+			cnt_b = cnt * 4;
+			if (cnt_b % 32 == 0) {
+				mdb_printf("\n%08x: ", w32 + cnt_b);
+			}
+			mdb_printf("%08x ", fw->ext_trace_buf[cnt]);
+		}
+	}
+
+	if ((ha->cfg_flags & CFG_ENABLE_FWFCETRACE) &&
+	    (ha->fwfcetracebuf.bp != NULL)) {
+		uint32_t cnt_b = 0;
+		uint32_t *w32 = ha->fwfcetracebuf.bp;
+
+		mdb_printf("\n\nFC Event Trace Buffer Memory");
+		/* show data address as a byte address, data as long words */
+		for (cnt = 0; cnt < FWFCESIZE / 4; cnt++) {
+			cnt_b = cnt * 4;
+			if (cnt_b % 32 == 0) {
+				mdb_printf("\n%08x: ", w32 + cnt_b);
+			}
+			mdb_printf("%08x ", fw->fce_trace_buf[cnt]);
+		}
+	}
+
+	mdb_free(fw, ha->ql_dump_size);
+
+	mdb_printf("\n\nreturn exit\n");
+
+	return (DCMD_OK);
+}
+
+/*
  * ql_gettrace_dcmd
  *	prints out the Extended Logging trace buffer
  *
--- a/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_api.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_api.c	Wed Oct 07 16:02:38 2009 -0700
@@ -139,7 +139,7 @@
 static void ql_idle_check(ql_adapter_state_t *);
 static int ql_loop_resync(ql_adapter_state_t *);
 static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
-static size_t ql_25xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
+static size_t ql_2581_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
 static int ql_save_config_regs(dev_info_t *);
 static int ql_restore_config_regs(dev_info_t *);
 static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
@@ -152,6 +152,7 @@
 static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
 static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
 static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
+static int ql_81xx_binary_fw_dump(ql_adapter_state_t *, ql_81xx_fw_dump_t *);
 static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
     void *);
 static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
@@ -1576,7 +1577,7 @@
 	ql_link_t		*link;
 	char			*buf;
 	timeout_id_t		timer_id = NULL;
-	int			rval = DDI_SUCCESS;
+	int			suspend, rval = DDI_SUCCESS;
 
 	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
 	if (ha == NULL) {
@@ -1794,12 +1795,12 @@
 			(void) ql_shutdown_ip(ha);
 		}
 
-		if ((rval = ql_suspend_adapter(ha)) != QL_SUCCESS) {
+		if ((suspend = ql_suspend_adapter(ha)) != QL_SUCCESS) {
 			ADAPTER_STATE_LOCK(ha);
 			ha->flags &= ~ADAPTER_SUSPENDED;
 			ADAPTER_STATE_UNLOCK(ha);
 			cmn_err(CE_WARN, "%s(%d): Fail suspend rval %xh",
-			    QL_NAME, ha->instance, rval);
+			    QL_NAME, ha->instance, suspend);
 
 			/* Restart IP if it was running. */
 			if (ha->flags & IP_ENABLED &&
@@ -1826,6 +1827,8 @@
 			(void) untimeout(timer_id);
 		}
 
+		EL(ha, "suspended\n");
+
 		break;
 
 	default:
@@ -3791,6 +3794,7 @@
 	uint8_t			*bptr;
 	int			rval2, rval = FC_SUCCESS;
 	uint32_t		opcode;
+	uint32_t		set_flags = 0;
 
 	ha = ql_fca_handle_to_state(fca_handle);
 	if (ha == NULL) {
@@ -3920,7 +3924,7 @@
 				rval = FC_FAILURE;
 			}
 			ql_reset_chip(ha);
-			(void) ql_abort_isp(ha);
+			set_flags |= ISP_ABORT_NEEDED;
 		} else {
 			/* Save copy of the firmware. */
 			if (pha->risc_code != NULL) {
@@ -4008,7 +4012,7 @@
 				rval = FC_FAILURE;
 			}
 			ql_reset_chip(ha);
-			(void) ql_abort_isp(ha);
+			set_flags |= ISP_ABORT_NEEDED;
 			break;
 		case QL_DIAG_REVLVL:
 			if (cmd->pm_stat_len <
@@ -4052,26 +4056,33 @@
 
 				bcopy(&mr.mb[0], &mr.mb[10],
 				    sizeof (uint16_t) * 8);
+
 				if (ql_mbx_wrap_test(ha, &mr) != QL_SUCCESS) {
 					EL(ha, "failed, QL_DIAG_LPBMBX "
 					    "FC_FAILURE\n");
 					rval = FC_FAILURE;
 					break;
-				}
-				if (mr.mb[i0] != mr.mb[i0 + 10]) {
-					EL(ha, "failed, QL_DIAG_LPBMBX "
-					    "FC_FAILURE-2\n");
-
+				} else {
+					for (i0 = 1; i0 < 8; i0++) {
+						if (mr.mb[i0] !=
+						    mr.mb[i0 + 10]) {
+							EL(ha, "failed, "
+							    "QL_DIAG_LPBMBX "
+							    "FC_FAILURE-2\n");
+							rval = FC_FAILURE;
+							break;
+						}
+					}
+				}
+
+				if (rval == FC_FAILURE) {
 					(void) ql_flash_errlog(ha,
 					    FLASH_ERRLOG_ISP_ERR, 0,
 					    RD16_IO_REG(ha, hccr),
 					    RD16_IO_REG(ha, istatus));
-
-					rval = FC_FAILURE;
-					break;
-				}
-			}
-			(void) ql_abort_isp(ha);
+					set_flags |= ISP_ABORT_NEEDED;
+				}
+			}
 			break;
 		case QL_DIAG_LPBDTA:
 			/*
@@ -4163,7 +4174,7 @@
 			ql_free_phys(ha, &buffer_rcv);
 
 			/* Needed to recover the f/w */
-			(void) ql_abort_isp(ha);
+			set_flags |= ISP_ABORT_NEEDED;
 
 			/* Restart IP if it was shutdown. */
 			if (pha->flags & IP_ENABLED &&
@@ -4464,7 +4475,7 @@
 			rval = FC_SUCCESS;
 		}
 		ql_reset_chip(ha);
-		(void) ql_abort_isp(ha);
+		set_flags |= ISP_ABORT_NEEDED;
 		PORTMANAGE_UNLOCK(ha);
 		break;
 	default:
@@ -4474,7 +4485,7 @@
 	}
 
 	/* Wait for suspension to end. */
-	ql_awaken_task_daemon(ha, NULL, 0, DRIVER_STALL);
+	ql_awaken_task_daemon(ha, NULL, set_flags, DRIVER_STALL);
 	timer = 0;
 
 	while (timer++ < 3000 &&
@@ -9606,11 +9617,7 @@
 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 
 	if (sp->pkt->pkt_timeout != 0 && sp->pkt->pkt_timeout < 0x10000) {
-		/* Make sure timeout >= 2 * R_A_TOV */
-		sp->isp_timeout = (uint16_t)
-		    (sp->pkt->pkt_timeout < ha->r_a_tov ? ha->r_a_tov :
-		    sp->pkt->pkt_timeout);
-
+		sp->isp_timeout = (uint16_t)(sp->pkt->pkt_timeout);
 		/*
 		 * The WATCHDOG_TIME must be rounded up + 1.  As an example,
 		 * consider a 1 second timeout. If the WATCHDOG_TIME is 1, it
@@ -11632,9 +11639,12 @@
 	if (CFG_IST(ha, CFG_CTRL_2422)) {
 		ha->ql_dump_size = (uint32_t)(sizeof (ql_24xx_fw_dump_t) +
 		    ha->fw_ext_memory_size);
-	} else if (CFG_IST(ha, CFG_CTRL_2581)) {
+	} else if (CFG_IST(ha, CFG_CTRL_25XX)) {
 		ha->ql_dump_size = (uint32_t)(sizeof (ql_25xx_fw_dump_t) +
 		    ha->fw_ext_memory_size);
+	} else if (CFG_IST(ha, CFG_CTRL_81XX)) {
+		ha->ql_dump_size = (uint32_t)(sizeof (ql_81xx_fw_dump_t) +
+		    ha->fw_ext_memory_size);
 	} else {
 		ha->ql_dump_size = sizeof (ql_fw_dump_t);
 	}
@@ -11645,7 +11655,9 @@
 	} else {
 		if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
 			rval = ql_2300_binary_fw_dump(ha, ha->ql_dump_ptr);
-		} else if (CFG_IST(ha, CFG_CTRL_2581)) {
+		} else if (CFG_IST(ha, CFG_CTRL_81XX)) {
+			rval = ql_81xx_binary_fw_dump(ha, ha->ql_dump_ptr);
+		} else if (CFG_IST(ha, CFG_CTRL_25XX)) {
 			rval = ql_25xx_binary_fw_dump(ha, ha->ql_dump_ptr);
 		} else if (CFG_IST(ha, CFG_CTRL_2422)) {
 			rval = ql_24xx_binary_fw_dump(ha, ha->ql_dump_ptr);
@@ -11704,7 +11716,7 @@
 	if (CFG_IST(ha, CFG_CTRL_2422)) {
 		return (ql_24xx_ascii_fw_dump(ha, bufp));
 	} else if (CFG_IST(ha, CFG_CTRL_2581)) {
-		return (ql_25xx_ascii_fw_dump(ha, bufp));
+		return (ql_2581_ascii_fw_dump(ha, bufp));
 	}
 
 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
@@ -12395,8 +12407,8 @@
 }
 
 /*
- * ql_25xx_ascii_fw_dump
- *	Converts ISP25xx firmware binary dump to ascii.
+ * ql_2581_ascii_fw_dump
+ *	Converts ISP25xx or ISP81xx firmware binary dump to ascii.
  *
  * Input:
  *	ha = adapter state pointer.
@@ -12409,9 +12421,10 @@
  *	Kernel context.
  */
 static size_t
-ql_25xx_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
+ql_2581_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
 {
 	uint32_t		cnt;
+	uint32_t		cnt1;
 	caddr_t			bp = bufp;
 	ql_25xx_fw_dump_t	*fw = ha->ql_dump_ptr;
 
@@ -12559,7 +12572,7 @@
 		bp += 9;
 	}
 
-	(void) sprintf(bp, "\n\nASEQ-0 GP Registers");
+	(void) sprintf(bp, "\n\nASEQ-0 Registers");
 	bp += strlen(bp);
 	for (cnt = 0; cnt < sizeof (fw->aseq_0_reg) / 4; cnt++) {
 		if (cnt % 8 == 0) {
@@ -12569,7 +12582,7 @@
 		bp += 9;
 	}
 
-	(void) sprintf(bp, "\n\nASEQ-1 GP Registers");
+	(void) sprintf(bp, "\n\nASEQ-1 Registers");
 	bp += strlen(bp);
 	for (cnt = 0; cnt < sizeof (fw->aseq_1_reg) / 4; cnt++) {
 		if (cnt % 8 == 0) {
@@ -12579,7 +12592,7 @@
 		bp += 9;
 	}
 
-	(void) sprintf(bp, "\n\nASEQ-2 GP Registers");
+	(void) sprintf(bp, "\n\nASEQ-2 Registers");
 	bp += strlen(bp);
 	for (cnt = 0; cnt < sizeof (fw->aseq_2_reg) / 4; cnt++) {
 		if (cnt % 8 == 0) {
@@ -12731,7 +12744,10 @@
 
 	(void) sprintf(bp, "\n\nFPM Hardware Registers");
 	bp += strlen(bp);
-	for (cnt = 0; cnt < sizeof (fw->fpm_hdw_reg) / 4; cnt++) {
+	cnt1 = CFG_IST(ha, CFG_CTRL_81XX) ?
+	    (uint32_t)(sizeof (((ql_81xx_fw_dump_t *)(fw))->fpm_hdw_reg)) :
+	    (uint32_t)(sizeof (fw->fpm_hdw_reg));
+	for (cnt = 0; cnt < cnt1 / 4; cnt++) {
 		if (cnt % 8 == 0) {
 			(void) sprintf(bp++, "\n");
 		}
@@ -12741,7 +12757,10 @@
 
 	(void) sprintf(bp, "\n\nFB Hardware Registers");
 	bp += strlen(bp);
-	for (cnt = 0; cnt < sizeof (fw->fb_hdw_reg) / 4; cnt++) {
+	cnt1 = CFG_IST(ha, CFG_CTRL_81XX) ?
+	    (uint32_t)(sizeof (((ql_81xx_fw_dump_t *)(fw))->fb_hdw_reg)) :
+	    (uint32_t)(sizeof (fw->fb_hdw_reg));
+	for (cnt = 0; cnt < cnt1 / 4; cnt++) {
 		if (cnt % 8 == 0) {
 			(void) sprintf(bp++, "\n");
 		}
@@ -14076,21 +14095,11 @@
 		/* Frame Buffer registers. */
 
 		/* FB hardware */
-		if (CFG_IST(ha, CFG_CTRL_81XX)) {
-			WRT32_IO_REG(ha, io_base_addr, 0x40C0);
-		} else {
-			WRT32_IO_REG(ha, io_base_addr, 0x6000);
-		}
+		WRT32_IO_REG(ha, io_base_addr, 0x6000);
 		bp = ql_read_regs(ha, fw->fb_hdw_reg, ha->iobase + 0xC0,
 		    16, 32);
-
-		if (CFG_IST(ha, CFG_CTRL_81XX)) {
-			WRT32_IO_REG(ha, io_base_addr, 0x40D0);
-		} else {
-			WRT32_IO_REG(ha, io_base_addr, 0x6010);
-		}
-		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
-
+		WRT32_IO_REG(ha, io_base_addr, 0x6010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
 		WRT32_IO_REG(ha, io_base_addr, 0x6020);
 		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
 		WRT32_IO_REG(ha, io_base_addr, 0x6030);
@@ -14109,12 +14118,550 @@
 		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
 		WRT32_IO_REG(ha, io_base_addr, 0x61B0);
 		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
-
-		if (CFG_IST(ha, CFG_CTRL_81XX)) {
-			WRT32_IO_REG(ha, io_base_addr, 0x61C0);
-		} else {
-			WRT32_IO_REG(ha, io_base_addr, 0x6F00);
-		}
+		WRT32_IO_REG(ha, io_base_addr, 0x6F00);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+	}
+
+	/* Get the request queue */
+	if (rval == QL_SUCCESS) {
+		uint32_t	cnt;
+		uint32_t	*w32 = (uint32_t *)ha->request_ring_bp;
+
+		/* Sync DMA buffer. */
+		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
+		    REQUEST_Q_BUFFER_OFFSET, sizeof (fw->req_q),
+		    DDI_DMA_SYNC_FORKERNEL);
+
+		for (cnt = 0; cnt < sizeof (fw->req_q) / 4; cnt++) {
+			fw->req_q[cnt] = *w32++;
+			LITTLE_ENDIAN_32(&fw->req_q[cnt]);
+		}
+	}
+
+	/* Get the respons queue */
+	if (rval == QL_SUCCESS) {
+		uint32_t	cnt;
+		uint32_t	*w32 = (uint32_t *)ha->response_ring_bp;
+
+		/* Sync DMA buffer. */
+		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
+		    RESPONSE_Q_BUFFER_OFFSET, sizeof (fw->rsp_q),
+		    DDI_DMA_SYNC_FORKERNEL);
+
+		for (cnt = 0; cnt < sizeof (fw->rsp_q) / 4; cnt++) {
+			fw->rsp_q[cnt] = *w32++;
+			LITTLE_ENDIAN_32(&fw->rsp_q[cnt]);
+		}
+	}
+
+	/* Reset RISC. */
+
+	ql_reset_chip(ha);
+
+	/* Memory. */
+
+	if (rval == QL_SUCCESS) {
+		/* Code RAM. */
+		rval = ql_read_risc_ram(ha, 0x20000,
+		    sizeof (fw->code_ram) / 4, fw->code_ram);
+	}
+	if (rval == QL_SUCCESS) {
+		/* External Memory. */
+		rval = ql_read_risc_ram(ha, 0x100000,
+		    ha->fw_ext_memory_size / 4, fw->ext_mem);
+	}
+
+	/* Get the FC event trace buffer */
+	if (rval == QL_SUCCESS) {
+		if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
+		    (ha->fwfcetracebuf.bp != NULL)) {
+			uint32_t	cnt;
+			uint32_t	*w32 = ha->fwfcetracebuf.bp;
+
+			/* Sync DMA buffer. */
+			(void) ddi_dma_sync(ha->fwfcetracebuf.dma_handle, 0,
+			    FWFCESIZE, DDI_DMA_SYNC_FORKERNEL);
+
+			for (cnt = 0; cnt < FWFCESIZE / 4; cnt++) {
+				fw->fce_trace_buf[cnt] = *w32++;
+			}
+		}
+	}
+
+	/* Get the extended trace buffer */
+	if (rval == QL_SUCCESS) {
+		if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) &&
+		    (ha->fwexttracebuf.bp != NULL)) {
+			uint32_t	cnt;
+			uint32_t	*w32 = ha->fwexttracebuf.bp;
+
+			/* Sync DMA buffer. */
+			(void) ddi_dma_sync(ha->fwexttracebuf.dma_handle, 0,
+			    FWEXTSIZE, DDI_DMA_SYNC_FORKERNEL);
+
+			for (cnt = 0; cnt < FWEXTSIZE / 4; cnt++) {
+				fw->ext_trace_buf[cnt] = *w32++;
+			}
+		}
+	}
+
+	if (rval != QL_SUCCESS) {
+		EL(ha, "failed=%xh\n", rval);
+	} else {
+		/*EMPTY*/
+		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
+	}
+
+	return (rval);
+}
+
+/*
+ * ql_81xx_binary_fw_dump
+ *
+ * Input:
+ *	ha:	adapter state pointer.
+ *	fw:	firmware dump context pointer.
+ *
+ * Returns:
+ *	ql local function return status code.
+ *
+ * Context:
+ *	Interrupt or Kernel context, no mailbox commands allowed.
+ */
+static int
+ql_81xx_binary_fw_dump(ql_adapter_state_t *ha, ql_81xx_fw_dump_t *fw)
+{
+	uint32_t	*reg32;
+	void		*bp;
+	clock_t		timer;
+	int		rval = QL_SUCCESS;
+
+	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
+
+	fw->r2h_status = RD32_IO_REG(ha, intr_info_lo);
+
+	/* Pause RISC. */
+	if ((RD32_IO_REG(ha, intr_info_lo) & RH_RISC_PAUSED) == 0) {
+		/* Disable ISP interrupts. */
+		WRT16_IO_REG(ha, ictrl, 0);
+
+		WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
+		for (timer = 30000;
+		    (RD32_IO_REG(ha, intr_info_lo) & RH_RISC_PAUSED) == 0 &&
+		    rval == QL_SUCCESS; timer--) {
+			if (timer) {
+				drv_usecwait(100);
+				if (timer % 10000 == 0) {
+					EL(ha, "risc pause %d\n", timer);
+				}
+			} else {
+				EL(ha, "risc pause timeout\n");
+				rval = QL_FUNCTION_TIMEOUT;
+			}
+		}
+	}
+
+	if (rval == QL_SUCCESS) {
+
+		/* Host Interface registers */
+
+		/* HostRisc registers. */
+		WRT32_IO_REG(ha, io_base_addr, 0x7000);
+		bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* PCIe registers. */
+		WRT32_IO_REG(ha, io_base_addr, 0x7c00);
+		WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
+		bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
+		    3, 32);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 1, 32);
+		WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x0);
+
+		/* Host interface registers. */
+		(void) ql_read_regs(ha, fw->host_reg, ha->iobase,
+		    sizeof (fw->host_reg) / 4, 32);
+
+		/* Disable ISP interrupts. */
+
+		WRT32_IO_REG(ha, ictrl, 0);
+		RD32_IO_REG(ha, ictrl);
+		ADAPTER_STATE_LOCK(ha);
+		ha->flags &= ~INTERRUPTS_ENABLED;
+		ADAPTER_STATE_UNLOCK(ha);
+
+		/* Shadow registers. */
+
+		WRT32_IO_REG(ha, io_base_addr, 0x0F70);
+		RD32_IO_REG(ha, io_base_addr);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0000000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[0] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0100000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[1] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0200000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[2] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0300000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[3] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0400000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[4] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0500000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[5] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0600000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[6] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0700000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[7] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0800000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[8] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0900000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[9] = RD_REG_DWORD(ha, reg32);
+
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+		WRT_REG_DWORD(ha, reg32, 0xB0A00000);
+		reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+		fw->shadow_reg[0xa] = RD_REG_DWORD(ha, reg32);
+
+		/* RISC I/O register. */
+
+		WRT32_IO_REG(ha, io_base_addr, 0x0010);
+		(void) ql_read_regs(ha, &fw->risc_io, ha->iobase + 0xC0,
+		    1, 32);
+
+		/* Mailbox registers. */
+
+		(void) ql_read_regs(ha, fw->mailbox_reg, ha->iobase + 0x80,
+		    sizeof (fw->mailbox_reg) / 2, 16);
+
+		/* Transfer sequence registers. */
+
+		/* XSEQ GP */
+		WRT32_IO_REG(ha, io_base_addr, 0xBF00);
+		bp = ql_read_regs(ha, fw->xseq_gp_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF10);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF20);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF30);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF40);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF50);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF60);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBF70);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XSEQ-0 */
+		WRT32_IO_REG(ha, io_base_addr, 0xBFC0);
+		bp = ql_read_regs(ha, fw->xseq_0_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBFD0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xBFE0);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XSEQ-1 */
+		WRT32_IO_REG(ha, io_base_addr, 0xBFF0);
+		(void) ql_read_regs(ha, fw->xseq_1_reg, ha->iobase + 0xC0,
+		    16, 32);
+
+		/* Receive sequence registers. */
+
+		/* RSEQ GP */
+		WRT32_IO_REG(ha, io_base_addr, 0xFF00);
+		bp = ql_read_regs(ha, fw->rseq_gp_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF10);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF20);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF30);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF40);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF50);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF60);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFF70);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* RSEQ-0 */
+		WRT32_IO_REG(ha, io_base_addr, 0xFFC0);
+		bp = ql_read_regs(ha, fw->rseq_0_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xFFD0);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* RSEQ-1 */
+		WRT32_IO_REG(ha, io_base_addr, 0xFFE0);
+		(void) ql_read_regs(ha, fw->rseq_1_reg, ha->iobase + 0xC0,
+		    sizeof (fw->rseq_1_reg) / 4, 32);
+
+		/* RSEQ-2 */
+		WRT32_IO_REG(ha, io_base_addr, 0xFFF0);
+		(void) ql_read_regs(ha, fw->rseq_2_reg, ha->iobase + 0xC0,
+		    sizeof (fw->rseq_2_reg) / 4, 32);
+
+		/* Auxiliary sequencer registers. */
+
+		/* ASEQ GP */
+		WRT32_IO_REG(ha, io_base_addr, 0xB000);
+		bp = ql_read_regs(ha, fw->aseq_gp_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB020);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB030);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB040);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB050);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB060);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB070);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* ASEQ-0 */
+		WRT32_IO_REG(ha, io_base_addr, 0xB0C0);
+		bp = ql_read_regs(ha, fw->aseq_0_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0xB0D0);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* ASEQ-1 */
+		WRT32_IO_REG(ha, io_base_addr, 0xB0E0);
+		(void) ql_read_regs(ha, fw->aseq_1_reg, ha->iobase + 0xC0,
+		    16, 32);
+
+		/* ASEQ-2 */
+		WRT32_IO_REG(ha, io_base_addr, 0xB0F0);
+		(void) ql_read_regs(ha, fw->aseq_2_reg, ha->iobase + 0xC0,
+		    16, 32);
+
+		/* Command DMA registers. */
+
+		WRT32_IO_REG(ha, io_base_addr, 0x7100);
+		(void) ql_read_regs(ha, fw->cmd_dma_reg, ha->iobase + 0xC0,
+		    sizeof (fw->cmd_dma_reg) / 4, 32);
+
+		/* Queues. */
+
+		/* RequestQ0 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7200);
+		bp = ql_read_regs(ha, fw->req0_dma_reg, ha->iobase + 0xC0,
+		    8, 32);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+
+		/* ResponseQ0 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7300);
+		bp = ql_read_regs(ha, fw->resp0_dma_reg, ha->iobase + 0xC0,
+		    8, 32);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+
+		/* RequestQ1 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7400);
+		bp = ql_read_regs(ha, fw->req1_dma_reg, ha->iobase + 0xC0,
+		    8, 32);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+
+		/* Transmit DMA registers. */
+
+		/* XMT0 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7600);
+		bp = ql_read_regs(ha, fw->xmt0_dma_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7610);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XMT1 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7620);
+		bp = ql_read_regs(ha, fw->xmt1_dma_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7630);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XMT2 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7640);
+		bp = ql_read_regs(ha, fw->xmt2_dma_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7650);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XMT3 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7660);
+		bp = ql_read_regs(ha, fw->xmt3_dma_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7670);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XMT4 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7680);
+		bp = ql_read_regs(ha, fw->xmt4_dma_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7690);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* XMT Common */
+		WRT32_IO_REG(ha, io_base_addr, 0x76A0);
+		(void) ql_read_regs(ha, fw->xmt_data_dma_reg,
+		    ha->iobase + 0xC0, sizeof (fw->xmt_data_dma_reg) / 4, 32);
+
+		/* Receive DMA registers. */
+
+		/* RCVThread0 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7700);
+		bp = ql_read_regs(ha, fw->rcvt0_data_dma_reg,
+		    ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7710);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* RCVThread1 */
+		WRT32_IO_REG(ha, io_base_addr, 0x7720);
+		bp = ql_read_regs(ha, fw->rcvt1_data_dma_reg,
+		    ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x7730);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* RISC registers. */
+
+		/* RISC GP */
+		WRT32_IO_REG(ha, io_base_addr, 0x0F00);
+		bp = ql_read_regs(ha, fw->risc_gp_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F10);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F20);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F30);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F40);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F50);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F60);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x0F70);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* Local memory controller (LMC) registers. */
+
+		/* LMC */
+		WRT32_IO_REG(ha, io_base_addr, 0x3000);
+		bp = ql_read_regs(ha, fw->lmc_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3020);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3030);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3040);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3050);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3060);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x3070);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* Fibre Protocol Module registers. */
+
+		/* FPM hardware */
+		WRT32_IO_REG(ha, io_base_addr, 0x4000);
+		bp = ql_read_regs(ha, fw->fpm_hdw_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4020);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4030);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4040);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4050);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4060);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4070);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4080);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x4090);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x40A0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x40B0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x40C0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x40D0);
+		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+
+		/* Frame Buffer registers. */
+
+		/* FB hardware */
+		WRT32_IO_REG(ha, io_base_addr, 0x6000);
+		bp = ql_read_regs(ha, fw->fb_hdw_reg, ha->iobase + 0xC0,
+		    16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6010);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6020);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6030);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6040);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6100);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6130);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6150);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6170);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6190);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x61B0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x61C0);
+		bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+		WRT32_IO_REG(ha, io_base_addr, 0x6F00);
 		(void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
 	}
 
@@ -16545,7 +17092,7 @@
 }
 
 /*
- * ql_isp_els_request_map - Extract into an els descriptor the info required
+ * ql_fca_isp_els_request - Extract into an els descriptor the info required
  *			    to build an els_passthru iocb from an fc packet.
  *
  * Input:	ha = adapter state pointer.
--- a/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_init.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_init.c	Wed Oct 07 16:02:38 2009 -0700
@@ -71,6 +71,7 @@
 static void ql_set_max_read_req(ql_adapter_state_t *);
 static void ql_configure_n_port_info(ql_adapter_state_t *);
 static void ql_clear_mcp(ql_adapter_state_t *);
+static void ql_mps_reset(ql_adapter_state_t *);
 
 /*
  * ql_initialize_adapter
@@ -2274,6 +2275,10 @@
 	size_t			byte_count;
 	ql_adapter_state_t	*ha = vha->pha;
 
+	if (CFG_IST(ha, CFG_CTRL_81XX)) {
+		ql_mps_reset(ha);
+	}
+
 	if (CFG_IST(ha, CFG_LOAD_FLASH_FW)) {
 		return (ql_load_flash_fw(ha));
 	}
@@ -4225,3 +4230,40 @@
 
 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
 }
+
+/*
+ * ql_mps_reset
+ *	Reset MPS for FCoE functions.
+ *
+ * Input:
+ *	ha = virtual adapter state pointer.
+ *
+ * Context:
+ *	Kernel context.
+ */
+static void
+ql_mps_reset(ql_adapter_state_t *ha)
+{
+	uint32_t	data, dctl = 1000;
+
+	do {
+		if (dctl-- == 0 || ql_wrt_risc_ram_word(ha, 0x7c00, 1) !=
+		    QL_SUCCESS) {
+			return;
+		}
+		if (ql_rd_risc_ram_word(ha, 0x7c00, &data) != QL_SUCCESS) {
+			ql_wrt_risc_ram_word(ha, 0x7c00, 0);
+			return;
+		}
+	} while (!(data & BIT_0));
+
+	if (ql_rd_risc_ram_word(ha, 0x7A15, &data) == QL_SUCCESS) {
+		dctl = (uint16_t)ql_pci_config_get16(ha, 0x54);
+		if ((data & 0xe0) != (dctl & 0xe0)) {
+			data &= 0xff1f;
+			data |= dctl & 0xe0;
+			ql_wrt_risc_ram_word(ha, 0x7A15, data);
+		}
+	}
+	ql_wrt_risc_ram_word(ha, 0x7c00, 0);
+}
--- a/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_isr.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_isr.c	Wed Oct 07 16:02:38 2009 -0700
@@ -1052,6 +1052,17 @@
 			EL(ha, "%xh Port Database Update, Login/Logout "
 			    "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
 			    mb[0], mb[1], mb[2], mb[3]);
+		} else if (CFG_IST(ha, CFG_CTRL_81XX) && mb[1] == 0xffff &&
+		    mb[2] == 0x7 && MSB(mb[3]) == 0xe) {
+			if (!(ha->task_daemon_flags & LOOP_DOWN)) {
+				*set_flags |= LOOP_DOWN;
+			}
+			ql_port_state(ha, FC_STATE_OFFLINE,
+			    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
+
+			if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
+				ha->loop_down_timer = LOOP_DOWN_TIMER_START;
+			}
 		} else {
 			EL(ha, "%xh Port Database Update received, mbx1=%xh,"
 			    " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2],
@@ -1657,10 +1668,6 @@
 	}
 
 	if (sp != NULL) {
-		ha->outstanding_cmds[index] = NULL;
-		sp->handle = 0;
-		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
-
 		/* Bad payload or header */
 		if (pkt->entry_status & (BIT_5 + BIT_4 + BIT_3 + BIT_2)) {
 			/* Bad payload or header, set error status. */
@@ -1793,10 +1800,6 @@
 			return (0);
 		}
 
-		ha->outstanding_cmds[index] = NULL;
-		sp->handle = 0;
-		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
-
 		/*
 		 * Fast path to good SCSI I/O completion
 		 */
@@ -1968,8 +1971,8 @@
 		}
 
 		if (sp != NULL) {
-			EL(ha, "sp=%x, resp_id=%x, get=%d\n", sp,
-			    resp_identifier, get_handle);
+			EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
+			    resp_identifier, get_handle, index);
 			break;
 		} else {
 			get_handle -= 1;
@@ -1980,7 +1983,8 @@
 				    RESPONSE_Q_BUFFER_OFFSET,
 				    RESPONSE_QUEUE_SIZE,
 				    DDI_DMA_SYNC_FORKERNEL);
-				EL(ha, "last chance DMA sync\n");
+				EL(ha, "last chance DMA sync, index=%xh\n",
+				    index);
 			}
 		}
 	}
--- a/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_mbx.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_mbx.c	Wed Oct 07 16:02:38 2009 -0700
@@ -93,8 +93,6 @@
 	ql_adapter_state_t	*ha = vha->pha;
 	int			mbx_cmd = mcp->mb[0];
 
-	ASSERT(!MUTEX_HELD(&ha->mutex));
-
 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 
 	/* Acquire mailbox register lock. */
@@ -1797,8 +1795,6 @@
 	mbx_cmd_t		*mcp = &mc;
 	port_database_23_t	*pd23;
 
-	ASSERT(!MUTEX_HELD(&ha->mutex));
-
 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 
 	pd23 = (port_database_23_t *)kmem_zalloc(PORT_DATABASE_SIZE, KM_SLEEP);
@@ -2953,6 +2949,99 @@
 }
 
 /*
+ * ql_wrt_risc_ram_word
+ *	Write RISC RAM word.
+ *
+ * Input:
+ *	ha:		adapter state pointer.
+ *	risc_address:	risc ram word address.
+ *	data:		data.
+ *
+ * Returns:
+ *	ql local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+ql_wrt_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
+    uint32_t data)
+{
+	int		rval;
+	mbx_cmd_t	mc = {0};
+	mbx_cmd_t	*mcp = &mc;
+
+	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
+
+	mcp->mb[0] = MBC_WRITE_RAM_EXTENDED;
+	mcp->mb[1] = LSW(risc_address);
+	mcp->mb[2] = LSW(data);
+	mcp->mb[3] = MSW(data);
+	mcp->mb[8] = MSW(risc_address);
+	mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->timeout = MAILBOX_TOV;
+
+	rval = ql_mailbox_command(ha, mcp);
+
+	if (rval != QL_SUCCESS) {
+		EL(ha, "failed, rval = %xh\n", rval);
+	} else {
+		/*EMPTY*/
+		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
+	}
+
+	return (rval);
+}
+
+/*
+ * ql_rd_risc_ram_word
+ *	Read RISC RAM word.
+ *
+ * Input:
+ *	ha:		adapter state pointer.
+ *	risc_address:	risc ram word address.
+ *	data:		data pointer.
+ *
+ * Returns:
+ *	ql local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+ql_rd_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
+    uint32_t *data)
+{
+	int		rval;
+	mbx_cmd_t	mc = {0};
+	mbx_cmd_t	*mcp = &mc;
+
+	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
+
+	mcp->mb[0] = MBC_READ_RAM_EXTENDED;
+	mcp->mb[1] = LSW(risc_address);
+	mcp->mb[8] = MSW(risc_address);
+	mcp->out_mb = MBX_8|MBX_1|MBX_0;
+	mcp->in_mb = MBX_3|MBX_2|MBX_0;
+	mcp->timeout = MAILBOX_TOV;
+
+	rval = ql_mailbox_command(ha, mcp);
+
+	if (rval != QL_SUCCESS) {
+		EL(ha, "failed, rval = %xh\n", rval);
+	} else {
+		*data = mcp->mb[2];
+		if (CFG_IST(ha, CFG_CTRL_242581)) {
+			*data |= mcp->mb[3] << 16;
+		}
+		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
+	}
+
+	return (rval);
+}
+
+/*
  * ql_issue_mbx_iocb
  *	Issue IOCB using mailbox command
  *
@@ -3643,8 +3732,7 @@
 	}
 
 	mcp->mb[0] = MBC_ECHO;
-	mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_81XX) ? opt :
-	    (opt | BIT_6));
+	mcp->mb[1] = opt;
 	mcp->mb[2] = findex;
 	mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
 	mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
--- a/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_xioctl.c	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_xioctl.c	Wed Oct 07 16:02:38 2009 -0700
@@ -3384,7 +3384,8 @@
 		return;
 	}
 
-	if (DRIVER_SUSPENDED(ha) || ql_stall_driver(ha, 0) != QL_SUCCESS) {
+	if ((ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) ||
+	    ql_stall_driver(ha, 0) != QL_SUCCESS) {
 		EL(ha, "failed, LOOP_NOT_READY\n");
 		kmem_free(bp, plbreq.TransferCount);
 		cmd->Status = EXT_STATUS_BUSY;
@@ -3400,11 +3401,15 @@
 	/* determine topology so we can send the loopback or the echo */
 	/* Echo is supported on 2300's only and above */
 
-	if ((ha->topology & QL_F_PORT) && ha->device_id >= 0x2300) {
+	if (!(ha->task_daemon_flags & LOOP_DOWN) &&
+	    (ha->topology & QL_F_PORT) &&
+	    ha->device_id >= 0x2300) {
 		QL_PRINT_9(CE_CONT, "(%d): F_PORT topology -- using echo\n",
 		    ha->instance);
 		plbrsp.CommandSent = INT_DEF_LB_ECHO_CMD;
-		rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount, 0, &mr);
+		rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount,
+		    (uint16_t)(CFG_IST(ha, CFG_CTRL_81XX) ? BIT_15 : BIT_6),
+		    &mr);
 	} else {
 		plbrsp.CommandSent = INT_DEF_LB_LOOPBACK_CMD;
 		rval = ql_diag_loopback(ha, 0, bp, plbreq.TransferCount,
@@ -6778,7 +6783,7 @@
 	}
 
 	(void) snprintf(fcache->verstr, FCHBA_OPTION_ROM_VERSION_LEN,
-	    "%d.%d", pcid->revisionlevel[1], pcid->revisionlevel[0]);
+	    "%d.%02d", pcid->revisionlevel[1], pcid->revisionlevel[0]);
 
 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
 
@@ -6802,7 +6807,7 @@
 	ql_flt_ptr_t	*fptr;
 	ql_flt_hdr_t	*fhdr;
 	ql_flt_region_t	*frgn;
-	uint8_t		*bp;
+	uint8_t		*bp, *eaddr;
 	int		rval;
 	uint32_t	len, faddr, cnt;
 	uint16_t	chksum, w16;
@@ -6868,8 +6873,9 @@
 	}
 
 	/* Process flash layout table regions */
+	eaddr = bp + sizeof (ql_flt_hdr_t) + len;
 	for (frgn = (ql_flt_region_t *)(bp + sizeof (ql_flt_hdr_t));
-	    (caddr_t)frgn < (caddr_t)(bp + FLASH_LAYOUT_TABLE_SIZE); frgn++) {
+	    (uint8_t *)frgn < eaddr; frgn++) {
 		faddr = CHAR_TO_LONG(frgn->beg_addr[0], frgn->beg_addr[1],
 		    frgn->beg_addr[2], frgn->beg_addr[3]);
 		faddr >>= 2;
--- a/usr/src/uts/common/sys/fibre-channel/fca/qlc/exioct.h	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/qlc/exioct.h	Wed Oct 07 16:02:38 2009 -0700
@@ -1016,11 +1016,12 @@
 					/* Statistics, Configuration) */
 
 typedef struct _EXT_MENLO_MANAGE_INFO {
-	UINT64				pDataBytes;	/* 4 */
+	UINT64				pDataBytes;	/* 8 */
 	EXT_MENLO_ACCESS_PARAMETERS	Parameters;	/* 12 */
-	UINT32				TotalByteCount;
-	UINT16				Operation;
-	UINT16				Reserved;
+	UINT32				TotalByteCount;	/* 4 */
+	UINT16				Operation;	/* 2 */
+	UINT16				Reserved;	/* 2 */
+	UINT16				Reserved1[2];	/* 4 */
 } EXT_MENLO_MANAGE_INFO, *PEXT_MENLO_MANAGE_INFO;
 
 #define	MENLO_FC_CHECKSUM_FAILURE	0x01
--- a/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_init.h	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_init.h	Wed Oct 07 16:02:38 2009 -0700
@@ -827,6 +827,49 @@
 	uint32_t ext_mem[1];
 } ql_25xx_fw_dump_t;
 
+typedef struct ql_81xx_fw_dump {
+	uint32_t r2h_status;
+	uint32_t hostrisc_reg[32];
+	uint32_t pcie_reg[4];
+	uint32_t host_reg[32];
+	uint16_t mailbox_reg[32];
+	uint32_t xseq_gp_reg[128];
+	uint32_t xseq_0_reg[48];
+	uint32_t xseq_1_reg[16];
+	uint32_t rseq_gp_reg[128];
+	uint32_t rseq_0_reg[32];
+	uint32_t rseq_1_reg[16];
+	uint32_t rseq_2_reg[16];
+	uint32_t aseq_gp_reg[128];
+	uint32_t aseq_0_reg[32];
+	uint32_t aseq_1_reg[16];
+	uint32_t aseq_2_reg[16];
+	uint32_t cmd_dma_reg[16];
+	uint32_t req0_dma_reg[15];
+	uint32_t resp0_dma_reg[15];
+	uint32_t req1_dma_reg[15];
+	uint32_t xmt0_dma_reg[32];
+	uint32_t xmt1_dma_reg[32];
+	uint32_t xmt2_dma_reg[32];
+	uint32_t xmt3_dma_reg[32];
+	uint32_t xmt4_dma_reg[32];
+	uint32_t xmt_data_dma_reg[16];
+	uint32_t rcvt0_data_dma_reg[32];
+	uint32_t rcvt1_data_dma_reg[32];
+	uint32_t risc_gp_reg[128];
+	uint32_t shadow_reg[11];
+	uint32_t risc_io;
+	uint32_t lmc_reg[128];
+	uint32_t fpm_hdw_reg[224];
+	uint32_t fb_hdw_reg[208];
+	uint32_t code_ram[0x2000];
+	uint32_t req_q[REQUEST_QUEUE_SIZE / 4];
+	uint32_t rsp_q[RESPONSE_QUEUE_SIZE / 4];
+	uint32_t ext_trace_buf[FWEXTSIZE / 4];
+	uint32_t fce_trace_buf[FWFCESIZE / 4];
+	uint32_t ext_mem[1];
+} ql_81xx_fw_dump_t;
+
 #ifdef _KERNEL
 
 /*
--- a/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_mbx.h	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_mbx.h	Wed Oct 07 16:02:38 2009 -0700
@@ -190,6 +190,7 @@
 #define	MBC_DUMP_RISC_RAM		0xa	/* Dump RISC RAM command. */
 #define	MBC_LOAD_RAM_EXTENDED		0xb	/* Load RAM extended. */
 #define	MBC_DUMP_RAM_EXTENDED		0xc	/* Dump RAM extended. */
+#define	MBC_WRITE_RAM_EXTENDED		0xd	/* Write RAM word. */
 #define	MBC_READ_RAM_EXTENDED		0xf	/* Read RAM extended. */
 #define	MBC_SERDES_TRANSMIT_PARAMETERS	0x10	/* Serdes Xmit Parameters */
 #define	MBC_2300_EXECUTE_IOCB		0x12	/* ISP2300 Execute IOCB cmd */
@@ -700,6 +701,8 @@
 int ql_get_id_list(ql_adapter_state_t *, caddr_t, uint32_t, ql_mbx_data_t *);
 int ql_wrt_risc_ram(ql_adapter_state_t *, uint32_t, uint64_t, uint32_t);
 int ql_rd_risc_ram(ql_adapter_state_t *, uint32_t, uint64_t, uint32_t);
+int ql_wrt_risc_ram_word(ql_adapter_state_t *, uint32_t, uint32_t);
+int ql_rd_risc_ram_word(ql_adapter_state_t *, uint32_t, uint32_t *);
 int ql_issue_mbx_iocb(ql_adapter_state_t *, caddr_t, uint32_t);
 int ql_mbx_wrap_test(ql_adapter_state_t *, ql_mbx_data_t *);
 int ql_execute_fw(ql_adapter_state_t *);
@@ -748,6 +751,7 @@
 	{MBC_DUMP_RISC_RAM, "MBC_DUMP_RISC_RAM"},			\
 	{MBC_LOAD_RAM_EXTENDED, "MBC_LOAD_RAM_EXTENDED"},		\
 	{MBC_DUMP_RAM_EXTENDED, "MBC_DUMP_RAM_EXTENDED"},		\
+	{MBC_WRITE_RAM_EXTENDED, "MBC_WRITE_RAM_EXTENDED"},		\
 	{MBC_READ_RAM_EXTENDED, "MBC_READ_RAM_EXTENDED"},		\
 	{MBC_SERDES_TRANSMIT_PARAMETERS, "MBC_SERDES_TRANSMIT_PARAMETERS"},\
 	{MBC_2300_EXECUTE_IOCB, "MBC_2300_EXECUTE_IOCB"},		\
--- a/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_open.h	Wed Oct 07 16:05:49 2009 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/qlc/ql_open.h	Wed Oct 07 16:02:38 2009 -0700
@@ -42,7 +42,7 @@
 #endif
 
 #ifndef QL_VERSION
-#define	QL_VERSION	"20090707-2.37"
+#define	QL_VERSION	"20090924-2.38"
 #endif
 
 #ifndef	QL_NAME