Print this page
Update tx waitq's code.
Create 2 threads, divide the workflow and deliver
to the hardware from the threads.
Enable Fast Path for capable devices.
Lint and cstyle fixes.
Fix problem with running against 64bit msgaddr attributes for DMA.
Default is now to run like this.
Major rework of mutexes.
During normal operation do not grab m_mutex during interrupt.
Use reply post queues instead.
Fixes to some address arithmetic using 32bit values.
Merge fixes for "4403 mpt_sas panic when pulling a drive", commit f7d0d869a9ae78d
Initial modifications using the code changes present between
the LSI source code for FreeBSD drivers. Specifically the changes
between from mpslsi-source-17.00.00.00 -> mpslsi-source-03.00.00.00.
This mainly involves using a different scatter/gather element in
frame setup.
Changes to enable driver to compile.
Header paths, object lists, etc.

@@ -20,10 +20,12 @@
  */
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
+ * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  */
 
 /*
  * Copyright (c) 2000 to 2010, LSI Corporation.
  * All rights reserved.

@@ -66,32 +68,33 @@
 #include <sys/note.h>
 #include <sys/scsi/scsi.h>
 #include <sys/pci.h>
 
 #pragma pack(1)
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_sas.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
 #pragma pack()
 
 /*
  * private header files.
  */
-#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
-#include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
+#include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
+#include <sys/scsi/adapters/mpt_sas3/mptsas3_smhba.h>
 
 /*
  * FMA header files.
  */
 #include <sys/fm/io/ddi.h>
 
 #if defined(MPTSAS_DEBUG)
 extern uint32_t mptsas_debug_flags;
+extern uint32_t mptsas_dbglog_imask;
 #endif
 
 /*
  *  prototypes
  */

@@ -203,11 +206,12 @@
         pMpi2ConfigRequest_t    request;
         pMpi2SGESimple64_t      sge;
         struct scsi_pkt         *pkt = cmd->cmd_pkt;
         mptsas_config_request_t *config = pkt->pkt_ha_private;
         uint8_t                 direction;
