changeset 10604:4dab88fc294c

6870264 Resets can timeout during heavy I/O 6873580 prtconf -v shows stale firmware revision after flashing controller firmware 6873602 Unknown events into mpt_sas driver should not be reported 6878420 MPTIOCTL_GET_ADAPTER_DATA does not fill in some values correctly 6878430 Commands sent using MPTIOCTL_PASS_THRU can timeout before they should 6878545 New MPT Events are not seen after the initial 50 events
author Yong-Feng Du <Yongfeng.Du@Sun.COM>
date Tue, 22 Sep 2009 14:06:23 +0800
parents f9779f6db716
children 4086dd59e147
files usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h
diffstat 3 files changed, 235 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c	Tue Sep 22 12:05:08 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c	Tue Sep 22 14:06:23 2009 +0800
@@ -490,7 +490,7 @@
 };
 
 
-#define	MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.17"
+#define	MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.18"
 #define	CDATE "MPTSAS was compiled on "__DATE__
 /* LINTED E_STATIC_UNUSED */
 static char *MPTWASCOMPILEDON = CDATE;
@@ -3229,6 +3229,14 @@
 		}
 		cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
 
+		/*
+		 * If initial timout is less than or equal to one tick, bump
+		 * the timeout by a tick so that command doesn't timeout before
+		 * its allotted time.
+		 */
+		if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
+			cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
+		}
 		return (TRUE);
 	} else {
 		int i;
@@ -4503,18 +4511,29 @@
 mptsas_wait_intr(mptsas_t *mpt, int polltime)
 {
 	int				cnt;
-	uint32_t			reply_index;
 	pMpi2ReplyDescriptorsUnion_t	reply_desc_union;
+	uint32_t			int_mask;
 
 	NDBG5(("mptsas_wait_intr"));
 
+	mpt->m_polled_intr = 1;
+
+	/*
+	 * Get the current interrupt mask.  When re-enabling ints, set mask to
+	 * saved value.
+	 */
+	int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
+	MPTSAS_DISABLE_INTR(mpt);
+
 	/*
 	 * Keep polling for at least (polltime * 1000) seconds
 	 */
-	reply_index = mpt->m_post_index;
 	for (cnt = 0; cnt < polltime; cnt++) {
+		(void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORCPU);
+
 		reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
-		    MPTSAS_GET_NEXT_REPLY(mpt, reply_index);
+		    MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
 
 		if (ddi_get32(mpt->m_acc_post_queue_hdl,
 		    &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
@@ -4523,27 +4542,34 @@
 			drv_usecwait(1000);
 			continue;
 		}
-		mpt->m_polled_intr = 1;
 		/*
 		 * The reply is valid, process it according to its
-		 * type.  Also, set a flag for updated the reply index
-		 * after they've all been processed.
+		 * type.
 		 */
 		mptsas_process_intr(mpt, reply_desc_union);
 
-		if (++reply_index == mpt->m_post_queue_depth) {
-			reply_index = 0;
-		}
-		/*
-		 * Update the global reply index
-		 */
-		mpt->m_post_index = reply_index;
+		if (++mpt->m_post_index == mpt->m_post_queue_depth) {
+			mpt->m_post_index = 0;
+		}
+
 		ddi_put32(mpt->m_datap,
-		    &mpt->m_reg->ReplyPostHostIndex, reply_index);
-
+		    &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
+
+		mpt->m_polled_intr = 0;
+		/*
+		 * Re-enable interrupts and quit.
+		 */
+		ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
+		    int_mask);
 		return (TRUE);
 
 	}
+
+	/*
+	 * Clear polling flag, re-enable interrupts and quit.
+	 */
+	mpt->m_polled_intr = 0;
+	ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
 	return (FALSE);
 }
 
@@ -4623,7 +4649,7 @@
 {
 	pMpi2AddressReplyDescriptor_t	address_reply;
 	pMPI2DefaultReply_t		reply;
-	uint32_t			reply_addr, reply_index;
+	uint32_t			reply_addr;
 	uint16_t			SMID;
 	mptsas_slots_t			*slots = mpt->m_active;
 	mptsas_cmd_t			*cmd = NULL;
@@ -4746,19 +4772,17 @@
 			/*
 			 * Return the reply frame to the free queue.
 			 */
-			reply_index = mpt->m_free_index;
 			ddi_put32(mpt->m_acc_free_queue_hdl,
 			    &((uint32_t *)(void *)
-			    mpt->m_free_queue)[reply_index], reply_addr);
+			    mpt->m_free_queue)[mpt->m_free_index], reply_addr);
 			(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 			    DDI_DMA_SYNC_FORDEV);
