Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Mar 2012 23:05:49 +0000 (UTC)
From:      Doug Ambrisko <ambrisko@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233711 - in head/sys: conf dev/mfi modules/mfi
Message-ID:  <201203302305.q2UN5nxA061843@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ambrisko
Date: Fri Mar 30 23:05:48 2012
New Revision: 233711
URL: http://svn.freebsd.org/changeset/base/233711

Log:
  MFhead_mfi r227068
  	First cut of new HW support from LSI and merge into FreeBSD.
  	Supports Drake Skinny and ThunderBolt cards.
  MFhead_mfi r227574
  	Style
  MFhead_mfi r227579
  	Use bus_addr_t instead of uintXX_t.
  MFhead_mfi r227580
  	MSI support
  MFhead_mfi r227612
  	More bus_addr_t and remove "#ifdef __amd64__".
  MFhead_mfi r227905
  	Improved timeout support from Scott.
  MFhead_mfi r228108
  	Make file.
  MFhead_mfi r228208
  	Fixed botched merge of Skinny support and enhanced handling
  	in call back routine.
  MFhead_mfi r228279
  	Remove superfluous !TAILQ_EMPTY() checks before TAILQ_FOREACH().
  MFhead_mfi r228310
  	Move mfi_decode_evt() to taskqueue.
  MFhead_mfi r228320
  	Implement MFI_DEBUG for 64bit S/G lists.
  MFhead_mfi r231988
  	Restore structure layout by reverting the array header to
  	use [0] instead of [1].
  MFhead_mfi r232412
  	Put wildcard pattern later in the match table.
  MFhead_mfi r232413
  	Use lower case for hexadecimal numbers to match surrounding
  	style.
  MFhead_mfi r232414
  	Add more Thunderbolt variants.
  MFhead_mfi r232888
  	Don't act on events prior to boot or when shutting down.
  	Add hw.mfi.detect_jbod_change to enable or disable acting
  	on JBOD type of disks being added on insert and removed on
  	removing.  Switch hw.mfi.msi to 1 by default since it works
  	better on newer cards.
  MFhead_mfi r233016
  	Release driver lock before taking Giant when deleting children.
  	Use TAILQ_FOREACH_SAFE when items can be deleted.  Make code a
  	little simplier to follow.  Fix a couple more style issues.
  MFhead_mfi r233620
  	Update mfi_spare/mfi_array with the actual number of elements
  	for array_ref and pd.  Change these max. #define names to avoid
  	name space collisions.  This will require an update to mfiutil
  	It avoids mfiutil having to do a magic calculation.
  
  	Add a note and #define to state that a "SYSTEM" disk is really
  	what the firmware calls a "JBOD" drive.
  
  Thanks to the many that helped, LSI for the initial code drop,
  mav, delphij, jhb, sbruno that all helped with code and testing.

Added:
  head/sys/dev/mfi/mfi_syspd.c   (contents, props changed)
     - copied, changed from r227068, projects/head_mfi/sys/dev/mfi/mfi_syspd.c
  head/sys/dev/mfi/mfi_tbolt.c   (contents, props changed)
     - copied, changed from r227068, projects/head_mfi/sys/dev/mfi/mfi_tbolt.c
Modified:
  head/sys/conf/files
  head/sys/dev/mfi/mfi.c
  head/sys/dev/mfi/mfi_cam.c
  head/sys/dev/mfi/mfi_debug.c
  head/sys/dev/mfi/mfi_disk.c
  head/sys/dev/mfi/mfi_ioctl.h
  head/sys/dev/mfi/mfi_linux.c
  head/sys/dev/mfi/mfi_pci.c
  head/sys/dev/mfi/mfireg.h
  head/sys/dev/mfi/mfivar.h
  head/sys/modules/mfi/Makefile
Directory Properties:
  head/sys/   (props changed)
  head/sys/conf/   (props changed)

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Fri Mar 30 22:52:08 2012	(r233710)
+++ head/sys/conf/files	Fri Mar 30 23:05:48 2012	(r233711)
@@ -1558,6 +1558,8 @@ dev/mfi/mfi.c			optional mfi
 dev/mfi/mfi_debug.c		optional mfi
 dev/mfi/mfi_pci.c		optional mfi pci
 dev/mfi/mfi_disk.c		optional mfi
+dev/mfi/mfi_syspd.c		optional mfi
+dev/mfi/mfi_tbolt.c		optional mfi
 dev/mfi/mfi_linux.c		optional mfi compat_linux
 dev/mfi/mfi_cam.c		optional mfip scbus
 dev/mii/acphy.c			optional miibus | acphy

Modified: head/sys/dev/mfi/mfi.c
==============================================================================
--- head/sys/dev/mfi/mfi.c	Fri Mar 30 22:52:08 2012	(r233710)
+++ head/sys/dev/mfi/mfi.c	Fri Mar 30 23:05:48 2012	(r233711)
@@ -53,6 +53,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_compat.h"
 #include "opt_mfi.h"
 
 #include <sys/param.h>
@@ -72,6 +73,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/uio.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
+#include <sys/taskqueue.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -79,10 +81,11 @@ __FBSDID("$FreeBSD$");
 #include <dev/mfi/mfireg.h>
 #include <dev/mfi/mfi_ioctl.h>
 #include <dev/mfi/mfivar.h>
+#include <sys/interrupt.h>
+#include <sys/priority.h>
 
 static int	mfi_alloc_commands(struct mfi_softc *);
 static int	mfi_comms_init(struct mfi_softc *);
