Page MenuHomeFreeBSD

D13453.diff
No OneTemporary

D13453.diff

Index: head/sys/dev/mpr/mpr.c
===================================================================
--- head/sys/dev/mpr/mpr.c
+++ head/sys/dev/mpr/mpr.c
@@ -1183,6 +1183,42 @@
*addr = segs[0].ds_addr;
}
+void
+mpr_memaddr_wait_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct mpr_busdma_context *ctx;
+ int need_unload, need_free;
+
+ ctx = (struct mpr_busdma_context *)arg;
+ need_unload = 0;
+ need_free = 0;
+
+ mpr_lock(ctx->softc);
+ ctx->error = error;
+ ctx->completed = 1;
+ if ((error == 0) && (ctx->abandoned == 0)) {
+ *ctx->addr = segs[0].ds_addr;
+ } else {
+ if (nsegs != 0)
+ need_unload = 1;
+ if (ctx->abandoned != 0)
+ need_free = 1;
+ }
+ if (need_free == 0)
+ wakeup(ctx);
+
+ mpr_unlock(ctx->softc);
+
+ if (need_unload != 0) {
+ bus_dmamap_unload(ctx->buffer_dmat,
+ ctx->buffer_dmamap);
+ *ctx->addr = 0;
+ }
+
+ if (need_free != 0)
+ free(ctx, M_MPR);
+}
+
static int
mpr_alloc_queues(struct mpr_softc *sc)
{
Index: head/sys/dev/mpr/mpr_user.c
===================================================================
--- head/sys/dev/mpr/mpr_user.c
+++ head/sys/dev/mpr/mpr_user.c
@@ -1314,6 +1314,13 @@
* Process POST reply.
*/
reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
+ if (reply == NULL) {
+ mpr_printf(sc, "%s: reply is NULL, probably due to "
+ "reinitialization", __func__);
+ status = MPR_DIAG_FAILURE;
+ goto done;
+ }
+
if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) {
status = MPR_DIAG_FAILURE;
@@ -1401,6 +1408,12 @@
* Process RELEASE reply.
*/
reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
+ if (reply == NULL) {
+ mpr_printf(sc, "%s: reply is NULL, probably due to "
+ "reinitialization", __func__);
+ status = MPR_DIAG_FAILURE;
+ goto done;
+ }
if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
status = MPR_DIAG_FAILURE;
@@ -1436,15 +1449,19 @@
uint32_t *return_code)
{
mpr_fw_diagnostic_buffer_t *pBuffer;
+ struct mpr_busdma_context *ctx;
uint8_t extended_type, buffer_type, i;
uint32_t buffer_size;
uint32_t unique_id;
int status;
+ int error;
extended_type = diag_register->ExtendedType;
buffer_type = diag_register->BufferType;
buffer_size = diag_register->RequestedBufferSize;
unique_id = diag_register->UniqueId;
+ ctx = NULL;
+ error = 0;
/*
* Check for valid buffer type
@@ -1493,7 +1510,7 @@
*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
return (MPR_DIAG_FAILURE);
}
- if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */
+ if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */
1, 0, /* algnmnt, boundary */
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -1506,17 +1523,83 @@
&sc->fw_diag_dmat)) {
mpr_dprint(sc, MPR_ERROR,
"Cannot allocate FW diag buffer DMA tag\n");
- return (ENOMEM);
- }
+ *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPR_DIAG_FAILURE;
+ goto bailout;
+ }
if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
mpr_dprint(sc, MPR_ERROR,
"Cannot allocate FW diag buffer memory\n");
- return (ENOMEM);
- }
- bzero(sc->fw_diag_buffer, buffer_size);
- bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map, sc->fw_diag_buffer,
- buffer_size, mpr_memaddr_cb, &sc->fw_diag_busaddr, 0);
+ *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPR_DIAG_FAILURE;
+ goto bailout;
+ }
+ bzero(sc->fw_diag_buffer, buffer_size);
+
+ ctx = malloc(sizeof(*ctx), M_MPR, M_WAITOK | M_ZERO);
+ if (ctx == NULL) {
+ device_printf(sc->mpr_dev, "%s: context malloc failed\n",
+ __func__);
+ *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPR_DIAG_FAILURE;
+ goto bailout;
+ }
+ ctx->addr = &sc->fw_diag_busaddr;
+ ctx->buffer_dmat = sc->fw_diag_dmat;
+ ctx->buffer_dmamap = sc->fw_diag_map;
+ ctx->softc = sc;
+ error = bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map,
+ sc->fw_diag_buffer, buffer_size, mpr_memaddr_wait_cb,
+ ctx, 0);
+ if (error == EINPROGRESS) {
+
+ /* XXX KDM */
+ device_printf(sc->mpr_dev, "%s: Deferred bus_dmamap_load\n",
+ __func__);
+ /*
+ * Wait for the load to complete. If we're interrupted,
+ * bail out.
+ */
+ mpr_lock(sc);
+ if (ctx->completed == 0) {
+ error = msleep(ctx, &sc->mpr_mtx, PCATCH, "mprwait", 0);
+ if (error != 0) {
+ /*
+ * We got an error from msleep(9). This is
+ * most likely due to a signal. Tell
+ * mpr_memaddr_wait_cb() that we've abandoned
+ * the context, so it needs to clean up when
+ * it is called.
+ */
+ ctx->abandoned = 1;
+
+ /* The callback will free this memory */
+ ctx = NULL;
+ mpr_unlock(sc);
+
+ device_printf(sc->mpr_dev, "Cannot "
+ "bus_dmamap_load FW diag buffer, error = "
+ "%d returned from msleep\n", error);
+ *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPR_DIAG_FAILURE;
+ goto bailout;
+ }
+ }
+ mpr_unlock(sc);
+ }
+
+ if ((error != 0) || (ctx->error != 0)) {
+ device_printf(sc->mpr_dev, "Cannot bus_dmamap_load FW diag "
+ "buffer, %serror = %d\n", error ? "" : "callback ",
+ error ? error : ctx->error);
+ *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPR_DIAG_FAILURE;
+ goto bailout;
+ }
+
+ bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map, BUS_DMASYNC_PREREAD);
+
pBuffer->size = buffer_size;
/*
@@ -1535,19 +1618,30 @@
pBuffer->unique_id = unique_id;
status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code);
+bailout:
+
/*
* In case there was a failure, free the DMA buffer.
*/
if (status == MPR_DIAG_FAILURE) {
- if (sc->fw_diag_busaddr != 0)
+ if (sc->fw_diag_busaddr != 0) {
bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
- if (sc->fw_diag_buffer != NULL)
+ sc->fw_diag_busaddr = 0;
+ }
+ if (sc->fw_diag_buffer != NULL) {
bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
sc->fw_diag_map);
- if (sc->fw_diag_dmat != NULL)
+ sc->fw_diag_buffer = NULL;
+ }
+ if (sc->fw_diag_dmat != NULL) {
bus_dma_tag_destroy(sc->fw_diag_dmat);
+ sc->fw_diag_dmat = NULL;
+ }
}
+ if (ctx != NULL)
+ free(ctx, M_MPR);
+
return (status);
}
@@ -1592,13 +1686,19 @@
*/
pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
if (status == MPR_DIAG_SUCCESS) {
- if (sc->fw_diag_busaddr != 0)
+ if (sc->fw_diag_busaddr != 0) {
bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
- if (sc->fw_diag_buffer != NULL)
+ sc->fw_diag_busaddr = 0;
+ }
+ if (sc->fw_diag_buffer != NULL) {
bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
sc->fw_diag_map);
- if (sc->fw_diag_dmat != NULL)
+ sc->fw_diag_buffer = NULL;
+ }
+ if (sc->fw_diag_dmat != NULL) {
bus_dma_tag_destroy(sc->fw_diag_dmat);
+ sc->fw_diag_dmat = NULL;
+ }
}
return (status);
@@ -1707,6 +1807,10 @@
*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
return (MPR_DIAG_FAILURE);
}
+
+ /* Sync the DMA map before we copy to userland. */
+ bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map,
+ BUS_DMASYNC_POSTREAD);
/*
* Copy the requested data from DMA to the diag_read_buffer. The DMA
Index: head/sys/dev/mpr/mprvar.h
===================================================================
--- head/sys/dev/mpr/mprvar.h
+++ head/sys/dev/mpr/mprvar.h
@@ -265,6 +265,16 @@
uint8_t mask[16];
};
+struct mpr_busdma_context {
+ int completed;
+ int abandoned;
+ int error;
+ bus_addr_t *addr;
+ struct mpr_softc *softc;
+ bus_dmamap_t buffer_dmamap;
+ bus_dma_tag_t buffer_dmat;
+};
+
struct mpr_queue {
struct mpr_softc *sc;
int qnum;
@@ -752,6 +762,7 @@
int mpr_read_config_page(struct mpr_softc *, struct mpr_config_params *);
int mpr_write_config_page(struct mpr_softc *, struct mpr_config_params *);
void mpr_memaddr_cb(void *, bus_dma_segment_t *, int , int );
+void mpr_memaddr_wait_cb(void *, bus_dma_segment_t *, int , int );
void mpr_init_sge(struct mpr_command *cm, void *req, void *sge);
int mpr_attach_user(struct mpr_softc *);
void mpr_detach_user(struct mpr_softc *);
Index: head/sys/dev/mps/mps.c
===================================================================
--- head/sys/dev/mps/mps.c
+++ head/sys/dev/mps/mps.c
@@ -111,6 +111,7 @@
SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
+MALLOC_DECLARE(M_MPSUSER);
/*
* Do a "Diagnostic Reset" aka a hard reset. This should get the chip out of
@@ -1158,6 +1159,42 @@
addr = arg;
*addr = segs[0].ds_addr;
+}
+
+void
+mps_memaddr_wait_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct mps_busdma_context *ctx;
+ int need_unload, need_free;
+
+ ctx = (struct mps_busdma_context *)arg;
+ need_unload = 0;
+ need_free = 0;
+
+ mps_lock(ctx->softc);
+ ctx->error = error;
+ ctx->completed = 1;
+ if ((error == 0) && (ctx->abandoned == 0)) {
+ *ctx->addr = segs[0].ds_addr;
+ } else {
+ if (nsegs != 0)
+ need_unload = 1;
+ if (ctx->abandoned != 0)
+ need_free = 1;
+ }
+ if (need_free == 0)
+ wakeup(ctx);
+
+ mps_unlock(ctx->softc);
+
+ if (need_unload != 0) {
+ bus_dmamap_unload(ctx->buffer_dmat,
+ ctx->buffer_dmamap);
+ *ctx->addr = 0;
+ }
+
+ if (need_free != 0)
+ free(ctx, M_MPSUSER);
}
static int
Index: head/sys/dev/mps/mps_user.c
===================================================================
--- head/sys/dev/mps/mps_user.c
+++ head/sys/dev/mps/mps_user.c
@@ -180,7 +180,7 @@
static int mps_user_reg_access(struct mps_softc *sc, mps_reg_access_t *data);
static int mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data);
-static MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
+MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
/* Macros from compat/freebsd32/freebsd32.h */
#define PTRIN(v) (void *)(uintptr_t)(v)
@@ -1222,6 +1222,12 @@
* Process POST reply.
*/
reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
+ if (reply == NULL) {
+ mps_printf(sc, "%s: reply is NULL, probably due to "
+ "reinitialization\n", __func__);
+ status = MPS_DIAG_FAILURE;
+ goto done;
+ }
if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) {
status = MPS_DIAG_FAILURE;
@@ -1309,6 +1315,12 @@
* Process RELEASE reply.
*/
reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
+ if (reply == NULL) {
+ mps_printf(sc, "%s: reply is NULL, probably due to "
+ "reinitialization\n", __func__);
+ status = MPS_DIAG_FAILURE;
+ goto done;
+ }
if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
status = MPS_DIAG_FAILURE;
@@ -1344,15 +1356,19 @@
uint32_t *return_code)
{
mps_fw_diagnostic_buffer_t *pBuffer;
+ struct mps_busdma_context *ctx;
uint8_t extended_type, buffer_type, i;
uint32_t buffer_size;
uint32_t unique_id;
int status;
+ int error;
extended_type = diag_register->ExtendedType;
buffer_type = diag_register->BufferType;
buffer_size = diag_register->RequestedBufferSize;
unique_id = diag_register->UniqueId;
+ ctx = NULL;
+ error = 0;
/*
* Check for valid buffer type
@@ -1401,7 +1417,7 @@
*return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
return (MPS_DIAG_FAILURE);
}
- if (bus_dma_tag_create( sc->mps_parent_dmat, /* parent */
+ if (bus_dma_tag_create( sc->mps_parent_dmat, /* parent */
1, 0, /* algnmnt, boundary */
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -1414,17 +1430,84 @@
&sc->fw_diag_dmat)) {
mps_dprint(sc, MPS_ERROR,
"Cannot allocate FW diag buffer DMA tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
+ *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPS_DIAG_FAILURE;
+ goto bailout;
+ }
+ if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
mps_dprint(sc, MPS_ERROR,
"Cannot allocate FW diag buffer memory\n");
- return (ENOMEM);
+ *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPS_DIAG_FAILURE;
+ goto bailout;
}
bzero(sc->fw_diag_buffer, buffer_size);
- bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map, sc->fw_diag_buffer,
- buffer_size, mps_memaddr_cb, &sc->fw_diag_busaddr, 0);
+
+ ctx = malloc(sizeof(*ctx), M_MPSUSER, M_WAITOK | M_ZERO);
+ if (ctx == NULL) {
+ device_printf(sc->mps_dev, "%s: context malloc failed\n",
+ __func__);
+ *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPS_DIAG_FAILURE;
+ goto bailout;
+ }
+ ctx->addr = &sc->fw_diag_busaddr;
+ ctx->buffer_dmat = sc->fw_diag_dmat;
+ ctx->buffer_dmamap = sc->fw_diag_map;
+ ctx->softc = sc;
+ error = bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map,
+ sc->fw_diag_buffer, buffer_size, mps_memaddr_wait_cb,
+ ctx, 0);
+
+ if (error == EINPROGRESS) {
+
+ /* XXX KDM */
+ device_printf(sc->mps_dev, "%s: Deferred bus_dmamap_load\n",
+ __func__);
+ /*
+ * Wait for the load to complete. If we're interrupted,
+ * bail out.
+ */
+ mps_lock(sc);
+ if (ctx->completed == 0) {
+ error = msleep(ctx, &sc->mps_mtx, PCATCH, "mpswait", 0);
+ if (error != 0) {
+ /*
+ * We got an error from msleep(9). This is
+ * most likely due to a signal. Tell
+ * mpr_memaddr_wait_cb() that we've abandoned
+ * the context, so it needs to clean up when
+ * it is called.
+ */
+ ctx->abandoned = 1;
+
+ /* The callback will free this memory */
+ ctx = NULL;
+ mps_unlock(sc);
+
+ device_printf(sc->mps_dev, "Cannot "
+ "bus_dmamap_load FW diag buffer, error = "
+ "%d returned from msleep\n", error);
+ *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPS_DIAG_FAILURE;
+ goto bailout;
+ }
+ }
+ mps_unlock(sc);
+ }
+
+ if ((error != 0) || (ctx->error != 0)) {
+ device_printf(sc->mps_dev, "Cannot bus_dmamap_load FW diag "
+ "buffer, %serror = %d\n", error ? "" : "callback ",
+ error ? error : ctx->error);
+ *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+ status = MPS_DIAG_FAILURE;
+ goto bailout;
+ }
+
+ bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map, BUS_DMASYNC_PREREAD);
+
pBuffer->size = buffer_size;
/*
@@ -1443,19 +1526,29 @@
pBuffer->unique_id = unique_id;
status = mps_post_fw_diag_buffer(sc, pBuffer, return_code);
+bailout:
/*
* In case there was a failure, free the DMA buffer.
*/
if (status == MPS_DIAG_FAILURE) {
- if (sc->fw_diag_busaddr != 0)
+ if (sc->fw_diag_busaddr != 0) {
bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
- if (sc->fw_diag_buffer != NULL)
+ sc->fw_diag_busaddr = 0;
+ }
+ if (sc->fw_diag_buffer != NULL) {
bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
sc->fw_diag_map);
- if (sc->fw_diag_dmat != NULL)
+ sc->fw_diag_buffer = NULL;
+ }
+ if (sc->fw_diag_dmat != NULL) {
bus_dma_tag_destroy(sc->fw_diag_dmat);
+ sc->fw_diag_dmat = NULL;
+ }
}
+ if (ctx != NULL)
+ free(ctx, M_MPSUSER);
+
return (status);
}
@@ -1500,13 +1593,19 @@
*/
pBuffer->unique_id = MPS_FW_DIAG_INVALID_UID;
if (status == MPS_DIAG_SUCCESS) {
- if (sc->fw_diag_busaddr != 0)
+ if (sc->fw_diag_busaddr != 0) {
bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
- if (sc->fw_diag_buffer != NULL)
+ sc->fw_diag_busaddr = 0;
+ }
+ if (sc->fw_diag_buffer != NULL) {
bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
sc->fw_diag_map);
- if (sc->fw_diag_dmat != NULL)
+ sc->fw_diag_buffer = NULL;
+ }
+ if (sc->fw_diag_dmat != NULL) {
bus_dma_tag_destroy(sc->fw_diag_dmat);
+ sc->fw_diag_dmat = NULL;
+ }
}
return (status);
@@ -1615,6 +1714,10 @@
*return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
return (MPS_DIAG_FAILURE);
}
+
+ /* Sync the DMA map before we copy to userland. */
+ bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map,
+ BUS_DMASYNC_POSTREAD);
/*
* Copy the requested data from DMA to the diag_read_buffer. The DMA
Index: head/sys/dev/mps/mpsvar.h
===================================================================
--- head/sys/dev/mps/mpsvar.h
+++ head/sys/dev/mps/mpsvar.h
@@ -263,6 +263,16 @@
u32 mask[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
};
+struct mps_busdma_context {
+ int completed;
+ int abandoned;
+ int error;
+ bus_addr_t *addr;
+ struct mps_softc *softc;
+ bus_dmamap_t buffer_dmamap;
+ bus_dma_tag_t buffer_dmat;
+};
+
struct mps_queue {
struct mps_softc *sc;
int qnum;
@@ -719,6 +729,7 @@
int mps_read_config_page(struct mps_softc *, struct mps_config_params *);
int mps_write_config_page(struct mps_softc *, struct mps_config_params *);
void mps_memaddr_cb(void *, bus_dma_segment_t *, int , int );
+void mps_memaddr_wait_cb(void *, bus_dma_segment_t *, int , int );
void mpi_init_sge(struct mps_command *cm, void *req, void *sge);
int mps_attach_user(struct mps_softc *);
void mps_detach_user(struct mps_softc *);

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 2, 7:38 PM (19 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13385544
Default Alt Text
D13453.diff (16 KB)

Event Timeline