-			if (++reply_index == mpt->m_free_queue_depth) {
-				reply_index = 0;
-			}
-			mpt->m_free_index = reply_index;
+			if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+				mpt->m_free_index = 0;
+			}
 
 			ddi_put32(mpt->m_datap,
-			    &mpt->m_reg->ReplyFreeHostIndex, reply_index);
+			    &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
 		}
 		return;
 	default:
@@ -4769,17 +4793,16 @@
 	/*
 	 * Return the reply frame to the free queue.
 	 */
-	reply_index = mpt->m_free_index;
 	ddi_put32(mpt->m_acc_free_queue_hdl,
-	    &((uint32_t *)(void *)mpt->m_free_queue)[reply_index],
+	    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 	    reply_addr);
 	(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 	    DDI_DMA_SYNC_FORDEV);
-	if (++reply_index == mpt->m_free_queue_depth) {
-		reply_index = 0;
-	}
-	mpt->m_free_index = reply_index;
-	ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, reply_index);
+	if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+		mpt->m_free_index = 0;
+	}
+	ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
+	    mpt->m_free_index);
 
 	if (cmd->cmd_flags & CFLAG_FW_CMD)
 		return;
@@ -4796,19 +4819,7 @@
 		 */
 		cmd->cmd_flags &= ~CFLAG_RETRY;
 	} else {
-		struct scsi_pkt *pkt = CMD2PKT(cmd);
-
-		ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
-		cmd->cmd_linkp = NULL;
-		cmd->cmd_flags |= CFLAG_FINISHED;
-		cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
-
-		if (pkt && pkt->pkt_comp) {
-			cmd->cmd_flags |= CFLAG_COMPLETED;
-			mutex_exit(&mpt->m_mutex);
-			mptsas_pkt_comp(pkt, cmd);
-			mutex_enter(&mpt->m_mutex);
-		}
+		mptsas_doneq_add(mpt, cmd);
 	}
 }
 
@@ -5136,7 +5147,6 @@
 mptsas_intr(caddr_t arg1, caddr_t arg2)
 {
 	mptsas_t			*mpt = (void *)arg1;
-	uint32_t			reply_index;
 	pMpi2ReplyDescriptorsUnion_t	reply_desc_union;
 	uchar_t				did_reply = FALSE;
 
@@ -5157,9 +5167,16 @@
 	}
 
 	/*
-	 * Save the current reply post host index value.
-	 */
-	reply_index = mpt->m_post_index;
+	 * If polling, interrupt was triggered by some shared interrupt because
+	 * IOC interrupts are disabled during polling, so polling routine will
+	 * handle any replies.  Considering this, if polling is happening,
+	 * return with interrupt unclaimed.
+	 */
+	if (mpt->m_polled_intr) {
+		mutex_exit(&mpt->m_mutex);
+		mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
+		return (DDI_INTR_UNCLAIMED);
+	}
 
 	/*
 	 * Read the istat register.
@@ -5168,14 +5185,14 @@
 		/*
 		 * read fifo until empty.
 		 */
-		(void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
-		    DDI_DMA_SYNC_FORCPU);
 #ifndef __lock_lint
 		_NOTE(CONSTCOND)
 #endif
 		while (TRUE) {
+			(void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
+			    DDI_DMA_SYNC_FORCPU);
 			reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
-			    MPTSAS_GET_NEXT_REPLY(mpt, reply_index);
+			    MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
 
 			if (ddi_get32(mpt->m_acc_post_queue_hdl,
 			    &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
@@ -5193,10 +5210,9 @@
 
 			mptsas_process_intr(mpt, reply_desc_union);
 
-			if (++reply_index == mpt->m_post_queue_depth) {
-				reply_index = 0;
-			}
-			mpt->m_post_index = reply_index;
+			if (++mpt->m_post_index == mpt->m_post_queue_depth) {
+				mpt->m_post_index = 0;
+			}
 		}
 
 		/*
@@ -5205,14 +5221,9 @@
 		 */
 		if (did_reply) {
 			ddi_put32(mpt->m_datap,
-			    &mpt->m_reg->ReplyPostHostIndex, reply_index);
+			    &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
 		}
 	} else {
-		if (mpt->m_polled_intr) {
-			mpt->m_polled_intr = 0;
-			mutex_exit(&mpt->m_mutex);
-			return (DDI_INTR_CLAIMED);
-		}
 		mutex_exit(&mpt->m_mutex);
 		return (DDI_INTR_UNCLAIMED);
 	}
@@ -5243,10 +5254,6 @@
 		mptsas_restart_waitq(mpt);
 	}
 