-        uint32_t                length, flagslength, request_desc_low;
+        uint32_t                length, flagslength;
+        uint64_t                request_desc;
 
         ASSERT(mutex_owned(&mpt->m_mutex));
 
         /*
          * Point to the correct message and clear it as well as the global

@@ -257,11 +261,11 @@
 
                 if (config->action == MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
                         direction = MPI2_SGE_FLAGS_HOST_TO_IOC;
                 }
                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
-                    (uint32_t)cmd->cmd_dma_addr);
+                    (uint32_t)(cmd->cmd_dma_addr&0xfffffffful));
                 ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
                     (uint32_t)(cmd->cmd_dma_addr >> 32));
         }
         ddi_put8(mpt->m_acc_req_frame_hdl, &request->Header.PageNumber,
             config->page_number);

@@ -277,14 +281,14 @@
         flagslength |= length;
         ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
 
         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
             DDI_DMA_SYNC_FORDEV);
-        request_desc_low = (cmd->cmd_slot << 16) +
+        request_desc = (cmd->cmd_slot << 16) +
             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
         cmd->cmd_rfm = NULL;
-        MPTSAS_START_CMD(mpt, request_desc_low, 0);
+        MPTSAS_START_CMD(mpt, request_desc);
         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
             DDI_SUCCESS) ||
             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
             DDI_SUCCESS)) {
                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);

@@ -307,10 +311,11 @@
         struct scsi_pkt         *pkt;
         pMpi2ConfigReply_t      reply;
         uint16_t                iocstatus = 0;
         uint32_t                iocloginfo;
         caddr_t                 page_memp;
+        boolean_t               free_dma = B_FALSE;
 
         va_start(ap, callback);
         ASSERT(mutex_owned(&mpt->m_mutex));
 
         /*

@@ -389,11 +394,11 @@
         if (cmd->cmd_rfm) {
                 config_flags |= MPTSAS_ADDRESS_REPLY;
                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
                     DDI_DMA_SYNC_FORCPU);
                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
-                    - mpt->m_reply_frame_dma_addr));
+                    - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
                 config.page_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
                     &reply->Header.PageType);
                 config.page_number = ddi_get8(mpt->m_acc_reply_frame_hdl,
                     &reply->Header.PageNumber);
                 config.page_length = ddi_get8(mpt->m_acc_reply_frame_hdl,

@@ -463,12 +468,18 @@
         attrs.dma_attr_granular = (uint32_t)len;
 
         if (mptsas_dma_addr_create(mpt, attrs,
             &cmd->cmd_dmahandle, &accessp, &page_memp,
             len, &cookie) == FALSE) {
+                mptsas_log(mpt, CE_WARN,
+                    "mptsas_dma_addr_create(len=0x%x) failed", (int)len);
+                rval = DDI_FAILURE;
                 goto page_done;
         }
+        /* NOW we can safely call mptsas_dma_addr_destroy(). */
+        free_dma = B_TRUE;
+
         cmd->cmd_dma_addr = cookie.dmac_laddress;
         bzero(page_memp, len);
 
         /*
          * Save the data for this request to be used in the call to start the

@@ -528,11 +539,11 @@
                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
                     DDI_DMA_SYNC_FORCPU);
                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
                     DDI_DMA_SYNC_FORCPU);
                 reply = (pMpi2ConfigReply_t)(mpt->m_reply_frame + (cmd->cmd_rfm
-                    - mpt->m_reply_frame_dma_addr));
+                    - (mpt->m_reply_frame_dma_addr&0xfffffffful)));
                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
                     &reply->IOCStatus);
                 iocstatus = MPTSAS_IOCSTATUS(iocstatus);
                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
                     &reply->IOCLogInfo);

@@ -582,10 +593,11 @@
                 }
                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
                     mpt->m_free_index);
         }
 
+        if (free_dma)
         mptsas_dma_addr_destroy(&cmd->cmd_dmahandle, &accessp);
 
         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
                 mptsas_remove_cmd(mpt, cmd);
                 config_flags &= (~MPTSAS_REQUEST_POOL_CMD);

@@ -604,11 +616,11 @@
 }
 
 int
 mptsas_send_config_request_msg(mptsas_t *mpt, uint8_t action, uint8_t pagetype,
         uint32_t pageaddress, uint8_t pagenumber, uint8_t pageversion,
-        uint8_t pagelength, uint32_t SGEflagslength, uint32_t SGEaddress32)
+        uint8_t pagelength, uint32_t SGEflagslength, uint64_t SGEaddress)
 {
         pMpi2ConfigRequest_t    config;
         int                     send_numbytes;
 
         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));

@@ -621,11 +633,15 @@
         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageLength, pagelength);
         ddi_put32(mpt->m_hshk_acc_hdl,
             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
         ddi_put32(mpt->m_hshk_acc_hdl,
-            &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);
+            &config->PageBufferSGE.MpiSimple.u.Address64.Low,
+            SGEaddress&0xfffffffful);
+        ddi_put32(mpt->m_hshk_acc_hdl,
+            &config->PageBufferSGE.MpiSimple.u.Address64.High,
+            SGEaddress >> 32);
         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 
         /*
          * Post message via handshake
          */

@@ -638,11 +654,11 @@
 
 int
 mptsas_send_extended_config_request_msg(mptsas_t *mpt, uint8_t action,
         uint8_t extpagetype, uint32_t pageaddress, uint8_t pagenumber,
         uint8_t pageversion, uint16_t extpagelength,
-        uint32_t SGEflagslength, uint32_t SGEaddress32)
+        uint32_t SGEflagslength, uint64_t SGEaddress)
 {
         pMpi2ConfigRequest_t    config;
         int                     send_numbytes;
 
         bzero(mpt->m_hshk_memp, sizeof (MPI2_CONFIG_REQUEST));

@@ -657,11 +673,15 @@
         ddi_put8(mpt->m_hshk_acc_hdl, &config->Header.PageVersion, pageversion);
         ddi_put16(mpt->m_hshk_acc_hdl, &config->ExtPageLength, extpagelength);
         ddi_put32(mpt->m_hshk_acc_hdl,
             &config->PageBufferSGE.MpiSimple.FlagsLength, SGEflagslength);
         ddi_put32(mpt->m_hshk_acc_hdl,
-            &config->PageBufferSGE.MpiSimple.u.Address32, SGEaddress32);
+            &config->PageBufferSGE.MpiSimple.u.Address64.Low,
+            SGEaddress&0xfffffffful);
+        ddi_put32(mpt->m_hshk_acc_hdl,
+            &config->PageBufferSGE.MpiSimple.u.Address64.High,
+            SGEaddress >> 32);
         send_numbytes = sizeof (MPI2_CONFIG_REQUEST);
 
         /*
          * Post message via handshake
          */

