From owner-svn-src-head@FreeBSD.ORG Wed Aug 1 17:31:32 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 156FB106564A; Wed, 1 Aug 2012 17:31:32 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 005E48FC12; Wed, 1 Aug 2012 17:31:32 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q71HVVed080048; Wed, 1 Aug 2012 17:31:31 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q71HVVsa080043; Wed, 1 Aug 2012 17:31:31 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201208011731.q71HVVsa080043@svn.freebsd.org> From: Alexander Motin Date: Wed, 1 Aug 2012 17:31:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r238974 - head/sys/dev/mps X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Aug 2012 17:31:32 -0000 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 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