mfi(4): Update to LSI's version 4.23 of the driver.
authorSascha Wildner <saw@online.de>
Thu, 29 Mar 2012 18:05:12 +0000 (20:05 +0200)
committerSascha Wildner <saw@online.de>
Thu, 29 Mar 2012 18:05:30 +0000 (20:05 +0200)
Brings in support for newer SAS2208 (aka Thunderbolt) based
controllers. It was tested with an Intel RS25DB080.

A few other things have been fixed too. Most x86_64/i386 specific
parts have been merged, MSI is now setup in mfi_pci.c properly.

Taken-from: FreeBSD (from their projects/ repository)

13 files changed:
share/man/man4/mfi.4
sys/conf/files
sys/dev/raid/mfi/Makefile
sys/dev/raid/mfi/mfi.c
sys/dev/raid/mfi/mfi_cam.c
sys/dev/raid/mfi/mfi_debug.c
sys/dev/raid/mfi/mfi_disk.c
sys/dev/raid/mfi/mfi_ioctl.h
sys/dev/raid/mfi/mfi_pci.c
sys/dev/raid/mfi/mfi_syspd.c
sys/dev/raid/mfi/mfi_tbolt.c [new file with mode: 0644]
sys/dev/raid/mfi/mfireg.h
sys/dev/raid/mfi/mfivar.h

index ffad85e..54979a8 100644 (file)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/mfi.4,v 1.13 2010/05/12 17:12:38 brueffer Exp $
 .\"
-.Dd August 11, 2011
+.Dd March 24, 2012
 .Dt MFI 4
 .Os
 .Sh NAME
@@ -127,6 +127,22 @@ Dell PERC5
 .It
 Dell PERC6
 .It
+Dell PERC H710 Embedded
+.It
+Dell PERC H710 Adapter
+.It
+Dell PERC H710 Mini (blades)
+.It
+Dell PERC H710 Mini (monolithics)
+.It
+Dell PERC H710P Adapter
+.It
+Dell PERC H710P Mini (blades)
+.It
+Dell PERC H710P Mini (monolithics)
+.It
+Dell PERC H810 Adapter
+.It
 IBM ServeRAID M1015 SAS/SATA
 .It
 IBM ServeRAID M5015 SAS/SATA
@@ -134,6 +150,10 @@ IBM ServeRAID M5015 SAS/SATA
 IBM ServeRAID-MR10i
 .It
 Intel RAID Controller SROMBSAS18E
+.It
+Intel RAID Controller RS25DB080
+.It
+Intel RAID Controller RS25NB008
 .El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/mfisyspd?" -compact
index e9f2474..ceff746 100644 (file)
@@ -578,6 +578,7 @@ dev/raid/mfi/mfi_debug.c    optional mfi
 dev/raid/mfi/mfi_pci.c         optional mfi pci
 dev/raid/mfi/mfi_disk.c                optional mfi
 dev/raid/mfi/mfi_syspd.c       optional mfi
+dev/raid/mfi/mfi_tbolt.c       optional mfi
 dev/raid/mfi/mfi_linux.c       optional mfi compat_linux
 dev/raid/mfi/mfi_cam.c         optional mfip scbus
 dev/netif/mii_layer/mii.c              optional miibus
index 809eac3..62557da 100644 (file)
@@ -8,7 +8,7 @@ SUBDIR+= mfi_linux
 .endif
 
 KMOD=  mfi
-SRCS=  mfi.c mfi_pci.c mfi_disk.c mfi_debug.c mfi_syspd.c
+SRCS=  mfi.c mfi_pci.c mfi_disk.c mfi_debug.c mfi_syspd.c mfi_tbolt.c
 SRCS+= opt_mfi.h opt_cam.h
 SRCS+= device_if.h bus_if.h pci_if.h
 
index 843f6d7..ad3bbaa 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi.c,v 1.62 2011/11/09 21:53:49 delphij Exp $
+ * FreeBSD projects/head_mfi/ r233016
  */
 
 #include "opt_mfi.h"
@@ -99,6 +70,7 @@
 #include <sys/signalvar.h>
 #include <sys/device.h>
 #include <sys/mplock2.h>
+#include <sys/taskqueue.h>
 
 #include <bus/cam/scsi/scsi_all.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 **);
@@ -122,33 +93,39 @@ 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 struct mfi_command *mfi_bio_command(struct mfi_softc *);
 static void    mfi_bio_complete(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_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);
 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);
+
 static void    mfi_filter_detach(struct knote *);
 static int     mfi_filter_read(struct knote *, long);
 static int     mfi_filter_write(struct knote *, long);
@@ -169,8 +146,10 @@ TUNABLE_INT("hw.mfi.max_cmds", &mfi_max_cmds);
 SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,
           0, "Max commands");
 
-static int     mfi_msi_enable = 1;
-TUNABLE_INT("hw.mfi.msi.enable", &mfi_msi_enable);
+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;
@@ -180,7 +159,7 @@ static d_kqfilter_t mfi_kqfilter;
 
 static struct dev_ops mfi_ops = {
        { "mfi", 0, 0 },
-       .d_open =       mfi_open,
+       .d_open =       mfi_open,
        .d_close =      mfi_close,
        .d_ioctl =      mfi_ioctl,
        .d_kqfilter =   mfi_kqfilter,
@@ -194,6 +173,7 @@ static struct filterops mfi_write_filterops =
 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)
@@ -261,13 +241,13 @@ 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)
+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)
 {
        if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
                MFI_WRITE4(sc, MFI_IQPL, (bus_add | frame_cnt << 1) | 1);
@@ -277,18 +257,16 @@ mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
        }
 }
 
-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;
-       bus_space_handle_t idb;
 
        cur_abs_reg_val = sc->mfi_read_fw_status(sc);
        fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
-       idb = sc->mfi_flags & MFI_FLAGS_SKINNY ? MFI_SKINNY_IDB : MFI_IDB;
        while (fw_state != MFI_FWSTATE_READY) {
                if (bootverbose)
                        device_printf(sc->mfi_dev, "Waiting for firmware to "
@@ -299,31 +277,43 @@ mfi_transition_firmware(struct mfi_softc *sc)
                        device_printf(sc->mfi_dev, "Firmware fault\n");
                        return (ENXIO);
                case MFI_FWSTATE_WAIT_HANDSHAKE:
-                       MFI_WRITE4(sc, 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, 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_FLUSH_CACHE:
-                       max_wait = 20;
+                       max_wait = MFI_RESET_WAIT_TIME;
                        break;
                case MFI_FWSTATE_DEVICE_SCAN:
-                       max_wait = 180; /* wait for 180 seconds */
+                       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, 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);
                }
@@ -349,25 +339,14 @@ mfi_transition_firmware(struct mfi_softc *sc)
        return (0);
 }
 
-#if defined(__x86_64__)
 static void
-mfi_addr64_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)
 {
-       uint64_t *addr;
+       bus_addr_t *addr;
 
        addr = arg;
        *addr = segs[0].ds_addr;
 }
-#else
-static void
-mfi_addr32_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
-{
-       uint32_t *addr;
-
-       addr = arg;
-       *addr = segs[0].ds_addr;
-}
-#endif
 
 int
 mfi_attach(struct mfi_softc *sc)
@@ -375,14 +354,20 @@ mfi_attach(struct mfi_softc *sc)
        uint32_t status;
        int error, commsz, framessz, sensesz;
        int frames, unit, max_fw_sge;
-       u_int irq_flags;
+       uint32_t tb_mem_size = 0;
 
-       device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.981\n");
+       if (sc == NULL)
+               return EINVAL;
+
+       device_printf(sc->mfi_dev, "Megaraid SAS driver Ver %s \n",
+           MEGASAS_VERSION);
 
        lockinit(&sc->mfi_io_lock, "MFI I/O lock", 0, LK_CANRECURSE);
        lockinit(&sc->mfi_config_lock, "MFI config", 0, LK_CANRECURSE);
        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);
 
@@ -391,11 +376,26 @@ 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 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;
@@ -411,6 +411,31 @@ 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 */
+                               &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
@@ -423,6 +448,97 @@ 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 */
+                               &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 */
+                               &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 */
+                               &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.
@@ -468,14 +584,8 @@ mfi_attach(struct mfi_softc *sc)
                return (ENOMEM);
        }
        bzero(sc->mfi_comms, commsz);
-#if defined(__x86_64__)
-       bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
-           sc->mfi_comms, commsz, mfi_addr64_cb, &sc->mfi_comms_busaddr, 0);
-#else
        bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
-           sc->mfi_comms, commsz, mfi_addr32_cb, &sc->mfi_comms_busaddr, 0);
-#endif
-
+           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
@@ -516,14 +626,8 @@ mfi_attach(struct mfi_softc *sc)
                return (ENOMEM);
        }
        bzero(sc->mfi_frames, framessz);
-#if defined(__x86_64__)
-       bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
-           sc->mfi_frames, framessz, mfi_addr64_cb, &sc->mfi_frames_busaddr,0);
-#else
        bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
-           sc->mfi_frames, framessz, mfi_addr32_cb, &sc->mfi_frames_busaddr,0);
-#endif
-
+           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
@@ -547,47 +651,48 @@ mfi_attach(struct mfi_softc *sc)
                device_printf(sc->mfi_dev, "Cannot allocate sense memory\n");
                return (ENOMEM);
        }
-#if defined(__x86_64__)
        bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
-           sc->mfi_sense, sensesz, mfi_addr64_cb, &sc->mfi_sense_busaddr, 0);
-#else
-       bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
-           sc->mfi_sense, sensesz, mfi_addr32_cb, &sc->mfi_sense_busaddr, 0);
-#endif
-
+           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;
+               }
 
-       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
-       if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
-               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
-               return (error);
-       }
-       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               if ((error = mfi_tbolt_alloc_cmd(sc)) != 0)
+                       return error;
+               if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
+                       mfi_intr_tbolt, sc, &sc->mfi_intr, NULL)) {
+                       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;
-       sc->mfi_irq_type = pci_alloc_1intr(sc->mfi_dev, mfi_msi_enable,
-           &sc->mfi_irq_rid, &irq_flags);
-       if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
-           &sc->mfi_irq_rid, irq_flags)) == NULL) {
-               device_printf(sc->mfi_dev, "Cannot allocate interrupt\n");
-               return (EINVAL);
-       }
-       if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
-           mfi_intr, sc, &sc->mfi_intr, NULL)) {
-               device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
-               return (EINVAL);
+               if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
+                       mfi_intr, sc, &sc->mfi_intr, NULL)) {
+                       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;
@@ -597,6 +702,10 @@ mfi_attach(struct mfi_softc *sc)
                    "hook\n");
                return (EINVAL);
        }
+       if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               return (error);
+       }
 
        /*
         * Register a shutdown handler.
@@ -676,8 +785,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) {
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                        mfi_release_command(cm);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               }
                else
                        break;
                sc->mfi_total_cmds++;
@@ -692,6 +804,8 @@ mfi_release_command(struct mfi_command *cm)
        struct mfi_frame_header *hdr;
        uint32_t *hdr_data;
 
+       KKASSERT(lockstatus(&cm->cm_sc->mfi_io_lock, curthread) != 0);
+
        /*
         * Zero out the important fields of the frame, but make sure the
         * context field is preserved.  For efficiency, handle the fields
@@ -716,13 +830,14 @@ mfi_release_command(struct mfi_command *cm)
        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;
@@ -852,9 +967,11 @@ mfi_get_controller_info(struct mfi_softc *sc)
            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)
@@ -871,6 +988,7 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
        struct mfi_command *cm = NULL;
        int error;
 
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
        error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_GETINFO,
            (void **)log_state, sizeof(**log_state));
        if (error)
@@ -889,11 +1007,12 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
 out:
        if (cm)
                mfi_release_command(cm);
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
        return (error);
 }
 
-static int
+int
 mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
 {
        struct mfi_evt_log_state *log_state = NULL;
@@ -907,6 +1026,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
 
        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)
                                kfree(log_state, M_MFIBUF);
@@ -929,7 +1049,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
        return 0;
 }
 
-static int
+int
 mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm)
 {
 
@@ -978,8 +1098,7 @@ mfi_free(struct mfi_softc *sc)
        if (sc->mfi_irq != NULL)
                bus_release_resource(sc->mfi_dev, SYS_RES_IRQ, sc->mfi_irq_rid,
                    sc->mfi_irq);
-       if (sc->mfi_irq_type == PCI_INTR_TYPE_MSI)
-               pci_release_msi(sc->mfi_dev);
+
        if (sc->mfi_sense_busaddr != 0)
                bus_dmamap_unload(sc->mfi_sense_dmat, sc->mfi_sense_dmamap);
        if (sc->mfi_sense != NULL)
@@ -1004,6 +1123,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) {
+                                       kfree(sc->mfi_cmd_pool_tbolt[i],
+                                           M_MFIBUF);
+                                       sc->mfi_cmd_pool_tbolt[i] = NULL;
+                               }
+                       }
+               }
+               if (sc->mfi_cmd_pool_tbolt != NULL) {
+                       kfree(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+                       sc->mfi_cmd_pool_tbolt = NULL;
+               }
+               if (sc->request_desc_pool != NULL) {
+                       kfree(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)
@@ -1054,12 +1231,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;
        lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -1084,6 +1256,14 @@ mfi_intr(void *arg)
        mfi_startio(sc);
        lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
+       /*
+        * 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;
 }
 
@@ -1104,6 +1284,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;
@@ -1117,14 +1300,15 @@ mfi_shutdown(struct mfi_softc *sc)
        lockmgr(&sc->mfi_io_lock, LK_RELEASE);
        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;
+       struct mfi_system_pd *syspd, *tmp;
+       int error, i, found;
 
        KKASSERT(lockstatus(&sc->mfi_config_lock, curthread) != 0);
        KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
@@ -1132,7 +1316,8 @@ mfi_syspdprobe(struct mfi_softc *sc)
        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 syspd list\n");
+               device_printf(sc->mfi_dev,
+                   "Error while forming SYSTEM PD list\n");
                goto out;
        }
 
@@ -1140,7 +1325,8 @@ mfi_syspdprobe(struct mfi_softc *sc)
        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 list\n");
+               device_printf(sc->mfi_dev,
+                   "Failed to get syspd device listing\n");
                goto out;
        }
        bus_dmamap_sync(sc->mfi_buffer_dmat,cm->cm_dmamap,
@@ -1148,36 +1334,37 @@ mfi_syspdprobe(struct mfi_softc *sc)
        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);
+               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)
-                       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;
-                       }
+               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;
                }
-               mfi_add_sys_pd(sc,pdlist->addr[i].device_id);
-skip_sys_pd_add:
-               ;
+               if (found == 0)
+                       mfi_add_sys_pd(sc, pdlist->addr[i].device_id);
        }
        /* 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;
-                       }
+       TAILQ_FOREACH_MUTABLE(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) {
+                       kprintf("DELETE\n");
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                        get_mplock();
-                       device_delete_child(sc->mfi_dev,syspd->pd_dev);
+                       device_delete_child(sc->mfi_dev, syspd->pd_dev);
                        rel_mplock();
-skip_sys_pd_delete:
-                       ;
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                }
        }
 out:
@@ -1281,10 +1468,125 @@ 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
+                                */
+                               lockmgr(&sc->mfi_config_lock, LK_EXCLUSIVE);
+                               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+                               mfi_syspdprobe(sc);
+                               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+                               lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+                       }
+               }
+               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) {
+                               get_mplock();
+                               device_delete_child(sc->mfi_dev, ld->ld_dev);
+                               rel_mplock();
+                       }
+               }
+               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) {
+                                               get_mplock();
+                                               device_delete_child(
+                                                   sc->mfi_dev,
+                                                   syspd->pd_dev);
+                                               rel_mplock();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               if (detail->code == MR_EVT_PD_INSERTED) {
+                       if (mfi_detect_jbod_change) {
+                               /* Probe for new SYSPD's */
+                               lockmgr(&sc->mfi_config_lock, LK_EXCLUSIVE);
+                               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+                               mfi_syspdprobe(sc);
+                               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+                               lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+                       }
+               }
+               break;
+       }
+}
+
+static void
+mfi_queue_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
+{
+       struct mfi_evt_queue_elm *elm;
+
+       KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+       elm = kmalloc(sizeof(*elm), M_MFIBUF, M_NOWAIT | M_ZERO);
+       if (elm == NULL)
+               return;
+       memcpy(&elm->detail, detail, sizeof(*detail));
+       TAILQ_INSERT_TAIL(&sc->mfi_evt_queue, elm, link);
+       taskqueue_enqueue(taskqueue_swi, &sc->mfi_evt_task);
+}
+
+static void
+mfi_handle_evt(void *context, int pending)
+{
+       TAILQ_HEAD(,mfi_evt_queue_elm) queue;
+       struct mfi_softc *sc;
+       struct mfi_evt_queue_elm *elm;
+
+       sc = context;
+       TAILQ_INIT(&queue);
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+       TAILQ_CONCAT(&queue, &sc->mfi_evt_queue, link);
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+       while ((elm = TAILQ_FIRST(&queue)) != NULL) {
+               TAILQ_REMOVE(&queue, elm, link);
+               mfi_decode_evt(sc, &elm->detail);
+               kfree(elm, M_MFIBUF);
+       }
 }
 
 static int
@@ -1310,12 +1612,16 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
                            < current_aen.members.evt_class)
                                current_aen.members.evt_class =
                                    prior_aen.members.evt_class;
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                        mfi_abort(sc, sc->mfi_aen_cm);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                }
        }
 
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
        error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_WAIT,
            (void **)&ed, sizeof(*ed));
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
        if (error) {
                goto out;
        }
@@ -1326,10 +1632,13 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
        cm->cm_flags = MFI_CMD_DATAIN;
        cm->cm_complete = mfi_aen_complete;
 
+       sc->last_seq_num = seq;
        sc->mfi_aen_cm = cm;
 
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
        mfi_enqueue_ready(cm);
        mfi_startio(sc);
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
 out:
        return (error);
@@ -1345,6 +1654,8 @@ mfi_aen_complete(struct mfi_command *cm)
        int seq = 0, aborted = 0;
 
        sc = cm->cm_sc;
+       KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
        hdr = &cm->cm_frame->header;
 
        if (sc->mfi_aen_cm == NULL)
@@ -1361,13 +1672,10 @@ mfi_aen_complete(struct mfi_command *cm)
                        KNOTE(&sc->mfi_kq.ki_note, 0);
                }
                detail = cm->cm_data;
-               /*
-                * XXX If this function is too expensive or is recursive, then
-                * events should be put onto a queue and processed later.
-                */
-               mfi_decode_evt(sc, detail);
+               mfi_queue_evt(sc, detail);
                seq = detail->seq + 1;