-static int	mfi_wait_command(struct mfi_softc *, struct mfi_command *);
 static int	mfi_get_controller_info(struct mfi_softc *);
 static int	mfi_get_log_state(struct mfi_softc *,
 		    struct mfi_evt_log_state **);
@@ -93,29 +96,39 @@ static void	mfi_data_cb(void *, bus_dma_
 static void	mfi_startup(void *arg);
 static void	mfi_intr(void *arg);
 static void	mfi_ldprobe(struct mfi_softc *sc);
+static void	mfi_syspdprobe(struct mfi_softc *sc);
+static void	mfi_handle_evt(void *context, int pending);
 static int	mfi_aen_register(struct mfi_softc *sc, int seq, int locale);
 static void	mfi_aen_complete(struct mfi_command *);
-static int	mfi_aen_setup(struct mfi_softc *, uint32_t);
 static int	mfi_add_ld(struct mfi_softc *sc, int);
 static void	mfi_add_ld_complete(struct mfi_command *);
+static int	mfi_add_sys_pd(struct mfi_softc *sc, int);
+static void	mfi_add_sys_pd_complete(struct mfi_command *);
 static struct mfi_command * mfi_bio_command(struct mfi_softc *);
 static void	mfi_bio_complete(struct mfi_command *);
-static int	mfi_mapcmd(struct mfi_softc *, struct mfi_command *);
+static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*);
+static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*);
 static int	mfi_send_frame(struct mfi_softc *, struct mfi_command *);
-static void	mfi_complete(struct mfi_softc *, struct mfi_command *);
 static int	mfi_abort(struct mfi_softc *, struct mfi_command *);
 static int	mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *);
 static void	mfi_timeout(void *);
 static int	mfi_user_command(struct mfi_softc *,
 		    struct mfi_ioc_passthru *);
-static void 	mfi_enable_intr_xscale(struct mfi_softc *sc);
-static void 	mfi_enable_intr_ppc(struct mfi_softc *sc);
-static int32_t 	mfi_read_fw_status_xscale(struct mfi_softc *sc);
-static int32_t 	mfi_read_fw_status_ppc(struct mfi_softc *sc);
-static int 	mfi_check_clear_intr_xscale(struct mfi_softc *sc);
-static int 	mfi_check_clear_intr_ppc(struct mfi_softc *sc);
-static void 	mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
-static void 	mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
+static void	mfi_enable_intr_xscale(struct mfi_softc *sc);
+static void	mfi_enable_intr_ppc(struct mfi_softc *sc);
+static int32_t	mfi_read_fw_status_xscale(struct mfi_softc *sc);
+static int32_t	mfi_read_fw_status_ppc(struct mfi_softc *sc);
+static int	mfi_check_clear_intr_xscale(struct mfi_softc *sc);
+static int	mfi_check_clear_intr_ppc(struct mfi_softc *sc);
+static void 	mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add,
+		    uint32_t frame_cnt);
+static void 	mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
+		    uint32_t frame_cnt);
+static int mfi_config_lock(struct mfi_softc *sc, uint32_t opcode);
+static void mfi_config_unlock(struct mfi_softc *sc, int locked);
+static int mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm);
+static void mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm);
+static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm);
 
 SYSCTL_NODE(_hw, OID_AUTO, mfi, CTLFLAG_RD, 0, "MFI driver parameters");
 static int	mfi_event_locale = MFI_EVT_LOCALE_ALL;
@@ -133,6 +146,11 @@ TUNABLE_INT("hw.mfi.max_cmds", &mfi_max_
 SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,
 	   0, "Max commands");
 
+static int	mfi_detect_jbod_change = 1;
+TUNABLE_INT("hw.mfi.detect_jbod_change", &mfi_detect_jbod_change);
+SYSCTL_INT(_hw_mfi, OID_AUTO, detect_jbod_change, CTLFLAG_RW,
+	   &mfi_detect_jbod_change, 0, "Detect a change to a JBOD");
+
 /* Management interface */
 static d_open_t		mfi_open;
 static d_close_t	mfi_close;
@@ -152,6 +170,7 @@ static struct cdevsw mfi_cdevsw = {
 MALLOC_DEFINE(M_MFIBUF, "mfibuf", "Buffers for the MFI driver");
 
 #define MFI_INQ_LENGTH SHORT_INQUIRY_LENGTH
+struct mfi_skinny_dma_info mfi_skinny;
 
 static void
 mfi_enable_intr_xscale(struct mfi_softc *sc)
@@ -162,12 +181,17 @@ mfi_enable_intr_xscale(struct mfi_softc 
 static void
 mfi_enable_intr_ppc(struct mfi_softc *sc)
 {
-	MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
 	if (sc->mfi_flags & MFI_FLAGS_1078) {
+		MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
 		MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM);
-	} else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+	}
+	else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+		MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
 		MFI_WRITE4(sc, MFI_OMSK, ~MFI_GEN2_EIM);
 	}
+	else if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+		MFI_WRITE4(sc, MFI_OMSK, ~0x00000001);
+	}
 }
 
 static int32_t
@@ -205,35 +229,51 @@ mfi_check_clear_intr_ppc(struct mfi_soft
 		if (!(status & MFI_1078_RM)) {
 			return 1;
 		}
-	} else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+	}
+	else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
 		if (!(status & MFI_GEN2_RM)) {
 			return 1;
 		}
 	}
