Author: mav
Date: Wed Aug  1 17:31:31 2012
New Revision: 238974
URL: http://svn.freebsd.org/changeset/base/238974

Log:
  Several fixes to allow firmware/BIOS flash access from user-level:
   - remove special handling of zero length transfers in mpi_pre_fw_upload();
   - add missing MPS_CM_FLAGS_DATAIN flag in mpi_pre_fw_upload();
   - move mps_user_setup_request() call into proper place;
   - increase user command timeout from 30 to 60 seconds;
   - avoid NULL dereference panic in case of firmware crash.
  Set max DMA segment size to 24bit, as MPI SGE supports it.
  Use mps_add_dmaseg() to add empty SGE instead of custom code.
  Tune endianness safety.
  
  Reviewed by:  Desai, Kashyap <kashyap.de...@lsi.com>
  Sponsored by: iXsystems, Inc.

Modified:
  head/sys/dev/mps/mps.c
  head/sys/dev/mps/mps_table.c
  head/sys/dev/mps/mps_user.c
  head/sys/dev/mps/mpsvar.h

Modified: head/sys/dev/mps/mps.c
==============================================================================
--- head/sys/dev/mps/mps.c      Wed Aug  1 17:26:22 2012        (r238973)
+++ head/sys/dev/mps/mps.c      Wed Aug  1 17:31:31 2012        (r238974)
@@ -924,7 +924,7 @@ mps_alloc_requests(struct mps_softc *sc)
                                NULL, NULL,             /* filter, filterarg */
                                 BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
                                 nsegs,                 /* nsegments */
-                                BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+                                BUS_SPACE_MAXSIZE_24BIT,/* maxsegsize */
                                 BUS_DMA_ALLOCNOW,      /* flags */
                                 busdma_lock_mutex,     /* lockfunc */
                                &sc->mps_mtx,           /* lockarg */
@@ -2014,7 +2014,6 @@ mps_push_sge(struct mps_command *cm, voi
        MPI2_SGE_SIMPLE64 *sge = sgep;
        int error, type;
        uint32_t saved_buf_len, saved_address_low, saved_address_high;
-       u32 sge_flags;
 
        type = (tc->Flags & MPI2_SGE_FLAGS_ELEMENT_MASK);
 
@@ -2034,14 +2033,12 @@ mps_push_sge(struct mps_command *cm, voi
                break;
        case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
                /* Driver only uses 64-bit SGE simple elements */
-               sge = sgep;
                if (len != MPS_SGE64_SIZE)
                        panic("SGE simple %p length %u or %zu?", sge,
                            MPS_SGE64_SIZE, len);
-               if (((sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT) &
+               if (((le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT) &
                    MPI2_SGE_FLAGS_ADDRESS_SIZE) == 0)
-                       panic("SGE simple %p flags %02x not marked 64-bit?",
-                           sge, sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT);
+                       panic("SGE simple %p not marked 64-bit?", sge);
 
                break;
        default:
@@ -2073,8 +2070,8 @@ mps_push_sge(struct mps_command *cm, voi
                 * Mark as last element in this chain if necessary.
                 */
                if (type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
-                       sge->FlagsLength |=
-                               (MPI2_SGE_FLAGS_LAST_ELEMENT << 
MPI2_SGE_FLAGS_SHIFT);
+                       sge->FlagsLength |= htole32(
+                           MPI2_SGE_FLAGS_LAST_ELEMENT << 
MPI2_SGE_FLAGS_SHIFT);
                }
 
                /*
@@ -2083,11 +2080,6 @@ mps_push_sge(struct mps_command *cm, voi
                 * understanding the code.
                 */
                cm->cm_sglsize -= len;
-               /* Endian Safe code */
-               sge_flags = sge->FlagsLength;
-               sge->FlagsLength = htole32(sge_flags);
-               sge->Address.High = htole32(sge->Address.High); 
-               sge->Address.Low =      htole32(sge->Address.Low);
                bcopy(sgep, cm->cm_sge, len);
                cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
                return (mps_add_chain(cm));
@@ -2127,27 +2119,22 @@ mps_push_sge(struct mps_command *cm, voi
                 * 2 SGL's for a bi-directional request, they both use the same
                 * DMA buffer (same cm command).
                 */
-               saved_buf_len = sge->FlagsLength & 0x00FFFFFF;
+               saved_buf_len = le32toh(sge->FlagsLength) & 0x00FFFFFF;
                saved_address_low = sge->Address.Low;
                saved_address_high = sge->Address.High;
                if (cm->cm_out_len) {
-                       sge->FlagsLength = cm->cm_out_len |
+                       sge->FlagsLength = htole32(cm->cm_out_len |
                            ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
                            MPI2_SGE_FLAGS_END_OF_BUFFER |
                            MPI2_SGE_FLAGS_HOST_TO_IOC |
                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
-                           MPI2_SGE_FLAGS_SHIFT);
+                           MPI2_SGE_FLAGS_SHIFT));
                        cm->cm_sglsize -= len;
-                       /* Endian Safe code */
-                       sge_flags = sge->FlagsLength;
-                       sge->FlagsLength = htole32(sge_flags);
-                       sge->Address.High = htole32(sge->Address.High); 
-                       sge->Address.Low =      htole32(sge->Address.Low);
                        bcopy(sgep, cm->cm_sge, len);
                        cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge
                            + len);
                }
-               sge->FlagsLength = saved_buf_len |
+               saved_buf_len |=
                    ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
                    MPI2_SGE_FLAGS_END_OF_BUFFER |
                    MPI2_SGE_FLAGS_LAST_ELEMENT |
@@ -2155,24 +2142,20 @@ mps_push_sge(struct mps_command *cm, voi
                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
                    MPI2_SGE_FLAGS_SHIFT);
                if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) {
-                       sge->FlagsLength |=
+                       saved_buf_len |=
                            ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
                            MPI2_SGE_FLAGS_SHIFT);
                } else {
-                       sge->FlagsLength |=
+                       saved_buf_len |=
                            ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
                            MPI2_SGE_FLAGS_SHIFT);
                }