@@ -1085,11 +1105,12 @@
         pMpi2SCSITaskManagementRequest_t        task;
         int                                     rval = FALSE;
         mptsas_cmd_t                            *cmd;
         struct scsi_pkt                         *pkt;
         mptsas_slots_t                          *slots = mpt->m_active;
-        uint32_t                                request_desc_low, i;
+        uint32_t                                i;
+        uint64_t                                request_desc;
         pMPI2DefaultReply_t                     reply_msg;
 
         /*
          * Can't start another task management routine.
          */

@@ -1141,13 +1162,13 @@
         /*
          * Send TM request using High Priority Queue.
          */
         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
             DDI_DMA_SYNC_FORDEV);
-        request_desc_low = (cmd->cmd_slot << 16) +
+        request_desc = (cmd->cmd_slot << 16) +
             MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
-        MPTSAS_START_CMD(mpt, request_desc_low, 0);
+        MPTSAS_START_CMD(mpt, request_desc);
         rval = mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
 
         if (pkt->pkt_reason == CMD_INCOMPLETE)
                 rval = FALSE;
 

@@ -1159,11 +1180,11 @@
         if (cmd->cmd_rfm && reply) {
                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
                     DDI_DMA_SYNC_FORCPU);
                 reply_msg = (pMPI2DefaultReply_t)
                     (mpt->m_reply_frame + (cmd->cmd_rfm -
-                    mpt->m_reply_frame_dma_addr));
+                    (mpt->m_reply_frame_dma_addr&0xfffffffful)));
                 if (reply_size > sizeof (MPI2_SCSI_TASK_MANAGE_REPLY)) {
                         reply_size = sizeof (MPI2_SCSI_TASK_MANAGE_REPLY);
                 }
                 mutex_exit(&mpt->m_mutex);
                 for (i = 0; i < reply_size; i++) {

@@ -1197,10 +1218,87 @@
         }
 
         return (rval);
 }
 