-
-	MFI_WRITE4(sc, MFI_ODCR0, status);
+	else if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+		if (!(status & MFI_SKINNY_RM)) {
+			return 1;
+		}
+	}
+	if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+		MFI_WRITE4(sc, MFI_OSTS, status);
+	else
+		MFI_WRITE4(sc, MFI_ODCR0, status);
 	return 0;
 }
 
 static void
-mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
 {
 	MFI_WRITE4(sc, MFI_IQP,(bus_add >>3)|frame_cnt);
 }
 
 static void
-mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
 {
-	MFI_WRITE4(sc, MFI_IQP, (bus_add |frame_cnt <<1)|1 );
+	if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+	    MFI_WRITE4(sc, MFI_IQPL, (bus_add | frame_cnt <<1)|1 );
+	    MFI_WRITE4(sc, MFI_IQPH, 0x00000000);
+	} else {
+	    MFI_WRITE4(sc, MFI_IQP, (bus_add | frame_cnt <<1)|1 );
+	}
 }
 
-static int
+int
 mfi_transition_firmware(struct mfi_softc *sc)
 {
 	uint32_t fw_state, cur_state;
 	int max_wait, i;
+	uint32_t cur_abs_reg_val = 0;
+	uint32_t prev_abs_reg_val = 0;
 
-	fw_state = sc->mfi_read_fw_status(sc)& MFI_FWSTATE_MASK;
+	cur_abs_reg_val = sc->mfi_read_fw_status(sc);
+	fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
 	while (fw_state != MFI_FWSTATE_READY) {
 		if (bootverbose)
 			device_printf(sc->mfi_dev, "Waiting for firmware to "
@@ -244,38 +284,60 @@ mfi_transition_firmware(struct mfi_softc
 			device_printf(sc->mfi_dev, "Firmware fault\n");
 			return (ENXIO);
 		case MFI_FWSTATE_WAIT_HANDSHAKE:
-			MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
-			max_wait = 2;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_OPERATIONAL:
-			MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_READY);
-			max_wait = 10;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, 7);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_READY);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_UNDEFINED:
 		case MFI_FWSTATE_BB_INIT:
-			max_wait = 2;
+			max_wait = MFI_RESET_WAIT_TIME;
+			break;
+		case MFI_FWSTATE_FW_INIT_2:
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_FW_INIT:
-		case MFI_FWSTATE_DEVICE_SCAN:
 		case MFI_FWSTATE_FLUSH_CACHE:
-			max_wait = 20;
+			max_wait = MFI_RESET_WAIT_TIME;
+			break;
+		case MFI_FWSTATE_DEVICE_SCAN:
+			max_wait = MFI_RESET_WAIT_TIME; /* wait for 180 seconds */
+			prev_abs_reg_val = cur_abs_reg_val;
 			break;
 		case MFI_FWSTATE_BOOT_MESSAGE_PENDING:
-			MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_HOTPLUG);
-			max_wait = 10;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_HOTPLUG);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_HOTPLUG);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		default:
-			device_printf(sc->mfi_dev,"Unknown firmware state %#x\n",
+			device_printf(sc->mfi_dev, "Unknown firmware state %#x\n",
 			    fw_state);
 			return (ENXIO);
 		}
 		for (i = 0; i < (max_wait * 10); i++) {
-			fw_state = sc->mfi_read_fw_status(sc) & MFI_FWSTATE_MASK;
+			cur_abs_reg_val = sc->mfi_read_fw_status(sc);
+			fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
 			if (fw_state == cur_state)
 				DELAY(100000);
 			else
 				break;
 		}
+		if (fw_state == MFI_FWSTATE_DEVICE_SCAN) {
+			/* Check the device scanning progress */
+			if (prev_abs_reg_val != cur_abs_reg_val) {
+				continue;
+			}
+		}
 		if (fw_state == cur_state) {
 			device_printf(sc->mfi_dev, "Firmware stuck in state "
 			    "%#x\n", fw_state);
@@ -286,26 +348,35 @@ mfi_transition_firmware(struct mfi_softc
 }
 
 static void
-mfi_addr32_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+mfi_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 {
-	uint32_t *addr;
+	bus_addr_t *addr;
 
 	addr = arg;
 	*addr = segs[0].ds_addr;
 }
 
+
 int
 mfi_attach(struct mfi_softc *sc)
 {
 	uint32_t status;
 	int error, commsz, framessz, sensesz;
 	int frames, unit, max_fw_sge;
+	uint32_t tb_mem_size = 0;
+
+	if (sc == NULL)
+		return EINVAL;
 
-	device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.00 \n");
+	device_printf(sc->mfi_dev, "Megaraid SAS driver Ver %s \n",
+	    MEGASAS_VERSION);
 
 	mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF);
 	sx_init(&sc->mfi_config_lock, "MFI config");
 	TAILQ_INIT(&sc->mfi_ld_tqh);
+	TAILQ_INIT(&sc->mfi_syspd_tqh);
+	TAILQ_INIT(&sc->mfi_evt_queue);
+	TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
 	TAILQ_INIT(&sc->mfi_aen_pids);
 	TAILQ_INIT(&sc->mfi_cam_ccbq);
 
@@ -314,15 +385,29 @@ mfi_attach(struct mfi_softc *sc)
 	mfi_initq_busy(sc);
 	mfi_initq_bio(sc);
 
+	sc->adpreset = 0;
+	sc->last_seq_num = 0;
+	sc->disableOnlineCtrlReset = 1;
+	sc->issuepend_done = 1;
+	sc->hw_crit_error = 0;
+
 	if (sc->mfi_flags & MFI_FLAGS_1064R) {
 		sc->mfi_enable_intr = mfi_enable_intr_xscale;
 		sc->mfi_read_fw_status = mfi_read_fw_status_xscale;
 		sc->mfi_check_clear_intr = mfi_check_clear_intr_xscale;
 		sc->mfi_issue_cmd = mfi_issue_cmd_xscale;
-	}
-	else {
+	} else if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		sc->mfi_enable_intr = mfi_tbolt_enable_intr_ppc;
+		sc->mfi_disable_intr = mfi_tbolt_disable_intr_ppc;
+		sc->mfi_read_fw_status = mfi_tbolt_read_fw_status_ppc;
+		sc->mfi_check_clear_intr = mfi_tbolt_check_clear_intr_ppc;
+		sc->mfi_issue_cmd = mfi_tbolt_issue_cmd_ppc;
+		sc->mfi_adp_reset = mfi_tbolt_adp_reset;
+		sc->mfi_tbolt = 1;
+		TAILQ_INIT(&sc->mfi_cmd_tbolt_tqh);
+	} else {
 		sc->mfi_enable_intr =  mfi_enable_intr_ppc;
- 		sc->mfi_read_fw_status = mfi_read_fw_status_ppc;
+		sc->mfi_read_fw_status = mfi_read_fw_status_ppc;
 		sc->mfi_check_clear_intr = mfi_check_clear_intr_ppc;
 		sc->mfi_issue_cmd = mfi_issue_cmd_ppc;
 	}