-               TAILQ_FOREACH_MUTABLE(mfi_aen_entry, &sc->mfi_aen_pids, aen_link, tmp) {
+               TAILQ_FOREACH_MUTABLE(mfi_aen_entry, &sc->mfi_aen_pids,
+                   aen_link, tmp) {
                        TAILQ_REMOVE(&sc->mfi_aen_pids, mfi_aen_entry,
                            aen_link);
                        lwkt_gettoken(&proc_token);
@@ -1384,7 +1692,9 @@ mfi_aen_complete(struct mfi_command *cm)
 
        /* set it up again so the driver can catch more events */
        if (!aborted) {
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                mfi_aen_setup(sc, seq);
+               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
        }
 }
 
@@ -1398,7 +1708,6 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
        struct mfi_evt_list *el;
        union mfi_evt class_locale;
        int error, i, seq, size;
-       uint32_t context = 0;
 
        class_locale.members.reserved = 0;
        class_locale.members.locale = mfi_event_locale;
@@ -1411,22 +1720,20 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
                return (ENOMEM);
 
        for (seq = start_seq;;) {
+               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                if ((cm = mfi_dequeue_free(sc)) == NULL) {
                        kfree(el, M_MFIBUF);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                        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;
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
                dcmd = &cm->cm_frame->dcmd;
                bzero(dcmd->mbox, MFI_MBOX_SIZE);
                dcmd->header.cmd = MFI_CMD_DCMD;
                dcmd->header.timeout = 0;
                dcmd->header.data_len = size;
-               dcmd->header.scsi_status = 0;
                dcmd->opcode = MFI_DCMD_CTRL_EVENT_GET;
                ((uint32_t *)&dcmd->mbox)[0] = seq;
                ((uint32_t *)&dcmd->mbox)[1] = class_locale.word;
@@ -1436,29 +1743,38 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
                cm->cm_data = el;
                cm->cm_len = size;
 
+               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                if ((error = mfi_mapcmd(sc, cm)) != 0) {
                        device_printf(sc->mfi_dev,
                            "Failed to get controller entries\n");
                        mfi_release_command(cm);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                        break;
                }
 
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
                    BUS_DMASYNC_POSTREAD);
                bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
 
                if (dcmd->header.cmd_status == MFI_STAT_NOT_FOUND) {
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                        mfi_release_command(cm);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                        break;
                }
                if (dcmd->header.cmd_status != MFI_STAT_OK) {
                        device_printf(sc->mfi_dev,
                            "Error %d fetching controller entries\n",
                            dcmd->header.cmd_status);
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                        mfi_release_command(cm);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                        break;
                }
+               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                mfi_release_command(cm);
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
                for (i = 0; i < el->count; i++) {
                        /*
@@ -1474,7 +1790,9 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
                                else if (el->event[i].seq < start_seq)
                                        break;
                        }
-                       mfi_decode_evt(sc, &el->event[i]);
+                       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+                       mfi_queue_evt(sc, &el->event[i]);
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
                }
                seq = el->event[el->count - 1].seq + 1;
        }
@@ -1515,7 +1833,7 @@ mfi_add_ld(struct mfi_softc *sc, int id)
                mfi_add_ld_complete(cm);
        } else {
                mfi_release_command(cm);
-               if(ld_info)             /* SSCD drives ld_info free here */
+               if (ld_info)            /* SSCD drives ld_info free here */
                        kfree(ld_info, M_MFIBUF);
        }
        return (0);
@@ -1558,7 +1876,7 @@ mfi_add_ld_complete(struct mfi_command *cm)
 }
 
 static int
-mfi_add_sys_pd(struct mfi_softc *sc,int id)
+mfi_add_sys_pd(struct mfi_softc *sc, int id)
 {
        struct mfi_command *cm;
        struct mfi_dcmd_frame *dcmd = NULL;
@@ -1567,13 +1885,14 @@ mfi_add_sys_pd(struct mfi_softc *sc,int id)
 
        KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
 
-       error = mfi_dcmd_command(sc,&cm,MFI_DCMD_PD_GET_INFO,
+       error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_GET_INFO,
            (void **)&pd_info, sizeof(*pd_info));
        if (error) {
                device_printf(sc->mfi_dev,
-                   "Failed to allocated for MFI_DCMD_PD_GET_INFO %d\n", error);
+                   "Failed to allocated for MFI_DCMD_PD_GET_INFO %d\n",
+                   error);
                if (pd_info)
-                       kfree(pd_info,M_MFIBUF);
+                       kfree(pd_info, M_MFIBUF);
                return (error);
        }
        cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_POLLED;
@@ -1584,12 +1903,12 @@ mfi_add_sys_pd(struct mfi_softc *sc,int id)
        if (mfi_mapcmd(sc, cm) != 0) {
                device_printf(sc->mfi_dev,
                    "Failed to get physical drive info %d\n", id);
-               kfree(pd_info,M_MFIBUF);
+               kfree(pd_info, M_MFIBUF);
                return (0);
        }
        bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
            BUS_DMASYNC_POSTREAD);
-       bus_dmamap_unload(sc->mfi_buffer_dmat,cm->cm_dmamap);
+       bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
        mfi_add_sys_pd_complete(cm);
        return (0);
 }
@@ -1612,7 +1931,7 @@ mfi_add_sys_pd_complete(struct mfi_command *cm)
                return;
        }
        if (pd_info->fw_state != MFI_PD_STATE_SYSTEM) {
-               device_printf(sc->mfi_dev,"PD=%x is not SYSTEM PD\n",
+               device_printf(sc->mfi_dev, "PD=%x is not SYSTEM PD\n",
                    pd_info->ref.v.device_id);
                kfree(pd_info, M_MFIBUF);
                mfi_release_command(cm);
@@ -1655,7 +1974,7 @@ mfi_bio_command(struct mfi_softc *sc)
        else
                cm = mfi_build_ldio(sc, bio);
        if (!cm)
-               mfi_enqueue_bio(sc,bio);
+               mfi_enqueue_bio(sc, bio);
        return cm;
 }
 
@@ -1666,7 +1985,7 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
        struct buf *bp;
        struct mfi_system_pd *disk;
        struct mfi_pass_frame *pass;
-       int flags = 0,blkcount = 0;
+       int flags = 0, blkcount = 0;
        uint32_t context = 0;
 
        if ((cm = mfi_dequeue_free(sc)) == NULL)
@@ -1710,13 +2029,8 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
        pass->header.sense_len = MFI_SENSE_LEN;
        pass->header.data_len = bp->b_bcount;
        pass->header.cdb_len = 10;
-#if defined(__x86_64__)
-       pass->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-       pass->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-       pass->sense_addr_lo = cm->cm_sense_busaddr;
-       pass->sense_addr_hi = 0;
-#endif
+       pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+       pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
        cm->cm_complete = mfi_bio_complete;
        cm->cm_private = bio;
        cm->cm_data = bp->b_data;
@@ -1728,7 +2042,7 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
 }
 
 static struct mfi_command *
-mfi_build_ldio(struct mfi_softc *sc,struct bio *bio)
+mfi_build_ldio(struct mfi_softc *sc, struct bio *bio)
 {
        struct mfi_io_frame *io;
        struct buf *bp;
@@ -1742,7 +2056,7 @@ mfi_build_ldio(struct mfi_softc *sc,struct bio *bio)
 
        /* Zero out the MFI frame */
        context = cm->cm_frame->header.context;
-       bzero(cm->cm_frame,sizeof(union mfi_frame));
+       bzero(cm->cm_frame, sizeof(union mfi_frame));
        cm->cm_frame->header.context = context;
        bp = bio->bio_buf;
        io = &cm->cm_frame->io;
@@ -1768,13 +2082,8 @@ mfi_build_ldio(struct mfi_softc *sc,struct bio *bio)
        io->header.scsi_status = 0;
        io->header.sense_len = MFI_SENSE_LEN;
        io->header.data_len = blkcount;
-#if defined(__x86_64__)
-       io->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-       io->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-       io->sense_addr_lo = cm->cm_sense_busaddr;
-       io->sense_addr_hi = 0;
-#endif
+       io->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+       io->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
        io->lba_hi = ((bio->bio_offset / MFI_SECTOR_LEN) & 0xffffffff00000000) >> 32;
        io->lba_lo = (bio->bio_offset / MFI_SECTOR_LEN) & 0xffffffff;
        cm->cm_complete = mfi_bio_complete;
@@ -1849,14 +2158,14 @@ mfi_startio(struct mfi_softc *sc)
        }
 }
 
-static int
+int
 mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
 {
        int error, polled;
 
        KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
 
-       if (cm->cm_data != NULL) {
+       if ((cm->cm_data != NULL) && (cm->cm_frame->header.cmd != MFI_CMD_STP)) {
                polled = (cm->cm_flags & MFI_CMD_POLLED) ? BUS_DMA_NOWAIT : 0;
                error = bus_dmamap_load(sc->mfi_buffer_dmat, cm->cm_dmamap,
                    cm->cm_data, cm->cm_len, mfi_data_cb, cm, polled);
@@ -1865,7 +2174,10 @@ mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
                        return (0);
                }
        } else {
-               error = mfi_send_frame(sc, cm);
+               if (sc->MFA_enabled)
+                       error = mfi_tbolt_send_frame(sc, cm);
+               else
+                       error = mfi_send_frame(sc, cm);
        }
 
        return (error);
@@ -1879,8 +2191,7 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
        union mfi_sgl *sgl;
        struct mfi_softc *sc;
        int i, j, first, dir;
-       int sgl_mapped = 0;
-       int sge_size = 0;
+       int sge_size;
 
        cm = (struct mfi_command *)arg;
        sc = cm->cm_sc;
@@ -1910,10 +2221,9 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                        sgl->sg_skinny[i].flag = 0;
                }
                hdr->flags |= MFI_FRAME_IEEE_SGL | MFI_FRAME_SGL64;
-               sgl_mapped = 1;
                sge_size = sizeof(struct mfi_sg_skinny);
-       }
-       if (!sgl_mapped) {
+               hdr->sg_count = nsegs;
+       } else {
                j = 0;
                if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
                        first = cm->cm_stp_len;
@@ -1932,7 +2242,6 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                                sgl->sg32[j++].len = segs[i].ds_len - first;
                                first = 0;
                        }
-                       sge_size = sizeof(struct mfi_sg32);
                } else {
                        for (i = 0; i < nsegs; i++) {
                                sgl->sg64[j].addr = segs[i].ds_addr + first;
@@ -1940,11 +2249,10 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                                first = 0;
                        }
                        hdr->flags |= MFI_FRAME_SGL64;
-                       sge_size = sizeof(struct mfi_sg64);
                }
                hdr->sg_count = j;
-       } else
-               hdr->sg_count = nsegs;
+               sge_size = sc->mfi_sge_size;
+       }
 
        dir = 0;
        if (cm->cm_flags & MFI_CMD_DATAIN) {
@@ -1955,8 +2263,6 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                dir |= BUS_DMASYNC_PREWRITE;
                hdr->flags |= MFI_FRAME_DIR_WRITE;
        }
-       if (cm->cm_frame->header.cmd == MFI_CMD_STP)
-               dir |= BUS_DMASYNC_PREWRITE;
        bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, dir);
        cm->cm_flags |= MFI_CMD_MAPPED;
 
@@ -1966,10 +2272,13 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
         * least 1 frame, so don't compensate for the modulo of the
         * following division.
         */
-       cm->cm_total_frame_size += (sge_size * nsegs);
+       cm->cm_total_frame_size += (sc->mfi_sge_size * nsegs);
        cm->cm_extra_frames = (cm->cm_total_frame_size - 1) / MFI_FRAME_SIZE;
 
-       mfi_send_frame(sc, cm);
+       if (sc->MFA_enabled)
+               mfi_tbolt_send_frame(sc, cm);
+       else
+               mfi_send_frame(sc, cm);
 }
 
 static int
@@ -2003,7 +2312,7 @@ mfi_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
        if (cm->cm_extra_frames > 7)
                cm->cm_extra_frames = 7;
 
-       sc->mfi_issue_cmd(sc,cm->cm_frame_busaddr,cm->cm_extra_frames);
+       sc->mfi_issue_cmd(sc, cm->cm_frame_busaddr, cm->cm_extra_frames);
 
        if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
                return (0);
@@ -2018,14 +2327,14 @@ mfi_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
 
        if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
                device_printf(sc->mfi_dev, "Frame %p timed out "
-                             "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
+                   "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
                return (ETIMEDOUT);
        }
 
        return (0);
 }
 
-static void
+void
 mfi_complete(struct mfi_softc *sc, struct mfi_command *cm)
 {
        int dir;
@@ -2075,22 +2384,20 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort)
        abort->header.flags = 0;
        abort->header.scsi_status = 0;
        abort->abort_context = cm_abort->cm_frame->header.context;
-#if defined(__x86_64__)
-       abort->abort_mfi_addr_lo = cm_abort->cm_frame_busaddr & 0xFFFFFFFF;
-       abort->abort_mfi_addr_hi = (cm_abort->cm_frame_busaddr & 0xFFFFFFFF00000000 ) >> 32  ;
-#else
-       abort->abort_mfi_addr_lo = cm_abort->cm_frame_busaddr;
-       abort->abort_mfi_addr_hi = 0;
-#endif
+       abort->abort_mfi_addr_lo = (uint32_t)cm_abort->cm_frame_busaddr;
+       abort->abort_mfi_addr_hi =
+           (uint32_t)((uint64_t)cm_abort->cm_frame_busaddr >> 32);
        cm->cm_data = NULL;
        cm->cm_flags = MFI_CMD_POLLED;
 
-       sc->mfi_aen_cm->cm_aen_abort = 1;
+       if (sc->mfi_aen_cm)
+               sc->mfi_aen_cm->cm_aen_abort = 1;
        mfi_mapcmd(sc, cm);
        mfi_release_command(cm);
 
        while (i < 5 && sc->mfi_aen_cm != NULL) {
-               lksleep(&sc->mfi_aen_cm, &sc->mfi_io_lock, 0, "mfiabort", 5 * hz);
+               lksleep(&sc->mfi_aen_cm, &sc->mfi_io_lock, 0, "mfiabort",
+                   5 * hz);
                i++;
        }
 
@@ -2098,7 +2405,8 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort)
 }
 
 int
-mfi_dump_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt, int len)
+mfi_dump_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt,
+    int len)
 {
        struct mfi_command *cm;
        struct mfi_io_frame *io;
@@ -2121,13 +2429,8 @@ mfi_dump_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt, int len)
        io->header.scsi_status = 0;
        io->header.sense_len = MFI_SENSE_LEN;
        io->header.data_len = (len + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN;
-#if defined(__x86_64__)
-       io->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-       io->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000 ) >> 32;
-#else
-       io->sense_addr_lo = cm->cm_sense_busaddr;
-       io->sense_addr_hi = 0;
-#endif
+       io->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+       io->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
        io->lba_hi = (lba & 0xffffffff00000000) >> 32;
        io->lba_lo = lba & 0xffffffff;
        cm->cm_data = virt;
@@ -2175,13 +2478,8 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt,
        pass->header.sense_len = MFI_SENSE_LEN;
        pass->header.data_len = len;
        pass->header.cdb_len = 10;
-#if defined(__x86_64__)
-       pass->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-       pass->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000 ) >> 32;
-#else
-       pass->sense_addr_lo = cm->cm_sense_busaddr;
-       pass->sense_addr_hi = 0;
-#endif
+       pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+       pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
        cm->cm_data = virt;
        cm->cm_len = len;
        cm->cm_sg = &pass->sgl;
@@ -2264,7 +2562,10 @@ mfi_config_unlock(struct mfi_softc *sc, int locked)
                lockmgr(&sc->mfi_config_lock, LK_RELEASE);
 }
 
-/* Perform pre-issue checks on commands from userland and possibly veto them. */
+/*
+ * Perform pre-issue checks on commands from userland and possibly veto
+ * them.
+ */
 static int
 mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm)
 {
@@ -2305,16 +2606,14 @@ mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm)
                mbox = (uint16_t *)cm->cm_frame->dcmd.mbox;
                syspd_id = mbox[0];
                if (mbox[2] == MFI_PD_STATE_UNCONFIGURED_GOOD) {
-                       if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
-                               TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
-                                       if (syspd->pd_id == syspd_id)
-                                               break;
-                               }
+                       TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+                               if (syspd->pd_id == syspd_id)
+                                       break;
                        }
                } else {
                        break;
                }
-               if(syspd)
+               if (syspd)
                        error = mfi_syspd_disable(syspd);
                break;
        default:
@@ -2372,23 +2671,154 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
                mbox = (uint16_t *)cm->cm_frame->dcmd.mbox;
                syspd_id = mbox[0];
                if (mbox[2] == MFI_PD_STATE_UNCONFIGURED_GOOD) {
-                       if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
-                               TAILQ_FOREACH(syspd,&sc->mfi_syspd_tqh,pd_link) {
-                                       if (syspd->pd_id == syspd_id)
-                                               break;
-                               }
+                       TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+                               if (syspd->pd_id == syspd_id)
+                                       break;
                        }
                } else {
                        break;
                }
                /* If the transition fails then enable the syspd again */
-               if(syspd && cm->cm_frame->header.cmd_status != MFI_STAT_OK)
+               if (syspd && cm->cm_frame->header.cmd_status != MFI_STAT_OK)
                        mfi_syspd_enable(syspd);
                break;
        }
 }
 
 static int
+mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
+{
+       struct mfi_config_data *conf_data = cm->cm_data;
+       struct mfi_command *ld_cm = NULL;
+       struct mfi_ld_info *ld_info = NULL;
+       int error = 0;
+
+       if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
+           (conf_data->ld[0].params.isSSCD == 1)) {
+               error = 1;
+       } else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
+               error = mfi_dcmd_command(sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
+                   (void **)&ld_info, sizeof(*ld_info));
+               if (error) {
+                       device_printf(sc->mfi_dev, "Failed to allocate"
+                           "MFI_DCMD_LD_GET_INFO %d", error);
+                       if (ld_info)
+                               kfree(ld_info, M_MFIBUF);
+                       return 0;
+               }
+               ld_cm->cm_flags = MFI_CMD_DATAIN;
+               ld_cm->cm_frame->dcmd.mbox[0]= cm->cm_frame->dcmd.mbox[0];
+               ld_cm->cm_frame->header.target_id = cm->cm_frame->dcmd.mbox[0];
+               if (mfi_wait_command(sc, ld_cm) != 0) {
+                       device_printf(sc->mfi_dev, "failed to get log drv\n");
+                       mfi_release_command(ld_cm);
+                       kfree(ld_info, M_MFIBUF);
+                       return 0;
+               }
+
+               if (ld_cm->cm_frame->header.cmd_status != MFI_STAT_OK) {
+                       kfree(ld_info, M_MFIBUF);
+                       mfi_release_command(ld_cm);
+                       return 0;
+               } else {
+                       ld_info = (struct mfi_ld_info *)ld_cm->cm_private;
+               }
+
+               if (ld_info->ld_config.params.isSSCD == 1)
+                       error = 1;
+
+               mfi_release_command(ld_cm);
+               kfree(ld_info, M_MFIBUF);
+       }
+       return error;
+}
+
+static int
+mfi_stp_cmd(struct mfi_softc *sc, struct mfi_command *cm,caddr_t arg)
+{
+       uint8_t i;
+       struct mfi_ioc_packet *ioc;
+       ioc = (struct mfi_ioc_packet *)arg;
+       int sge_size, error;
+       struct megasas_sge *kern_sge;
+
+       memset(sc->kbuff_arr, 0, sizeof(sc->kbuff_arr));
+       kern_sge =(struct megasas_sge *) ((uintptr_t)cm->cm_frame + ioc->mfi_sgl_off);
+       cm->cm_frame->header.sg_count = ioc->mfi_sge_count;
+
+       if (sizeof(bus_addr_t) == 8) {
+               cm->cm_frame->header.flags |= MFI_FRAME_SGL64;
+               cm->cm_extra_frames = 2;
+               sge_size = sizeof(struct mfi_sg64);
+       } else {
+               cm->cm_extra_frames =  (cm->cm_total_frame_size - 1) / MFI_FRAME_SIZE;
+               sge_size = sizeof(struct mfi_sg32);
+       }
+
+       cm->cm_total_frame_size += (sge_size * ioc->mfi_sge_count);
+       for (i = 0; i < ioc->mfi_sge_count; i++) {
+                       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 */
+                       ioc->mfi_sgl[i].iov_len,/* maxsize */
+                       2,                      /* nsegments */
+                       ioc->mfi_sgl[i].iov_len,/* maxsegsize */
+                       BUS_DMA_ALLOCNOW,       /* flags */
+                       &sc->mfi_kbuff_arr_dmat[i])) {
+                       device_printf(sc->mfi_dev,
+                           "Cannot allocate mfi_kbuff_arr_dmat tag\n");
+                       return (ENOMEM);
+               }
+
+               if (bus_dmamem_alloc(sc->mfi_kbuff_arr_dmat[i],
+                   (void **)&sc->kbuff_arr[i], BUS_DMA_NOWAIT,
+                   &sc->mfi_kbuff_arr_dmamap[i])) {
+                       device_printf(sc->mfi_dev,
+                           "Cannot allocate mfi_kbuff_arr_dmamap memory\n");
+                       return (ENOMEM);
+               }
+
+               bus_dmamap_load(sc->mfi_kbuff_arr_dmat[i],
+                   sc->mfi_kbuff_arr_dmamap[i], sc->kbuff_arr[i],
+                   ioc->mfi_sgl[i].iov_len, mfi_addr_cb,
+                   &sc->mfi_kbuff_arr_busaddr[i], 0);
+
+               if (!sc->kbuff_arr[i]) {
+                       device_printf(sc->mfi_dev,
+                           "Could not allocate memory for kbuff_arr info\n");
+                       return -1;
+               }
+               kern_sge[i].phys_addr = sc->mfi_kbuff_arr_busaddr[i];
+               kern_sge[i].length = ioc->mfi_sgl[i].iov_len;
+
+               if (sizeof(bus_addr_t) == 8) {
+                       cm->cm_frame->stp.sgl.sg64[i].addr =
+                           kern_sge[i].phys_addr;
+                       cm->cm_frame->stp.sgl.sg64[i].len =
+                           ioc->mfi_sgl[i].iov_len;
+               } else {
+                       cm->cm_frame->stp.sgl.sg32[i].len =
+                           kern_sge[i].phys_addr;
+                       cm->cm_frame->stp.sgl.sg32[i].len =
+                           ioc->mfi_sgl[i].iov_len;
+               }
+
+               error = copyin(ioc->mfi_sgl[i].iov_base,
+                   sc->kbuff_arr[i],
+                   ioc->mfi_sgl[i].iov_len);
+               if (error != 0) {
+                       device_printf(sc->mfi_dev, "Copy in failed\n");
+                       return error;
+               }
+       }
+
+       cm->cm_flags |=MFI_CMD_MAPPED;
+       return 0;
+}
+
+static int
 mfi_user_command(struct mfi_softc *sc, struct mfi_ioc_passthru *ioc)
 {
        struct mfi_command *cm;
@@ -2453,59 +2883,7 @@ out:
        return (error);
 }
 