+               sge->FlagsLength = htole32(saved_buf_len);
                sge->Address.Low = saved_address_low;
                sge->Address.High = saved_address_high;
        }
 
        cm->cm_sglsize -= len;
-       /* Endian Safe code */
-       sge_flags = sge->FlagsLength;
-       sge->FlagsLength = htole32(sge_flags);
-       sge->Address.High = htole32(sge->Address.High); 
-       sge->Address.Low =      htole32(sge->Address.Low);
        bcopy(sgep, cm->cm_sge, len);
        cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
        return (0);
@@ -2190,10 +2173,10 @@ mps_add_dmaseg(struct mps_command *cm, v
        /*
         * This driver always uses 64-bit address elements for simplicity.
         */
+       bzero(&sge, sizeof(sge));
        flags |= MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
            MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
-       /* Set Endian safe macro in mps_push_sge */
-       sge.FlagsLength = len | (flags << MPI2_SGE_FLAGS_SHIFT);
+       sge.FlagsLength = htole32(len | (flags << MPI2_SGE_FLAGS_SHIFT));
        mps_from_u64(pa, &sge.Address);
 
        return (mps_push_sge(cm, &sge, sizeof sge, segsleft));
@@ -2290,7 +2273,6 @@ mps_data_cb2(void *arg, bus_dma_segment_
 int
 mps_map_command(struct mps_softc *sc, struct mps_command *cm)
 {
-       MPI2_SGE_SIMPLE32 *sge;
        int error = 0;
 
        if (cm->cm_flags & MPS_CM_FLAGS_USE_UIO) {
@@ -2301,15 +2283,8 @@ mps_map_command(struct mps_softc *sc, st
                    cm->cm_data, cm->cm_length, mps_data_cb, cm, 0);
        } else {
                /* Add a zero-length element as needed */
-               if (cm->cm_sge != NULL) {
-                       sge = (MPI2_SGE_SIMPLE32 *)cm->cm_sge;
-                       sge->FlagsLength = htole32((MPI2_SGE_FLAGS_LAST_ELEMENT 
|
-                           MPI2_SGE_FLAGS_END_OF_BUFFER |
-                           MPI2_SGE_FLAGS_END_OF_LIST |
-                           MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
-                           MPI2_SGE_FLAGS_SHIFT);
-                       sge->Address = 0;
-               }
+               if (cm->cm_sge != NULL)
+                       mps_add_dmaseg(cm, 0, 0, 0, 1);
                mps_enqueue_request(sc, cm);    
        }
 

Modified: head/sys/dev/mps/mps_table.c
==============================================================================
--- head/sys/dev/mps/mps_table.c        Wed Aug  1 17:26:22 2012        
(r238973)
+++ head/sys/dev/mps/mps_table.c        Wed Aug  1 17:31:31 2012        
(r238974)
@@ -463,10 +463,12 @@ mps_print_sgl(struct mps_softc *sc, stru
        sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4];
        printf("SGL for command %p\n", cm);
 
+       hexdump(frame, 128, NULL, 0);
        while (frame != NULL) {
-               flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
-               printf("seg%d flags=0x%x len=0x%x addr=0x%jx\n", i, flags,
-                   sge->FlagsLength & 0xffffff, mps_to_u64(&sge->Address));
+               flags = le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT;
+               printf("seg%d flags=0x%02x len=0x%06x addr=0x%016jx\n",
+                   i, flags, le32toh(sge->FlagsLength) & 0xffffff,
+                   mps_to_u64(&sge->Address));
                if (flags & (MPI2_SGE_FLAGS_END_OF_LIST |
                    MPI2_SGE_FLAGS_END_OF_BUFFER))
                        break;
@@ -475,8 +477,8 @@ mps_print_sgl(struct mps_softc *sc, stru
                if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) {
                        sgc = (MPI2_SGE_CHAIN32 *)sge;
                        printf("chain flags=0x%x len=0x%x Offset=0x%x "
-                           "Address=0x%x\n", sgc->Flags, sgc->Length,
-                           sgc->NextChainOffset, sgc->Address);
+                           "Address=0x%x\n", sgc->Flags, le16toh(sgc->Length),
+                           sgc->NextChainOffset, le32toh(sgc->Address));
                        if (chain == NULL)
                                chain = TAILQ_FIRST(&cm->cm_chain_list);
                        else

Modified: head/sys/dev/mps/mps_user.c
==============================================================================
--- head/sys/dev/mps/mps_user.c Wed Aug  1 17:26:22 2012        (r238973)
+++ head/sys/dev/mps/mps_user.c Wed Aug  1 17:31:31 2012        (r238974)
@@ -534,11 +534,6 @@ mpi_pre_fw_upload(struct mps_command *cm
                return (EINVAL);
 
        mpi_init_sge(cm, req, &req->SGL);
-       if (cmd->len == 0) {
-               /* Perhaps just asking what the size of the fw is? */
-               return (0);
-       }
-
        bzero(&tc, sizeof tc);
 
        /*
@@ -554,6 +549,8 @@ mpi_pre_fw_upload(struct mps_command *cm
        tc.ImageOffset = 0;
        tc.ImageSize = cmd->len;
 
+       cm->cm_flags |= MPS_CM_FLAGS_DATAIN;
+
        return (mps_push_sge(cm, &tc, sizeof tc, 0));
 }
 
@@ -692,13 +689,6 @@ mps_user_command(struct mps_softc *sc, s
        mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X  "
            "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
 
-       err = mps_user_setup_request(cm, cmd);
-       if (err != 0) {
-               mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
-                   hdr->Function );
-               goto RetFreeUnlocked;
-       }
-
        if (cmd->len > 0) {
                buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
                if(!buf) {
@@ -716,8 +706,15 @@ mps_user_command(struct mps_softc *sc, s
        cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE;
        cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 
+       err = mps_user_setup_request(cm, cmd);
+       if (err != 0) {
+               mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
+                   hdr->Function );
+               goto RetFreeUnlocked;
+       }
+
        mps_lock(sc);
-       err = mps_wait_command(sc, cm, 30);
+       err = mps_wait_command(sc, cm, 60);
 
        if (err) {
                mps_printf(sc, "%s: invalid request: error %d\n",
@@ -726,7 +723,10 @@ mps_user_command(struct mps_softc *sc, s
        }
 
        rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
-       sz = rpl->MsgLength * 4;
+       if (rpl != NULL)
+               sz = rpl->MsgLength * 4;
+       else
+               sz = 0;
        
        if (sz > cmd->rpl_len) {
                mps_printf(sc,

Modified: head/sys/dev/mps/mpsvar.h
==============================================================================
--- head/sys/dev/mps/mpsvar.h   Wed Aug  1 17:26:22 2012        (r238973)
+++ head/sys/dev/mps/mpsvar.h   Wed Aug  1 17:31:31 2012        (r238974)
@@ -32,7 +32,7 @@
 #ifndef _MPSVAR_H
 #define _MPSVAR_H
 
-#define MPS_DRIVER_VERSION     "14.00.00.01-fbsd"
+#define MPS_DRIVER_VERSION     "14.00.00.02-fbsd"
 
 #define MPS_DB_MAX_WAIT                2500
 
@@ -627,15 +627,15 @@ do {                                                      
        \
 static __inline void
 mps_from_u64(uint64_t data, U64 *mps)
 {
-       (mps)->High = (uint32_t)((data) >> 32);
-       (mps)->Low = (uint32_t)((data) & 0xffffffff);
+       (mps)->High = htole32((uint32_t)((data) >> 32));
+       (mps)->Low = htole32((uint32_t)((data) & 0xffffffff));
 }
 
 static __inline uint64_t
 mps_to_u64(U64 *data)
 {
 
-       return (((uint64_t)data->High << 32) | data->Low);
+       return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low));
 }
 
 static __inline void
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to