-	if (mpt->m_polled_intr) {
-		mpt->m_polled_intr = 0;
-	}
-
 	mutex_exit(&mpt->m_mutex);
 	return (DDI_INTR_CLAIMED);
 }
@@ -5999,7 +6006,7 @@
 	i = (uint8_t)(event / 32);
 	j = (uint8_t)(event % 32);
 	if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
-		i = mpt->m_event_number;
+		i = mpt->m_event_index;
 		mpt->m_events[i].Type = event;
 		mpt->m_events[i].Number = ++mpt->m_event_number;
 		bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
@@ -6025,7 +6032,7 @@
 			if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
 				i = 0;
 			}
-			mpt->m_event_number = i;
+			mpt->m_event_index = (uint8_t)i;
 
 			/*
 			 * Set flag to send the event.
@@ -6686,7 +6693,7 @@
 	m_replyh_arg_t			*replyh_arg;
 	pMpi2EventNotificationReply_t	eventreply;
 	uint32_t			event, iocloginfo, rfm;
-	uint32_t			status, reply_index;
+	uint32_t			status;
 	uint8_t				port;
 	mptsas_t			*mpt;
 	uint_t				iocstatus;
@@ -7146,24 +7153,23 @@
 		break;
 	}
 	default:
-		mptsas_log(mpt, CE_NOTE, "mptsas%d: unknown event %x received",
-		    mpt->m_instance, event);
+		NDBG20(("mptsas%d: unknown event %x received",
+		    mpt->m_instance, event));
 		break;
 	}
 
 	/*
 	 * Return the reply frame to the free queue.
 	 */
-	reply_index = mpt->m_free_index;
 	ddi_put32(mpt->m_acc_free_queue_hdl,
-	    &((uint32_t *)(void *)mpt->m_free_queue)[reply_index], rfm);
+	    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
 	(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 	    DDI_DMA_SYNC_FORDEV);
-	if (++reply_index == mpt->m_free_queue_depth) {
-		reply_index = 0;
-	}
-	mpt->m_free_index = reply_index;
-	ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, reply_index);
+	if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+		mpt->m_free_index = 0;
+	}
+	ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
+	    mpt->m_free_index);
 	mutex_exit(&mpt->m_mutex);
 }
 
@@ -7766,18 +7772,11 @@
 	/*
 	 * only add scsi pkts that have completion routines to
 	 * the doneq.  no intr cmds do not have callbacks.
-	 * run the callback on an ARQ pkt immediately.  This
-	 * frees the ARQ for other check conditions.
-	 */
-	if (pkt->pkt_comp && !(cmd->cmd_flags & CFLAG_CMDARQ)) {
+	 */
+	if (pkt && (pkt->pkt_comp)) {
 		*mpt->m_donetail = cmd;
 		mpt->m_donetail = &cmd->cmd_linkp;
 		mpt->m_doneq_len++;
-	} else if (pkt->pkt_comp && (cmd->cmd_flags & CFLAG_CMDARQ)) {
-		cmd->cmd_flags |= CFLAG_COMPLETED;
-		mutex_exit(&mpt->m_mutex);
-		mptsas_pkt_comp(pkt, cmd);
-		mutex_enter(&mpt->m_mutex);
 	}
 }
 
@@ -9308,7 +9307,6 @@
 	Mpi2SCSIIOReply_t		rep_msg;
 	int				i, status = 0, pt_flags = 0, rv = 0;
 	int				rvalue;
-	uint32_t			reply_index;
 	uint8_t				function;
 
 	ASSERT(mutex_owned(&mpt->m_mutex));