@@ -335,6 +420,32 @@ mfi_attach(struct mfi_softc *sc)
 		return (ENXIO);
 	}
 
+	/* Start: LSIP200113393 */
+	if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				MEGASAS_MAX_NAME*sizeof(bus_addr_t),			/* maxsize */
+				1,			/* msegments */
+				MEGASAS_MAX_NAME*sizeof(bus_addr_t),			/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->verbuf_h_dmat)) {
+		device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmat DMA tag\n");
+		return (ENOMEM);
+	}
+	if (bus_dmamem_alloc(sc->verbuf_h_dmat, (void **)&sc->verbuf,
+	    BUS_DMA_NOWAIT, &sc->verbuf_h_dmamap)) {
+		device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmamap memory\n");
+		return (ENOMEM);
+	}
+	bzero(sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t));
+	bus_dmamap_load(sc->verbuf_h_dmat, sc->verbuf_h_dmamap,
+	    sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t),
+	    mfi_addr_cb, &sc->verbuf_h_busaddr, 0);
+	/* End: LSIP200113393 */
+
 	/*
 	 * Get information needed for sizing the contiguous memory for the
 	 * frame pool.  Size down the sgl parameter since we know that
@@ -347,6 +458,100 @@ mfi_attach(struct mfi_softc *sc)
 	max_fw_sge = (status & MFI_FWSTATE_MAXSGL_MASK) >> 16;
 	sc->mfi_max_sge = min(max_fw_sge, ((MFI_MAXPHYS / PAGE_SIZE) + 1));
 
+	/* ThunderBolt Support get the contiguous memory */
+
+	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		mfi_tbolt_init_globals(sc);
+		device_printf(sc->mfi_dev, "MaxCmd = %x MaxSgl = %x state = %x \n",
+		    sc->mfi_max_fw_cmds, sc->mfi_max_sge, status);
+		tb_mem_size = mfi_tbolt_get_memory_requirement(sc);
+
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				tb_mem_size,		/* maxsize */
+				1,			/* msegments */
+				tb_mem_size,		/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->mfi_tb_dmat)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms DMA tag\n");
+			return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_dmat, (void **)&sc->request_message_pool,
+		BUS_DMA_NOWAIT, &sc->mfi_tb_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->request_message_pool, tb_mem_size);
+		bus_dmamap_load(sc->mfi_tb_dmat, sc->mfi_tb_dmamap,
+		sc->request_message_pool, tb_mem_size, mfi_addr_cb, &sc->mfi_tb_busaddr, 0);
+
+		/* For ThunderBolt memory init */
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				0x100, 0,		/* alignmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				MFI_FRAME_SIZE,		/* maxsize */
+				1,			/* msegments */
+				MFI_FRAME_SIZE,		/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->mfi_tb_init_dmat)) {
+		device_printf(sc->mfi_dev, "Cannot allocate init DMA tag\n");
+		return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_init_dmat, (void **)&sc->mfi_tb_init,
+		    BUS_DMA_NOWAIT, &sc->mfi_tb_init_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate init memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->mfi_tb_init, MFI_FRAME_SIZE);
+		bus_dmamap_load(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap,
+		sc->mfi_tb_init, MFI_FRAME_SIZE, mfi_addr_cb,
+		    &sc->mfi_tb_init_busaddr, 0);
+		if (mfi_tbolt_init_desc_pool(sc, sc->request_message_pool,
+		    tb_mem_size)) {
+			device_printf(sc->mfi_dev,
+			    "Thunderbolt pool preparation error\n");
+			return 0;
+		}
+
+		/*
+		  Allocate DMA memory mapping for MPI2 IOC Init descriptor,
+		  we are taking it diffrent from what we have allocated for Request
+		  and reply descriptors to avoid confusion later
+		*/
+		tb_mem_size = sizeof(struct MPI2_IOC_INIT_REQUEST);
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				tb_mem_size,		/* maxsize */
+				1,			/* msegments */
+				tb_mem_size,		/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->mfi_tb_ioc_init_dmat)) {
+			device_printf(sc->mfi_dev,
+			    "Cannot allocate comms DMA tag\n");
+			return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_ioc_init_dmat,
+		    (void **)&sc->mfi_tb_ioc_init_desc,
+		    BUS_DMA_NOWAIT, &sc->mfi_tb_ioc_init_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->mfi_tb_ioc_init_desc, tb_mem_size);
+		bus_dmamap_load(sc->mfi_tb_ioc_init_dmat, sc->mfi_tb_ioc_init_dmamap,
+		sc->mfi_tb_ioc_init_desc, tb_mem_size, mfi_addr_cb,
+		    &sc->mfi_tb_ioc_init_busaddr, 0);
+	}
 	/*
 	 * Create the dma tag for data buffers.  Used both for block I/O
 	 * and for various internal data queries.
@@ -396,8 +601,7 @@ mfi_attach(struct mfi_softc *sc)
 	}
 	bzero(sc->mfi_comms, commsz);
 	bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
-	    sc->mfi_comms, commsz, mfi_addr32_cb, &sc->mfi_comms_busaddr, 0);
-
+	    sc->mfi_comms, commsz, mfi_addr_cb, &sc->mfi_comms_busaddr, 0);
 	/*
 	 * Allocate DMA memory for the command frames.  Keep them in the
 	 * lower 4GB for efficiency.  Calculate the size of the commands at
@@ -414,6 +618,8 @@ mfi_attach(struct mfi_softc *sc)
 	} else {
 		sc->mfi_sge_size = sizeof(struct mfi_sg32);
 	}
+	if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+		sc->mfi_sge_size = sizeof(struct mfi_sg_skinny);
 	frames = (sc->mfi_sge_size * sc->mfi_max_sge - 1) / MFI_FRAME_SIZE + 2;
 	sc->mfi_cmd_size = frames * MFI_FRAME_SIZE;
 	framessz = sc->mfi_cmd_size * sc->mfi_max_fw_cmds;
@@ -438,8 +644,7 @@ mfi_attach(struct mfi_softc *sc)
 	}
 	bzero(sc->mfi_frames, framessz);
 	bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
-	    sc->mfi_frames, framessz, mfi_addr32_cb, &sc->mfi_frames_busaddr,0);
-
+	    sc->mfi_frames, framessz, mfi_addr_cb, &sc->mfi_frames_busaddr,0);
 	/*
 	 * Allocate DMA memory for the frame sense data.  Keep them in the
 	 * lower 4GB for efficiency
@@ -465,32 +670,47 @@ mfi_attach(struct mfi_softc *sc)
 		return (ENOMEM);
 	}
 	bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
-	    sc->mfi_sense, sensesz, mfi_addr32_cb, &sc->mfi_sense_busaddr, 0);
-
+	    sc->mfi_sense, sensesz, mfi_addr_cb, &sc->mfi_sense_busaddr, 0);
 	if ((error = mfi_alloc_commands(sc)) != 0)
 		return (error);
 
-	if ((error = mfi_comms_init(sc)) != 0)
-		return (error);
+	/* Before moving the FW to operational state, check whether
+	 * hostmemory is required by the FW or not
+	 */
 
