svn commit: r227068 - in projects/head_mfi/sys: conf dev/mfi modules/mfi

Doug Ambrisko ambrisko at FreeBSD.org
Fri Nov 4 02:34:53 UTC 2011


Author: ambrisko
Date: Fri Nov  4 02:34:52 2011
New Revision: 227068
URL: http://svn.freebsd.org/changeset/base/227068

Log:
  First cut at updating mfi(4) to support newer LSI MegaRAID SAS cards.
  Specifically, add support for "Drake Skinny" and "ThunderBolt" LSI
  cards.
  
  Initial code was supplied by LSI under BSD license.  Several improvements
  were done by myself.  Such things like making it work in a static kernel,
  be able to boot of the RAID, performance improvements.  I removed some
  fairly complicated code that seemed to directly access the disks under
  the firmware.  It doesn't seem to be needed and significantly slowed
  down the performance of the driver and caused tons of sense errors to
  be reported.
  
  This code is being checked in this area so others can help me get it into
  shape to commit into the FreeBSD tree.  Assistance has been volunteered
  by iXsystems.
  
  We might want to re-work the JBOD attachment that creates /dev/mfisyspd?
  node for each disk.
  
  Performance is faster then prior cards.  It works okay with WITNESS
  and INVARIANTS on amd64 and i386.  I recall seeing a use after
  free time bug with FreeBSD 8 and a Drake Skinny card with WITNESS
  and INVARIANTS on.
  
  First task is get all of the new structures to be named in FreeBSD
  style format.
  
  Next is probably to deal with the 64bit addressing changes that are
  mostly around the #ifdef __amd64__ checks.
  
  Thanks to LSI for providing the initial code.
  
  Obtained from:	LSI

Added:
  projects/head_mfi/sys/dev/mfi/mfi_syspd.c
  projects/head_mfi/sys/dev/mfi/mfi_tbolt.c
Modified:
  projects/head_mfi/sys/conf/files
  projects/head_mfi/sys/dev/mfi/mfi.c
  projects/head_mfi/sys/dev/mfi/mfi_cam.c
  projects/head_mfi/sys/dev/mfi/mfi_disk.c
  projects/head_mfi/sys/dev/mfi/mfi_ioctl.h
  projects/head_mfi/sys/dev/mfi/mfi_linux.c
  projects/head_mfi/sys/dev/mfi/mfi_pci.c
  projects/head_mfi/sys/dev/mfi/mfireg.h
  projects/head_mfi/sys/dev/mfi/mfivar.h
  projects/head_mfi/sys/modules/mfi/Makefile

Modified: projects/head_mfi/sys/conf/files
==============================================================================
--- projects/head_mfi/sys/conf/files	Fri Nov  4 01:58:55 2011	(r227067)
+++ projects/head_mfi/sys/conf/files	Fri Nov  4 02:34:52 2011	(r227068)
@@ -1410,6 +1410,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: projects/head_mfi/sys/dev/mfi/mfi.c
==============================================================================
--- projects/head_mfi/sys/dev/mfi/mfi.c	Fri Nov  4 01:58:55 2011	(r227067)
+++ projects/head_mfi/sys/dev/mfi/mfi.c	Fri Nov  4 02:34:52 2011	(r227068)
@@ -79,10 +79,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,16 +94,18 @@ 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 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 *);
@@ -110,12 +113,17 @@ static int	mfi_user_command(struct mfi_s
 		    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 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_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;
@@ -152,6 +160,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 +171,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 +219,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,25 +274,41 @@ 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, MFI_FWINIT_READY);
+			    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",
@@ -270,12 +316,20 @@ mfi_transition_firmware(struct mfi_softc
 			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 +340,31 @@ 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_aen_pids);
 	TAILQ_INIT(&sc->mfi_cam_ccbq);
 
@@ -314,15 +373,32 @@ mfi_attach(struct mfi_softc *sc)
 	mfi_initq_busy(sc);
 	mfi_initq_bio(sc);
 
+	//atomic_set(&sc->fw_reset_no_pci_access, 0);
+	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 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;
 	}
@@ -334,6 +410,32 @@ mfi_attach(struct mfi_softc *sc)
 		    "error %d\n", error);
 		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
@@ -347,6 +449,94 @@ 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,			/* algnmnt, 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 +586,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 +603,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 +629,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,40 +655,63 @@ 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;
+		sc->mfi_irq_rid = 0;
+		if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
+			&sc->mfi_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+			device_printf(sc->mfi_dev, "Cannot allocate interrupt\n");
+			return (EINVAL);
+		}
+		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.  XXX This should happen in
-	 * mfi_pci.c
-	 */
-	sc->mfi_irq_rid = 0;
-	if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
-	    &sc->mfi_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
-		device_printf(sc->mfi_dev, "Cannot allocate 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_irq_rid = 0;
+		if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
+			&sc->mfi_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+			device_printf(sc->mfi_dev, "Cannot allocate 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;
 	sc->mfi_ich.ich_arg = sc;
@@ -507,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.
@@ -548,6 +765,8 @@ mfi_attach(struct mfi_softc *sc)
 	return (0);
 }
 
+	
+	
 static int
 mfi_alloc_commands(struct mfi_softc *sc)
 {
@@ -578,8 +797,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++;
@@ -594,6 +816,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
@@ -618,6 +842,7 @@ 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);
 }
@@ -629,13 +854,19 @@ mfi_dcmd_command(struct mfi_softc *sc, s
 	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);