-#ifdef __x86_64__
 #define        PTRIN(p)                ((void *)(uintptr_t)(p))
-#else
-#define        PTRIN(p)                (p)
-#endif
-
-static int
-mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
-{
-       struct mfi_config_data *conf_data = cm->cm_data;
-       struct mfi_command *ld_cm = NULL;
-       struct mfi_ld_info *ld_info = NULL;
-       int error = 0;
-
-       if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
-           (conf_data->ld[0].params.isSSCD == 1)) {
-               error = 1;
-       } else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
-               error = mfi_dcmd_command(sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
-                   (void **)&ld_info, sizeof(*ld_info));
-               if (error) {
-                       device_printf(sc->mfi_dev,"Failed to allocate "
-                           "MFI_DCMD_LD_GET_INFO %d", error);
-                       if (ld_info)
-                               kfree(ld_info, M_MFIBUF);
-                       return 0;
-               }
-               ld_cm->cm_flags = MFI_CMD_DATAIN;
-               ld_cm->cm_frame->dcmd.mbox[0]= cm->cm_frame->dcmd.mbox[0];
-               ld_cm->cm_frame->header.target_id = cm->cm_frame->dcmd.mbox[0];
-               if (mfi_wait_command(sc, ld_cm) != 0) {
-                       device_printf(sc->mfi_dev, "failed to get log drv\n");
-                       mfi_release_command(ld_cm);
-                       kfree(ld_info, M_MFIBUF);
-                       return 0;
-               }
-
-               if (ld_cm->cm_frame->header.cmd_status != MFI_STAT_OK) {
-                       kfree(ld_info, M_MFIBUF);
-                       mfi_release_command(ld_cm);
-                       return 0;
-               } else {
-                       ld_info = (struct mfi_ld_info *)ld_cm->cm_private;
-               }
-
-               if (ld_info->ld_config.params.isSSCD == 1)
-                       error = 1;
-
-               mfi_release_command(ld_cm);
-               kfree(ld_info, M_MFIBUF);
-       }
-       return error;
-}
 
 static int
 mfi_ioctl(struct dev_ioctl_args *ap)
@@ -2517,26 +2895,29 @@ mfi_ioctl(struct dev_ioctl_args *ap)
        struct mfi_softc *sc;
        union mfi_statrequest *ms;
        struct mfi_ioc_packet *ioc;
-#ifdef __x86_64__
-       struct mfi_ioc_packet32 *ioc32;
-#endif
        struct mfi_ioc_aen *aen;
        struct mfi_command *cm = NULL;
        uint32_t context;
        union mfi_sense_ptr sense_ptr;
        uint8_t *data = NULL, *temp, *addr, skip_pre_post = 0;
        size_t len;
-       int i;
+       int i, res;
        struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg;
-#ifdef __x86_64__
-       struct mfi_ioc_passthru32 *iop32 = (struct mfi_ioc_passthru32 *)arg;
-       struct mfi_ioc_passthru iop_swab;
-#endif
        int error, locked;
+       union mfi_sgl *sgl;
 
        sc = dev->si_drv1;
        error = 0;
 
+       if (sc->adpreset)
+               return EBUSY;
+
+       if (sc->hw_crit_error)
+               return EBUSY;
+
+       if (sc->issuepend_done == 0)
+               return EBUSY;
+
        switch (cmd) {
        case MFIIO_STATS:
                ms = (union mfi_statrequest *)arg;
@@ -2578,9 +2959,6 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                break;
        }
        case MFI_CMD:
-#ifdef __x86_64__
-       case MFI_CMD32:
-#endif
                {
                devclass_t devclass;
                ioc = (struct mfi_ioc_packet *)arg;
@@ -2604,9 +2982,10 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                 * will clobber some data
                 */
                context = cm->cm_frame->header.context;
+               cm->cm_frame->header.context = cm->cm_index;
 
                bcopy(ioc->mfi_frame.raw, cm->cm_frame,
-                   2 * MFI_DCMD_FRAME_SIZE);  /* this isn't quite right */
+                   2 * MEGAMFI_FRAME_SIZE);
                cm->cm_total_frame_size = (sizeof(union mfi_sgl)
                    * ioc->mfi_sge_count) + ioc->mfi_sgl_off;
                cm->cm_frame->header.scsi_status = 0;
@@ -2615,6 +2994,7 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                        cm->cm_sg =
                            (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off];
                }
+               sgl = cm->cm_sg;
                cm->cm_flags = 0;
                if (cm->cm_frame->header.flags & MFI_FRAME_DATAIN)
                        cm->cm_flags |= MFI_CMD_DATAIN;
@@ -2625,18 +3005,7 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                        cm->cm_flags |= MFI_CMD_DATAIN | MFI_CMD_DATAOUT;
                cm->cm_len = cm->cm_frame->header.data_len;
                if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
-#ifdef __x86_64__
-                       if (cmd == MFI_CMD) {
-#endif
-                               /* Native */
-                               cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
-#ifdef __x86_64__
-                       } else {
-                               /* 32bit on 64bit */
-                               ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                               cm->cm_stp_len = ioc32->mfi_sgl[0].iov_len;
-                       }
-#endif
+                       cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
                        cm->cm_len += cm->cm_stp_len;
                }
                if (cm->cm_len &&
@@ -2650,49 +3019,38 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                /* restore header context */
                cm->cm_frame->header.context = context;
 
-               temp = data;
-               if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
-                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
-                       for (i = 0; i < ioc->mfi_sge_count; i++) {
-#ifdef __x86_64__
-                               if (cmd == MFI_CMD) {
-#endif
-                                       /* Native */
+               if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+                       res = mfi_stp_cmd(sc, cm, arg);
+                       if (res != 0)
+                               goto out;
+               } else {
+                       temp = data;
+                       if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
+                           (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
+                               for (i = 0; i < ioc->mfi_sge_count; i++) {
                                        addr = ioc->mfi_sgl[i].iov_base;
                                        len = ioc->mfi_sgl[i].iov_len;
-#ifdef __x86_64__
-                               } else {
-                                       /* 32bit on 64bit */
-                                       ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       len = ioc32->mfi_sgl[i].iov_len;
+                                       error = copyin(addr, temp, len);
+                                       if (error != 0) {
+                                               device_printf(sc->mfi_dev,
+                                                   "Copy in failed\n");
+                                               goto out;
+                                       }
+                                       temp = &temp[len];
                                }
-#endif
-                               error = copyin(addr, temp, len);
-                               if (error != 0) {
-                                       device_printf(sc->mfi_dev,
-                                           "Copy in failed\n");
-                                       goto out;
-                               }
-                               temp = &temp[len];
                        }
                }
 
                if (cm->cm_frame->header.cmd == MFI_CMD_DCMD)
-                       locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
+                       locked = mfi_config_lock(sc,
+                            cm->cm_frame->dcmd.opcode);
 
                if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
-#if defined(__x86_64__)
                        cm->cm_frame->pass.sense_addr_lo =
-                           (cm->cm_sense_busaddr & 0xFFFFFFFF);
+                           (uint32_t)cm->cm_sense_busaddr;
                        cm->cm_frame->pass.sense_addr_hi =
-                           (cm->cm_sense_busaddr& 0xFFFFFFFF00000000) >> 32;
-#else
-                       cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
-                       cm->cm_frame->pass.sense_addr_hi = 0;
-#endif
+                           (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
                }
-
                lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                skip_pre_post = mfi_check_for_sscd(sc, cm);
                if (!skip_pre_post) {
@@ -2714,31 +3072,21 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                        mfi_check_command_post(sc, cm);
                lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
-               temp = data;
-               if ((cm->cm_flags & MFI_CMD_DATAIN) ||
-                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
-                       for (i = 0; i < ioc->mfi_sge_count; i++) {
-#ifdef __x86_64__
-                               if (cmd == MFI_CMD) {
-#endif
-                                       /* Native */
+               if (cm->cm_frame->header.cmd != MFI_CMD_STP) {
+                       temp = data;
+                       if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+                           (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
+                               for (i = 0; i < ioc->mfi_sge_count; i++) {
                                        addr = ioc->mfi_sgl[i].iov_base;
                                        len = ioc->mfi_sgl[i].iov_len;
-#ifdef __x86_64__
-                               } else {
-                                       /* 32bit on 64bit */
-                                       ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       len = ioc32->mfi_sgl[i].iov_len;
+                                       error = copyout(temp, addr, len);
+                                       if (error != 0) {
+                                               device_printf(sc->mfi_dev,
+                                                   "Copy out failed\n");
+                                               goto out;
+                                       }
+                                       temp = &temp[len];
                                }
-#endif
-                               error = copyout(temp, addr, len);
-                               if (error != 0) {
-                                       device_printf(sc->mfi_dev,
-                                           "Copy out failed\n");
-                                       goto out;
-                               }
-                               temp = &temp[len];
                        }
                }
 
@@ -2747,14 +3095,6 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                        bcopy(&ioc->mfi_frame.raw[ioc->mfi_sense_off],
                            &sense_ptr.sense_ptr_data[0],
                            sizeof(sense_ptr.sense_ptr_data));
-#ifdef __x86_64__
-                       if (cmd != MFI_CMD) {
-                               /*
-                                * not 64bit native so zero out any address
-                                * over 32bit */
-                               sense_ptr.addr.high = 0;
-                       }
-#endif
                        error = copyout(cm->cm_sense, sense_ptr.user_space,
                            ioc->mfi_sense_len);
                        if (error != 0) {
@@ -2769,6 +3109,26 @@ out:
                mfi_config_unlock(sc, locked);
                if (data)
                        kfree(data, M_MFIBUF);
+               if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+                       for (i = 0; i < 2; i++) {
+                               if (sc->kbuff_arr[i]) {
+                                       if (sc->mfi_kbuff_arr_busaddr != 0)
+                                               bus_dmamap_unload(
+                                                   sc->mfi_kbuff_arr_dmat[i],
+                                                   sc->mfi_kbuff_arr_dmamap[i]
+                                                   );
+                                       if (sc->kbuff_arr[i] != NULL)
+                                               bus_dmamem_free(
+                                                   sc->mfi_kbuff_arr_dmat[i],
+                                                   sc->kbuff_arr[i],
+                                                   sc->mfi_kbuff_arr_dmamap[i]
+                                                   );
+                                       if (sc->mfi_kbuff_arr_dmat[i] != NULL)
+                                               bus_dma_tag_destroy(
+                                                   sc->mfi_kbuff_arr_dmat[i]);
+                               }
+                       }
+               }
                if (cm) {
                        lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
                        mfi_release_command(cm);
@@ -2825,20 +3185,8 @@ out:
                            cmd, arg, flag));
                        break;
                }
-#ifdef __x86_64__
-       case MFIIO_PASSTHRU32:
-               iop_swab.ioc_frame      = iop32->ioc_frame;
-               iop_swab.buf_size       = iop32->buf_size;
-               iop_swab.buf            = PTRIN(iop32->buf);
-               iop                     = &iop_swab;
-               /* FALLTHROUGH */
-#endif
        case MFIIO_PASSTHRU:
                error = mfi_user_command(sc, iop);
-#ifdef __x86_64__
-               if (cmd == MFIIO_PASSTHRU32)
-                       iop32->ioc_frame = iop_swab.ioc_frame;
-#endif
                break;
        default:
                device_printf(sc->mfi_dev, "IOCTL 0x%lx not handled\n", cmd);
@@ -2934,15 +3282,10 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag)
                        locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
 
                if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
-#if defined(__x86_64__)
                        cm->cm_frame->pass.sense_addr_lo =
-                           (cm->cm_sense_busaddr & 0xFFFFFFFF);
+                           (uint32_t)cm->cm_sense_busaddr;
                        cm->cm_frame->pass.sense_addr_hi =
-                           (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-                       cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
-                       cm->cm_frame->pass.sense_addr_hi = 0;
-#endif
+                           (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
                }
 
                lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -3145,8 +3488,8 @@ mfi_dump_all(void)
                TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
                        if (cm->cm_timestamp < deadline) {
                                device_printf(sc->mfi_dev,
-                                   "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm,
-                                   (int)(time_second - cm->cm_timestamp));
+                                   "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
+                                   cm, (int)(time_second - cm->cm_timestamp));
                                MFI_PRINT_CMD(cm);
                                timedout++;
                        }
@@ -3172,17 +3515,28 @@ mfi_timeout(void *data)
        int timedout = 0;
 
        deadline = time_second - MFI_CMD_TIMEOUT;
+       if (sc->adpreset == 0) {
+               if (!mfi_tbolt_reset(sc)) {
+                       callout_reset(&sc->mfi_watchdog_callout,
+                           MFI_CMD_TIMEOUT * hz, mfi_timeout, sc);
+                       return;
+               }
+       }
        lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
        TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
                if (sc->mfi_aen_cm == cm)
                        continue;
                if ((sc->mfi_aen_cm != cm) && (cm->cm_timestamp < deadline)) {
-                       device_printf(sc->mfi_dev,
-                           "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm,
-                           (int)(time_second - cm->cm_timestamp));
-                       MFI_PRINT_CMD(cm);
-                       MFI_VALIDATE_CMD(sc, cm);
-                       timedout++;
+                       if (sc->adpreset != 0 && sc->issuepend_done == 0) {
+                               cm->cm_timestamp = time_second;
+                       } else {
+                               device_printf(sc->mfi_dev,
+                                   "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
+                                    cm, (int)(time_second - cm->cm_timestamp));
+                               MFI_PRINT_CMD(cm);
+                               MFI_VALIDATE_CMD(sc, cm);
+                               timedout++;
+                       }
                }
        }
 
index d4fc2c0..b7a8ca2 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_cam.c,v 1.7 2011/10/13 20:06:19 marius Exp $
+ * FreeBSD projects/head_mfi/ r232949
  */
 
 #include "opt_mfi.h"
@@ -151,6 +122,7 @@ mfip_attach(device_t dev)
                                device_get_unit(dev), &mfisc->mfi_io_lock, 1,
                                MFI_SCSI_MAX_CMDS, sc->devq);
        if (sc->sim == NULL) {
+               cam_simq_release(sc->devq);
                device_printf(dev, "CAM SIM attach failed\n");
                return (EINVAL);
        }
@@ -159,6 +131,7 @@ mfip_attach(device_t dev)
        if (xpt_bus_register(sc->sim, 0) != 0) {
                device_printf(dev, "XPT bus registration failed\n");
                cam_sim_free(sc->sim);
+               cam_simq_release(sc->devq);
                lockmgr(&mfisc->mfi_io_lock, LK_RELEASE);
                return (EINVAL);
        }
@@ -183,6 +156,9 @@ mfip_detach(device_t dev)
                lockmgr(&sc->mfi_sc->mfi_io_lock, LK_RELEASE);
        }
 
+       if (sc->devq != NULL)
+               cam_simq_release(sc->devq);
+
        return (0);
 }
 
index e3b5e74..648f855 100644 (file)
@@ -24,6 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_debug.c,v 1.3 2006/10/16 04:18:38 scottl Exp $
+ * FreeBSD projects/head_mfi/ r228320
  */
 
 #include "opt_mfi.h"
@@ -58,7 +59,8 @@ mfi_print_frame_flags(device_t dev, uint32_t flags)
            "\2SGL64"
            "\3SENSE64"
            "\4WRITE"
-           "\5READ");
+           "\5READ"
+           "\6IEEESGL");
 }
 
 static void
