Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Aug 2012 17:31:31 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238974 - head/sys/dev/mps
Message-ID:  <201208011731.q71HVVsa080043@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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.Desai@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208011731.q71HVVsa080043>