@@ -655,6 +886,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;
@@ -676,11 +908,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;
@@ -741,10 +979,13 @@ 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.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)
 		free(ci, M_MFIBUF);
@@ -760,6 +1001,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)
@@ -778,11 +1020,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;
@@ -817,7 +1060,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)
 {
 
@@ -840,7 +1083,6 @@ mfi_wait_command(struct mfi_softc *sc, s
 		msleep(cm, &sc->mfi_io_lock, PRIBIO, "mfiwait", 0);
 	return (cm->cm_error);
 }
-
 void
 mfi_free(struct mfi_softc *sc)
 {
@@ -889,7 +1131,70 @@ mfi_free(struct mfi_softc *sc)
 		    sc->mfi_comms_dmamap);
 	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 pcaket 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)
@@ -912,10 +1217,12 @@ mfi_startup(void *arg)
 
 	config_intrhook_disestablish(&sc->mfi_ich);
 
-	sc->mfi_enable_intr(sc);
+	//sc->mfi_enable_intr(sc);
 	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);
 }
@@ -976,6 +1283,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;
@@ -986,9 +1296,80 @@ mfi_shutdown(struct mfi_softc *sc)
 	}
 
 	mfi_release_command(cm);
+	sc->shutdown_issued = 1;
 	mtx_unlock(&sc->mfi_io_lock);
 	return (error);
 }
+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;
+	int error, i;
+
+	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;
+	}
+	for (i=0;i<pdlist->count;i++) {
+	    if(pdlist->addr[i].device_id == pdlist->addr[i].encl_device_id)
+		goto skip_sys_pd_add;
+	    /* Get each PD and add it to the system */
+	    if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
+	        TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh,pd_link) {
+		if (syspd->pd_id == pdlist->addr[i].device_id)
+		    goto skip_sys_pd_add;
+	        }
+	    }
+	    mfi_add_sys_pd(sc,pdlist->addr[i].device_id);
+	    skip_sys_pd_add:;
+	
+	}
+	/* Delete SYSPD's whose state has been changed */
+	if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
+	    TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh,pd_link) {
+			for (i=0;i<pdlist->count;i++) {
+				if (syspd->pd_id == pdlist->addr[i].device_id)
+				    goto skip_sys_pd_delete;
+			}
+			mtx_lock(&Giant);
+			device_delete_child(sc->mfi_dev,syspd->pd_dev);
+			mtx_unlock(&Giant);
+skip_sys_pd_delete:;
+		}
+	}
+out:
+	if (pdlist)
+	    free(pdlist, M_MFIBUF);
+	if (cm)
+	    mfi_release_command(cm);
+
+	return;
+}
 
 static void
 mfi_ldprobe(struct mfi_softc *sc)
@@ -1082,8 +1463,79 @@ format_class(int8_t class)
 }
 
 static void
-mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
+mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail,uint8_t probe_sys_pd)
 {
+	struct mfi_system_pd *syspd = NULL;
+	switch (detail->arg_type) {
+	case MR_EVT_ARGS_NONE:
+#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
+		if (detail->code == MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED) {
+		    device_printf(sc->mfi_dev,"HostBus scan raised\n");
+		    if (probe_sys_pd) {
+			/* 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 (!TAILQ_EMPTY(&sc->mfi_ld_tqh)) {
+			if (detail->args.ld_state.new_state == MFI_LD_STATE_OFFLINE ) {
+				/* Remove the LD */
+				struct mfi_disk *ld = NULL;
+				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:
+#define MR_EVT_PD_REMOVED  0x0070
+#define MR_EVT_PD_INSERTED 0x005b
+		if (detail->code == MR_EVT_PD_REMOVED) {
+		    if (probe_sys_pd) {
+		    	/* If the removed device is a SYSPD then delete it */
+			if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
+			    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 (probe_sys_pd) {
+		    	/* 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;
+	}
 
 	device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
 	    format_timestamp(detail->time), detail->evt_class.members.locale,
@@ -1113,12 +1565,16 @@ mfi_aen_register(struct mfi_softc *sc, i
 			    < current_aen.members.evt_class)
 				current_aen.members.evt_class =
 				    prior_aen.members.evt_class;
+			mtx_lock(&sc->mfi_io_lock);
 			mfi_abort(sc, sc->mfi_aen_cm);
+			mtx_unlock(&sc->mfi_io_lock);
 		}
 	}
 
+	mtx_lock(&sc->mfi_io_lock);
 	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_WAIT,
 	    (void **)&ed, sizeof(*ed));
+	mtx_unlock(&sc->mfi_io_lock);
 	if (error) {
 		goto out;
 	}
@@ -1128,11 +1584,14 @@ mfi_aen_register(struct mfi_softc *sc, i
 	((uint32_t *)&dcmd->mbox)[1] = locale;
 	cm->cm_flags = MFI_CMD_DATAIN;
 	cm->cm_complete = mfi_aen_complete;
-
+	
+	sc->last_seq_num = seq;
 	sc->mfi_aen_cm = cm;
 
+	mtx_lock(&sc->mfi_io_lock);
 	mfi_enqueue_ready(cm);
 	mfi_startio(sc);
+	mtx_unlock(&sc->mfi_io_lock);
 
 out:
 	return (error);
@@ -1148,6 +1607,8 @@ mfi_aen_complete(struct mfi_command *cm)
 	int seq = 0, aborted = 0;
 
 	sc = cm->cm_sc;
+	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+
 	hdr = &cm->cm_frame->header;
 
 	if (sc->mfi_aen_cm == NULL)

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


More information about the svn-src-projects mailing list