-	if ((error = mfi_get_controller_info(sc)) != 0)
-		return (error);
+	/* ThunderBolt MFI_IOC2 INIT */
+	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		sc->mfi_disable_intr(sc);
+		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0) {
+			device_printf(sc->mfi_dev,
+			    "TB Init has failed with error %d\n",error);
+			return error;
+		}
 
-	mtx_lock(&sc->mfi_io_lock);
-	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
-		mtx_unlock(&sc->mfi_io_lock);
-		return (error);
-	}
-	mtx_unlock(&sc->mfi_io_lock);
+		if ((error = mfi_tbolt_alloc_cmd(sc)) != 0)
+			return error;
+		if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq,
+		    INTR_MPSAFE|INTR_TYPE_BIO, NULL, mfi_intr_tbolt, sc,
+		    &sc->mfi_intr)) {
+			device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+			return (EINVAL);
+		}
+		sc->mfi_enable_intr(sc);
+		sc->map_id = 0;
+	} else {
+		if ((error = mfi_comms_init(sc)) != 0)
+			return (error);
 
-	/*
-	 * Set up the interrupt handler.
-	 */
-	if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE|INTR_TYPE_BIO,
-	    NULL, mfi_intr, sc, &sc->mfi_intr)) {
-		device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
-		return (EINVAL);
+		if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq,
+		    INTR_MPSAFE|INTR_TYPE_BIO, NULL, mfi_intr, sc, &sc->mfi_intr)) {
+			device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+			return (EINVAL);
+		}
+		sc->mfi_enable_intr(sc);
 	}
+	if ((error = mfi_get_controller_info(sc)) != 0)
+		return (error);
+	sc->disableOnlineCtrlReset = 0;
 
 	/* Register a config hook to probe the bus for arrays */
 	sc->mfi_ich.ich_func = mfi_startup;
@@ -500,6 +720,10 @@ mfi_attach(struct mfi_softc *sc)
 		    "hook\n");
 		return (EINVAL);
 	}