+/*
+ * Complete firmware download frame for v2.0 cards.
+ */
+static void
+mptsas_uflash2(pMpi2FWDownloadRequest fwdownload,
+    ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
+    ddi_dma_cookie_t flsh_cookie)
+{
+        pMpi2FWDownloadTCSGE_t  tcsge;
+        pMpi2SGESimple64_t      sge;
+        uint32_t                flagslength;
+
+        ddi_put8(acc_hdl, &fwdownload->Function,
+            MPI2_FUNCTION_FW_DOWNLOAD);
+        ddi_put8(acc_hdl, &fwdownload->ImageType, type);
+        ddi_put8(acc_hdl, &fwdownload->MsgFlags,
+            MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
+        ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
+
+        tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
+        ddi_put8(acc_hdl, &tcsge->ContextSize, 0);
+        ddi_put8(acc_hdl, &tcsge->DetailsLength, 12);
+        ddi_put8(acc_hdl, &tcsge->Flags, 0);
+        ddi_put32(acc_hdl, &tcsge->ImageOffset, 0);
+        ddi_put32(acc_hdl, &tcsge->ImageSize, size);
+
+        sge = (pMpi2SGESimple64_t)(tcsge + 1);
+        flagslength = size;
+        flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
+            MPI2_SGE_FLAGS_END_OF_BUFFER |
+            MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+            MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
+            MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
+            MPI2_SGE_FLAGS_HOST_TO_IOC |
+            MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
+        ddi_put32(acc_hdl, &sge->FlagsLength, flagslength);
+        ddi_put32(acc_hdl, &sge->Address.Low,
+            flsh_cookie.dmac_address);
+        ddi_put32(acc_hdl, &sge->Address.High,
+            (uint32_t)(flsh_cookie.dmac_laddress >> 32));
+}
+
+/*
+ * Complete firmware download frame for v2.5 cards.
+ */
+static void
+mptsas_uflash25(pMpi25FWDownloadRequest fwdownload,
+    ddi_acc_handle_t acc_hdl, uint32_t size, uint8_t type,
+    ddi_dma_cookie_t flsh_cookie)
+{
+        pMpi2IeeeSgeSimple64_t  sge;
+        uint8_t                 flags;
+
+        ddi_put8(acc_hdl, &fwdownload->Function,
+            MPI2_FUNCTION_FW_DOWNLOAD);
+        ddi_put8(acc_hdl, &fwdownload->ImageType, type);
+        ddi_put8(acc_hdl, &fwdownload->MsgFlags,
+            MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
+        ddi_put32(acc_hdl, &fwdownload->TotalImageSize, size);
+
+        ddi_put32(acc_hdl, &fwdownload->ImageOffset, 0);
+        ddi_put32(acc_hdl, &fwdownload->ImageSize, size);
+
+        sge = (pMpi2IeeeSgeSimple64_t)&fwdownload->SGL;
+        flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+            MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
+            MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
+        ddi_put8(acc_hdl, &sge->Flags, flags);
+        ddi_put32(acc_hdl, &sge->Length, size);
+        ddi_put32(acc_hdl, &sge->Address.Low,
+            flsh_cookie.dmac_address);
+        ddi_put32(acc_hdl, &sge->Address.High,
+            (uint32_t)(flsh_cookie.dmac_laddress >> 32));
+}
+
+static int mptsas_enable_mpi25_flashupdate = 0;
+
 int
 mptsas_update_flash(mptsas_t *mpt, caddr_t ptrbuffer, uint32_t size,
     uint8_t type, int mode)
 {
 

@@ -1214,19 +1312,28 @@
         ddi_dma_attr_t          flsh_dma_attrs;
         ddi_dma_cookie_t        flsh_cookie;
         ddi_dma_handle_t        flsh_dma_handle;
         ddi_acc_handle_t        flsh_accessp;
         caddr_t                 memp, flsh_memp;
-        uint32_t                flagslength;
-        pMpi2FWDownloadRequest  fwdownload;
-        pMpi2FWDownloadTCSGE_t  tcsge;
-        pMpi2SGESimple64_t      sge;
         mptsas_cmd_t            *cmd;
         struct scsi_pkt         *pkt;
         int                     i;
         int                     rvalue = 0;
-        uint32_t                request_desc_low;
+        uint64_t                request_desc;
+
+        if (mpt->m_MPI25) {
+                /*
+                 * The code is there but not tested yet.
+                 * User has to know there are risks here.
+                 */
+                mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): "
+                    "Updating firmware through MPI 2.5 has not been "
+                    "tested yet!\n"
+                    "To enable set mptsas_enable_mpi25_flashupdate to 1\n");
+                if (!mptsas_enable_mpi25_flashupdate)
+                        return (-1);
+        }
 
         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
                 mptsas_log(mpt, CE_WARN, "mptsas_update_flash(): allocation "
                     "failed. event ack command pool is full\n");
                 return (rvalue);

@@ -1283,49 +1390,27 @@
          * Fill in fw download message
          */
         ASSERT(cmd->cmd_slot != 0);
         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
         bzero(memp, mpt->m_req_frame_size);
-        fwdownload = (void *)memp;
-        ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->Function,
-            MPI2_FUNCTION_FW_DOWNLOAD);
-        ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->ImageType, type);
-        ddi_put8(mpt->m_acc_req_frame_hdl, &fwdownload->MsgFlags,
-            MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &fwdownload->TotalImageSize, size);
 
-        tcsge = (pMpi2FWDownloadTCSGE_t)&fwdownload->SGL;
-        ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->ContextSize, 0);
-        ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->DetailsLength, 12);
-        ddi_put8(mpt->m_acc_req_frame_hdl, &tcsge->Flags, 0);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageOffset, 0);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &tcsge->ImageSize, size);
-
-        sge = (pMpi2SGESimple64_t)(tcsge + 1);
-        flagslength = size;
-        flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
-            MPI2_SGE_FLAGS_END_OF_BUFFER |
-            MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-            MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
-            MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
-            MPI2_SGE_FLAGS_HOST_TO_IOC |
-            MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &sge->FlagsLength, flagslength);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.Low,
-            flsh_cookie.dmac_address);
-        ddi_put32(mpt->m_acc_req_frame_hdl, &sge->Address.High,
-            (uint32_t)(flsh_cookie.dmac_laddress >> 32));
+        if (mpt->m_MPI25)
+                mptsas_uflash25((pMpi25FWDownloadRequest)memp,
+                    mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);
+        else
+                mptsas_uflash2((pMpi2FWDownloadRequest)memp,
+                    mpt->m_acc_req_frame_hdl, size, type, flsh_cookie);
 
         /*
          * Start command
          */
         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
             DDI_DMA_SYNC_FORDEV);