@@ -68,7 +70,15 @@ mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count)
 
        kprintf("SG List:\n");
        for (i = 0; i < count; i++) {
-               if (hdr->flags & MFI_FRAME_SGL64) {
+               if (hdr->flags & MFI_FRAME_IEEE_SGL) {
+                       kprintf("0x%lx:%06d ", (u_long)sgl->sg_skinny[i].addr,
+                           sgl->sg_skinny[i].len);
+                       columns += 26;
+                       if (columns > 77) {
+                               kprintf("\n");
+                               columns = 0;
+                       }
+               } else if (hdr->flags & MFI_FRAME_SGL64) {
                        kprintf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr,
                            sgl->sg64[i].len);
                        columns += 26;
@@ -235,7 +245,12 @@ mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm,
        hdr = &cm->cm_frame->header;
        count = 0;
        for (i = 0; i < hdr->sg_count; i++) {
-               count += cm->cm_sg->sg32[i].len;
+               if (hdr->flags & MFI_FRAME_IEEE_SGL)
+                       count += cm->cm_sg->sg_skinny[i].len;
+               else if (hdr->flags & MFI_FRAME_SGL64)
+                       count += cm->cm_sg->sg64[i].len;
+               else
+                       count += cm->cm_sg->sg32[i].len;
        }
        /*
        count++;
index 53534b1..eeef124 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_disk.c,v 1.8 2008/11/17 23:30:19 jhb Exp $
+ * FreeBSD projects/head_mfi/ r232888
  */
 
 #include "opt_mfi.h"
@@ -281,7 +252,7 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
        struct bio *bio = ap->a_bio;
        struct buf *bp = bio->bio_buf;
        struct mfi_disk *sc = ap->a_head.a_dev->si_drv1;
-       struct mfi_softc *controller;
+       struct mfi_softc *controller = sc->ld_controller;
 
        if (sc == NULL) {
                bp->b_error = EINVAL;
@@ -291,6 +262,16 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
                return (0);
        }
 
+       if (controller->hw_crit_error) {
+               bp->b_error = EBUSY;
+               return (0);
+       }
+
+       if (controller->issuepend_done == 0) {
+               bp->b_error = EBUSY;
+               return (0);
+       }
+
        /*
         * XXX swildner
         *
@@ -310,7 +291,6 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
                return (0);
        }
 
-       controller = sc->ld_controller;
        bio->bio_driver_info = sc;
        lockmgr(&controller->mfi_io_lock, LK_EXCLUSIVE);
        mfi_enqueue_bio(controller, bio);
index 8450495..15eea40 100644 (file)
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_ioctl.h,v 1.9 2009/08/13 23:18:45 scottl Exp $
+ * FreeBSD projects/head_mfi/ r227612
  */
 
 #include <sys/conf.h>
 
+#include <sys/bus_dma.h>
+
 #include <dev/raid/mfi/mfireg.h>
 
-#if defined(__x86_64__) /* Assume amd64 wants 32 bit Linux */
 struct iovec32 {
        u_int32_t       iov_base;
        int             iov_len;
 };
-#endif
+
+struct megasas_sge
+{
+       bus_addr_t phys_addr;
+       uint32_t length;
+};
 
 #define MFIQ_FREE      0
 #define MFIQ_BIO       1
@@ -80,23 +87,6 @@ struct mfi_ioc_packet {
        struct iovec mfi_sgl[MAX_IOCTL_SGE];
 } __packed;
 
-#ifdef __x86_64__
-struct mfi_ioc_packet32 {
-       uint16_t        mfi_adapter_no;
-       uint16_t        mfi_pad1;
-       uint32_t        mfi_sgl_off;
-       uint32_t        mfi_sge_count;
-       uint32_t        mfi_sense_off;
-       uint32_t        mfi_sense_len;
-       union {
-               uint8_t raw[128];
-               struct mfi_frame_header hdr;
-       } mfi_frame;
-
-       struct iovec32 mfi_sgl[MAX_IOCTL_SGE];
-} __packed;
-#endif
-
 struct mfi_ioc_aen {
        uint16_t        aen_adapter_no;
        uint16_t        aen_pad1;
@@ -105,9 +95,6 @@ struct mfi_ioc_aen {
 } __packed;
 
 #define MFI_CMD                _IOWR('M', 1, struct mfi_ioc_packet)
-#ifdef __x86_64__
-#define MFI_CMD32      _IOWR('M', 1, struct mfi_ioc_packet32)
-#endif
 #define MFI_SET_AEN    _IOW('M', 3, struct mfi_ioc_aen)
 
 #define MAX_LINUX_IOCTL_SGE    16
@@ -137,19 +124,8 @@ struct mfi_ioc_passthru {
        uint8_t                 *buf;
 } __packed;
 
-#ifdef __x86_64__
-struct mfi_ioc_passthru32 {
-       struct mfi_dcmd_frame   ioc_frame;
-       uint32_t                buf_size;
-       uint32_t                buf;
-} __packed;
-#endif
-
 #define MFIIO_STATS    _IOWR('Q', 101, union mfi_statrequest)
 #define MFIIO_PASSTHRU _IOWR('C', 102, struct mfi_ioc_passthru)
-#ifdef __x86_64__
-#define MFIIO_PASSTHRU32       _IOWR('C', 102, struct mfi_ioc_passthru32)
-#endif
 
 struct mfi_linux_ioc_aen {
        uint16_t        laen_adapter_no;
index cb3163d..629537e 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_pci.c,v 1.16 2010/03/02 17:34:11 kib Exp $
+ * FreeBSD projects/head_mfi/ r232888
  */
 
 /* PCI/PCI-X/PCIe bus interface for the LSI MegaSAS controllers */
@@ -96,7 +67,6 @@
 #include <sys/malloc.h>
 #include <sys/uio.h>
 #include <sys/eventhandler.h>
-
 #include <sys/rman.h>
 
 #include <bus/pci/pcireg.h>
@@ -134,6 +104,9 @@ static devclass_t   mfi_devclass;
 DRIVER_MODULE(mfi, pci, mfi_pci_driver, mfi_devclass, NULL, NULL);
 MODULE_VERSION(mfi, 1);
 
+static int     mfi_msi_enable = 1;
+TUNABLE_INT("hw.mfi.msi.enable", &mfi_msi_enable);
+
 struct mfi_ident {
        uint16_t        vendor;
        uint16_t        device;
@@ -142,6 +115,17 @@ struct mfi_ident {
        int             flags;
        const char      *desc;
 } mfi_identifiers[] = {
+       {0x1000, 0x005b, 0x1028, 0x1f2d, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H810 Adapter"},
+       {0x1000, 0x005b, 0x1028, 0x1f30, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710 Embedded"},
+       {0x1000, 0x005b, 0x1028, 0x1f31, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710P Adapter"},
+       {0x1000, 0x005b, 0x1028, 0x1f33, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710P Mini (blades)"},
+       {0x1000, 0x005b, 0x1028, 0x1f34, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710P Mini (monolithics)"},
+       {0x1000, 0x005b, 0x1028, 0x1f35, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710 Adapter"},
+       {0x1000, 0x005b, 0x1028, 0x1f37, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710 Mini (blades)"},
+       {0x1000, 0x005b, 0x1028, 0x1f38, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Dell PERC H710 Mini (monolithics)"},
+       {0x1000, 0x005b, 0x8086, 0x9265, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Intel (R) RAID Controller RS25DB080"},
+       {0x1000, 0x005b, 0x8086, 0x9285, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "Intel (R) RAID Controller RS25NB008"},
+       {0x1000, 0x005b, 0xffff, 0xffff, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT, "ThunderBolt"},
        {0x1000, 0x0060, 0x1028, 0xffff, MFI_FLAGS_1078,  "Dell PERC 6"},
        {0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078,  "LSI MegaSAS 1078"},
        {0x1000, 0x0071, 0xffff, 0xffff, MFI_FLAGS_SKINNY, "Drake Skinny"},
@@ -200,6 +184,7 @@ mfi_pci_attach(device_t dev)
        struct mfi_ident *m;
        uint32_t command;
        int error;
+       u_int irq_flags;
 
        sc = device_get_softc(dev);
        bzero(sc, sizeof(*sc));
@@ -227,7 +212,8 @@ mfi_pci_attach(device_t dev)
                /* 1068/1078: Memory mapped BAR is at offset 0x10 */
                sc->mfi_regs_rid = PCIR_BAR(0);
        } else if ((sc->mfi_flags & MFI_FLAGS_GEN2) ||
-                  (sc->mfi_flags & MFI_FLAGS_SKINNY)) {
+                  (sc->mfi_flags & MFI_FLAGS_SKINNY) ||
+                  (sc->mfi_flags & MFI_FLAGS_TBOLT)) {
                /* GEN2/Skinny: Memory mapped BAR is at offset 0x14 */
                sc->mfi_regs_rid = PCIR_BAR(1);
        }
@@ -256,6 +242,16 @@ mfi_pci_attach(device_t dev)
                goto out;
        }
 
+       /* Allocate IRQ resource. */
+       sc->mfi_irq_rid = 0;
+       sc->mfi_irq_type = pci_alloc_1intr(sc->mfi_dev, mfi_msi_enable,
+           &sc->mfi_irq_rid, &irq_flags);
+       if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
+           &sc->mfi_irq_rid, irq_flags)) == NULL) {
+               device_printf(sc->mfi_dev, "Cannot allocate interrupt\n");
+               return (EINVAL);
+       }
+
        error = mfi_attach(sc);
 out:
        if (error) {
@@ -270,9 +266,8 @@ static int
 mfi_pci_detach(device_t dev)
 {
        struct mfi_softc *sc;
-       struct mfi_disk *ld;
-       struct mfi_system_pd *syspd = NULL;
-       int error;
+       device_t *devlist;
+       int error, devcount, i;
 
        sc = device_get_softc(dev);
 
@@ -286,20 +281,13 @@ mfi_pci_detach(device_t dev)
        sc->mfi_detaching = 1;
        lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
-       while ((ld = TAILQ_FIRST(&sc->mfi_ld_tqh)) != NULL) {
-               if ((error = device_delete_child(dev, ld->ld_dev)) != 0) {
-                       sc->mfi_detaching = 0;
-                       lockmgr(&sc->mfi_config_lock, LK_RELEASE);
-                       return (error);
-               }
-       }
-       while ((syspd = TAILQ_FIRST(&sc->mfi_syspd_tqh)) != NULL) {
-               if ((error = device_delete_child(dev,syspd->pd_dev)) != 0) {
-                       sc->mfi_detaching = 0;
-                       lockmgr(&sc->mfi_config_lock, LK_RELEASE);
-                       return (error);
-               }
+       if ((error = device_get_children(sc->mfi_dev, &devlist, &devcount)) != 0) {
+               lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+               return error;
        }
+       for (i = 0; i < devcount; i++)
+               device_delete_child(sc->mfi_dev, devlist[i]);
+       kfree(devlist, M_TEMP);
        lockmgr(&sc->mfi_config_lock, LK_RELEASE);
 
        EVENTHANDLER_DEREGISTER(shutdown_final, sc->mfi_eh);
@@ -318,8 +306,8 @@ mfi_pci_free(struct mfi_softc *sc)
                bus_release_resource(sc->mfi_dev, SYS_RES_MEMORY,
                    sc->mfi_regs_rid, sc->mfi_regs_resource);
        }
-
-       return;
+       if (sc->mfi_irq_type == PCI_INTR_TYPE_MSI)
+               pci_release_msi(sc->mfi_dev);
 }
 
 static int
index b929de1..f56a803 100644 (file)
@@ -29,6 +29,7 @@
  * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_pddisk.c,v 1.2.2.6 2007/08/24 17:29:18 jhb Exp $
+ * FreeBSD projects/head_mfi/ r232888
  */
 
 #include "opt_mfi.h"
@@ -212,7 +213,8 @@ mfi_syspd_disable(struct mfi_system_pd *sc)
        if (sc->pd_flags & MFI_DISK_FLAGS_OPEN) {
                if (sc->pd_controller->mfi_delete_busy_volumes)
                        return (0);
-               device_printf(sc->pd_dev, "Unable to delete busy syspd device\n");
+               device_printf(sc->pd_dev,
+                   "Unable to delete busy syspd device\n");
                return (EBUSY);
        }
        sc->pd_flags |= MFI_DISK_FLAGS_DISABLED;
@@ -233,7 +235,7 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
        struct bio *bio = ap->a_bio;
        struct buf *bp = bio->bio_buf;
        struct mfi_system_pd *sc = ap->a_head.a_dev->si_drv1;
-       struct mfi_softc *controller;
+       struct mfi_softc *controller = sc->pd_controller;
 
        if (sc == NULL) {
                bp->b_error = EINVAL;
@@ -243,6 +245,16 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
                return (0);
        }
 
+       if (controller->hw_crit_error) {
+               bp->b_error = EBUSY;
+               return (0);
+       }
+
+       if (controller->issuepend_done == 0) {
+               bp->b_error = EBUSY;
+               return (0);
+       }
+
        /*
         * XXX swildner
         *
@@ -262,7 +274,6 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
                return (0);
        }
 
-       controller = sc->pd_controller;
        bio->bio_driver_info = sc;
        lockmgr(&controller->mfi_io_lock, LK_EXCLUSIVE);
        mfi_enqueue_bio(controller, bio);
@@ -272,26 +283,6 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
        return (0);
 }
 
-#if 0
-void
-mfi_disk_complete(struct bio *bio)
-{
-       struct mfi_system_pd *sc = bio->bio_driver_info;
-       struct buf *bp = bio->bio_buf;
-
-       devstat_end_transaction_buf(&sc->pd_devstat, bp);
-       if (bio->b_flags & B_ERROR) {
-               if (bp->b_error == 0)
-                       bp->b_error = EIO;
-               diskerr(bio, sc->pd_disk.d_cdev, "hard error", -1, 1);
-               kprintf("\n");
-       } else {
-               bp->b_resid = 0;
-       }
-       biodone(bio);
-}
-#endif
-
 static int
 mfi_syspd_dump(struct dev_dump_args *ap)
 {
@@ -307,8 +298,8 @@ mfi_syspd_dump(struct dev_dump_args *ap)
        parent_sc = sc->pd_controller;
 
        if (len > 0) {
-               if ((error = mfi_dump_syspd_blocks(parent_sc, sc->pd_id, offset /
-                   MFI_SECTOR_LEN, virt, len)) != 0)
+               if ((error = mfi_dump_syspd_blocks(parent_sc,
+                   sc->pd_id, offset / MFI_SECTOR_LEN, virt, len)) != 0)
                        return (error);
        } else {
                /* mfi_sync_cache(parent_sc, sc->ld_id); */
diff --git a/sys/dev/raid/mfi/mfi_tbolt.c b/sys/dev/raid/mfi/mfi_tbolt.c
new file mode 100644 (file)
index 0000000..551a648
--- /dev/null
@@ -0,0 +1,1342 @@
+/*-
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *            Copyright 1994-2009 The FreeBSD Project.
+ *            All rights reserved.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies,either expressed or implied, of the FreeBSD Project.
+ *
+ * $FreeBSD: src/sys/dev/mfi/mfi_tbolt.c,v 1.00 2010/06/30 16:00:00 Bharat Gusain Exp $
+ * FreeBSD projects/head_mfi/ r232949
+ */
+
+#include "opt_mfi.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/buf2.h>
+#include <sys/ioccom.h>
+#include <sys/eventhandler.h>
+#include <sys/callout.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <dev/raid/mfi/mfireg.h>
+#include <dev/raid/mfi/mfi_ioctl.h>
+#include <dev/raid/mfi/mfivar.h>
+
+struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc);
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index);
+void mfi_tbolt_complete_cmd(struct mfi_softc *sc);
+int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd);
+static inline void mfi_tbolt_return_cmd(struct mfi_softc *sc,
+    struct mfi_cmd_tbolt *cmd);
+union mfi_mpi2_request_descriptor *mfi_tbolt_build_mpt_cmd(struct mfi_softc
+    *sc, struct mfi_command *cmd);
+uint8_t
+mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd);
+union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc
+    *sc, struct mfi_command *mfi_cmd);
+int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd);
+void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd);
+static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command
+    *mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd);
+static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command
+    *mfi_cmd, uint8_t *cdb);
+void
+map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
+     uint8_t ext_status);
+static void mfi_issue_pending_cmds_again (struct mfi_softc *sc);
+static void mfi_kill_hba (struct mfi_softc *sc);
+static void mfi_process_fw_state_chg_isr(void *arg);
+uint8_t mfi_tbolt_get_map_info(struct mfi_softc *sc);
+
+#define MFI_FUSION_ENABLE_INTERRUPT_MASK       (0x00000008)
+
+void
+mfi_tbolt_enable_intr_ppc(struct mfi_softc *sc)
+{
+       MFI_WRITE4(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK);
+       MFI_READ4(sc, MFI_OMSK);
+}
+
+void
+mfi_tbolt_disable_intr_ppc(struct mfi_softc *sc)
+{
+       MFI_WRITE4(sc, MFI_OMSK, 0xFFFFFFFF);
+       MFI_READ4(sc, MFI_OMSK);
+}
+
+int32_t
+mfi_tbolt_read_fw_status_ppc(struct mfi_softc *sc)
+{
+       return MFI_READ4(sc, MFI_OSP0);
+}
+
+int32_t
+mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *sc)
+{
+       int32_t status, mfi_status = 0;
+
+       status = MFI_READ4(sc, MFI_OSTS);
+
+       if (status & 1) {
+               MFI_WRITE4(sc, MFI_OSTS, status);
+               MFI_READ4(sc, MFI_OSTS);
+               if (status & MFI_STATE_CHANGE_INTERRUPT) {
+                       mfi_status |= MFI_FIRMWARE_STATE_CHANGE;
+               }
+
+               return mfi_status;
+       }
+       if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
+               return 1;
+
+       MFI_READ4(sc, MFI_OSTS);
+       return 0;
+}
+
+
+void
+mfi_tbolt_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
+   uint32_t frame_cnt)
+{
+       bus_add |= (MFI_REQ_DESCRIPT_FLAGS_MFA
+           << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+       MFI_WRITE4(sc, MFI_IQPL, (uint32_t)bus_add);
+       MFI_WRITE4(sc, MFI_IQPH, (uint32_t)((uint64_t)bus_add >> 32));
+}
+
+/**
+ * mfi_tbolt_adp_reset - For controller reset
+ * @regs: MFI register set
+ */
+int mfi_tbolt_adp_reset(struct mfi_softc *sc)
+{
+       int retry = 0, i = 0;
+       int HostDiag;
+
+       MFI_WRITE4(sc, MFI_WSR, 0xF);
+       MFI_WRITE4(sc, MFI_WSR, 4);
+       MFI_WRITE4(sc, MFI_WSR, 0xB);
+       MFI_WRITE4(sc, MFI_WSR, 2);
+       MFI_WRITE4(sc, MFI_WSR, 7);
+       MFI_WRITE4(sc, MFI_WSR, 0xD);
+
+       for (i = 0; i < 10000; i++) ;
+
+       HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
+
+       while (!( HostDiag & DIAG_WRITE_ENABLE)) {
+               for (i = 0; i < 1000; i++);
+               HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
+               device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
+                   "hostdiag=%x\n", retry, HostDiag);
+
+               if (retry++ >= 100)
+                       return 1;
+       }
+
+       device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: HostDiag=%x\n", HostDiag);
+
+       MFI_WRITE4(sc, MFI_HDR, (HostDiag | DIAG_RESET_ADAPTER));
+
+       for (i=0; i < 10; i++) {
+               for (i = 0; i < 10000; i++);
+       }
+
+       HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
+       while (HostDiag & DIAG_RESET_ADAPTER) {
+               for (i = 0; i < 1000; i++) ;
+               HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
+               device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
+                   "hostdiag=%x\n", retry, HostDiag);
+
+               if (retry++ >= 1000)
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ *******************************************************************************************
+ * Description:
+ *      This routine initialize Thunderbolt specific device information
+ *******************************************************************************************
+ */
+void mfi_tbolt_init_globals(struct mfi_softc *sc)
+{
+       /* Initialize single reply size and Message size */
+       sc->reply_size = MEGASAS_THUNDERBOLT_REPLY_SIZE;
+       sc->raid_io_msg_size = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+
+       /*
+        * Calculating how many SGEs allowed in a allocated main message
+        * (size of the Message - Raid SCSI IO message size(except SGE))
+        * / size of SGE
+        * (0x100 - (0x90 - 0x10)) / 0x10 = 8
+        */
+       sc->max_SGEs_in_main_message =
+           (uint8_t)((sc->raid_io_msg_size
+           - (sizeof(struct mfi_mpi2_request_raid_scsi_io)
+           - sizeof(MPI2_SGE_IO_UNION))) / sizeof(MPI2_SGE_IO_UNION));
+       /*
+        * (Command frame size allocaed in SRB ext - Raid SCSI IO message size)
+        * / size of SGL ;
+        * (1280 - 256) / 16 = 64
+        */
+       sc->max_SGEs_in_chain_message = (MR_COMMAND_SIZE
+           - sc->raid_io_msg_size) / sizeof(MPI2_SGE_IO_UNION);
+       /*
+        * (0x08-1) + 0x40 = 0x47 - 0x01 = 0x46  one is left for command
+        * colscing
+       */
+       sc->mfi_max_sge = (sc->max_SGEs_in_main_message - 1)
+           + sc->max_SGEs_in_chain_message - 1;
+       /*
+       * This is the offset in number of 4 * 32bit words to the next chain
+       * (0x100 - 0x10)/0x10 = 0xF(15)
+       */
+       sc->chain_offset_value_for_main_message = (sc->raid_io_msg_size
+           - sizeof(MPI2_SGE_IO_UNION))/16;
+       sc->chain_offset_value_for_mpt_ptmsg
+           = offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL)/16;
+       sc->mfi_cmd_pool_tbolt = NULL;
+       sc->request_desc_pool = NULL;
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *      This function calculates the memory requirement for Thunderbolt
+ *      controller
+ * Return Value:
+ *      Total required memory in bytes
+ ****************************************************************************
+ */
+
+uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *sc)
+{
+       uint32_t size;
+
+       size = MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT;      /* for Alignment */
+       size += sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1);
+       size += sc->reply_size * sc->mfi_max_fw_cmds;
+       /* this is for SGL's */
+       size += MEGASAS_MAX_SZ_CHAIN_FRAME * sc->mfi_max_fw_cmds;
+       return size;
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *      This function will prepare message pools for the Thunderbolt controller
+ * Arguments:
+ *      DevExt - HBA miniport driver's adapter data storage structure
+ *      pMemLocation - start of the memory allocated for Thunderbolt.
+ * Return Value:
+ *      TRUE if successful
+ *      FALSE if failed
+ ****************************************************************************
+ */
+int mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
+    uint32_t tbolt_contg_length)
+{
+       uint32_t     offset = 0;
+       uint8_t      *addr = mem_location;
+
+       /* Request Descriptor Base physical Address */
+
+       /* For Request Decriptors Virtual Memory */
+       /* Initialise the aligned IO Frames Virtual Memory Pointer */
+       if (((uintptr_t)addr) & (0xFF)) {
+               addr = &addr[sc->raid_io_msg_size];
+               addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
+               sc->request_message_pool_align = addr;
+       } else
+               sc->request_message_pool_align = addr;
+
+       offset = sc->request_message_pool_align - sc->request_message_pool;
+       sc->request_msg_busaddr = sc->mfi_tb_busaddr + offset;
+
+       /* DJA XXX should this be bus dma ??? */
+       /* Skip request message pool */
+       addr = &addr[sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1)];
+       /* Reply Frame Pool is initialized */
+       sc->reply_frame_pool = (struct mfi_mpi2_reply_header *) addr;
+       if (((uintptr_t)addr) & (0xFF)) {
+               addr = &addr[sc->reply_size];
+               addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
+       }
+       sc->reply_frame_pool_align
+                   = (struct mfi_mpi2_reply_header *)addr;
+
+       offset = (uintptr_t)sc->reply_frame_pool_align
+           - (uintptr_t)sc->request_message_pool;
+       sc->reply_frame_busaddr = sc->mfi_tb_busaddr + offset;
+
+       /* Skip Reply Frame Pool */
+       addr += sc->reply_size * sc->mfi_max_fw_cmds;
+       sc->reply_pool_limit = addr;
+
+       /* initializing reply address to 0xFFFFFFFF */
+       memset((uint8_t *)sc->reply_frame_pool, 0xFF,
+              (sc->reply_size * sc->mfi_max_fw_cmds));
+
+       offset = sc->reply_size * sc->mfi_max_fw_cmds;
+       sc->sg_frame_busaddr = sc->reply_frame_busaddr + offset;
+       /* initialize the last_reply_idx to 0 */
+       sc->last_reply_idx = 0;
+       offset = (sc->sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME *
+           sc->mfi_max_fw_cmds)) - sc->mfi_tb_busaddr;
+       if (offset > tbolt_contg_length)
+               device_printf(sc->mfi_dev, "Error:Initialized more than "
+                   "allocated\n");
+       return 0;
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *   This routine prepare and issue INIT2 frame to the Firmware
+ ****************************************************************************
+ */
+
+int
+mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
+{
+       struct MPI2_IOC_INIT_REQUEST   *mpi2IocInit;
+       struct mfi_init_frame   *mfi_init;
+       uintptr_t                       offset = 0;
+       bus_addr_t                      phyAddress;
+       MFI_ADDRESS                     *mfiAddressTemp;
+       struct mfi_command *cm;
+       int error;
+
+       mpi2IocInit = (struct MPI2_IOC_INIT_REQUEST *)sc->mfi_tb_ioc_init_desc;
+       /* Check if initialization is already completed */
+       if (sc->MFA_enabled) {
+               return 1;
+       }
+
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+       if ((cm = mfi_dequeue_free(sc)) == NULL) {
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               return (EBUSY);
+       }
+       cm->cm_frame = (union mfi_frame *)((uintptr_t)sc->mfi_tb_init);
+       cm->cm_frame_busaddr = sc->mfi_tb_init_busaddr;
+       cm->cm_dmamap = sc->mfi_tb_init_dmamap;
+       cm->cm_frame->header.context = 0;
+       cm->cm_sc = sc;
+       cm->cm_index = 0;
+
+       /*
+        * Abuse the SG list area of the frame to hold the init_qinfo
+        * object;
+        */
+       mfi_init = &cm->cm_frame->init;
+
+       bzero(mpi2IocInit, sizeof(struct MPI2_IOC_INIT_REQUEST));
+       mpi2IocInit->Function  = MPI2_FUNCTION_IOC_INIT;
+       mpi2IocInit->WhoInit   = MPI2_WHOINIT_HOST_DRIVER;
+
+       /* set MsgVersion and HeaderVersion host driver was built with */
+       mpi2IocInit->MsgVersion = MPI2_VERSION;
+       mpi2IocInit->HeaderVersion = MPI2_HEADER_VERSION;
+       mpi2IocInit->SystemRequestFrameSize = sc->raid_io_msg_size/4;
+       mpi2IocInit->ReplyDescriptorPostQueueDepth
+           = (uint16_t)sc->mfi_max_fw_cmds;
+       mpi2IocInit->ReplyFreeQueueDepth = 0; /* Not supported by MR. */
+
+       /* Get physical address of reply frame pool */
+       offset = (uintptr_t) sc->reply_frame_pool_align
+           - (uintptr_t)sc->request_message_pool;
+       phyAddress = sc->mfi_tb_busaddr + offset;
+       mfiAddressTemp =
+           (MFI_ADDRESS *)&mpi2IocInit->ReplyDescriptorPostQueueAddress;
+       mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
+       mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
+
+       /* Get physical address of request message pool */
+       offset = sc->request_message_pool_align - sc->request_message_pool;
+       phyAddress =  sc->mfi_tb_busaddr + offset;
+       mfiAddressTemp = (MFI_ADDRESS *)&mpi2IocInit->SystemRequestFrameBaseAddress;
+       mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
+       mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
+       mpi2IocInit->ReplyFreeQueueAddress =  0; /* Not supported by MR. */
+       mpi2IocInit->TimeStamp = time_second;
+
+       if (sc->verbuf) {
+               ksnprintf((char *)sc->verbuf, strlen(MEGASAS_VERSION) + 2, "%s\n",
+                MEGASAS_VERSION);
+               mfi_init->driver_ver_lo = (uint32_t)sc->verbuf_h_busaddr;
+               mfi_init->driver_ver_hi =
+                   (uint32_t)((uint64_t)sc->verbuf_h_busaddr >> 32);
+       }
+       /* Get the physical address of the mpi2 ioc init command */
+       phyAddress =  sc->mfi_tb_ioc_init_busaddr;
+       mfi_init->qinfo_new_addr_lo = (uint32_t)phyAddress;
+       mfi_init->qinfo_new_addr_hi = (uint32_t)((uint64_t)phyAddress >> 32);
+       mfi_init->header.flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+       mfi_init->header.cmd = MFI_CMD_INIT;
+       mfi_init->header.data_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
+       mfi_init->header.cmd_status = MFI_STAT_INVALID_STATUS;
+
+       cm->cm_data = NULL;
+       cm->cm_flags |= MFI_CMD_POLLED;
+       cm->cm_timestamp = time_second;
+       if ((error = mfi_mapcmd(sc, cm)) != 0) {
+               device_printf(sc->mfi_dev, "failed to send IOC init2 "
+                   "command %d at %lx\n", error, (long)cm->cm_frame_busaddr);
+               mfi_release_command(cm);
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               return (error);
+       }
+       mfi_release_command(cm);
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+
+       if (mfi_init->header.cmd_status == 0) {
+               sc->MFA_enabled = 1;
+       }
+       else {
+               device_printf(sc->mfi_dev, "Init command Failed %x\n",
+                   mfi_init->header.cmd_status);
+               return 1;
+       }
+
+       return 0;
+
+}
+
+int mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
+{
+       struct mfi_cmd_tbolt *cmd;
+       bus_addr_t io_req_base_phys;
+       uint8_t *io_req_base;
+       int i = 0, j = 0, offset = 0;
+
+       /*
+        * sc->mfi_cmd_pool_tbolt is an array of struct mfi_cmd_tbolt pointers.
+        * Allocate the dynamic array first and then allocate individual
+        * commands.
+        */
+       sc->request_desc_pool = kmalloc(sizeof(
+           union mfi_mpi2_request_descriptor) * sc->mfi_max_fw_cmds,
+           M_MFIBUF, M_NOWAIT|M_ZERO);
+       sc->mfi_cmd_pool_tbolt = kmalloc(sizeof(struct mfi_cmd_tbolt*)
+           * sc->mfi_max_fw_cmds, M_MFIBUF, M_NOWAIT|M_ZERO);
+
+       if (!sc->mfi_cmd_pool_tbolt) {
+               device_printf(sc->mfi_dev, "out of memory. Could not alloc "
+                   "memory for cmd_list_fusion\n");
+               return 1;
+       }
+
+       for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
+               sc->mfi_cmd_pool_tbolt[i] = kmalloc(sizeof(
+                   struct mfi_cmd_tbolt),M_MFIBUF, M_NOWAIT|M_ZERO);
+
+               if (!sc->mfi_cmd_pool_tbolt[i]) {
+                       device_printf(sc->mfi_dev, "Could not alloc cmd list "
+                           "fusion\n");
+
+                       for (j = 0; j < i; j++)
+                               kfree(sc->mfi_cmd_pool_tbolt[j], M_MFIBUF);
+
+                       kfree(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+                       sc->mfi_cmd_pool_tbolt = NULL;
+               }
+       }
+
+       /*
+        * The first 256 bytes (SMID 0) is not used. Don't add to the cmd
+        *list
+        */
+       io_req_base = sc->request_message_pool_align
+               + MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+       io_req_base_phys = sc->request_msg_busaddr
+               + MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+
+       /*
+        * Add all the commands to command pool (instance->cmd_pool)
+        */
+       /* SMID 0 is reserved. Set SMID/index from 1 */
+
+       for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
+               cmd = sc->mfi_cmd_pool_tbolt[i];
+               offset = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * i;
+               cmd->index = i + 1;
+               cmd->request_desc = (union mfi_mpi2_request_descriptor *)
+                   (sc->request_desc_pool + i);
+               cmd->io_request = (struct mfi_mpi2_request_raid_scsi_io *)
+                   (io_req_base + offset);
+               cmd->io_request_phys_addr = io_req_base_phys + offset;
+               cmd->sg_frame = (MPI2_SGE_IO_UNION *)(sc->reply_pool_limit
+                   + i * MEGASAS_MAX_SZ_CHAIN_FRAME);
+               cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i
+                   * MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+               TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next);
+       }
+       return 0;
+}
+
+int mfi_tbolt_reset(struct mfi_softc *sc)
+{
+       uint32_t fw_state;
+
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+       if (atomic_read(&sc->fw_reset_no_pci_access)) {
+               device_printf(sc->mfi_dev, "NO PCI ACCESS\n");
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               return 1;
+       }
+
+       if (sc->hw_crit_error) {
+               device_printf(sc->mfi_dev, "HW CRITICAL ERROR\n");
+               lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+               return 1;
+       }
+
+       if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+               fw_state = sc->mfi_read_fw_status(sc);
+               if ((fw_state & MFI_FWSTATE_FAULT) == MFI_FWSTATE_FAULT) {
+                       if ((sc->disableOnlineCtrlReset == 0)
+                           && (sc->adpreset == 0)) {
+                               device_printf(sc->mfi_dev, "Adapter RESET "
+                                   "condition is detected\n");
+                               sc->adpreset = 1;
+                               sc->issuepend_done = 0;
+                               sc->MFA_enabled = 0;
+                               sc->last_reply_idx = 0;
+                               mfi_process_fw_state_chg_isr((void *) sc);
+                       }
+                       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+                       return 0;
+               }
+       }
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+       return 1;
+}
+
+/*
+ * mfi_intr_tbolt - isr entry point
+ */
+void mfi_intr_tbolt(void *arg)
+{
+       struct mfi_softc *sc = (struct mfi_softc *)arg;
+
+       if (sc->mfi_check_clear_intr(sc) == 1) {
+               return;
+       }
+       if (sc->mfi_detaching)
+               return;
+       lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+       mfi_tbolt_complete_cmd(sc);
+       if (sc->mfi_flags & MFI_FLAGS_QFRZN)
+               sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
+       mfi_startio(sc);
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+       return;
+}
+
+/**
+ * map_cmd_status -    Maps FW cmd status to OS cmd status
+ * @cmd :              Pointer to cmd
+ * @status :           status of cmd returned by FW
+ * @ext_status :       ext status of cmd returned by FW
+ */
+
+void
+map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
+    uint8_t ext_status)
+{
+
+       switch (status) {
+
+               case MFI_STAT_OK:
+                       mfi_cmd->cm_frame->header.cmd_status = 0;
+                       mfi_cmd->cm_frame->dcmd.header.cmd_status = 0;
+                       break;
+
+               case MFI_STAT_SCSI_IO_FAILED:
+               case MFI_STAT_LD_INIT_IN_PROGRESS:
+                       mfi_cmd->cm_frame->header.cmd_status = status;
+                       mfi_cmd->cm_frame->header.scsi_status = ext_status;
+                       mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+                       mfi_cmd->cm_frame->dcmd.header.scsi_status
+                           = ext_status;
+                       break;
+
+               case MFI_STAT_SCSI_DONE_WITH_ERROR:
+                       mfi_cmd->cm_frame->header.cmd_status = ext_status;
+                       mfi_cmd->cm_frame->dcmd.header.cmd_status = ext_status;
+                       break;
+
+               case MFI_STAT_LD_OFFLINE:
+               case MFI_STAT_DEVICE_NOT_FOUND:
+                       mfi_cmd->cm_frame->header.cmd_status = status;
+                       mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+                       break;
+
+               default:
+                       mfi_cmd->cm_frame->header.cmd_status = status;
+                       mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+                       break;
+               }
+}
+
+/**
+ * mfi_tbolt_return_cmd -      Return a cmd to free command pool
+ * @instance:          Adapter soft state
+ * @cmd:               Command packet to be returned to free command pool
+ */
+static inline void
+mfi_tbolt_return_cmd(struct mfi_softc *sc, struct mfi_cmd_tbolt *cmd)
+{
+       KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
+       TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
+}
+
+void mfi_tbolt_complete_cmd(struct mfi_softc *sc)
+{
+       struct mfi_mpi2_reply_header *desc, *reply_desc;
+       struct mfi_command *cmd_mfi;    /* For MFA Cmds */
+       struct mfi_cmd_tbolt *cmd_tbolt;
+       uint16_t smid;
+       uint8_t reply_descript_type;
+       struct mfi_mpi2_request_raid_scsi_io  *scsi_io_req;
+       uint32_t status, extStatus;
+       uint16_t num_completed;
+       union desc_value val;
+
+       desc = (struct mfi_mpi2_reply_header *)
+               ((uintptr_t)sc->reply_frame_pool_align
+               + sc->last_reply_idx * sc->reply_size);
+       reply_desc = desc;
+
+       if (!reply_desc)
+               device_printf(sc->mfi_dev, "reply desc is NULL!!\n");
+
+       reply_descript_type = reply_desc->ReplyFlags
+            & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+       if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+               return;
+
+       num_completed = 0;
+       val.word = ((union mfi_mpi2_reply_descriptor *)desc)->words;
+
+       /* Read Reply descriptor */
+       while ((val.u.low != 0xFFFFFFFF) && (val.u.high != 0xFFFFFFFF)) {
+
+               smid = reply_desc->SMID;
+               if (!smid || smid > sc->mfi_max_fw_cmds + 1) {
+                       device_printf(sc->mfi_dev, "smid is %x. Cannot "
+                           "proceed. Returning \n", smid);
+                       return;
+               }
+
+               cmd_tbolt = sc->mfi_cmd_pool_tbolt[smid - 1];
+               cmd_mfi = &sc->mfi_commands[cmd_tbolt->sync_cmd_idx];
+               scsi_io_req = cmd_tbolt->io_request;
+
+               /* Check if internal commands */
+               status = cmd_mfi->cm_frame->dcmd.header.cmd_status;
+               extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
+
+               switch (scsi_io_req->Function) {
+               case MPI2_FUNCTION_LD_IO_REQUEST:
+                       /* Regular Path IO. */
+                       /* Map the Fw Error Status. */
+                       map_tbolt_cmd_status(cmd_mfi, status,
+                           extStatus);
+                       if ((cmd_mfi->cm_frame->dcmd.opcode
+                           == MFI_DCMD_LD_MAP_GET_INFO)
+                           && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
+                                       if (cmd_mfi->cm_frame->header.cmd_status
+                                           != 0)
+                                               device_printf(sc->mfi_dev,
+                                                   "map sync failed\n");
+                                       else {
+                                               sc->map_id++;
+                                               device_printf(sc->mfi_dev,
+                                                   "map sync completed\n");
+                                               mfi_release_command(cmd_mfi);
+                                       }
+                               }
+                       if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
+                           == MFI_ON_MFIQ_BUSY
+                           && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
+                               /* BHARAT poll workaround */
+                               mfi_remove_busy(cmd_mfi);
+                               cmd_mfi->cm_error = 0;
+                               mfi_complete(sc, cmd_mfi);
+                       }
+                       mfi_tbolt_return_cmd(sc, cmd_tbolt);
+                       break;
+               case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:
+                       map_tbolt_cmd_status(cmd_mfi, status, extStatus);
+                       if ((cmd_mfi->cm_frame->dcmd.opcode
+                           == MFI_DCMD_LD_MAP_GET_INFO)
+                           && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
+                               if (cmd_mfi->cm_frame->header.cmd_status != 0)
+                                       device_printf(sc->mfi_dev,
+                                           "map sync failed\n");
+                               else {
+                                       sc->map_id++;
+                                       device_printf(sc->mfi_dev,
+                                           "map sync completed\n");
+                                       mfi_release_command(cmd_mfi);
+                               }
+                       }
+                       if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
+                           == MFI_ON_MFIQ_BUSY
+                           && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
+                               /* BHARAT poll workaround */
+                               mfi_remove_busy(cmd_mfi);
+                               cmd_mfi->cm_error = 0;
+                               mfi_complete(sc, cmd_mfi);
+                       }
+                       mfi_tbolt_return_cmd(sc, cmd_tbolt);
+                       break;
+               }
+
+               sc->last_reply_idx++;
+               if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
+                       MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
+                       sc->last_reply_idx = 0;
+               }
+               /*set it back to all 0xfff.*/
+               ((union mfi_mpi2_reply_descriptor*)desc)->words =
+                       ~((uint64_t)0x00);
+
+               num_completed++;
+
+               /* Get the next reply descriptor */
+               desc = (struct mfi_mpi2_reply_header *)
+                   ((uintptr_t)sc->reply_frame_pool_align
+                   + sc->last_reply_idx * sc->reply_size);
+               reply_desc = desc;
+               val.word = ((union mfi_mpi2_reply_descriptor*)desc)->words;
+               reply_descript_type = reply_desc->ReplyFlags
+                   & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+               if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+                       break;
+       }
+
+       if (!num_completed)
+               return;
+
+       /* update replyIndex to FW */
+       if (sc->last_reply_idx)
+               MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
+
+       return;
+}
+
+/**
+ * mfi_get_cmd -       Get a command from the free pool
+ * @instance:          Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+
+struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc
+                                                 *sc)
+{
+       struct mfi_cmd_tbolt *cmd = NULL;
+
+       KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
+       cmd = TAILQ_FIRST(&sc->mfi_cmd_tbolt_tqh);
+       TAILQ_REMOVE(&sc->mfi_cmd_tbolt_tqh, cmd, next);
+       memset((uint8_t *)cmd->sg_frame, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
+       memset((uint8_t *)cmd->io_request, 0,
+           MEGASAS_THUNDERBOLT_NEW_MSG_SIZE);
+       return cmd;
+}
+
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index)
+{
+       uint8_t *p;
+
+       if (index >= sc->mfi_max_fw_cmds) {
+               device_printf(sc->mfi_dev, "Invalid SMID (0x%x)request "
+                   "for descriptor\n", index);
+               return NULL;
+       }
+       p = sc->request_desc_pool + sizeof(union mfi_mpi2_request_descriptor)
+           * index;
+       memset(p, 0, sizeof(union mfi_mpi2_request_descriptor));
+       return (union mfi_mpi2_request_descriptor *)p;
+}
+
+
+/* Used to build IOCTL cmd */
+uint8_t
+mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
+{
+       MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
+       struct mfi_mpi2_request_raid_scsi_io *io_req;
+       struct mfi_cmd_tbolt *cmd;
+
+       cmd = mfi_tbolt_get_cmd(sc);
+       if (!cmd)
+               return EBUSY;
+       mfi_cmd->cm_extra_frames = cmd->index; /* Frame count used as SMID */
+       cmd->sync_cmd_idx = mfi_cmd->cm_index;
+       io_req = cmd->io_request;
+       mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
+
+       io_req->Function = MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
+       io_req->SGLOffset0 = offsetof(struct mfi_mpi2_request_raid_scsi_io,
+           SGL) / 4;
+       io_req->ChainOffset = sc->chain_offset_value_for_mpt_ptmsg;
+
+       mpi25_ieee_chain->Address = mfi_cmd->cm_frame_busaddr;
+
+       /*
+         In MFI pass thru, nextChainOffset will always be zero to
+         indicate the end of the chain.
+       */
+       mpi25_ieee_chain->Flags= MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT
+               | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
+
+       /* setting the length to the maximum length */
+       mpi25_ieee_chain->Length = 1024;
+
+       return 0;
+}
+
+void
+mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd)
+{
+       uint32_t start_lba_lo = 0, start_lba_hi = 0, device_id;
+       struct mfi_mpi2_request_raid_scsi_io    *io_request;
+       struct IO_REQUEST_INFO io_info;
+
+       device_id = mfi_cmd->cm_frame->io.header.target_id;
+       io_request = cmd->io_request;
+       io_request->RaidContext.TargetID = device_id;
+       io_request->RaidContext.Status = 0;
+       io_request->RaidContext.exStatus =0;
+
+       start_lba_lo = mfi_cmd->cm_frame->io.lba_lo;
+       start_lba_hi = mfi_cmd->cm_frame->io.lba_hi;
+
+       memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
+       io_info.ldStartBlock = ((uint64_t)start_lba_hi << 32) | start_lba_lo;
+       io_info.numBlocks = mfi_cmd->cm_frame->io.header.data_len;
+       io_info.ldTgtId = device_id;
+       if ((mfi_cmd->cm_frame->header.flags & MFI_FRAME_DIR_READ) ==
+           MFI_FRAME_DIR_READ)
+               io_info.isRead = 1;
+
+               io_request->RaidContext.timeoutValue
+                    = MFI_FUSION_FP_DEFAULT_TIMEOUT;
+               io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST;
+               io_request->DevHandle = device_id;
+               cmd->request_desc->header.RequestFlags
+                   = (MFI_REQ_DESCRIPT_FLAGS_LD_IO
+                   << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+       if ((io_request->IoFlags == 6) && (io_info.numBlocks == 0))
+               io_request->RaidContext.RegLockLength = 0x100;
+       io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len
+           * MFI_SECTOR_LEN;
+}
+
+int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
+{
+       if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
+           || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+               return 1;
+       else
+               return 0;
+}
+
+int
+mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd)
+{
+       uint32_t device_id;
+       uint32_t sge_count;
+       uint8_t cdb[32], cdb_len;
+
+       memset(cdb, 0, 32);
+       struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request;
+
+       device_id = mfi_cmd->cm_frame->header.target_id;
+
+       /* Have to build CDB here for TB as BSD don't have a scsi layer */
+       if ((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1)
+               return 1;
+
+       /* Just the CDB length,rest of the Flags are zero */
+       io_request->IoFlags = cdb_len;
+       memcpy(io_request->CDB.CDB32, cdb, 32);
+
+       if (mfi_tbolt_is_ldio(mfi_cmd))
+               mfi_tbolt_build_ldio(sc, mfi_cmd , cmd);
+       else
+               return 1;
+
+       /*
+        * Construct SGL
+        */
+       sge_count = mfi_tbolt_make_sgl(sc, mfi_cmd,
+           (pMpi25IeeeSgeChain64_t) &io_request->SGL, cmd);
+       if (sge_count > sc->mfi_max_sge) {
+               device_printf(sc->mfi_dev, "Error. sge_count (0x%x) exceeds "
+                   "max (0x%x) allowed\n", sge_count, sc->mfi_max_sge);
+               return 1;
+       }
+       io_request->RaidContext.numSGE = sge_count;
+       io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+
+       if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+               io_request->Control = MPI2_SCSIIO_CONTROL_WRITE;
+       else
+               io_request->Control = MPI2_SCSIIO_CONTROL_READ;
+
+       io_request->SGLOffset0 = offsetof(
+           struct mfi_mpi2_request_raid_scsi_io, SGL)/4;
+
+       io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr;
+       io_request->SenseBufferLength = MFI_SENSE_LEN;
+       return 0;
+}
+
+static int
+mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    uint8_t *cdb)
+{
+       uint32_t lba_lo, lba_hi, num_lba;
+       uint8_t cdb_len;
+
+       if (mfi_cmd == NULL || cdb == NULL)
+               return 1;
+       num_lba = mfi_cmd->cm_frame->io.header.data_len;
+       lba_lo = mfi_cmd->cm_frame->io.lba_lo;
+       lba_hi = mfi_cmd->cm_frame->io.lba_hi;
+
+       if ((num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) {
+               if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+                       /* Read 6 or Write 6 */
+                       cdb[0] = (uint8_t) (0x0A);
+               else
+                       cdb[0] = (uint8_t) (0x08);
+
+               cdb[4] = (uint8_t) num_lba;
+               cdb[3] = (uint8_t) (lba_lo & 0xFF);
+               cdb[2] = (uint8_t) (lba_lo >> 8);
+               cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F);
+               cdb_len = 6;
+       } else if ((num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) {
+               if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+                       /* Read 10 or Write 10 */
+                       cdb[0] = (uint8_t) (0x2A);
+               else
+                       cdb[0] = (uint8_t) (0x28);
+               cdb[8] = (uint8_t) (num_lba & 0xFF);
+               cdb[7] = (uint8_t) (num_lba >> 8);
+               cdb[5] = (uint8_t) (lba_lo & 0xFF);
+               cdb[4] = (uint8_t) (lba_lo >> 8);
+               cdb[3] = (uint8_t) (lba_lo >> 16);
+               cdb[2] = (uint8_t) (lba_lo >> 24);
+               cdb_len = 10;
+       } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) {
+               if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+                       /* Read 12 or Write 12 */
+                       cdb[0] = (uint8_t) (0xAA);
+               else
+                       cdb[0] = (uint8_t) (0xA8);
+               cdb[9] = (uint8_t) (num_lba & 0xFF);
+               cdb[8] = (uint8_t) (num_lba >> 8);
+               cdb[7] = (uint8_t) (num_lba >> 16);
+               cdb[6] = (uint8_t) (num_lba >> 24);
+               cdb[5] = (uint8_t) (lba_lo & 0xFF);
+               cdb[4] = (uint8_t) (lba_lo >> 8);
+               cdb[3] = (uint8_t) (lba_lo >> 16);
+               cdb[2] = (uint8_t) (lba_lo >> 24);
+               cdb_len = 12;
+       } else {
+               if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+                       cdb[0] = (uint8_t) (0x8A);
+               else
+                       cdb[0] = (uint8_t) (0x88);
+               cdb[13] = (uint8_t) (num_lba & 0xFF);
+               cdb[12] = (uint8_t) (num_lba >> 8);
+               cdb[11] = (uint8_t) (num_lba >> 16);
+               cdb[10] = (uint8_t) (num_lba >> 24);
+               cdb[9] = (uint8_t) (lba_lo & 0xFF);
+               cdb[8] = (uint8_t) (lba_lo >> 8);
+               cdb[7] = (uint8_t) (lba_lo >> 16);
+               cdb[6] = (uint8_t) (lba_lo >> 24);
+               cdb[5] = (uint8_t) (lba_hi & 0xFF);
+               cdb[4] = (uint8_t) (lba_hi >> 8);
+               cdb[3] = (uint8_t) (lba_hi >> 16);
+               cdb[2] = (uint8_t) (lba_hi >> 24);
+               cdb_len = 16;
+       }
+       return cdb_len;
+}
+
+static int
+mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+                  pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd)
+{
+       uint8_t i, sg_processed, sg_to_process;
+       uint8_t sge_count, sge_idx;
+       union mfi_sgl *os_sgl;
+
+       /*
+        * Return 0 if there is no data transfer
+        */
+       if (!mfi_cmd->cm_sg || !mfi_cmd->cm_len) {
+               device_printf(sc->mfi_dev, "Buffer empty \n");
+               return 0;
+       }
+       os_sgl = mfi_cmd->cm_sg;
+       sge_count = mfi_cmd->cm_frame->header.sg_count;
+
+       if (sge_count > sc->mfi_max_sge) {
+               device_printf(sc->mfi_dev, "sgl ptr %p sg_cnt %d \n",
+                   os_sgl, sge_count);
+               return sge_count;
+       }
+
+       if (sge_count > sc->max_SGEs_in_main_message)
+               /* One element to store the chain info */
+               sge_idx = sc->max_SGEs_in_main_message - 1;
+       else
+               sge_idx = sge_count;
+
+       for (i = 0; i < sge_idx; i++) {
+               /*
+                * For 32bit BSD we are getting 32 bit SGL's from OS
+                * but FW only take 64 bit SGL's so copying from 32 bit
+                * SGL's to 64.
+                */
+               if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+                       sgl_ptr->Length = os_sgl->sg_skinny[i].len;
+                       sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
+               } else {
+                       sgl_ptr->Length = os_sgl->sg32[i].len;
+                       sgl_ptr->Address = os_sgl->sg32[i].addr;
+               }
+               sgl_ptr->Flags = 0;
+               sgl_ptr++;
+               cmd->io_request->ChainOffset = 0;
+       }
+
+       sg_processed = i;
+
+       if (sg_processed < sge_count) {
+               pMpi25IeeeSgeChain64_t sg_chain;
+               sg_to_process = sge_count - sg_processed;
+               cmd->io_request->ChainOffset =
+                   sc->chain_offset_value_for_main_message;
+               sg_chain = sgl_ptr;
+               /* Prepare chain element */
+               sg_chain->NextChainOffset = 0;
+               sg_chain->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+                   MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+               sg_chain->Length =  (sizeof(MPI2_SGE_IO_UNION) *
+                   (sge_count - sg_processed));
+               sg_chain->Address = cmd->sg_frame_phys_addr;
+               sgl_ptr = (pMpi25IeeeSgeChain64_t)cmd->sg_frame;
+               for (; i < sge_count; i++) {
+                       if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+                               sgl_ptr->Length = os_sgl->sg_skinny[i].len;
+                               sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
+                       } else {
+                               sgl_ptr->Length = os_sgl->sg32[i].len;
+                               sgl_ptr->Address = os_sgl->sg32[i].addr;
+                       }
+                       sgl_ptr->Flags = 0;
+                       sgl_ptr++;
+               }
+       }
+       return sge_count;
+}
+
+union mfi_mpi2_request_descriptor *
+mfi_build_and_issue_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
+{
+       struct mfi_cmd_tbolt *cmd;
+       union mfi_mpi2_request_descriptor *req_desc = NULL;
+       uint16_t index;
+       cmd = mfi_tbolt_get_cmd(sc);
+       if (!cmd)
+               return NULL;
+       mfi_cmd->cm_extra_frames = cmd->index;
+       cmd->sync_cmd_idx = mfi_cmd->cm_index;
+
+       index = cmd->index;
+       req_desc = mfi_tbolt_get_request_descriptor(sc, index-1);
+       if (mfi_tbolt_build_io(sc, mfi_cmd, cmd))
+               return NULL;
+       req_desc->header.SMID = index;
+       return req_desc;
+}
+
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_build_mpt_cmd(struct mfi_softc *sc, struct mfi_command *cmd)
+{
+       union mfi_mpi2_request_descriptor *req_desc = NULL;
+       uint16_t index;
+       if (mfi_build_mpt_pass_thru(sc, cmd)) {
+               device_printf(sc->mfi_dev, "Couldn't build MFI pass thru "
+                   "cmd\n");
+               return NULL;
+       }
+       /* For fusion the frame_count variable is used for SMID */
+       index = cmd->cm_extra_frames;
+
+       req_desc = mfi_tbolt_get_request_descriptor(sc, index - 1);
+       if (!req_desc)
+               return NULL;
+
+       bzero(req_desc, sizeof(req_desc));
+       req_desc->header.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+           MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+       req_desc->header.SMID = index;
+       return req_desc;
+}
+
+int
+mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
+{
+       struct mfi_frame_header *hdr;
+       uint8_t *cdb;
+       union mfi_mpi2_request_descriptor *req_desc = NULL;
+       int tm = MFI_POLL_TIMEOUT_SECS * 1000;
+
+       hdr = &cm->cm_frame->header;
+       cdb = cm->cm_frame->pass.cdb;
+       if (sc->adpreset)
+               return 1;
+       if ((cm->cm_flags & MFI_CMD_POLLED) == 0) {
+               cm->cm_timestamp = time_second;
+               mfi_enqueue_busy(cm);
+       }
+       else {
+               hdr->cmd_status = 0xff;
+               hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+       }
+
+       if (hdr->cmd == MFI_CMD_PD_SCSI_IO) {
+               /* check for inquiry commands coming from CLI */
+               if (cdb[0] != 0x28 || cdb[0] != 0x2A) {
+                       if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) ==
+                           NULL) {
+                               device_printf(sc->mfi_dev, "Mapping from MFI "
+                                   "to MPT Failed \n");
+                               return 1;
+                       }
+               }
+               else
+                       device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n");
+       }
+       else if (hdr->cmd == MFI_CMD_LD_SCSI_IO ||
+           hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) {
+               if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) {
+                       device_printf(sc->mfi_dev, "LDIO Failed \n");
+                       return 1;
+               }
+       } else
+               if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
+                       device_printf(sc->mfi_dev, "Mapping from MFI to MPT "
+                           "Failed\n");
+                       return 1;
+               }
+       MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF));
+       MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20));
+
+       if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
+               return 0;
+
+       /* This is a polled command, so busy-wait for it to complete. */
+       while (hdr->cmd_status == 0xff) {
+               DELAY(1000);
+               tm -= 1;
+               if (tm <= 0)
+                       break;
+       }
+
+       if (hdr->cmd_status == 0xff) {
+               device_printf(sc->mfi_dev, "Frame %p timed out "
+                     "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
+               return (ETIMEDOUT);
+       }
+       return 0;
+}
+
+static void mfi_issue_pending_cmds_again (struct mfi_softc *sc)
+{
+       struct mfi_command *cm, *tmp;
+
+       KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+       TAILQ_FOREACH_REVERSE_MUTABLE(cm, &sc->mfi_busy, BUSYQ, cm_link, tmp) {
+
+               cm->retry_for_fw_reset++;
+
+               /*
+                * If a command has continuously been tried multiple times
+                * and causing a FW reset condition, no further recoveries
+                * should be performed on the controller
+                */
+               if (cm->retry_for_fw_reset == 3) {
+                       device_printf(sc->mfi_dev, "megaraid_sas: command %d "
+                           "was tried multiple times during adapter reset"
+                           "Shutting down the HBA\n", cm->cm_index);
+                       mfi_kill_hba(sc);
+                       sc->hw_crit_error = 1;
+                       return;
+               }
+
+               if ((cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0) {
+                       struct mfi_cmd_tbolt *cmd;
+                       mfi_remove_busy(cm);
+                       cmd = sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames -
+                           1 ];
+                       mfi_tbolt_return_cmd(sc, cmd);
+                       if ((cm->cm_flags & MFI_ON_MFIQ_MASK) == 0) {
+                               if (cm->cm_frame->dcmd.opcode !=
+                                   MFI_DCMD_CTRL_EVENT_WAIT) {
+                                       device_printf(sc->mfi_dev,
+                                           "APJ ****requeue command %d \n",
+                                           cm->cm_index);
+                                       mfi_requeue_ready(cm);
+                               }
+                       }
+                       else
+                               mfi_release_command(cm);
+               }
+       }
+       mfi_startio(sc);
+}
+
+static void mfi_kill_hba (struct mfi_softc *sc)
+{
+       if (sc->mfi_flags & MFI_FLAGS_TBOLT)
+               MFI_WRITE4 (sc, 0x00,MFI_STOP_ADP);
+       else
+               MFI_WRITE4 (sc, MFI_IDB,MFI_STOP_ADP);
+}
+
+static void mfi_process_fw_state_chg_isr(void *arg)
+{
+       struct mfi_softc *sc= (struct mfi_softc *)arg;
+       struct mfi_cmd_tbolt *cmd;
+       int error, status;
+
+       if (sc->adpreset == 1) {
+               device_printf(sc->mfi_dev, "First stage of FW reset "
+                    "initiated...\n");
+
+               sc->mfi_adp_reset(sc);
+               sc->mfi_enable_intr(sc);
+
+               device_printf(sc->mfi_dev, "First stage of reset complete, "
+                   "second stage initiated...\n");
+
+               sc->adpreset = 2;
+
+               /* waiting for about 20 second before start the second init */
+               for (int wait = 0; wait < 20000; wait++)
+                       DELAY(1000);
+               device_printf(sc->mfi_dev, "Second stage of FW reset "
+                    "initiated...\n");
+               while ((status = MFI_READ4(sc, MFI_RSR)) & 0x04);
+
+               sc->mfi_disable_intr(sc);
+
+               /* We expect the FW state to be READY */
+               if (mfi_transition_firmware(sc)) {
+                       device_printf(sc->mfi_dev, "controller is not in "
+                           "ready state\n");
+                       mfi_kill_hba(sc);
+                       sc->hw_crit_error= 1;
+                       return ;
+               }
+               if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
+                               return;
+
+               lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+
+               sc->mfi_enable_intr(sc);
+               sc->adpreset = 0;
+               kfree(sc->mfi_aen_cm->cm_data, M_MFIBUF);
+               mfi_remove_busy(sc->mfi_aen_cm);
+               cmd = sc->mfi_cmd_pool_tbolt[sc->mfi_aen_cm->cm_extra_frames
+                   - 1];
+               mfi_tbolt_return_cmd(sc, cmd);
+               if (sc->mfi_aen_cm) {
+                       mfi_release_command(sc->mfi_aen_cm);
+                       sc->mfi_aen_cm = NULL;
+               }
+               if (sc->map_update_cmd) {
+                       mfi_release_command(sc->map_update_cmd);
+                       sc->map_update_cmd = NULL;
+               }
+               mfi_issue_pending_cmds_again(sc);
+
+               /*
+                * Issue pending command can result in adapter being marked
+                * dead because of too many re-tries. Check for that
+                * condition before clearing the reset condition on the FW
+                */
+               if (!sc->hw_crit_error) {
+                       /*
+                        * Initiate AEN (Asynchronous Event Notification)
+                        */
+                       mfi_aen_setup(sc, sc->last_seq_num);
+                       sc->issuepend_done = 1;
+                       device_printf(sc->mfi_dev, "second stage of reset "
+                           "complete, FW is ready now.\n");
+               } else {
+                       device_printf(sc->mfi_dev, "second stage of reset "
+                            "never completed, hba was marked offline.\n");
+               }
+       } else {
+               device_printf(sc->mfi_dev, "mfi_process_fw_state_chg_isr "
+                   "called with unhandled value:%d\n", sc->adpreset);
+       }
+       lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+}
index d64af71..c331497 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfireg.h,v 1.16 2011/07/14 20:20:33 jhb Exp $
+ * FreeBSD projects/head_mfi/ r232888
  */
 
 #ifndef _MFIREG_H
