Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/mpr/mpr_user.c
Show First 20 Lines • Show All 1,308 Lines • ▼ Show 20 Lines | if (status || (cm == NULL)) { | ||||
status = MPR_DIAG_FAILURE; | status = MPR_DIAG_FAILURE; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* | /* | ||||
* 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; | ||||
mpr_dprint(sc, MPR_FAULT, "%s: post of FW Diag Buffer failed " | mpr_dprint(sc, MPR_FAULT, "%s: post of FW Diag Buffer failed " | ||||
"with IOCStatus = 0x%x, IOCLogInfo = 0x%x and " | "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and " | ||||
"TransferLength = 0x%x\n", __func__, | "TransferLength = 0x%x\n", __func__, | ||||
le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo), | le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo), | ||||
le32toh(reply->TransferLength)); | le32toh(reply->TransferLength)); | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (status || (cm == NULL)) { | ||||
status = MPR_DIAG_FAILURE; | status = MPR_DIAG_FAILURE; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* | /* | ||||
* 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; | ||||
mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer " | mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer " | ||||
"failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n", | "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n", | ||||
__func__, le16toh(reply->IOCStatus), | __func__, le16toh(reply->IOCStatus), | ||||
le32toh(reply->IOCLogInfo)); | le32toh(reply->IOCLogInfo)); | ||||
goto done; | goto done; | ||||
Show All 19 Lines | done: | ||||
return (status); | return (status); | ||||
} | } | ||||
static int | static int | ||||
mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, | mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, | ||||
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 | ||||
*/ | */ | ||||
if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) { | if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) { | ||||
*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; | *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; | ||||
return (MPR_DIAG_FAILURE); | return (MPR_DIAG_FAILURE); | ||||
} | } | ||||
Show All 32 Lines | mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, | ||||
/* | /* | ||||
* Post a new buffer after checking if it's enabled. The DMA buffer | * Post a new buffer after checking if it's enabled. The DMA buffer | ||||
* that is allocated will be contiguous (nsegments = 1). | * that is allocated will be contiguous (nsegments = 1). | ||||
*/ | */ | ||||
if (!pBuffer->enabled) { | if (!pBuffer->enabled) { | ||||
*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 */ | ||||
NULL, NULL, /* filter, filterarg */ | NULL, NULL, /* filter, filterarg */ | ||||
buffer_size, /* maxsize */ | buffer_size, /* maxsize */ | ||||
1, /* nsegments */ | 1, /* nsegments */ | ||||
buffer_size, /* maxsegsize */ | buffer_size, /* maxsegsize */ | ||||
0, /* flags */ | 0, /* flags */ | ||||
NULL, NULL, /* lockfunc, lockarg */ | NULL, NULL, /* lockfunc, lockarg */ | ||||
&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; | |||||
goto bailout; | |||||
} | } | ||||
bzero(sc->fw_diag_buffer, buffer_size); | 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); | 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; | ||||
/* | /* | ||||
* Copy the given info to the diag buffer and post the buffer. | * Copy the given info to the diag buffer and post the buffer. | ||||
*/ | */ | ||||
pBuffer->buffer_type = buffer_type; | pBuffer->buffer_type = buffer_type; | ||||
pBuffer->immediate = FALSE; | pBuffer->immediate = FALSE; | ||||
if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) { | if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) { | ||||
for (i = 0; i < (sizeof (pBuffer->product_specific) / 4); | for (i = 0; i < (sizeof (pBuffer->product_specific) / 4); | ||||
i++) { | i++) { | ||||
pBuffer->product_specific[i] = | pBuffer->product_specific[i] = | ||||
diag_register->ProductSpecific[i]; | diag_register->ProductSpecific[i]; | ||||
} | } | ||||
} | } | ||||
pBuffer->extended_type = extended_type; | pBuffer->extended_type = extended_type; | ||||
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); | ||||
} | } | ||||
static int | static int | ||||
mpr_diag_unregister(struct mpr_softc *sc, | mpr_diag_unregister(struct mpr_softc *sc, | ||||
mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code) | mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code) | ||||
{ | { | ||||
mpr_fw_diagnostic_buffer_t *pBuffer; | mpr_fw_diagnostic_buffer_t *pBuffer; | ||||
Show All 28 Lines | mpr_diag_unregister(struct mpr_softc *sc, | ||||
} | } | ||||
/* | /* | ||||
* At this point, return the current status no matter what happens with | * At this point, return the current status no matter what happens with | ||||
* the DMA buffer. | * the DMA buffer. | ||||
*/ | */ | ||||
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); | ||||
} | } | ||||
static int | static int | ||||
mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query, | mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query, | ||||
uint32_t *return_code) | uint32_t *return_code) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | mpr_diag_read_buffer(struct mpr_softc *sc, | ||||
/* | /* | ||||
* Make sure requested read is within limits | * Make sure requested read is within limits | ||||
*/ | */ | ||||
if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead > | if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead > | ||||
pBuffer->size) { | pBuffer->size) { | ||||
*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; | *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; | ||||
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. | ||||
*/ | */ | ||||
pData = (uint8_t *)(sc->fw_diag_buffer + | pData = (uint8_t *)(sc->fw_diag_buffer + | ||||
diag_read_buffer->StartingOffset); | diag_read_buffer->StartingOffset); | ||||
if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0) | if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0) | ||||
▲ Show 20 Lines • Show All 802 Lines • Show Last 20 Lines |