-        request_desc_low = (cmd->cmd_slot << 16) +
+        request_desc = (cmd->cmd_slot << 16) +
             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
         cmd->cmd_rfm = NULL;
-        MPTSAS_START_CMD(mpt, request_desc_low, 0);
+        MPTSAS_START_CMD(mpt, request_desc);
 
         rvalue = 0;
         (void) cv_reltimedwait(&mpt->m_fw_cv, &mpt->m_mutex,
             drv_usectohz(60 * MICROSEC), TR_CLOCK_TICK);
         if (!(cmd->cmd_flags & CFLAG_FINISHED)) {

@@ -1355,11 +1440,11 @@
         uint8_t                 tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
         uint16_t                *devhdl, *bay_num, *enclosure;
         uint64_t                *sas_wwn;
         uint32_t                *dev_info;
         uint8_t                 *physport, *phynum;
-        uint16_t                *pdevhdl;
+        uint16_t                *pdevhdl, *io_flags;
         uint32_t                page_address;
 
         if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) &&
             (iocstatus != MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)) {
                 mptsas_log(mpt, CE_WARN, "mptsas_get_sas_device_page0 "

@@ -1389,11 +1474,11 @@
         physport = va_arg(ap, uint8_t *);
         phynum = va_arg(ap, uint8_t *);
         pdevhdl = va_arg(ap, uint16_t *);
         bay_num = va_arg(ap, uint16_t *);
         enclosure = va_arg(ap, uint16_t *);
-
+        io_flags = va_arg(ap, uint16_t *);
 
         sasdevpage = (pMpi2SasDevicePage0_t)page_memp;
 
         *dev_info = ddi_get32(accessp, &sasdevpage->DeviceInfo);
         *devhdl = ddi_get16(accessp, &sasdevpage->DevHandle);

@@ -1406,10 +1491,23 @@
         *physport = ddi_get8(accessp, &sasdevpage->PhysicalPort);
         *phynum = ddi_get8(accessp, &sasdevpage->PhyNum);
         *pdevhdl = ddi_get16(accessp, &sasdevpage->ParentDevHandle);
         *bay_num = ddi_get16(accessp, &sasdevpage->Slot);
         *enclosure = ddi_get16(accessp, &sasdevpage->EnclosureHandle);
+        *io_flags = ddi_get16(accessp, &sasdevpage->Flags);
+
+        if (*io_flags & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
+                /*
+                 * Leave a messages about FP cabability in the log.
+                 */
+                mptsas_log(mpt, CE_CONT,
+                    "!w%016"PRIx64" FastPath Capable%s", *sas_wwn,
+                    (*io_flags &
+                    MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)?
+                    " and Enabled":" but Disabled");
+        }
+
         return (rval);
 }
 
 /*
  * Request MPI configuration page SAS device page 0 to get DevHandle, device

@@ -1417,11 +1515,11 @@
  */
 int
 mptsas_get_sas_device_page0(mptsas_t *mpt, uint32_t page_address,
     uint16_t *dev_handle, uint64_t *sas_wwn, uint32_t *dev_info,
     uint8_t *physport, uint8_t *phynum, uint16_t *pdev_handle,
-    uint16_t *bay_num, uint16_t *enclosure)
+    uint16_t *bay_num, uint16_t *enclosure, uint16_t *io_flags)
 {
         int rval = DDI_SUCCESS;
 
         ASSERT(mutex_owned(&mpt->m_mutex));
 

@@ -1432,11 +1530,11 @@
         rval = mptsas_access_config_page(mpt,
             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
             MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0, page_address,
             mptsas_sasdevpage_0_cb, page_address, dev_handle, sas_wwn,
             dev_info, physport, phynum, pdev_handle,
-            bay_num, enclosure);
+            bay_num, enclosure, io_flags);
 
         return (rval);
 }
 
 static int

@@ -1855,10 +1953,11 @@
         uint16_t                iocstatus;
         uint8_t                 port_flags, page_number, action;
         uint32_t                reply_size = 256; /* Big enough for any page */
         uint_t                  state;
         int                     rval = DDI_FAILURE;