@@ -94,6 +65,8 @@
  * seems to also call this interface 'MFI', so that will be used here.
  */
 
+#define MEGAMFI_FRAME_SIZE              64
+
 /*
  * Start with the register set.  All registers are 32 bits wide.
  * The usual Intel IOP style setup.
 #define MFI_OQP                0x44    /* Outbound queue port */
 
 /*
+ * ThunderBolt specific Register
+ */
+
+#define MFI_RPI                0x6c            /* reply_post_host_index */
+#define MFI_ILQP       0xc0            /* inbound_low_queue_port */
+#define MFI_IHQP       0xc4            /* inbound_high_queue_port */
+
+/*
  * 1078 specific related register
  */
 #define MFI_ODR0       0x9c            /* outbound doorbell register0 */
 #define MFI_1078_RM    0x80000000      /* reply 1078 message interrupt  */
 #define MFI_ODC                0x4             /* outbound doorbell change interrupt */
 
+/* OCR registers */
+#define MFI_WSR                0x004           /* write sequence register */
+#define MFI_HDR                0x008           /* host diagnostic register */
+#define MFI_RSR                0x3c3           /* Reset Status Register */
+
 /*
  * GEN2 specific changes
  */
 #define MFI_GEN2_RM    0x00000001      /* reply GEN2 message interrupt */
 
 /*
- * gen2 specific changes
- */
-#define MFI_GEN2_EIM   0x00000005      /* gen2 enable interrupt mask */
-#define MFI_GEN2_RM    0x00000001      /* reply gen2 message interrupt */
-
-/*
  * skinny specific changes
  */
 #define MFI_SKINNY_IDB 0x00    /* Inbound doorbell is at 0x00 for skinny */
 /* Bits for MFI_OSTS */
 #define MFI_OSTS_INTR_VALID    0x00000002
 