+	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
+		mtx_unlock(&sc->mfi_io_lock);
+		return (error);
+	}
 
 	/*
 	 * Register a shutdown handler.
@@ -571,8 +795,11 @@ mfi_alloc_commands(struct mfi_softc *sc)
 		cm->cm_sc = sc;
 		cm->cm_index = i;
 		if (bus_dmamap_create(sc->mfi_buffer_dmat, 0,
-		    &cm->cm_dmamap) == 0)
+		    &cm->cm_dmamap) == 0) {
+			mtx_lock(&sc->mfi_io_lock);
 			mfi_release_command(cm);
+			mtx_unlock(&sc->mfi_io_lock);
+		}
 		else
 			break;
 		sc->mfi_total_cmds++;
@@ -587,6 +814,8 @@ mfi_release_command(struct mfi_command *
 	struct mfi_frame_header *hdr;
 	uint32_t *hdr_data;
 
+	mtx_assert(&cm->cm_sc->mfi_io_lock, MA_OWNED);
+
 	/*
 	 * Zero out the important fields of the frame, but make sure the
 	 * context field is preserved.  For efficiency, handle the fields
@@ -611,24 +840,31 @@ mfi_release_command(struct mfi_command *
 	cm->cm_data = NULL;
 	cm->cm_sg = 0;
 	cm->cm_total_frame_size = 0;
+	cm->retry_for_fw_reset = 0;
 
 	mfi_enqueue_free(cm);
 }
 
 static int
-mfi_dcmd_command(struct mfi_softc *sc, struct mfi_command **cmp, uint32_t opcode,
-    void **bufp, size_t bufsize)
+mfi_dcmd_command(struct mfi_softc *sc, struct mfi_command **cmp,
+    uint32_t opcode, void **bufp, size_t bufsize)
 {
 	struct mfi_command *cm;
 	struct mfi_dcmd_frame *dcmd;
 	void *buf = NULL;
-	
+	uint32_t context = 0;
+
 	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
-	
+
 	cm = mfi_dequeue_free(sc);
 	if (cm == NULL)
 		return (EBUSY);
 
+	/* Zero out the MFI frame */
+	context = cm->cm_frame->header.context;
+	bzero(cm->cm_frame, sizeof(union mfi_frame));
+	cm->cm_frame->header.context = context;
+
 	if ((bufsize > 0) && (bufp != NULL)) {
 		if (*bufp == NULL) {
 			buf = malloc(bufsize, M_MFIBUF, M_NOWAIT|M_ZERO);
@@ -648,6 +884,7 @@ mfi_dcmd_command(struct mfi_softc *sc, s
 	dcmd->header.timeout = 0;
 	dcmd->header.flags = 0;
 	dcmd->header.data_len = bufsize;
+	dcmd->header.scsi_status = 0;
 	dcmd->opcode = opcode;
 	cm->cm_sg = &dcmd->sgl;
 	cm->cm_total_frame_size = MFI_DCMD_FRAME_SIZE;
@@ -669,11 +906,17 @@ mfi_comms_init(struct mfi_softc *sc)
 	struct mfi_init_frame *init;
 	struct mfi_init_qinfo *qinfo;
 	int error;
+	uint32_t context = 0;
 
 	mtx_lock(&sc->mfi_io_lock);
 	if ((cm = mfi_dequeue_free(sc)) == NULL)
 		return (EBUSY);
 
+	/* Zero out the MFI frame */
+	context = cm->cm_frame->header.context;
+	bzero(cm->cm_frame, sizeof(union mfi_frame));
+	cm->cm_frame->header.context = context;
+
 	/*
 	 * Abuse the SG list area of the frame to hold the init_qinfo
 	 * object;
@@ -734,9 +977,11 @@ mfi_get_controller_info(struct mfi_softc
 	    BUS_DMASYNC_POSTREAD);
 	bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
 
-	max_sectors_1 = (1 << ci->stripe_sz_ops.min) * ci->max_strips_per_io;
+	max_sectors_1 = (1 << ci->stripe_sz_ops.max) * ci->max_strips_per_io;
 	max_sectors_2 = ci->max_request_size;
 	sc->mfi_max_io = min(max_sectors_1, max_sectors_2);
+	sc->disableOnlineCtrlReset =
+	    ci->properties.OnOffProperties.disableOnlineCtrlReset;
 
 out:
 	if (ci)
@@ -753,6 +998,7 @@ mfi_get_log_state(struct mfi_softc *sc, 
 	struct mfi_command *cm = NULL;
 	int error;
 
+	mtx_lock(&sc->mfi_io_lock);
 	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_GETINFO,
 	    (void **)log_state, sizeof(**log_state));
 	if (error)
@@ -771,11 +1017,12 @@ mfi_get_log_state(struct mfi_softc *sc, 
 out:
 	if (cm)
 		mfi_release_command(cm);
+	mtx_unlock(&sc->mfi_io_lock);
 
 	return (error);
 }
 
-static int
+int
 mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
 {
 	struct mfi_evt_log_state *log_state = NULL;
@@ -789,6 +1036,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint
 
 	if (seq_start == 0) {
 		error = mfi_get_log_state(sc, &log_state);
+		sc->mfi_boot_seq_num = log_state->boot_seq_num;
 		if (error) {
 			if (log_state)
 				free(log_state, M_MFIBUF);
@@ -810,7 +1058,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint
 	return 0;
 }
 
-static int
+int
 mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm)
 {
 
@@ -883,6 +1131,64 @@ mfi_free(struct mfi_softc *sc)
 	if (sc->mfi_comms_dmat != NULL)
 		bus_dma_tag_destroy(sc->mfi_comms_dmat);
 
+	/* ThunderBolt contiguous memory free here */
+	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		if (sc->mfi_tb_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_dmat, sc->mfi_tb_dmamap);
+		if (sc->request_message_pool != NULL)
+			bus_dmamem_free(sc->mfi_tb_dmat, sc->request_message_pool,
+			    sc->mfi_tb_dmamap);
+		if (sc->mfi_tb_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_dmat);
+
+		/* Version buffer memory free */
+		/* Start LSIP200113393 */
+		if (sc->verbuf_h_busaddr != 0)
+			bus_dmamap_unload(sc->verbuf_h_dmat, sc->verbuf_h_dmamap);
+		if (sc->verbuf != NULL)
+			bus_dmamem_free(sc->verbuf_h_dmat, sc->verbuf,
+			    sc->verbuf_h_dmamap);
+		if (sc->verbuf_h_dmat != NULL)
+			bus_dma_tag_destroy(sc->verbuf_h_dmat);
+
+		/* End LSIP200113393 */
+		/* ThunderBolt INIT packet memory Free */
+		if (sc->mfi_tb_init_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap);
+		if (sc->mfi_tb_init != NULL)
+			bus_dmamem_free(sc->mfi_tb_init_dmat, sc->mfi_tb_init,
+			    sc->mfi_tb_init_dmamap);
+		if (sc->mfi_tb_init_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_init_dmat);
+
+		/* ThunderBolt IOC Init Desc memory free here */
+		if (sc->mfi_tb_ioc_init_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_ioc_init_dmat,
+			    sc->mfi_tb_ioc_init_dmamap);
+		if (sc->mfi_tb_ioc_init_desc != NULL)
+			bus_dmamem_free(sc->mfi_tb_ioc_init_dmat,
+			    sc->mfi_tb_ioc_init_desc,
+			    sc->mfi_tb_ioc_init_dmamap);
+		if (sc->mfi_tb_ioc_init_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_ioc_init_dmat);
+		for (int i = 0; i < sc->mfi_max_fw_cmds; i++) {
+			if (sc->mfi_cmd_pool_tbolt != NULL) {
+				if (sc->mfi_cmd_pool_tbolt[i] != NULL) {
+					free(sc->mfi_cmd_pool_tbolt[i],
+					    M_MFIBUF);
+					sc->mfi_cmd_pool_tbolt[i] = NULL;
+				}
+			}
+		}
+		if (sc->mfi_cmd_pool_tbolt != NULL) {
+			free(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+			sc->mfi_cmd_pool_tbolt = NULL;
+		}
+		if (sc->request_desc_pool != NULL) {
+			free(sc->request_desc_pool, M_MFIBUF);
+			sc->request_desc_pool = NULL;
+		}
+	}
 	if (sc->mfi_buffer_dmat != NULL)
 		bus_dma_tag_destroy(sc->mfi_buffer_dmat);
 	if (sc->mfi_parent_dmat != NULL)
@@ -909,6 +1215,8 @@ mfi_startup(void *arg)
 	sx_xlock(&sc->mfi_config_lock);
 	mtx_lock(&sc->mfi_io_lock);
 	mfi_ldprobe(sc);
+	if (sc->mfi_flags & MFI_FLAGS_SKINNY)
+	    mfi_syspdprobe(sc);
 	mtx_unlock(&sc->mfi_io_lock);
 	sx_xunlock(&sc->mfi_config_lock);
 }
@@ -925,12 +1233,7 @@ mfi_intr(void *arg)
 	if (sc->mfi_check_clear_intr(sc))
 		return;
 
-	/*
-	 * Do a dummy read to flush the interrupt ACK that we just performed,
-	 * ensuring that everything is really, truly consistent.
-	 */
-	(void)sc->mfi_read_fw_status(sc);
-
+restart:
 	pi = sc->mfi_comms->hw_pi;
 	ci = sc->mfi_comms->hw_ci;
 	mtx_lock(&sc->mfi_io_lock);
@@ -955,6 +1258,14 @@ mfi_intr(void *arg)
 	mfi_startio(sc);
 	mtx_unlock(&sc->mfi_io_lock);
 
+	/*
+	 * Dummy read to flush the bus; this ensures that the indexes are up
+	 * to date.  Restart processing if more commands have come it.
+	 */
+	(void)sc->mfi_read_fw_status(sc);
+	if (pi != sc->mfi_comms->hw_pi)
+		goto restart;
+
 	return;
 }
 
@@ -975,6 +1286,9 @@ mfi_shutdown(struct mfi_softc *sc)
 	if (sc->mfi_aen_cm != NULL)
 		mfi_abort(sc, sc->mfi_aen_cm);
 
+	if (sc->map_update_cmd != NULL)
+		mfi_abort(sc, sc->map_update_cmd);
+
 	dcmd = &cm->cm_frame->dcmd;
 	dcmd->header.flags = MFI_FRAME_DIR_NONE;
 	cm->cm_flags = MFI_CMD_POLLED;
@@ -990,6 +1304,81 @@ mfi_shutdown(struct mfi_softc *sc)
 }
 
 static void
