Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mpr/mpr_user.c
Context not available. | |||||
* Process POST reply. | * Process POST reply. | ||||
*/ | */ | ||||
reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_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) != | if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != | ||||
MPI2_IOCSTATUS_SUCCESS) { | MPI2_IOCSTATUS_SUCCESS) { | ||||
status = MPR_DIAG_FAILURE; | status = MPR_DIAG_FAILURE; | ||||
Context not available. | |||||
* Process RELEASE reply. | * Process RELEASE reply. | ||||
*/ | */ | ||||
reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_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) != | if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != | ||||
MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) { | MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) { | ||||
status = MPR_DIAG_FAILURE; | status = MPR_DIAG_FAILURE; | ||||
Context not available. | |||||
uint32_t *return_code) | uint32_t *return_code) | ||||
{ | { | ||||
mpr_fw_diagnostic_buffer_t *pBuffer; | mpr_fw_diagnostic_buffer_t *pBuffer; | ||||
struct mpr_busdma_context *ctx; | |||||
uint8_t extended_type, buffer_type, i; | uint8_t extended_type, buffer_type, i; | ||||
uint32_t buffer_size; | uint32_t buffer_size; | ||||
uint32_t unique_id; | uint32_t unique_id; | ||||
int status; | int status; | ||||
int error; | |||||
extended_type = diag_register->ExtendedType; | extended_type = diag_register->ExtendedType; | ||||
buffer_type = diag_register->BufferType; | buffer_type = diag_register->BufferType; | ||||
buffer_size = diag_register->RequestedBufferSize; | buffer_size = diag_register->RequestedBufferSize; | ||||
unique_id = diag_register->UniqueId; | unique_id = diag_register->UniqueId; | ||||
ctx = NULL; | |||||
error = 0; | |||||
/* | /* | ||||
* Check for valid buffer type | * Check for valid buffer type | ||||
Context not available. | |||||
*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER; | *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER; | ||||
return (MPR_DIAG_FAILURE); | 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 */ | 1, 0, /* algnmnt, boundary */ | ||||
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ | BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ | ||||
BUS_SPACE_MAXADDR, /* highaddr */ | BUS_SPACE_MAXADDR, /* highaddr */ | ||||
Context not available. | |||||
&sc->fw_diag_dmat)) { | &sc->fw_diag_dmat)) { | ||||
mpr_dprint(sc, MPR_ERROR, | mpr_dprint(sc, MPR_ERROR, | ||||
"Cannot allocate FW diag buffer DMA tag\n"); | "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, | if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer, | ||||
BUS_DMA_NOWAIT, &sc->fw_diag_map)) { | BUS_DMA_NOWAIT, &sc->fw_diag_map)) { | ||||
mpr_dprint(sc, MPR_ERROR, | mpr_dprint(sc, MPR_ERROR, | ||||
"Cannot allocate FW diag buffer memory\n"); | "Cannot allocate FW diag buffer memory\n"); | ||||
return (ENOMEM); | *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER; | ||||
} | status = MPR_DIAG_FAILURE; | ||||
bzero(sc->fw_diag_buffer, buffer_size); | goto bailout; | ||||
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); | 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; | pBuffer->size = buffer_size; | ||||
/* | /* | ||||
Context not available. | |||||
pBuffer->unique_id = unique_id; | pBuffer->unique_id = unique_id; | ||||
status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code); | status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code); | ||||
bailout: | |||||
/* | /* | ||||
* In case there was a failure, free the DMA buffer. | * In case there was a failure, free the DMA buffer. | ||||
*/ | */ | ||||
if (status == MPR_DIAG_FAILURE) { | 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); | 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, | bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer, | ||||
sc->fw_diag_map); | 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); | bus_dma_tag_destroy(sc->fw_diag_dmat); | ||||
sc->fw_diag_dmat = NULL; | |||||
} | |||||
} | } | ||||
if (ctx != NULL) | |||||
free(ctx, M_MPR); | |||||
return (status); | return (status); | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID; | pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID; | ||||
if (status == MPR_DIAG_SUCCESS) { | 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); | 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, | bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer, | ||||
sc->fw_diag_map); | 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); | bus_dma_tag_destroy(sc->fw_diag_dmat); | ||||
sc->fw_diag_dmat = NULL; | |||||
} | |||||
} | } | ||||
return (status); | return (status); | ||||
Context not available. | |||||
return (MPR_DIAG_FAILURE); | 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 | * Copy the requested data from DMA to the diag_read_buffer. The DMA | ||||
* buffer that was allocated is one contiguous buffer. | * buffer that was allocated is one contiguous buffer. | ||||
Context not available. |