+/* OCR specific flags */
+#define MFI_FIRMWARE_STATE_CHANGE      0x00000002
+#define MFI_STATE_CHANGE_INTERRUPT     0x00000004  /* MFI state change interrrupt */
+
 /*
  * Firmware state values.  Found in OMSG0 during initialization.
  */
 #define MFI_FWSTATE_MAXCMD_MASK                0x0000ffff
 #define MFI_FWSTATE_HOSTMEMREQD_MASK   0x08000000
 #define MFI_FWSTATE_BOOT_MESSAGE_PENDING       0x90000000
+#define MFI_RESET_REQUIRED             0x00000001
+
+/* ThunderBolt Support */
+#define MFI_FWSTATE_TB_MASK            0xf0000000
+#define MFI_FWSTATE_TB_RESET           0x00000000
+#define MFI_FWSTATE_TB_READY           0x10000000
+#define MFI_FWSTATE_TB_OPERATIONAL     0x20000000
+#define MFI_FWSTATE_TB_FAULT           0x40000000
 
 /*
  * Control bits to drive the card to ready state.  These go into the IDB
 #define MFI_FWINIT_CLEAR_HANDSHAKE 0x00000008 /* Respond to WAIT_HANDSHAKE */
 #define MFI_FWINIT_HOTPLUG     0x00000010
 