+mfi_syspdprobe(struct mfi_softc *sc)
+{
+	struct mfi_frame_header *hdr;
+	struct mfi_command *cm = NULL;
+	struct mfi_pd_list *pdlist = NULL;
+	struct mfi_system_pd *syspd, *tmp;
+	int error, i, found;
+
+	sx_assert(&sc->mfi_config_lock, SA_XLOCKED);
+	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+	/* Add SYSTEM PD's */
+	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_LIST_QUERY,
+	    (void **)&pdlist, sizeof(*pdlist));
+	if (error){
+		device_printf(sc->mfi_dev,
+		    "Error while forming SYSTEM PD list\n");
+		goto out;
+	}
+
+	cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_POLLED;
+	cm->cm_frame->dcmd.mbox[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
+	cm->cm_frame->dcmd.mbox[1] = 0;
+	if (mfi_mapcmd(sc, cm) != 0) {
+		device_printf(sc->mfi_dev,
+		    "Failed to get syspd device listing\n");
+		goto out;
+	}
+	bus_dmamap_sync(sc->mfi_buffer_dmat,cm->cm_dmamap,
+	    BUS_DMASYNC_POSTREAD);
+	bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
+	hdr = &cm->cm_frame->header;
+	if (hdr->cmd_status != MFI_STAT_OK) {
+		device_printf(sc->mfi_dev,
+		    "MFI_DCMD_PD_LIST_QUERY failed %x\n", hdr->cmd_status);
+		goto out;
+	}
+	/* Get each PD and add it to the system */
+	for (i = 0; i < pdlist->count; i++) {
+		if (pdlist->addr[i].device_id ==
+		    pdlist->addr[i].encl_device_id)
+			continue;
+		found = 0;
+		TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+			if (syspd->pd_id == pdlist->addr[i].device_id)
+				found = 1;
+		}
+		if (found == 0)
+			mfi_add_sys_pd(sc, pdlist->addr[i].device_id);
+	}
+	/* Delete SYSPD's whose state has been changed */
+	TAILQ_FOREACH_SAFE(syspd, &sc->mfi_syspd_tqh, pd_link, tmp) {
+		found = 0;
+		for (i = 0; i < pdlist->count; i++) {
+			if (syspd->pd_id == pdlist->addr[i].device_id)
+				found = 1;
+		}
+		if (found == 0) {
+			printf("DELETE\n");
+			mtx_unlock(&sc->mfi_io_lock);
+			mtx_lock(&Giant);
+			device_delete_child(sc->mfi_dev, syspd->pd_dev);
+			mtx_unlock(&Giant);
+			mtx_lock(&sc->mfi_io_lock);
+		}
+	}
+out:
+	if (pdlist)
+	    free(pdlist, M_MFIBUF);
+	if (cm)
+	    mfi_release_command(cm);
+
+	return;
+}
+
+static void
 mfi_ldprobe(struct mfi_softc *sc)
 {
 	struct mfi_frame_header *hdr;
@@ -1083,10 +1472,124 @@ format_class(int8_t class)
 static void
 mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
 {
+	struct mfi_system_pd *syspd = NULL;
 
 	device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
 	    format_timestamp(detail->time), detail->evt_class.members.locale,
-	    format_class(detail->evt_class.members.evt_class), detail->description);
+	    format_class(detail->evt_class.members.evt_class),
+	    detail->description);
+
+        /* Don't act on old AEN's or while shutting down */
+        if (detail->seq < sc->mfi_boot_seq_num || sc->mfi_detaching)
+                return;
+
+	switch (detail->arg_type) {
+	case MR_EVT_ARGS_NONE:
+		if (detail->code == MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED) {
+		    device_printf(sc->mfi_dev, "HostBus scan raised\n");
+			if (mfi_detect_jbod_change) {
+				/*
+				 * Probe for new SYSPD's and Delete
+				 * invalid SYSPD's
+				 */
+				sx_xlock(&sc->mfi_config_lock);
+				mtx_lock(&sc->mfi_io_lock);
+				mfi_syspdprobe(sc);
+				mtx_unlock(&sc->mfi_io_lock);
+				sx_xunlock(&sc->mfi_config_lock);
+			}
+		}
+		break;
+	case MR_EVT_ARGS_LD_STATE:
+		/* During load time driver reads all the events starting
+		 * from the one that has been logged after shutdown. Avoid
+		 * these old events.
+		 */
+		if (detail->args.ld_state.new_state == MFI_LD_STATE_OFFLINE ) {
+			/* Remove the LD */
+			struct mfi_disk *ld;
+			TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link) {
+				if (ld->ld_id ==
+				    detail->args.ld_state.ld.target_id)
+					break;
+			}
+			/*
+			Fix: for kernel panics when SSCD is removed
+			KASSERT(ld != NULL, ("volume dissappeared"));
+			*/
+			if (ld != NULL) {
+				mtx_lock(&Giant);
+				device_delete_child(sc->mfi_dev, ld->ld_dev);
+				mtx_unlock(&Giant);
+			}
+		}
+		break;
+	case MR_EVT_ARGS_PD:
+		if (detail->code == MR_EVT_PD_REMOVED) {
+			if (mfi_detect_jbod_change) {
+				/*
+				 * If the removed device is a SYSPD then
+				 * delete it
+				 */
+				TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh,
+				    pd_link) {
+					if (syspd->pd_id ==
+					    detail->args.pd.device_id) {
+						mtx_lock(&Giant);
+						device_delete_child(
+						    sc->mfi_dev,
+						    syspd->pd_dev);
+						mtx_unlock(&Giant);
+						break;
+					}
+				}
+			}
+		}
+		if (detail->code == MR_EVT_PD_INSERTED) {
+			if (mfi_detect_jbod_change) {
+				/* Probe for new SYSPD's */
+				sx_xlock(&sc->mfi_config_lock);
+				mtx_lock(&sc->mfi_io_lock);
+				mfi_syspdprobe(sc);
+				mtx_unlock(&sc->mfi_io_lock);
+				sx_xunlock(&sc->mfi_config_lock);
+			}
+		}
+		break;
+	}
+}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203302305.q2UN5nxA061843>