Diagnostic buffer fixes for the mps(4) and mpr(4) drivers.

In mp{r,s}_diag_register(), which is used to register diagnostic
buffers with the mp{r,s}(4) firmware, we allocate DMAable memory.

There were several issues here:
 o No checking of the bus_dmamap_load() return value.  If the load
   failed or got deferred, mp{r,s}_diag_register() continued on as if
   nothing had happened.  We now check the return value and bail
   out if it fails.

 o No waiting for a deferred load callback.  bus_dmamap_load()
   calls a supplied callback when the mapping is done.  This is
   generally done immediately, but it can be deferred.
   mp{r,s}_diag_register() did not check to see whether the callback
   was already done before proceeding on.  We now sleep until the
   callback is done if it is deferred.

 o No call to bus_dmamap_sync(... BUS_DMASYNC_PREREAD) after the
   memory is allocated and loaded.  This is necessary on some
   platforms to synchronize host memory that is going to be updated
   by a device.

Both drivers would also panic if the firmware was reinitialized while
a diagnostic buffer operation was in progress.  This fixes that problem
as well.  (The driver will reinitialize the firmware in various
circumstances, but the problem I ran into was that the firmware would
generate an IOC Fault due to a PCIe error.)

mp{r,s}var.h:
	Add a new structure, struct mpr_busdma_context, that is
	used for deferred busdma load callbacks.

	Add a prototype for mp{r,s}_memaddr_wait_cb().
mp{r,s}.c:
	Add a new busdma callback function, mp{r,s}_memaddr_wait_cb().
	This provides synchronization for callers that want to
	wait on a deferred bus_dmamap_load() callback.

mp{r,s}_user.c:
	In bus_dmamap_register(), add a call to bus_dmamap_sync()
	with the BUS_DMASYNC_PREREAD flag set after an allocation
	is loaded.

	Also, check the return value of bus_dmamap_load().  If it
	fails, bail out.  If it is EINPROGRESS, wait for the
	callback to happen.  We use an interruptible sleep (msleep
	with PCATCH) and let the callback clean things up if we get
	interrupted.

	In mpr_diag_read_buffer() and mps_diag_read_buffer(), call
	bus_dmamap_sync(..., BUS_DMASYNC_POSTREAD) before copying
	the data out to make sure the data is in stable storage.

	In mp{r,s}_post_fw_diag_buffer() and
	mp{r,s}_release_fw_diag_buffer(), check the reply to see
	whether it is NULL.  It can be NULL (and the command non-NULL)
	if the controller gets reinitialized while we're waiting for
	the command to complete but the driver structures aren't
	reallocated.  The driver structures generally won't be
	reallocated unless there is a firmware upgrade that changes
	one of the IOCFacts.

	When freeing diagnostic buffers in mp{r,s}_diag_register()
	and mp{r,s}_diag_unregister(), zero/NULL out the buffer after
	freeing it.  This will prevent a duplicate free in some
	situations.

Sponsored by:	Spectra Logic
Reviewed by:	mav, scottl
MFC after:	1 week
Differential Revision:	D13453
This commit is contained in:
Kenneth D. Merry 2018-02-06 15:58:22 +00:00
parent 95eff7c0c3
commit e2997a03b7
6 changed files with 330 additions and 28 deletions

View File

@ -1183,6 +1183,42 @@ mpr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
*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)
{

View File

@ -1314,6 +1314,13 @@ mpr_post_fw_diag_buffer(struct mpr_softc *sc,
* 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 @@ mpr_release_fw_diag_buffer(struct mpr_softc *sc,
* 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 @@ mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
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 @@ mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
*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 @@ mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
&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 @@ mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
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 @@ mpr_diag_unregister(struct mpr_softc *sc,
*/
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);
@ -1708,6 +1808,10 @@ mpr_diag_read_buffer(struct mpr_softc *sc,
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
* buffer that was allocated is one contiguous buffer.

View File

@ -265,6 +265,16 @@ struct mpr_event_handle {
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_detach_sas(struct mpr_softc *sc);
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 *);

View File

@ -111,6 +111,7 @@ static void mps_parse_debug(struct mps_softc *sc, char *list);
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
@ -1160,6 +1161,42 @@ mps_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
*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
mps_alloc_queues(struct mps_softc *sc)
{

View File

@ -180,7 +180,7 @@ static int mps_user_event_report(struct mps_softc *sc,
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 @@ mps_post_fw_diag_buffer(struct mps_softc *sc,
* 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 @@ mps_release_fw_diag_buffer(struct mps_softc *sc,
* 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 @@ mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
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 @@ mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
*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 @@ mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
&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 @@ mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
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 @@ mps_diag_unregister(struct mps_softc *sc,
*/
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);
@ -1616,6 +1715,10 @@ mps_diag_read_buffer(struct mps_softc *sc,
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
* buffer that was allocated is one contiguous buffer.

View File

@ -263,6 +263,16 @@ struct mps_event_handle {
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_detach_sas(struct mps_softc *sc);
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 *);