+/* ADP reset flags */
+#define MFI_STOP_ADP           0x00000020
+#define MFI_ADP_RESET          0x00000040
+#define DIAG_WRITE_ENABLE      0x00000080
+#define DIAG_RESET_ADAPTER     0x00000004
+
 /* MFI Commands */
 typedef enum {
        MFI_CMD_INIT =          0x00,
@@ -220,6 +218,8 @@ typedef enum {
        MFI_DCMD_PD_GET_PROGRESS =      0x02060000,
        MFI_DCMD_PD_LOCATE_START =      0x02070100,
        MFI_DCMD_PD_LOCATE_STOP =       0x02070200,
+       MFI_DCMD_LD_MAP_GET_INFO =      0x0300e101,
+       MFI_DCMD_LD_SYNC =              0x0300e102,
        MFI_DCMD_LD_GET_LIST =          0x03010000,
        MFI_DCMD_LD_GET_INFO =          0x03020000,
        MFI_DCMD_LD_GET_PROP =          0x03030000,
@@ -262,6 +262,35 @@ typedef enum {
 #define MFI_FRAME_DIR_BOTH                     0x0018
 #define MFI_FRAME_IEEE_SGL                     0x0020
 
+/* ThunderBolt Specific */
+
+/*
+ * Pre-TB command size and TB command size.
+ * We will be checking it at the load time for the time being
+ */
+#define MR_COMMAND_SIZE (MFI_FRAME_SIZE*20) /* 1280 bytes */
+
+#define MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT  256
+/*
+ * We are defining only 128 byte message to reduce memory move over head
+ * and also it will reduce the SRB extension size by 128byte compared with
+ * 256 message size
+ */
+#define MEGASAS_THUNDERBOLT_NEW_MSG_SIZE       256
+#define MEGASAS_THUNDERBOLT_MAX_COMMANDS       1024
+#define MEGASAS_THUNDERBOLT_MAX_REPLY_COUNT    1024
+#define MEGASAS_THUNDERBOLT_REPLY_SIZE         8
+#define MEGASAS_THUNDERBOLT_MAX_CHAIN_COUNT    1
+#define MEGASAS_MAX_SZ_CHAIN_FRAME             1024
+
+#define MPI2_FUNCTION_PASSTHRU_IO_REQUEST       0xF0
+#define MPI2_FUNCTION_LD_IO_REQUEST             0xF1
+
+#define MR_INTERNAL_MFI_FRAMES_SMID             1
+#define MR_CTRL_EVENT_WAIT_SMID                 2
+#define MR_INTERNAL_DRIVER_RESET_SMID           3
+
+
 /* MFI Status codes */
 typedef enum {
        MFI_STAT_OK =                   0x00,
@@ -373,6 +402,10 @@ typedef enum {
        MR_EVT_ARGS_ECC
 } mfi_evt_args;
 
+#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED    0x0152
+#define MR_EVT_PD_REMOVED                      0x0070
+#define MR_EVT_PD_INSERTED                     0x005b
+
 typedef enum {
        MR_LD_CACHE_WRITE_BACK =        0x01,
        MR_LD_CACHE_WRITE_ADAPTIVE =    0x02,
@@ -406,7 +439,7 @@ typedef enum {
        MR_PD_QUERY_TYPE_POWER_STATE =  2,
        MR_PD_QUERY_TYPE_MEDIA_TYPE =   3,
        MR_PD_QUERY_TYPE_SPEED =        4,
-       MR_PD_QUERY_TYPE_EXPOSED_TO_HOST =      5, /*query for system drives */
+       MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5 /*query for system drives */
 } mfi_pd_query_type;
 
 /*
@@ -448,9 +481,9 @@ struct mfi_sg_skinny {
 } __packed;
 
 union mfi_sgl {
-       struct mfi_sg32 sg32[1];
-       struct mfi_sg64 sg64[1];
-       struct mfi_sg_skinny sg_skinny[1];
+       struct mfi_sg32         sg32[1];
+       struct mfi_sg64         sg64[1];
+       struct mfi_sg_skinny    sg_skinny[1];
 } __packed;
 
 /* Message frames.  All messages have a common header */
@@ -466,7 +499,7 @@ struct mfi_frame_header {
        uint32_t        context;
        /*
         * pad0 is MSI Specific. Not used by Driver. Zero the value before
-        * sending the command to f/w
+        * sending the command to f/w.
         */
        uint32_t        pad0;
        uint16_t        flags;
@@ -482,9 +515,29 @@ struct mfi_init_frame {
        uint32_t        qinfo_new_addr_hi;
        uint32_t        qinfo_old_addr_lo;
        uint32_t        qinfo_old_addr_hi;
-       uint32_t        reserved[6];
+       // Start LSIP200113393
+       uint32_t        driver_ver_lo;      /*28h */
+       uint32_t        driver_ver_hi;      /*2Ch */
+
+       uint32_t        reserved[4];
+       // End LSIP200113393
 } __packed;
 
+/*
+ * Define MFI Address Context union.
+ */
+#ifdef MFI_ADDRESS_IS_uint64_t
+    typedef uint64_t     MFI_ADDRESS;
+#else
+    typedef union _MFI_ADDRESS {
+        struct {
+            uint32_t     addressLow;
+            uint32_t     addressHigh;
+        } u;
+        uint64_t     address;
+    } MFI_ADDRESS, *PMFI_ADDRESS;
+#endif
+
 #define MFI_IO_FRAME_SIZE 40
 struct mfi_io_frame {
        struct mfi_frame_header header;
@@ -515,6 +568,7 @@ struct mfi_dcmd_frame {
 struct mfi_abort_frame {
        struct mfi_frame_header header;
        uint32_t        abort_context;
+       /* pad is changed to reserved.*/
        uint32_t        reserved0;
        uint32_t        abort_mfi_addr_lo;
        uint32_t        abort_mfi_addr_hi;
@@ -543,6 +597,7 @@ struct mfi_stp_frame {
 union mfi_frame {
        struct mfi_frame_header header;
        struct mfi_init_frame   init;
+       /* ThunderBolt Initialization */
        struct mfi_io_frame     io;
        struct mfi_pass_frame   pass;
        struct mfi_dcmd_frame   dcmd;
@@ -592,7 +647,61 @@ struct mfi_ctrl_props {
        uint16_t        ecc_bucket_leak_rate;
        uint8_t         restore_hotspare_on_insertion;
        uint8_t         expose_encl_devices;
-       uint8_t         reserved[38];
+       uint8_t         maintainPdFailHistory;
+       uint8_t         disallowHostRequestReordering;
+       /* set TRUE to abort CC on detecting an inconsistency */
+       uint8_t         abortCCOnError;
+       /* load balance mode (MR_LOAD_BALANCE_MODE) */
+       uint8_t         loadBalanceMode;
+       /*
+        * 0 - use auto detect logic of backplanes like SGPIO, i2c SEP using
+        *     h/w mechansim like GPIO pins
+        * 1 - disable auto detect SGPIO,
+        * 2 - disable i2c SEP auto detect
+        * 3 - disable both auto detect
+        */
+       uint8_t         disableAutoDetectBackplane;
+       /*
+        * % of source LD to be reserved for a VDs snapshot in snapshot
+        * repository, for metadata and user data: 1=5%, 2=10%, 3=15% and so on
+        */
+       uint8_t         snapVDSpace;
+
+       /*
+        * Add properties that can be controlled by a bit in the following
+        * structure.
+        */
+       struct {
+               /* set TRUE to disable copyBack (0=copback enabled) */
+               uint32_t        copyBackDisabled                :1;
+               uint32_t        SMARTerEnabled                  :1;
+               uint32_t        prCorrectUnconfiguredAreas      :1;
+               uint32_t        useFdeOnly                      :1;
+               uint32_t        disableNCQ                      :1;
+               uint32_t        SSDSMARTerEnabled               :1;
+               uint32_t        SSDPatrolReadEnabled            :1;
+               uint32_t        enableSpinDownUnconfigured      :1;
+               uint32_t        autoEnhancedImport              :1;
+               uint32_t        enableSecretKeyControl          :1;
+               uint32_t        disableOnlineCtrlReset          :1;
+               uint32_t        allowBootWithPinnedCache        :1;
+               uint32_t        disableSpinDownHS               :1;
+               uint32_t        enableJBOD                      :1;
+               uint32_t        reserved                        :18;
+       } OnOffProperties;
+       /*
+        * % of source LD to be reserved for auto snapshot in snapshot
+        * repository, for metadata and user data: 1=5%, 2=10%, 3=15% and so on.
+        */
+       uint8_t         autoSnapVDSpace;
+       /*
+        * Snapshot writeable VIEWs capacity as a % of source LD capacity:
+        * 0=READ only, 1=5%, 2=10%, 3=15% and so on.
+        */
+       uint8_t         viewSpace;
+       /* # of idle minutes before device is spun down (0=use FW defaults) */
+       uint16_t        spinDownTime;
+       uint8_t         reserved[24];
 } __packed;
 
 /* PCI information about the card. */
@@ -1152,7 +1261,7 @@ struct mfi_ld_info {
        uint8_t                 reserved2[16];
 } __packed;
 
-#define MAX_ARRAYS 16
+#define MAX_ARRAYS 128
 struct mfi_spare {
        union mfi_pd_ref        ref;
        uint8_t                 spare_type;
@@ -1301,6 +1410,452 @@ struct mfi_pr_properties {
        uint32_t                clear_freq;
 };
 
+/* ThunderBolt support */
+
+/*
+ * Raid Context structure which describes MegaRAID specific IO Paramenters
+ * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames
+ */
+typedef struct _MPI2_SCSI_IO_VENDOR_UNIQUE {
+       uint16_t        resvd0;         /* 0x00 - 0x01 */
+       uint16_t        timeoutValue;   /* 0x02 - 0x03 */
+       uint8_t         regLockFlags;
+       uint8_t         armId;
+       uint16_t        TargetID;       /* 0x06 - 0x07 */
+
+       uint64_t        RegLockLBA;     /* 0x08 - 0x0F */
+
+       uint32_t        RegLockLength;  /* 0x10 - 0x13 */
+
+       uint16_t        SMID;           /* 0x14 - 0x15 nextLMId */
+       uint8_t         exStatus;       /* 0x16 */
+       uint8_t         Status;         /* 0x17 status */
+
+       uint8_t         RAIDFlags;      /* 0x18 */
+       uint8_t         numSGE;         /* 0x19 numSge */
+       uint16_t        configSeqNum;   /* 0x1A - 0x1B */
+       uint8_t         spanArm;        /* 0x1C */
+       uint8_t         resvd2[3];      /* 0x1D - 0x1F */
+} MPI2_SCSI_IO_VENDOR_UNIQUE, MPI25_SCSI_IO_VENDOR_UNIQUE;
+
+/*** DJA *****/
+
+/*****************************************************************************
+*
+*        Message Functions
+*
+*****************************************************************************/
+
+#define NA_MPI2_FUNCTION_SCSI_IO_REQUEST            (0x00) /* SCSI IO */
+#define MPI2_FUNCTION_SCSI_TASK_MGMT                (0x01) /* SCSI Task Management */
+#define MPI2_FUNCTION_IOC_INIT                      (0x02) /* IOC Init */
+#define MPI2_FUNCTION_IOC_FACTS                     (0x03) /* IOC Facts */
+#define MPI2_FUNCTION_CONFIG                        (0x04) /* Configuration */
+#define MPI2_FUNCTION_PORT_FACTS                    (0x05) /* Port Facts */
+#define MPI2_FUNCTION_PORT_ENABLE                   (0x06) /* Port Enable */
+#define MPI2_FUNCTION_EVENT_NOTIFICATION            (0x07) /* Event Notification */
+#define MPI2_FUNCTION_EVENT_ACK                     (0x08) /* Event Acknowledge */
+#define MPI2_FUNCTION_FW_DOWNLOAD                   (0x09) /* FW Download */
+#define MPI2_FUNCTION_TARGET_ASSIST                 (0x0B) /* Target Assist */
+#define MPI2_FUNCTION_TARGET_STATUS_SEND            (0x0C) /* Target Status Send */
+#define MPI2_FUNCTION_TARGET_MODE_ABORT             (0x0D) /* Target Mode Abort */
+#define MPI2_FUNCTION_FW_UPLOAD                     (0x12) /* FW Upload */
+#define MPI2_FUNCTION_RAID_ACTION                   (0x15) /* RAID Action */
+#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH      (0x16) /* SCSI IO RAID Passthrough */
+#define MPI2_FUNCTION_TOOLBOX                       (0x17) /* Toolbox */
+#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR      (0x18) /* SCSI Enclosure Processor */
+#define MPI2_FUNCTION_SMP_PASSTHROUGH               (0x1A) /* SMP Passthrough */
+#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL           (0x1B) /* SAS IO Unit Control */
+#define MPI2_FUNCTION_SATA_PASSTHROUGH              (0x1C) /* SATA Passthrough */
+#define MPI2_FUNCTION_DIAG_BUFFER_POST              (0x1D) /* Diagnostic Buffer Post */
+#define MPI2_FUNCTION_DIAG_RELEASE                  (0x1E) /* Diagnostic Release */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST      (0x24) /* Target Command Buffer Post Base */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST      (0x25) /* Target Command Buffer Post List */
+#define MPI2_FUNCTION_RAID_ACCELERATOR              (0x2C) /* RAID Accelerator */
+#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F) /* Host Based Discovery Action */
+#define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30) /* Power Management Control */
+#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0) /* beginning of product-specific range */
+#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC          (0xFF) /* end of product-specific range */
+
+/* Doorbell functions */
+#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET        (0x40)
+#define MPI2_FUNCTION_HANDSHAKE                     (0x42)
+
+/*****************************************************************************
+*
+*        MPI Version Definitions
+*
+*****************************************************************************/
+
+#define MPI2_VERSION_MAJOR                  (0x02)
+#define MPI2_VERSION_MINOR                  (0x00)
+#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT            (8)
+#define MPI2_VERSION_MINOR_MASK             (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT            (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) |   \
+                                      MPI2_VERSION_MINOR)
+
+#define MPI2_VERSION_02_00                  (0x0200)
+
+/* versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT            (0x10)
+#define MPI2_HEADER_VERSION_DEV             (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
+#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) |         \
+                                       MPI2_HEADER_VERSION_DEV)
+
+
+/* IOCInit Request message */
+struct MPI2_IOC_INIT_REQUEST {
+       uint8_t         WhoInit;                        /* 0x00 */
+       uint8_t         Reserved1;                      /* 0x01 */
+       uint8_t         ChainOffset;                    /* 0x02 */
+       uint8_t         Function;                       /* 0x03 */
+       uint16_t        Reserved2;                      /* 0x04 */
+       uint8_t         Reserved3;                      /* 0x06 */
+       uint8_t         MsgFlags;                       /* 0x07 */
+       uint8_t         VP_ID;                          /* 0x08 */
+       uint8_t         VF_ID;                          /* 0x09 */
+       uint16_t        Reserved4;                      /* 0x0A */
+       uint16_t        MsgVersion;                     /* 0x0C */
+       uint16_t        HeaderVersion;                  /* 0x0E */
+       uint32_t        Reserved5;                      /* 0x10 */
+       uint16_t        Reserved6;                      /* 0x14 */
+       uint8_t         Reserved7;                      /* 0x16 */
+       uint8_t         HostMSIxVectors;                /* 0x17 */
+       uint16_t        Reserved8;                      /* 0x18 */
+       uint16_t        SystemRequestFrameSize;         /* 0x1A */
+       uint16_t        ReplyDescriptorPostQueueDepth;  /* 0x1C */
+       uint16_t        ReplyFreeQueueDepth;            /* 0x1E */
+       uint32_t        SenseBufferAddressHigh;         /* 0x20 */
+       uint32_t        SystemReplyAddressHigh;         /* 0x24 */
+       uint64_t        SystemRequestFrameBaseAddress;  /* 0x28 */
+       uint64_t        ReplyDescriptorPostQueueAddress;/* 0x30 */
+       uint64_t        ReplyFreeQueueAddress;          /* 0x38 */
+       uint64_t        TimeStamp;                      /* 0x40 */
+};
+
+/* WhoInit values */
+#define MPI2_WHOINIT_NOT_INITIALIZED            (0x00)
+#define MPI2_WHOINIT_SYSTEM_BIOS                (0x01)
+#define MPI2_WHOINIT_ROM_BIOS                   (0x02)
+#define MPI2_WHOINIT_PCI_PEER                   (0x03)
+#define MPI2_WHOINIT_HOST_DRIVER                (0x04)
+#define MPI2_WHOINIT_MANUFACTURER               (0x05)
+
+struct MPI2_SGE_CHAIN_UNION {
+       uint16_t        Length;
+       uint8_t         NextChainOffset;
+       uint8_t         Flags;
+       union {
+               uint32_t        Address32;
+               uint64_t        Address64;
+       } u;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE32 {
+       uint32_t        Address;
+       uint32_t        FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE64 {
+       uint64_t        Address;
+       uint32_t        Length;
+       uint16_t        Reserved1;
+       uint8_t         Reserved2;
+       uint8_t         Flags;
+};
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION {
+       struct MPI2_IEEE_SGE_SIMPLE32   Simple32;
+       struct MPI2_IEEE_SGE_SIMPLE64   Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION {
+       uint32_t        FlagsLength;
+       union {
+               uint32_t        Address32;
+               uint64_t        Address64;
+       } u;
+} MPI2_SGE_SIMPLE_UNION;
+
+/****************************************************************************
+*  IEEE SGE field definitions and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK   (0x80)
+
+#define MPI2_IEEE32_SGE_FLAGS_SHIFT             (24)
+
+#define MPI2_IEEE32_SGE_LENGTH_MASK             (0x00FFFFFF)
+
+/* Element Type */
+
+#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT      (0x00)
+#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT       (0x80)
+
+/* Data Location Address Space */
+
+#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
+
+/* Address Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
+
+/*******************/
+/* SCSI IO Control bits */
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK      (0xFC000000)
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT     (26)
+
+#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK  (0x03000000)
+#define MPI2_SCSIIO_CONTROL_NODATATRANSFER      (0x00000000)
+#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
+#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL       (0x03000000)
+
+#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK        (0x00007800)
+#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT       (11)
+
+#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK  (0x00000700)
+#define MPI2_SCSIIO_CONTROL_SIMPLEQ             (0x00000000)
+#define MPI2_SCSIIO_CONTROL_HEADOFQ             (0x00000100)
+#define MPI2_SCSIIO_CONTROL_ORDEREDQ            (0x00000200)
+#define MPI2_SCSIIO_CONTROL_ACAQ                (0x00000400)
+
+#define MPI2_SCSIIO_CONTROL_TLR_MASK            (0x000000C0)
+#define MPI2_SCSIIO_CONTROL_NO_TLR              (0x00000000)
+#define MPI2_SCSIIO_CONTROL_TLR_ON              (0x00000040)
+#define MPI2_SCSIIO_CONTROL_TLR_OFF             (0x00000080)
+
+/*******************/
+
+typedef struct {
+       uint8_t         CDB[20];                    /* 0x00 */
+       uint32_t        PrimaryReferenceTag;        /* 0x14 */
+       uint16_t        PrimaryApplicationTag;      /* 0x18 */
+       uint16_t        PrimaryApplicationTagMask;  /* 0x1A */
+       uint32_t        TransferLength;             /* 0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32;
+
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
+       struct MPI2_IEEE_SGE_SIMPLE32   Chain32;
+       struct MPI2_IEEE_SGE_SIMPLE64   Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION;
+
+typedef union _MPI2_SIMPLE_SGE_UNION {
+       MPI2_SGE_SIMPLE_UNION           MpiSimple;
+       MPI2_IEEE_SGE_SIMPLE_UNION      IeeeSimple;
+} MPI2_SIMPLE_SGE_UNION;
+
+typedef union _MPI2_SGE_IO_UNION {
+       MPI2_SGE_SIMPLE_UNION           MpiSimple;
+       struct MPI2_SGE_CHAIN_UNION     MpiChain;
+       MPI2_IEEE_SGE_SIMPLE_UNION      IeeeSimple;
+       MPI2_IEEE_SGE_CHAIN_UNION       IeeeChain;
+} MPI2_SGE_IO_UNION;
+
+typedef union {
+       uint8_t                 CDB32[32];
+       MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+       MPI2_SGE_SIMPLE_UNION   SGE;
+} MPI2_SCSI_IO_CDB_UNION;
+
+
+/* MPI 2.5 SGLs */
+
+#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST        (0x40)
+
+typedef struct _MPI25_IEEE_SGE_CHAIN64 {
+       uint64_t        Address;
+       uint32_t        Length;
+       uint16_t        Reserved1;
+       uint8_t         NextChainOffset;
+       uint8_t         Flags;
+} MPI25_IEEE_SGE_CHAIN64, *pMpi25IeeeSgeChain64_t;
+
+/* use MPI2_IEEE_SGE_FLAGS_ defines for the Flags field */
+
+
+/********/
+
+/*
+ * RAID SCSI IO Request Message
+ * Total SGE count will be one less than  _MPI2_SCSI_IO_REQUEST
+ */
+struct mfi_mpi2_request_raid_scsi_io {
+       uint16_t                DevHandle;                      /* 0x00 */
+       uint8_t                 ChainOffset;                    /* 0x02 */
+       uint8_t                 Function;                       /* 0x03 */
+       uint16_t                Reserved1;                      /* 0x04 */
+       uint8_t                 Reserved2;                      /* 0x06 */
+       uint8_t                 MsgFlags;                       /* 0x07 */
+       uint8_t                 VP_ID;                          /* 0x08 */
+       uint8_t                 VF_ID;                          /* 0x09 */
+       uint16_t                Reserved3;                      /* 0x0A */
+       uint32_t                SenseBufferLowAddress;          /* 0x0C */
+       uint16_t                SGLFlags;                       /* 0x10 */
+       uint8_t                 SenseBufferLength;              /* 0x12 */
+       uint8_t                 Reserved4;                      /* 0x13 */
+       uint8_t                 SGLOffset0;                     /* 0x14 */
+       uint8_t                 SGLOffset1;                     /* 0x15 */
+       uint8_t                 SGLOffset2;                     /* 0x16 */
+       uint8_t                 SGLOffset3;                     /* 0x17 */
+       uint32_t                SkipCount;                      /* 0x18 */
+       uint32_t                DataLength;                     /* 0x1C */
+       uint32_t                BidirectionalDataLength;        /* 0x20 */
+       uint16_t                IoFlags;                        /* 0x24 */
+       uint16_t                EEDPFlags;                      /* 0x26 */
+       uint32_t                EEDPBlockSize;                  /* 0x28 */
+       uint32_t                SecondaryReferenceTag;          /* 0x2C */
+       uint16_t                SecondaryApplicationTag;        /* 0x30 */
+       uint16_t                ApplicationTagTranslationMask;  /* 0x32 */
+       uint8_t                 LUN[8];                         /* 0x34 */
+       uint32_t                Control;                        /* 0x3C */
+       MPI2_SCSI_IO_CDB_UNION  CDB;                            /* 0x40 */
+       MPI2_SCSI_IO_VENDOR_UNIQUE      RaidContext;              /* 0x60 */
+       MPI2_SGE_IO_UNION       SGL;                            /* 0x80 */
+} __packed;
+
+/*
+ * MPT RAID MFA IO Descriptor.
+ */
+typedef struct _MFI_RAID_MFA_IO_DESCRIPTOR {
+       uint32_t        RequestFlags : 8;
+       uint32_t        MessageAddress1 : 24; /* bits 31:8*/
+       uint32_t        MessageAddress2;      /* bits 61:32 */
+} MFI_RAID_MFA_IO_REQUEST_DESCRIPTOR,*PMFI_RAID_MFA_IO_REQUEST_DESCRIPTOR;
+
+struct mfi_mpi2_request_header {
+       uint8_t         RequestFlags;       /* 0x00 */
+       uint8_t         MSIxIndex;          /* 0x01 */
+       uint16_t        SMID;               /* 0x02 */
+       uint16_t        LMID;               /* 0x04 */
+};
+
+/* defines for the RequestFlags field */
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK               (0x0E)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET             (0x02)
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE            (0x08)
+#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR        (0x0A)
+
+#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
+
+struct mfi_mpi2_request_high_priority {
+       struct mfi_mpi2_request_header  header;
+       uint16_t                        reserved;
+};
+
+struct mfi_mpi2_request_scsi_io {
+       struct mfi_mpi2_request_header  header;
+       uint16_t                        scsi_io_dev_handle;
+};
+
+struct mfi_mpi2_request_scsi_target {
+       struct mfi_mpi2_request_header  header;
+       uint16_t                        scsi_target_io_index;
+};
+
+/* Request Descriptors */
+union mfi_mpi2_request_descriptor {
+       struct mfi_mpi2_request_header          header;
+       struct mfi_mpi2_request_high_priority   high_priority;
+       struct mfi_mpi2_request_scsi_io         scsi_io;
+       struct mfi_mpi2_request_scsi_target     scsi_target;
+       uint64_t                                words;
+};
+
+
+struct mfi_mpi2_reply_header {
+       uint8_t         ReplyFlags;                 /* 0x00 */
+       uint8_t         MSIxIndex;                  /* 0x01 */
+       uint16_t        SMID;                       /* 0x02 */
+};
+
+/* defines for the ReplyFlags field */
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK                   (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS             (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY               (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS        (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER       (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS    (0x05)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                      (0x0F)
+
+/* values for marking a reply descriptor as unused */
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK             (0xFFFFFFFF)
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK             (0xFFFFFFFF)
+
+struct mfi_mpi2_reply_default {
+       struct mfi_mpi2_reply_header    header;
+       uint32_t                        DescriptorTypeDependent2;
+};
+
+struct mfi_mpi2_reply_address {
+       struct mfi_mpi2_reply_header    header;
+       uint32_t                        ReplyFrameAddress;
+};
+
+struct mfi_mpi2_reply_scsi_io {
+       struct mfi_mpi2_reply_header    header;
+       uint16_t                        TaskTag;                /* 0x04 */
+       uint16_t                        Reserved1;              /* 0x06 */
+};
+
+struct mfi_mpi2_reply_target_assist {
+       struct mfi_mpi2_reply_header    header;
+       uint8_t                         SequenceNumber;         /* 0x04 */
+       uint8_t                         Reserved1;              /* 0x04 */
+       uint16_t                        IoIndex;                /* 0x06 */
+};
+
+struct mfi_mpi2_reply_target_cmd_buffer {
+       struct mfi_mpi2_reply_header    header;
+       uint8_t                         SequenceNumber;         /* 0x04 */
+       uint8_t                         Flags;                  /* 0x04 */
+       uint16_t                        InitiatorDevHandle;     /* 0x06 */
+       uint16_t                        IoIndex;                /* 0x06 */
+};
+
+struct mfi_mpi2_reply_raid_accel {
+       struct mfi_mpi2_reply_header    header;
+       uint8_t                         SequenceNumber;         /* 0x04 */
+       uint32_t                        Reserved;               /* 0x04 */
+};
+
+/* union of Reply Descriptors */
+union mfi_mpi2_reply_descriptor {
+       struct mfi_mpi2_reply_header            header;
+       struct mfi_mpi2_reply_scsi_io           scsi_io;
+       struct mfi_mpi2_reply_target_assist     target_assist;
+       struct mfi_mpi2_reply_target_cmd_buffer target_cmd;
+       struct mfi_mpi2_reply_raid_accel        raid_accel;
+       struct mfi_mpi2_reply_default           reply_default;
+       uint64_t                                words;
+};
+
+struct IO_REQUEST_INFO {
+       uint64_t        ldStartBlock;
+       uint32_t        numBlocks;
+       uint16_t        ldTgtId;
+       uint8_t         isRead;
+       uint16_t        devHandle;
+       uint64_t        pdBlock;
+       uint8_t         fpOkForIo;
+};
+
 #define MFI_SCSI_MAX_TARGETS   128
 #define MFI_SCSI_MAX_LUNS      8
 #define MFI_SCSI_INITIATOR_ID  255
index 56518a8..0de856b 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfivar.h,v 1.14 2011/09/29 08:37:53 mav Exp $
+ * FreeBSD projects/head_mfi/ r232949
  */
 
 #ifndef _MFIVAR_H
@@ -90,6 +61,7 @@
 #include <sys/eventhandler.h>
 #include <sys/lock.h>
 #include <sys/sysctl.h>
+#include <sys/taskqueue.h>
 
 /*
  * SCSI structures and definitions are used from here, but no linking
@@ -103,6 +75,9 @@ struct mfi_hwcomms {
        uint32_t                hw_reply_q[1];
 };
 
+#define        MEGASAS_MAX_NAME        32
+#define        MEGASAS_VERSION         "4.23"
+
 struct mfi_softc;
 struct disk;
 struct ccb_hdr;
@@ -112,17 +87,9 @@ struct mfi_command {
        time_t                  cm_timestamp;
        struct mfi_softc        *cm_sc;
        union mfi_frame         *cm_frame;
-#if defined(__x86_64__)
-       uint64_t                cm_frame_busaddr;
-#else
-       uint32_t                cm_frame_busaddr;
-#endif
+       bus_addr_t              cm_frame_busaddr;
        struct mfi_sense        *cm_sense;
-#if defined(__x86_64__)
-       uint64_t                cm_sense_busaddr;
-#else
-       uint32_t                cm_sense_busaddr;
-#endif
+       bus_addr_t              cm_sense_busaddr;
        bus_dmamap_t            cm_dmamap;
        union mfi_sgl           *cm_sg;
        void                    *cm_data;
@@ -141,6 +108,7 @@ struct mfi_command {
 #define MFI_ON_MFIQ_BUSY       (1<<7)
 #define MFI_ON_MFIQ_MASK       ((1<<5)|(1<<6)|(1<<7))
        int                     cm_aen_abort;
+       uint8_t                 retry_for_fw_reset;
        void                    (* cm_complete)(struct mfi_command *cm);
        void                    *cm_private;
        int                     cm_index;
@@ -182,11 +150,31 @@ struct mfi_system_pd {
        int             pd_flags;
 };
 
+struct mfi_evt_queue_elm {
+       TAILQ_ENTRY(mfi_evt_queue_elm)  link;
+       struct mfi_evt_detail           detail;
+};
+
 struct mfi_aen {
        TAILQ_ENTRY(mfi_aen) aen_link;
        struct proc                     *p;
 };
 
+struct mfi_skinny_dma_info {
+       bus_dma_tag_t   dmat[514];
+       bus_dmamap_t    dmamap[514];
+       uint32_t        mem[514];
+       int             noofmaps;
+};
+
+struct mfi_cmd_tbolt;
+typedef struct {
+       volatile unsigned int val;
+} atomic_t;
+
+#define        atomic_read(v)  ((v)->val)
+#define        atomic_set(v,i) ((v)->val - (i))
+
 struct mfi_softc {
        device_t                        mfi_dev;
        int                             mfi_flags;
@@ -198,11 +186,21 @@ struct mfi_softc {
 #define MFI_FLAGS_1078         (1<<5)
 #define MFI_FLAGS_GEN2         (1<<6)
 #define MFI_FLAGS_SKINNY       (1<<7)
+#define MFI_FLAGS_TBOLT                (1<<8)
+       // Start: LSIP200113393
+       bus_dma_tag_t                   verbuf_h_dmat;
+       bus_dmamap_t                    verbuf_h_dmamap;
+       uint32_t                        verbuf_h_busaddr;
+       uint32_t                        *verbuf;
+       void                            *kbuff_arr[MAX_IOCTL_SGE];
+       bus_dma_tag_t                   mfi_kbuff_arr_dmat[2];
+       bus_dmamap_t                    mfi_kbuff_arr_dmamap[2];
+       bus_addr_t                      mfi_kbuff_arr_busaddr[2];
 
        struct mfi_hwcomms              *mfi_comms;
        TAILQ_HEAD(,mfi_command)        mfi_free;
        TAILQ_HEAD(,mfi_command)        mfi_ready;
-       TAILQ_HEAD(,mfi_command)        mfi_busy;
+       TAILQ_HEAD(BUSYQ,mfi_command)   mfi_busy;
        struct bio_queue_head           mfi_bioq;
        struct mfi_qstat                mfi_qstat[MFIQ_COUNT];
 
@@ -216,19 +214,28 @@ struct mfi_softc {
 
        bus_dma_tag_t                   mfi_comms_dmat;
        bus_dmamap_t                    mfi_comms_dmamap;
-       uint32_t                        mfi_comms_busaddr;
+       bus_addr_t                      mfi_comms_busaddr;
 
        bus_dma_tag_t                   mfi_frames_dmat;
        bus_dmamap_t                    mfi_frames_dmamap;
-       uint32_t                        mfi_frames_busaddr;
+       bus_addr_t                      mfi_frames_busaddr;
        union mfi_frame                 *mfi_frames;
 
+       bus_dma_tag_t                   mfi_tb_init_dmat;
+       bus_dmamap_t                    mfi_tb_init_dmamap;
+       bus_addr_t                      mfi_tb_init_busaddr;
+       bus_addr_t                      mfi_tb_ioc_init_busaddr;
+       union mfi_frame                 *mfi_tb_init;
+
+       TAILQ_HEAD(,mfi_evt_queue_elm)  mfi_evt_queue;
+       struct task                     mfi_evt_task;
        TAILQ_HEAD(,mfi_aen)            mfi_aen_pids;
        struct mfi_command              *mfi_aen_cm;
        struct mfi_command              *mfi_skinny_cm;
        uint32_t                        mfi_aen_triggered;
        uint32_t                        mfi_poll_waiting;
        struct kqinfo                   mfi_kq;
+       uint32_t                        mfi_boot_seq_num;
        int                             mfi_delete_busy_volumes;
        int                             mfi_keep_deleted_volumes;
        int                             mfi_detaching;
@@ -245,6 +252,14 @@ struct mfi_softc {
 
        struct intr_config_hook         mfi_ich;
        eventhandler_tag                eh;
+       /* OCR flags */
+       atomic_t fw_reset_no_pci_access;
+       uint8_t adpreset;
+       uint8_t issuepend_done;
+       uint8_t disableOnlineCtrlReset;
+       uint32_t mfiStatus;
+       uint32_t last_seq_num;
+       uint32_t volatile hw_crit_error;
 
        /*
         * Allocation for the command array.  Used as an indexable array to
@@ -295,9 +310,98 @@ struct mfi_softc {
 
        /* Controller type specific interfaces */
        void    (*mfi_enable_intr)(struct mfi_softc *sc);
+       void    (*mfi_disable_intr)(struct mfi_softc *sc);
        int32_t (*mfi_read_fw_status)(struct mfi_softc *sc);
        int     (*mfi_check_clear_intr)(struct mfi_softc *sc);
-       void    (*mfi_issue_cmd)(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
+       void    (*mfi_issue_cmd)(struct mfi_softc *sc, bus_addr_t bus_add,
+                   uint32_t frame_cnt);
+       int     (*mfi_adp_reset)(struct mfi_softc *sc);
+       int     (*mfi_adp_check_reset)(struct mfi_softc *sc);
+
+       /* ThunderBolt */
+       uint32_t                        mfi_tbolt;
+       uint32_t                        MFA_enabled;
+       uint64_t                        map_id;
+       struct mfi_command              *map_update_cmd;
+       /* Single Reply structure size */
+       uint16_t                        reply_size;
+       /* Singler message size. */
+       uint16_t                        raid_io_msg_size;
+       TAILQ_HEAD(TB, mfi_cmd_tbolt)   mfi_cmd_tbolt_tqh;
+       /* ThunderBolt base contiguous memory mapping. */
+       bus_dma_tag_t                   mfi_tb_dmat;
+       bus_dmamap_t                    mfi_tb_dmamap;
+       bus_addr_t                      mfi_tb_busaddr;
+       /* ThunderBolt Contiguous DMA memory Mapping */
+       uint8_t *                       request_message_pool;
+       uint8_t *                       request_message_pool_align;
+       uint8_t *                       request_desc_pool;
+       //uint32_t                      request_desc_busaddr;
+       bus_addr_t                      request_msg_busaddr;
+       bus_addr_t                      reply_frame_busaddr;
+       bus_addr_t                      sg_frame_busaddr;
+       /* ThunderBolt IOC Init Descriptor */
+       bus_dma_tag_t                   mfi_tb_ioc_init_dmat;
+       bus_dmamap_t                    mfi_tb_ioc_init_dmamap;
+       uint8_t *                       mfi_tb_ioc_init_desc;
+       struct mfi_cmd_tbolt            **mfi_cmd_pool_tbolt;
+       /* Virtual address of reply Frame Pool */
+       struct mfi_mpi2_reply_header*   reply_frame_pool;
+       struct mfi_mpi2_reply_header*   reply_frame_pool_align;
+
+       /* Last reply frame address */
+       uint8_t *                       reply_pool_limit;
+       uint16_t                        last_reply_idx;
+       uint8_t                         max_SGEs_in_chain_message;
+       uint8_t                         max_SGEs_in_main_message;
+       uint8_t                         chain_offset_value_for_main_message;
+       uint8_t                         chain_offset_value_for_mpt_ptmsg;
+};
+
+union desc_value {
+       uint64_t        word;
+       struct {
+               uint32_t        low;
+               uint32_t        high;
+       }u;
+};
+
+// TODO find the right definition
+#define XXX_MFI_CMD_OP_INIT2                    0x9
+/*
+ * Request descriptor types
+ */
+#define MFI_REQ_DESCRIPT_FLAGS_LD_IO           0x7
+#define MFI_REQ_DESCRIPT_FLAGS_MFA             0x1
+#define MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT      0x1
+#define MFI_FUSION_FP_DEFAULT_TIMEOUT          0x14
+#define MFI_LOAD_BALANCE_FLAG                  0x1
+#define MFI_DCMD_MBOX_PEND_FLAG                        0x1
+
+//#define MR_PROT_INFO_TYPE_CONTROLLER 0x08
+#define        MEGASAS_SCSI_VARIABLE_LENGTH_CMD        0x7f
+#define MEGASAS_SCSI_SERVICE_ACTION_READ32     0x9
+#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32    0xB
+#define        MEGASAS_SCSI_ADDL_CDB_LEN               0x18
+#define MEGASAS_RD_WR_PROTECT_CHECK_ALL                0x20
+#define MEGASAS_RD_WR_PROTECT_CHECK_NONE       0x60
+#define MEGASAS_EEDPBLOCKSIZE                  512
+struct mfi_cmd_tbolt {
+       union mfi_mpi2_request_descriptor *request_desc;
+       struct mfi_mpi2_request_raid_scsi_io *io_request;
+       bus_addr_t              io_request_phys_addr;
+       bus_addr_t              sg_frame_phys_addr;
+       bus_addr_t              sense_phys_addr;
+       MPI2_SGE_IO_UNION       *sg_frame;
+       uint8_t                 *sense;
+       TAILQ_ENTRY(mfi_cmd_tbolt) next;
+       /*
+        * Context for a MFI frame.
+        * Used to get the mfi cmd from list when a MFI cmd is completed
+        */
+       uint32_t                sync_cmd_idx;
+       uint16_t                index;
+       uint8_t                 status;
 };
 
 extern int mfi_attach(struct mfi_softc *);
@@ -310,7 +414,28 @@ extern void mfi_disk_enable(struct mfi_disk *);
 extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
 extern int mfi_syspd_disable(struct mfi_system_pd *);
 extern void mfi_syspd_enable(struct mfi_system_pd *);
-extern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
+extern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *,
+    int);
+extern int mfi_transition_firmware(struct mfi_softc *sc);
+extern int mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start);
+extern void mfi_complete(struct mfi_softc *sc, struct mfi_command *cm);
+extern int mfi_mapcmd(struct mfi_softc *sc,struct mfi_command *cm);
+extern int mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm);
+extern void mfi_tbolt_enable_intr_ppc(struct mfi_softc *);
+extern void mfi_tbolt_disable_intr_ppc(struct mfi_softc *);
+extern int32_t mfi_tbolt_read_fw_status_ppc(struct mfi_softc *);
+extern int32_t mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *);
+extern void mfi_tbolt_issue_cmd_ppc(struct mfi_softc *, bus_addr_t, uint32_t);
+extern void mfi_tbolt_init_globals(struct mfi_softc*);
+extern uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *);
+extern int mfi_tbolt_init_desc_pool(struct mfi_softc *, uint8_t *, uint32_t);
+extern int mfi_tbolt_init_MFI_queue(struct mfi_softc *);
+extern void mfi_intr_tbolt(void *arg);
+extern int mfi_tbolt_alloc_cmd(struct mfi_softc *sc);
+extern int mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm);
+extern int mfi_tbolt_adp_reset(struct mfi_softc *sc);
+extern int mfi_tbolt_reset(struct mfi_softc *sc);
+extern int mfi_tbolt_sync_map_info(struct mfi_softc *sc);
 
 #define MFIQ_ADD(sc, qname)                                    \
        do {                                                    \
@@ -451,9 +576,10 @@ mfi_print_sense(struct mfi_softc *sc, void *sense)
 
 MALLOC_DECLARE(M_MFIBUF);
 
+#define MFI_RESET_WAIT_TIME 180
 #define MFI_CMD_TIMEOUT 30
-#define MFI_MAXPHYS (128 * 1024)
 #define SKINNY_MEMORY 0x02000000
+#define MFI_MAXPHYS (128 * 1024)
 
 #ifdef MFI_DEBUG
 extern void mfi_print_cmd(struct mfi_command *cm);