+        boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
 
         /*
          * Initialize our "state machine".  This is a bit convoluted,
          * but it keeps us from having to do the ddi allocations numerous
          * times.

@@ -1881,10 +1980,12 @@
             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
                 mptsas_log(mpt, CE_WARN,
                     "mptsas_get_sas_io_unit_page_hndshk: recv dma failed");
                 goto cleanup;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
+        free_recv = B_TRUE;
 
         page_dma_attrs = mpt->m_msg_dma_attr;
         page_dma_attrs.dma_attr_sgllen = 1;
         page_dma_attrs.dma_attr_granular = reply_size;
 

@@ -1893,10 +1994,12 @@
             reply_size, &page_cookie) == FALSE) {
                 mptsas_log(mpt, CE_WARN,
                     "mptsas_get_sas_io_unit_page_hndshk: page dma failed");
                 goto cleanup;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
+        free_page = B_TRUE;
 
         /*
          * Now we cycle through the state machine.  Here's what happens:
          * 1. Read IO unit page 0 and set phy information
          * 2. See if Read IO unit page1 is needed because of port configuration

@@ -1915,11 +2018,11 @@
                         flags_length |= ((uint32_t)(
                             MPI2_SGE_FLAGS_LAST_ELEMENT |
                             MPI2_SGE_FLAGS_END_OF_BUFFER |
                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
-                            MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
                             MPI2_SGE_FLAGS_IOC_TO_HOST |
                             MPI2_SGE_FLAGS_END_OF_LIST) <<
                             MPI2_SGE_FLAGS_SHIFT);
 
                         break;

@@ -1931,11 +2034,11 @@
                         flags_length |= ((uint32_t)(
                             MPI2_SGE_FLAGS_LAST_ELEMENT |
                             MPI2_SGE_FLAGS_END_OF_BUFFER |
                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
-                            MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
                             MPI2_SGE_FLAGS_IOC_TO_HOST |
                             MPI2_SGE_FLAGS_END_OF_LIST) <<
                             MPI2_SGE_FLAGS_SHIFT);
 
                         break;

@@ -1975,11 +2078,11 @@
 
                 if (mptsas_send_extended_config_request_msg(mpt, action,
                     MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0, page_number,
                     ddi_get8(recv_accessp, &configreply->Header.PageVersion),
                     ddi_get16(recv_accessp, &configreply->ExtPageLength),
-                    flags_length, page_cookie.dmac_address)) {
+                    flags_length, page_cookie.dmac_laddress)) {
                         goto cleanup;
                 }
 
                 if (mptsas_get_handshake_msg(mpt, recv_memp, recv_numbytes,
                     recv_accessp)) {

@@ -2128,11 +2231,13 @@
                 rval = DDI_FAILURE;
                 goto cleanup;
         }
 
 cleanup:
+        if (free_recv)
         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
+        if (free_page)
         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
         if (rval != DDI_SUCCESS) {
                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
         }

@@ -2157,10 +2262,11 @@
         int                             recv_numbytes;
         pMpi2ManufacturingPage5_t       m5;
         uint32_t                        flagslength;
         int                             rval = DDI_SUCCESS;
         uint_t                          iocstatus;
+        boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
 
         MPTSAS_DISABLE_INTR(mpt);
 
         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5, 0, 0, 0, 0)) {

@@ -2177,12 +2283,15 @@
         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
 
         if (mptsas_dma_addr_create(mpt, recv_dma_attrs,
             &recv_dma_handle, &recv_accessp, &recv_memp,
             (sizeof (MPI2_CONFIG_REPLY)), NULL) == FALSE) {
+                rval = DDI_FAILURE;
                 goto done;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
+        free_recv = B_TRUE;
 
         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
         configreply = (pMpi2ConfigReply_t)recv_memp;
         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
 

@@ -2211,33 +2320,40 @@
         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_5));
 
         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_5)),
             &page_cookie) == FALSE) {
+                rval = DDI_FAILURE;
                 goto done;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
+        free_page = B_TRUE;
+
         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_5));
         m5 = (pMpi2ManufacturingPage5_t)page_memp;
+        NDBG20(("mptsas_get_manufacture_page5: paddr 0x%x%08x",
+            (uint32_t)(page_cookie.dmac_laddress>>32),
+            (uint32_t)(page_cookie.dmac_laddress&0xfffffffful)));
 
         /*
          * Give reply address to IOC to store config page in and send
          * config request out.
          */
 
         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_5);
         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-            MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+            MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
             MPI2_SGE_FLAGS_IOC_TO_HOST |
             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
 
         if (mptsas_send_config_request_msg(mpt,
             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 5,
             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
             ddi_get8(recv_accessp, &configreply->Header.PageLength),
-            flagslength, page_cookie.dmac_address)) {
+            flagslength, page_cookie.dmac_laddress)) {
                 rval = DDI_FAILURE;
                 goto done;
         }
 
         /*

@@ -2301,11 +2417,13 @@
         }
 done:
         /*
          * free up memory
          */