@@ -9551,18 +9549,16 @@
 	 * if this reply is an ADDRESS reply.
 	 */
 	if (pt_flags & MPTSAS_ADDRESS_REPLY) {
-		reply_index = mpt->m_free_index;
 		ddi_put32(mpt->m_acc_free_queue_hdl,
-		    &((uint32_t *)(void *)mpt->m_free_queue)[reply_index],
+		    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 		    cmd->cmd_rfm);
 		(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 		    DDI_DMA_SYNC_FORDEV);
-		if (++reply_index == mpt->m_free_queue_depth) {
-			reply_index = 0;
-		}
-		mpt->m_free_index = reply_index;
+		if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+			mpt->m_free_index = 0;
+		}
 		ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
-		    reply_index);
+		    mpt->m_free_index);
 	}
 	if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
 		mptsas_remove_cmd(mpt, cmd);
@@ -9745,7 +9741,6 @@
 {
 	int	*reg_data;
 	uint_t	reglen;
-	char	*fw_rev;
 
 	/*
 	 * Lookup the 'reg' property and extract the other data
@@ -9782,24 +9777,9 @@
 	}
 
 	/*
-	 * Lookup the 'firmware-version' property and extract the data
-	 */
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, mpt->m_dip,
-	    DDI_PROP_DONTPASS, "firmware-version", &fw_rev) ==
-	    DDI_PROP_SUCCESS) {
-		/*
-		 * Version is a string of 4 bytes which fits into the DWORD
-		 */
-		(void) strcpy((char *)&adapter_data->MpiFirmwareVersion,
-		    fw_rev);
-		ddi_prop_free(fw_rev);
-	} else {
-		/*
-		 * If we can't determine the PCI data then we fill in FF's for
-		 * the data to indicate this.
-		 */
-		adapter_data->MpiFirmwareVersion = 0xFFFFFFFF;
-	}
+	 * Saved in the mpt->m_fwversion
+	 */
+	adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
 }
 
 static void
@@ -9810,9 +9790,12 @@
 	mptsas_lookup_pci_data(mpt, adapter_data);
 	adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
 	adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
+	adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
 	adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
 	adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
 	(void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
+	adapter_data->BiosVersion = 0;
+	(void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
 }
 
 static void
@@ -10138,9 +10121,16 @@
 {
 	ddi_dma_cookie_t	cookie;
 	uint32_t		i;
+	mptsas_slots_t		*new_active;
 
 	if (first_time == FALSE) {
 		/*
+		 * De-allocate buffers before re-allocating them using the
+		 * latest IOC facts.
+		 */
+		mptsas_hba_fini(mpt);
+
+		/*
 		 * Setup configuration space
 		 */
 		if (mptsas_config_space_init(mpt) == FALSE) {
@@ -10164,53 +10154,78 @@
 	 */
 	if (mptsas_ioc_reset(mpt) == MPTSAS_RESET_FAIL) {
 		mptsas_log(mpt, CE_WARN, "hard reset failed!");
-		return (DDI_FAILURE);
-	}
-	/*
-	 * Do some initilization only needed during attach
-	 */
-	if (first_time) {
-		/*
-		 * Get ioc facts from adapter
-		 */
-		if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts "
-			    "failed");
-			goto fail;
-		}
-
-		/*
-		 * Allocate request message frames
-		 */
-		if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames "
-			    "failed");
-			goto fail;
-		}
-		/*
-		 * Allocate reply free queue
-		 */
-		if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue "
+		goto fail;
+	}
+	/*
+	 * IOC facts can change after a diag reset so all buffers that are
+	 * based on these numbers must be de-allocated and re-allocated.  Get
+	 * new IOC facts each time chip is initialized.
+	 */
+	if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
+		mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts "
+		    "failed");
+		goto fail;
+	}
+	/*
+	 * Re-allocate active slots here if not the first reset.  Since
+	 * m_active could have a different number of slots allocated after a
+	 * reset, just de-allocate the old m_active structure and re-allocate a
+	 * new one.  Save the tables and IR info from the old m_active.
+	 */
+	if (first_time == FALSE) {
+		new_active = kmem_zalloc(MPTSAS_SLOTS_SIZE(mpt), KM_SLEEP);
+		if (new_active == NULL) {
+			mptsas_log(mpt, CE_WARN, "Re-alloc of active slots "
 			    "failed!");
 			goto fail;
-		}
-		/*
-		 * Allocate reply descriptor post queue
-		 */
-		if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue "
-			    "failed!");
-			goto fail;
-		}
-		/*
-		 * Allocate reply message frames
-		 */
-		if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames "
-			    "failed!");
-			goto fail;
-		}
+		} else {
+			new_active->m_n_slots = (mpt->m_max_requests - 2);
+			new_active->m_size = MPTSAS_SLOTS_SIZE(mpt);
+			new_active->m_tags = 1;
+			new_active->m_tgttbl = mpt->m_active->m_tgttbl;
+			new_active->m_smptbl = mpt->m_active->m_smptbl;
+			new_active->m_num_raid_configs =
+			    mpt->m_active->m_num_raid_configs;
+			for (i = 0; i < new_active->m_num_raid_configs; i++) {
+				new_active->m_raidconfig[i] =
+				    mpt->m_active->m_raidconfig[i];
+			}
+			kmem_free(mpt->m_active, mpt->m_active->m_size);
+			mpt->m_active = new_active;
+		}
+	}
+
+	/*
+	 * Allocate request message frames
+	 */
+	if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames "
+		    "failed");
+		goto fail;
+	}
+	/*
+	 * Allocate reply free queue
+	 */
+	if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue "
+		    "failed!");
+		goto fail;
+	}
+	/*
+	 * Allocate reply descriptor post queue
+	 */
+	if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue "
+		    "failed!");
+		goto fail;
+	}
+	/*
+	 * Allocate reply message frames
+	 */
+	if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames "
+		    "failed!");
+		goto fail;
 	}
 
 	/*
@@ -10226,14 +10241,9 @@
 
 	/*
 	 * Initialize reply post index and request index.  Reply free index is
-	 * initialized after the next loop.  m_tags must only be initialized if
-	 * this is not the first time because m_active is not allocated if this
-	 * is the first time.
+	 * initialized after the next loop.
 	 */
 	mpt->m_post_index = 0;
