summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-08-01 17:31:31 +0000
committermav <mav@FreeBSD.org>2012-08-01 17:31:31 +0000
commitd35997f97e5bca6ac7e1dffebc4f7bc0bf4a168e (patch)
tree79e17377a681fc12123cfa9b9acf9d7ba8fdaf18 /sys/dev
parent58f7ae85c74dabb278901c6e1c4afae9578733f2 (diff)
downloadFreeBSD-src-d35997f97e5bca6ac7e1dffebc4f7bc0bf4a168e.zip
FreeBSD-src-d35997f97e5bca6ac7e1dffebc4f7bc0bf4a168e.tar.gz
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mps/mps.c57
-rw-r--r--sys/dev/mps/mps_table.c12
-rw-r--r--sys/dev/mps/mps_user.c28
-rw-r--r--sys/dev/mps/mpsvar.h8
4 files changed, 41 insertions, 64 deletions
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
index 1d935be..ce94a06 100644
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -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, void *sgep, size_t len, int segsleft)
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, void *sgep, size_t len, int segsleft)
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, void *sgep, size_t len, int segsleft)
* 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, void *sgep, size_t len, int segsleft)
* 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, void *sgep, size_t len, int segsleft)
* 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, void *sgep, size_t len, int segsleft)
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, vm_paddr_t pa, size_t len, u_int flags,
/*
* 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_t *segs, int nsegs, bus_size_t mapsize,
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, struct mps_command *cm)
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);
}
diff --git a/sys/dev/mps/mps_table.c b/sys/dev/mps/mps_table.c
index c9acefe..e004f8d 100644
--- a/sys/dev/mps/mps_table.c
+++ b/sys/dev/mps/mps_table.c
@@ -463,10 +463,12 @@ mps_print_sgl(struct mps_softc *sc, struct mps_command *cm, int offset)
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, struct mps_command *cm, int offset)
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
diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c
index 98dc511..ee03573 100644
--- a/sys/dev/mps/mps_user.c
+++ b/sys/dev/mps/mps_user.c
@@ -534,11 +534,6 @@ mpi_pre_fw_upload(struct mps_command *cm, struct mps_usr_command *cmd)
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, struct mps_usr_command *cmd)
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, struct mps_usr_command *cmd)
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, struct mps_usr_command *cmd)
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, struct mps_usr_command *cmd)
}
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,
diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h
index 2acb75b..ac0f0da 100644
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -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
OpenPOWER on IntegriCloud