+        if (free_recv)
         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
+        if (free_page)
         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
         MPTSAS_ENABLE_INTR(mpt);
 
         return (rval);
 }

@@ -2523,10 +2641,11 @@
         pMpi2ManufacturingPage0_t       m0;
         uint32_t                        flagslength;
         int                             rval = DDI_SUCCESS;
         uint_t                          iocstatus;
         uint8_t                         i = 0;
+        boolean_t               free_recv = B_FALSE, free_page = B_FALSE;
 
         MPTSAS_DISABLE_INTR(mpt);
 
         if (mptsas_send_config_request_msg(mpt, MPI2_CONFIG_ACTION_PAGE_HEADER,
             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0, 0, 0, 0, 0)) {

@@ -2543,12 +2662,16 @@
         recv_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_REPLY));
 
         if (mptsas_dma_addr_create(mpt, recv_dma_attrs, &recv_dma_handle,
             &recv_accessp, &recv_memp, (sizeof (MPI2_CONFIG_REPLY)),
             NULL) == FALSE) {
+                rval = DDI_FAILURE;
                 goto done;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(recv_dma_handle). */
+        free_recv = B_TRUE;
+
         bzero(recv_memp, sizeof (MPI2_CONFIG_REPLY));
         configreply = (pMpi2ConfigReply_t)recv_memp;
         recv_numbytes = sizeof (MPI2_CONFIG_REPLY);
 
         /*

@@ -2576,12 +2699,16 @@
         page_dma_attrs.dma_attr_granular = (sizeof (MPI2_CONFIG_PAGE_MAN_0));
 
         if (mptsas_dma_addr_create(mpt, page_dma_attrs, &page_dma_handle,
             &page_accessp, &page_memp, (sizeof (MPI2_CONFIG_PAGE_MAN_0)),
             &page_cookie) == FALSE) {
+                rval = DDI_FAILURE;
                 goto done;
         }
+        /* Now safe to call mptsas_dma_addr_destroy(page_dma_handle). */
+        free_page = B_TRUE;
+
         bzero(page_memp, sizeof (MPI2_CONFIG_PAGE_MAN_0));
         m0 = (pMpi2ManufacturingPage0_t)page_memp;
 
         /*
          * Give reply address to IOC to store config page in and send

@@ -2589,20 +2716,20 @@
          */
 
         flagslength = sizeof (MPI2_CONFIG_PAGE_MAN_0);
         flagslength |= ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT |
             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-            MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+            MPI2_SGE_FLAGS_SYSTEM_ADDRESS | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
             MPI2_SGE_FLAGS_IOC_TO_HOST |
             MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
 
         if (mptsas_send_config_request_msg(mpt,
             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
             MPI2_CONFIG_PAGETYPE_MANUFACTURING, 0, 0,
             ddi_get8(recv_accessp, &configreply->Header.PageVersion),
             ddi_get8(recv_accessp, &configreply->Header.PageLength),
-            flagslength, page_cookie.dmac_address)) {
+            flagslength, page_cookie.dmac_laddress)) {
                 rval = DDI_FAILURE;
                 goto done;
         }
 
         /*

@@ -2671,11 +2798,13 @@
         }
 done:
         /*
          * free up memory
          */
+        if (free_recv)
         mptsas_dma_addr_destroy(&recv_dma_handle, &recv_accessp);
+        if (free_page)
         mptsas_dma_addr_destroy(&page_dma_handle, &page_accessp);
         MPTSAS_ENABLE_INTR(mpt);
 
         return (rval);
 }