-	if (!first_time) {
-		mpt->m_active->m_tags = 1;
-	}
 
 	/*
 	 * Initialize the Reply Free Queue with the physical addresses of our
@@ -10280,7 +10290,7 @@
 	 * is complete, get the base WWID.
 	 */
 
-	if (first_time) {
+	if (first_time == TRUE) {
 		if (mptsas_set_initiator_mode(mpt)) {
 			mptsas_log(mpt, CE_WARN, "mptsas_set_initiator_mode "
 			    "failed!");
@@ -10297,7 +10307,7 @@
 	/*
 	 * enable events
 	 */
-	if (first_time != TRUE) {
+	if (first_time == FALSE) {
 		if (mptsas_ioc_enable_event_notification(mpt)) {
 			goto fail;
 		}
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c	Tue Sep 22 12:05:08 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c	Tue Sep 22 14:06:23 2009 +0800
@@ -304,7 +304,6 @@
 	int			rval = DDI_SUCCESS, config_flags = 0;
 	mptsas_cmd_t		*cmd;
 	struct scsi_pkt		*pkt;
-	uint32_t		reply_index;
 	pMpi2ConfigReply_t	reply;
 	uint16_t		iocstatus = 0;
 	uint32_t		iocloginfo;
@@ -429,18 +428,16 @@
 	 * if this reply is an ADDRESS reply.
 	 */
 	if (config_flags & MPTSAS_ADDRESS_REPLY) {
-		reply_index = mpt->m_free_index;
 		ddi_put32(mpt->m_acc_free_queue_hdl,
-		    &((uint32_t *)(void *)mpt->m_free_queue)[reply_index],
+		    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 		    cmd->cmd_rfm);
 		(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 		    DDI_DMA_SYNC_FORDEV);
-		if (++reply_index == mpt->m_free_queue_depth) {
-			reply_index = 0;
+		if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+			mpt->m_free_index = 0;
 		}
-		mpt->m_free_index = reply_index;
 		ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
-		    reply_index);
+		    mpt->m_free_index);
 		config_flags &= (~MPTSAS_ADDRESS_REPLY);
 	}
 
@@ -578,18 +575,16 @@
 	 * if this reply is an ADDRESS reply.
 	 */
 	if (config_flags & MPTSAS_ADDRESS_REPLY) {
-		reply_index = mpt->m_free_index;
 		ddi_put32(mpt->m_acc_free_queue_hdl,
-		    &((uint32_t *)(void *)mpt->m_free_queue)[reply_index],
+		    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
 		    cmd->cmd_rfm);
 		(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
 		    DDI_DMA_SYNC_FORDEV);
-		if (++reply_index == mpt->m_free_queue_depth) {
-			reply_index = 0;
+		if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+			mpt->m_free_index = 0;
 		}
-		mpt->m_free_index = reply_index;
 		ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
-		    reply_index);
+		    mpt->m_free_index);
 	}
 
 	if (cmd->cmd_dmahandle != NULL) {
@@ -1086,7 +1081,7 @@
 	mptsas_cmd_t				*cmd;
 	struct scsi_pkt				*pkt;
 	mptsas_slots_t				*slots = mpt->m_active;
-	uint32_t				request_desc_low, int_mask;
+	uint32_t				request_desc_low;
 
 	/*
 	 * Can't start another task management routine.
@@ -1137,22 +1132,14 @@
 	ddi_put8(mpt->m_acc_req_frame_hdl, &task->TaskType, task_type);
 
 	/*
-	 * Get the current interrupt mask.  When re-enabling ints, set mask to
-	 * saved value.
-	 */
-	int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
-
-	/*
 	 * Send TM request using High Priority Queue.
 	 */
-	MPTSAS_DISABLE_INTR(mpt);
 	(void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
 	    DDI_DMA_SYNC_FORDEV);
 	request_desc_low = (cmd->cmd_slot << 16) +
 	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
 	MPTSAS_START_CMD(mpt, request_desc_low, 0);
 	rval = mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
-	ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
 
 	if (pkt->pkt_reason == CMD_INCOMPLETE)
 		rval = FALSE;
@@ -1755,6 +1742,54 @@
 	return (rval);
 }
 
+static int
+mptsas_biospage_3_cb(mptsas_t *mpt, caddr_t page_memp,
+    ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
+    va_list ap)
+{
+#ifndef __lock_lint
+	_NOTE(ARGUNUSED(ap))
+#endif
+	pMpi2BiosPage3_t	sasbiospage;
+	int			rval = DDI_SUCCESS;
+	uint32_t		*bios_version;
+
+	if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
+	    (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
+		mptsas_log(mpt, CE_WARN, "mptsas_get_bios_page3 header: "
+		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, iocloginfo);
+		rval = DDI_FAILURE;
+		return (rval);
+	}
+	bios_version = va_arg(ap, uint32_t *);
+	sasbiospage = (pMpi2BiosPage3_t)page_memp;
+	*bios_version = ddi_get32(accessp, &sasbiospage->BiosVersion);
+
+	return (rval);
+}
+
+/*
+ * Request MPI configuration page BIOS page 3 to get BIOS version.  Since all
+ * other information in this page is not needed, just ignore it.
+ */
+int
+mptsas_get_bios_page3(mptsas_t *mpt, uint32_t *bios_version)
+{
+	int rval = DDI_SUCCESS;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	/*
+	 * Get the header and config page.  reply contains the reply frame,
+	 * which holds status info for the request.
+	 */
+	rval = mptsas_access_config_page(mpt,
+	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, MPI2_CONFIG_PAGETYPE_BIOS, 3,
+	    0, mptsas_biospage_3_cb, bios_version);
+
+	return (rval);
+}
+
 /*
  * Read IO unit page 0 to get information for each PHY. If needed, Read IO Unit
  * page1 to update the PHY information.  This is the handshaking version of
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h	Tue Sep 22 12:05:08 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h	Tue Sep 22 14:06:23 2009 +0800
@@ -407,7 +407,6 @@
 	m_raidconfig_t		m_raidconfig[MPTSAS_MAX_RAIDCONFIGS];
 	uint8_t			m_num_raid_configs;
 	uint16_t		m_tags;
-	uint32_t		m_buffer;
 	size_t			m_size;
 	uint16_t		m_n_slots;
 	mptsas_cmd_t		*m_slot[1];
@@ -791,6 +790,7 @@
 	/*
 	 * Event recording
 	 */
+	uint8_t			m_event_index;
 	uint32_t		m_event_number;
 	uint32_t		m_event_mask[4];
 	mptsas_event_entry_t	m_events[MPTSAS_EVENT_QUEUE_SIZE];
@@ -1237,6 +1237,7 @@
 int mptsas_get_manufacture_page5(mptsas_t *mpt);
 int mptsas_get_sas_port_page0(mptsas_t *mpt, uint32_t page_address,
     uint64_t *sas_wwn, uint8_t *portwidth);
+int mptsas_get_bios_page3(mptsas_t *mpt,  uint32_t *bios_version);
 
 /*
  * RAID functions