Changeset View
Standalone View
sys/dev/mpr/mpr.c
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
static void mpr_periodic(void *); | static void mpr_periodic(void *); | ||||
static int mpr_reregister_events(struct mpr_softc *sc); | static int mpr_reregister_events(struct mpr_softc *sc); | ||||
static void mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm); | static void mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm); | ||||
static int mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts); | static int mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts); | ||||
static int mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag); | static int mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag); | ||||
static int mpr_debug_sysctl(SYSCTL_HANDLER_ARGS); | static int mpr_debug_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int mpr_dump_reqs(SYSCTL_HANDLER_ARGS); | static int mpr_dump_reqs(SYSCTL_HANDLER_ARGS); | ||||
static void mpr_parse_debug(struct mpr_softc *sc, char *list); | static void mpr_parse_debug(struct mpr_softc *sc, char *list); | ||||
static void adjust_iocfacts_endianness(MPI2_IOC_FACTS_REPLY *facts); | |||||
SYSCTL_NODE(_hw, OID_AUTO, mpr, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_hw, OID_AUTO, mpr, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
"MPR Driver Parameters"); | "MPR Driver Parameters"); | ||||
MALLOC_DEFINE(M_MPR, "mpr", "mpr driver memory"); | MALLOC_DEFINE(M_MPR, "mpr", "mpr driver memory"); | ||||
/* | /* | ||||
* Do a "Diagnostic Reset" aka a hard reset. This should get the chip out of | * Do a "Diagnostic Reset" aka a hard reset. This should get the chip out of | ||||
▲ Show 20 Lines • Show All 286 Lines • ▼ Show 20 Lines | mpr_resize_queues(struct mpr_softc *sc) | ||||
* Gen3 and beyond uses the IOCMaxChainSegmentSize from IOC Facts to | * Gen3 and beyond uses the IOCMaxChainSegmentSize from IOC Facts to | ||||
* get the size of a Chain Frame. Previous versions use the size as a | * get the size of a Chain Frame. Previous versions use the size as a | ||||
* Request Frame for the Chain Frame size. If IOCMaxChainSegmentSize | * Request Frame for the Chain Frame size. If IOCMaxChainSegmentSize | ||||
* is 0, use the default value. The IOCMaxChainSegmentSize is the | * is 0, use the default value. The IOCMaxChainSegmentSize is the | ||||
* number of 16-byte elelements that can fit in a Chain Frame, which is | * number of 16-byte elelements that can fit in a Chain Frame, which is | ||||
* the size of an IEEE Simple SGE. | * the size of an IEEE Simple SGE. | ||||
*/ | */ | ||||
if (sc->facts->MsgVersion >= MPI2_VERSION_02_05) { | if (sc->facts->MsgVersion >= MPI2_VERSION_02_05) { | ||||
chain_seg_size = htole16(sc->facts->IOCMaxChainSegmentSize); | chain_seg_size = sc->facts->IOCMaxChainSegmentSize; | ||||
if (chain_seg_size == 0) | if (chain_seg_size == 0) | ||||
chain_seg_size = MPR_DEFAULT_CHAIN_SEG_SIZE; | chain_seg_size = MPR_DEFAULT_CHAIN_SEG_SIZE; | ||||
sc->chain_frame_size = chain_seg_size * | sc->chain_frame_size = chain_seg_size * | ||||
MPR_MAX_CHAIN_ELEMENT_SIZE; | MPR_MAX_CHAIN_ELEMENT_SIZE; | ||||
} else { | } else { | ||||
sc->chain_frame_size = sc->reqframesz; | sc->chain_frame_size = sc->reqframesz; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 624 Lines • ▼ Show 20 Lines | mpr_request_sync(struct mpr_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply, | ||||
* message is always in the 4th byte, so clock out the first 2 words | * message is always in the 4th byte, so clock out the first 2 words | ||||
* manually, then loop the rest. | * manually, then loop the rest. | ||||
*/ | */ | ||||
data16 = (uint16_t *)reply; | data16 = (uint16_t *)reply; | ||||
if (mpr_wait_db_int(sc) != 0) { | if (mpr_wait_db_int(sc) != 0) { | ||||
mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell 0\n"); | mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell 0\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* | |||||
* If in a BE platform, swap bytes using le16toh to not | |||||
* disturb 8 bit field neighbors in destination structure | |||||
* pointed by data16. | |||||
*/ | |||||
data16[0] = | data16[0] = | ||||
luporl: Why data16[0] is not converted with le16toh() while the other elements of data16[] are? | |||||
Done Inline ActionsIt looks like the first 16 bits of MPI2_DEFAULT_REPLY are not used afscoelho_gmail.com: It looks like the first 16 bits of MPI2_DEFAULT_REPLY are not used | |||||
Done Inline ActionsOk, but I would use le16toh() here too, just in case the first 16 bits are used someday and for consistency with the other data16 elements that are all being converted. luporl: Ok, but I would use le16toh() here too, just in case the first 16 bits are used someday and for… | |||||
mpr_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK; | le16toh(mpr_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK); | ||||
scottlUnsubmitted Done Inline ActionsAs stated previously, this is wrong. The le16toh() call should wrap just the return from mpr_regread(), and not include the bitwise & operation and the MPI2_DOORBELL_DATA_MASK macro. scottl: As stated previously, this is wrong. The `le16toh()` call should wrap just the return from… | |||||
mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | ||||
if (mpr_wait_db_int(sc) != 0) { | if (mpr_wait_db_int(sc) != 0) { | ||||
mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell 1\n"); | mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell 1\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
data16[1] = | data16[1] = | ||||
mpr_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK; | le16toh(mpr_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK); | ||||
Done Inline ActionsThis part is a bit confusing. mpr_regread() uses bus_space_read_4() that, on big-endian (BE) platforms, already converts from little-endian (LE) to big-endian, right? IIUC, adjust_iocfacts_endianness() is the part that really fixes the endianess of the reply, with several leXXtoh() calls, as it has the knowledge of the fields present in the reply. And the comment there tell us that these le16toh() calls here are only needed to preserve U8 fields in their original offsets. So my suggestion here is to change all data16[] conversions to be16toh(), to make it clear what is happening. luporl: This part is a bit confusing.
`mpr_regread()` uses `bus_space_read_4()` that, on big-endian… | |||||
Done Inline ActionsIt is a bit confusing, yes. If not swapping values here, adjust_iocfacts_endianness would have to adjust 8 bit fields with adjacent fields, and I thought it would be even more confusing. The suggestion of be16toh is a good one, thanks. afscoelho_gmail.com: It is a bit confusing, yes. If not swapping values here, adjust_iocfacts_endianness would have… | |||||
Done Inline ActionsYou need 2 more spaces here. luporl: You need 2 more spaces here. | |||||
mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | ||||
/* Number of 32bit words in the message */ | /* Number of 32bit words in the message */ | ||||
ioc_sz = reply->MsgLength; | ioc_sz = reply->MsgLength; | ||||
/* | /* | ||||
* Figure out how many 16bit words to clock in without overrunning. | * Figure out how many 16bit words to clock in without overrunning. | ||||
* The precision loss with dividing reply_sz can safely be | * The precision loss with dividing reply_sz can safely be | ||||
* ignored because the messages can only be multiples of 32bits. | * ignored because the messages can only be multiples of 32bits. | ||||
*/ | */ | ||||
residual = 0; | residual = 0; | ||||
count = MIN((reply_sz / 4), ioc_sz) * 2; | count = MIN((reply_sz / 4), ioc_sz) * 2; | ||||
if (count < ioc_sz * 2) { | if (count < ioc_sz * 2) { | ||||
residual = ioc_sz * 2 - count; | residual = ioc_sz * 2 - count; | ||||
mpr_dprint(sc, MPR_ERROR, "Driver error, throwing away %d " | mpr_dprint(sc, MPR_ERROR, "Driver error, throwing away %d " | ||||
"residual message words\n", residual); | "residual message words\n", residual); | ||||
} | } | ||||
for (i = 2; i < count; i++) { | for (i = 2; i < count; i++) { | ||||
if (mpr_wait_db_int(sc) != 0) { | if (mpr_wait_db_int(sc) != 0) { | ||||
mpr_dprint(sc, MPR_FAULT, | mpr_dprint(sc, MPR_FAULT, | ||||
"Timeout reading doorbell %d\n", i); | "Timeout reading doorbell %d\n", i); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
data16[i] = mpr_regread(sc, MPI2_DOORBELL_OFFSET) & | data16[i] = le16toh(mpr_regread(sc, MPI2_DOORBELL_OFFSET) & | ||||
MPI2_DOORBELL_DATA_MASK; | MPI2_DOORBELL_DATA_MASK); | ||||
scottlUnsubmitted Done Inline ActionsYeah, as above, I have no idea how this can work on a BE platform. scottl: Yeah, as above, I have no idea how this can work on a BE platform. | |||||
mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | mpr_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0); | ||||
} | } | ||||
/* | /* | ||||
Done Inline ActionsIt would be better to put this comment before the first use of le16toh() data16. luporl: It would be better to put this comment before the first use of le16toh() data16. | |||||
* Pull out residual words that won't fit into the provided buffer. | * Pull out residual words that won't fit into the provided buffer. | ||||
* This keeps the chip from hanging due to a driver programming | * This keeps the chip from hanging due to a driver programming | ||||
* error. | * error. | ||||
*/ | */ | ||||
while (residual--) { | while (residual--) { | ||||
if (mpr_wait_db_int(sc) != 0) { | if (mpr_wait_db_int(sc) != 0) { | ||||
mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell\n"); | mpr_dprint(sc, MPR_FAULT, "Timeout reading doorbell\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
Show All 33 Lines | mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm) | ||||
KASSERT(cm->cm_state == MPR_CM_STATE_BUSY, ("command not busy\n")); | KASSERT(cm->cm_state == MPR_CM_STATE_BUSY, ("command not busy\n")); | ||||
cm->cm_state = MPR_CM_STATE_INQUEUE; | cm->cm_state = MPR_CM_STATE_INQUEUE; | ||||
if (sc->atomic_desc_capable) { | if (sc->atomic_desc_capable) { | ||||
rd.u.low = cm->cm_desc.Words.Low; | rd.u.low = cm->cm_desc.Words.Low; | ||||
mpr_regwrite(sc, MPI26_ATOMIC_REQUEST_DESCRIPTOR_POST_OFFSET, | mpr_regwrite(sc, MPI26_ATOMIC_REQUEST_DESCRIPTOR_POST_OFFSET, | ||||
rd.u.low); | rd.u.low); | ||||
} else { | } else { | ||||
rd.u.low = cm->cm_desc.Words.Low; | rd.u.low = htole32(cm->cm_desc.Words.Low); | ||||
rd.u.high = cm->cm_desc.Words.High; | rd.u.high = htole32(cm->cm_desc.Words.High); | ||||
scottlUnsubmitted Not Done Inline ActionsProbably makes sense to pre-swap these values. Not necessary for this review, however. scottl: Probably makes sense to pre-swap these values. Not necessary for this review, however. | |||||
rd.word = htole64(rd.word); | |||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET, | mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET, | ||||
rd.u.low); | rd.u.low); | ||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET, | mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET, | ||||
rd.u.high); | rd.u.high); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Ioc facts are read in 16 bit words and and stored with le16toh, | |||||
* this takes care of proper U8 fields endianness in | |||||
* MPI2_IOC_FACTS_REPLY, but we still need to swap back U16 fields. | |||||
Not Done Inline ActionsThis function swaps U16 and U32 fields. luporl: This function swaps U16 and U32 fields. | |||||
*/ | |||||
static void | |||||
adjust_iocfacts_endianness(MPI2_IOC_FACTS_REPLY *facts) | |||||
{ | |||||
facts->HeaderVersion = le16toh(facts->HeaderVersion); | |||||
facts->Reserved1 = le16toh(facts->Reserved1); | |||||
facts->IOCExceptions = le16toh(facts->IOCExceptions); | |||||
facts->IOCStatus = le16toh(facts->IOCStatus); | |||||
facts->IOCLogInfo = le32toh(facts->IOCLogInfo); | |||||
facts->RequestCredit = le16toh(facts->RequestCredit); | |||||
facts->ProductID = le16toh(facts->ProductID); | |||||
facts->IOCCapabilities = le32toh(facts->IOCCapabilities); | |||||
facts->IOCRequestFrameSize = le16toh(facts->IOCRequestFrameSize); | |||||
Done Inline ActionsWhy do you need two calls to le32toh()here, with masks, instead of only one with no mask? luporl: Why do you need two calls to `le32toh()`here, with masks, instead of only one with no mask? | |||||
facts->IOCMaxChainSegmentSize = le16toh(facts->IOCMaxChainSegmentSize); | |||||
facts->MaxInitiators = le16toh(facts->MaxInitiators); | |||||
facts->MaxTargets = le16toh(facts->MaxTargets); | |||||
facts->MaxSasExpanders = le16toh(facts->MaxSasExpanders); | |||||
facts->MaxEnclosures = le16toh(facts->MaxEnclosures); | |||||
facts->ProtocolFlags = le16toh(facts->ProtocolFlags); | |||||
facts->HighPriorityCredit = le16toh(facts->HighPriorityCredit); | |||||
facts->MaxReplyDescriptorPostQueueDepth = le16toh(facts->MaxReplyDescriptorPostQueueDepth); | |||||
facts->MaxDevHandle = le16toh(facts->MaxDevHandle); | |||||
facts->MaxPersistentEntries = le16toh(facts->MaxPersistentEntries); | |||||
facts->MinDevHandle = le16toh(facts->MinDevHandle); | |||||
} | |||||
Done Inline ActionsIndentation is wrong. Each level of indentation must be a (non-expanded) tab. 4 extra spaces should be used when continuing a line of code. See style(9). luporl: Indentation is wrong.
Each level of indentation must be a (non-expanded) tab. 4 extra spaces… | |||||
/* | |||||
* Just the FACTS, ma'am. | * Just the FACTS, ma'am. | ||||
*/ | */ | ||||
static int | static int | ||||
mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts) | mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts) | ||||
{ | { | ||||
MPI2_DEFAULT_REPLY *reply; | MPI2_DEFAULT_REPLY *reply; | ||||
MPI2_IOC_FACTS_REQUEST request; | MPI2_IOC_FACTS_REQUEST request; | ||||
int error, req_sz, reply_sz; | int error, req_sz, reply_sz; | ||||
MPR_FUNCTRACE(sc); | MPR_FUNCTRACE(sc); | ||||
mpr_dprint(sc, MPR_INIT, "%s entered\n", __func__); | mpr_dprint(sc, MPR_INIT, "%s entered\n", __func__); | ||||
req_sz = sizeof(MPI2_IOC_FACTS_REQUEST); | req_sz = sizeof(MPI2_IOC_FACTS_REQUEST); | ||||
reply_sz = sizeof(MPI2_IOC_FACTS_REPLY); | reply_sz = sizeof(MPI2_IOC_FACTS_REPLY); | ||||
reply = (MPI2_DEFAULT_REPLY *)facts; | reply = (MPI2_DEFAULT_REPLY *)facts; | ||||
bzero(&request, req_sz); | bzero(&request, req_sz); | ||||
request.Function = MPI2_FUNCTION_IOC_FACTS; | request.Function = MPI2_FUNCTION_IOC_FACTS; | ||||
error = mpr_request_sync(sc, &request, reply, req_sz, reply_sz, 5); | error = mpr_request_sync(sc, &request, reply, req_sz, reply_sz, 5); | ||||
adjust_iocfacts_endianness(facts); | |||||
mpr_dprint(sc, MPR_TRACE, "facts->IOCCapabilities 0x%x\n", facts->IOCCapabilities); | |||||
mpr_dprint(sc, MPR_INIT, "%s exit, error= %d\n", __func__, error); | mpr_dprint(sc, MPR_INIT, "%s exit, error= %d\n", __func__, error); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
mpr_send_iocinit(struct mpr_softc *sc) | mpr_send_iocinit(struct mpr_softc *sc) | ||||
{ | { | ||||
MPI2_IOC_INIT_REQUEST init; | MPI2_IOC_INIT_REQUEST init; | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | mpr_send_iocinit(struct mpr_softc *sc) | ||||
init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr); | init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr); | ||||
getmicrotime(&now); | getmicrotime(&now); | ||||
time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000); | time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000); | ||||
init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF); | init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF); | ||||
init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF); | init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF); | ||||
init.HostPageSize = HOST_PAGE_SIZE_4K; | init.HostPageSize = HOST_PAGE_SIZE_4K; | ||||
error = mpr_request_sync(sc, &init, &reply, req_sz, reply_sz, 5); | error = mpr_request_sync(sc, &init, &reply, req_sz, reply_sz, 5); | ||||
if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) | if ((le16toh(reply.IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) | ||||
error = ENXIO; | error = ENXIO; | ||||
mpr_dprint(sc, MPR_INIT, "IOCInit status= 0x%x\n", reply.IOCStatus); | mpr_dprint(sc, MPR_INIT, "IOCInit status= 0x%x\n", le16toh(reply.IOCStatus)); | ||||
mpr_dprint(sc, MPR_INIT, "%s exit\n", __func__); | mpr_dprint(sc, MPR_INIT, "%s exit\n", __func__); | ||||
return (error); | return (error); | ||||
} | } | ||||
void | void | ||||
mpr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) | mpr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) | ||||
{ | { | ||||
bus_addr_t *addr; | bus_addr_t *addr; | ||||
▲ Show 20 Lines • Show All 288 Lines • ▼ Show 20 Lines | if (!sc->commands) { | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
for (i = 1; i < sc->num_reqs; i++) { | for (i = 1; i < sc->num_reqs; i++) { | ||||
cm = &sc->commands[i]; | cm = &sc->commands[i]; | ||||
cm->cm_req = sc->req_frames + i * sc->reqframesz; | cm->cm_req = sc->req_frames + i * sc->reqframesz; | ||||
cm->cm_req_busaddr = sc->req_busaddr + i * sc->reqframesz; | cm->cm_req_busaddr = sc->req_busaddr + i * sc->reqframesz; | ||||
cm->cm_sense = &sc->sense_frames[i]; | cm->cm_sense = &sc->sense_frames[i]; | ||||
cm->cm_sense_busaddr = sc->sense_busaddr + i * MPR_SENSE_LEN; | cm->cm_sense_busaddr = sc->sense_busaddr + i * MPR_SENSE_LEN; | ||||
cm->cm_desc.Default.SMID = i; | cm->cm_desc.Default.SMID = htole16(i); | ||||
scottlUnsubmitted Not Done Inline ActionsThe SMID doesn’t need to be byte swapped. It's a host-private cookie that is opaque to the controller. Be sure to also not byte-swap the retrieval of the SMID on completion. scottl: The SMID doesn’t need to be byte swapped. It's a host-private cookie that is opaque to the… | |||||
afscoelho_gmail.comAuthorUnsubmitted Done Inline ActionsI put this here because the original code assumes that SMID is LE, lines 2555 and 2597 for example. afscoelho_gmail.com: I put this here because the original code assumes that SMID is LE, lines 2555 and 2597 for… | |||||
cm->cm_sc = sc; | cm->cm_sc = sc; | ||||
cm->cm_state = MPR_CM_STATE_BUSY; | cm->cm_state = MPR_CM_STATE_BUSY; | ||||
TAILQ_INIT(&cm->cm_chain_list); | TAILQ_INIT(&cm->cm_chain_list); | ||||
TAILQ_INIT(&cm->cm_prp_page_list); | TAILQ_INIT(&cm->cm_prp_page_list); | ||||
callout_init_mtx(&cm->cm_callout, &sc->mpr_mtx, 0); | callout_init_mtx(&cm->cm_callout, &sc->mpr_mtx, 0); | ||||
/* XXX Is a failure here a critical problem? */ | /* XXX Is a failure here a critical problem? */ | ||||
if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) | if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | mpr_init_queues(struct mpr_softc *sc) | ||||
*/ | */ | ||||
if (sc->num_replies >= sc->fqdepth) | if (sc->num_replies >= sc->fqdepth) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* | /* | ||||
* Initialize all of the free queue entries. | * Initialize all of the free queue entries. | ||||
*/ | */ | ||||
for (i = 0; i < sc->fqdepth; i++) { | for (i = 0; i < sc->fqdepth; i++) { | ||||
sc->free_queue[i] = sc->reply_busaddr + (i * sc->replyframesz); | sc->free_queue[i] = htole32(sc->reply_busaddr + (i * sc->replyframesz)); | ||||
} | } | ||||
sc->replyfreeindex = sc->num_replies; | sc->replyfreeindex = sc->num_replies; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* Get the driver parameter tunables. Lowest priority are the driver defaults. | /* Get the driver parameter tunables. Lowest priority are the driver defaults. | ||||
* Next are the global settings, if they exist. Highest are the per-unit | * Next are the global settings, if they exist. Highest are the per-unit | ||||
▲ Show 20 Lines • Show All 1,058 Lines • ▼ Show 20 Lines | mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, | ||||
evtreq->SASBroadcastPrimitiveMasks = 0; | evtreq->SASBroadcastPrimitiveMasks = 0; | ||||
#ifdef MPR_DEBUG_ALL_EVENTS | #ifdef MPR_DEBUG_ALL_EVENTS | ||||
{ | { | ||||
u_char fullmask[16]; | u_char fullmask[16]; | ||||
memset(fullmask, 0x00, 16); | memset(fullmask, 0x00, 16); | ||||
bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16); | bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16); | ||||
} | } | ||||
#else | #else | ||||
bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16); | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | ||||
evtreq->EventMasks[i] = htole32(sc->event_mask[i]); | |||||
Done Inline ActionsYou should use 2 tabs here. luporl: You should use 2 tabs here. | |||||
#endif | #endif | ||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | ||||
cm->cm_data = NULL; | cm->cm_data = NULL; | ||||
error = mpr_request_polled(sc, &cm); | error = mpr_request_polled(sc, &cm); | ||||
if (cm != NULL) | if (cm != NULL) | ||||
reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; | reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; | ||||
if ((reply == NULL) || | if ((reply == NULL) || | ||||
Show All 37 Lines | mpr_reregister_events(struct mpr_softc *sc) | ||||
evtreq->SASBroadcastPrimitiveMasks = 0; | evtreq->SASBroadcastPrimitiveMasks = 0; | ||||
#ifdef MPR_DEBUG_ALL_EVENTS | #ifdef MPR_DEBUG_ALL_EVENTS | ||||
{ | { | ||||
u_char fullmask[16]; | u_char fullmask[16]; | ||||
memset(fullmask, 0x00, 16); | memset(fullmask, 0x00, 16); | ||||
bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16); | bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16); | ||||
} | } | ||||
#else | #else | ||||
bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16); | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | ||||
evtreq->EventMasks[i] = htole32(sc->event_mask[i]); | |||||
Done Inline ActionsYou should use 2 tabs here. luporl: You should use 2 tabs here. | |||||
#endif | #endif | ||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | ||||
cm->cm_data = NULL; | cm->cm_data = NULL; | ||||
cm->cm_complete = mpr_reregister_events_complete; | cm->cm_complete = mpr_reregister_events_complete; | ||||
error = mpr_map_command(sc, cm); | error = mpr_map_command(sc, cm); | ||||
mpr_dprint(sc, MPR_TRACE, "%s finished with error %d\n", __func__, | mpr_dprint(sc, MPR_TRACE, "%s finished with error %d\n", __func__, | ||||
▲ Show 20 Lines • Show All 656 Lines • ▼ Show 20 Lines | sge->FlagsLength = cm->cm_out_len | | ||||
MPI2_SGE_FLAGS_END_OF_BUFFER | | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||||
MPI2_SGE_FLAGS_HOST_TO_IOC | | MPI2_SGE_FLAGS_HOST_TO_IOC | | ||||
MPI2_SGE_FLAGS_64_BIT_ADDRESSING) << | MPI2_SGE_FLAGS_64_BIT_ADDRESSING) << | ||||
MPI2_SGE_FLAGS_SHIFT); | MPI2_SGE_FLAGS_SHIFT); | ||||
cm->cm_sglsize -= len; | cm->cm_sglsize -= len; | ||||
/* Endian Safe code */ | /* Endian Safe code */ | ||||
sge_flags = sge->FlagsLength; | sge_flags = sge->FlagsLength; | ||||
sge->FlagsLength = htole32(sge_flags); | sge->FlagsLength = htole32(sge_flags); | ||||
sge->Address.High = htole32(sge->Address.High); | |||||
sge->Address.Low = htole32(sge->Address.Low); | |||||
bcopy(sge, cm->cm_sge, len); | bcopy(sge, cm->cm_sge, len); | ||||
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len); | cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len); | ||||
} | } | ||||
sge->FlagsLength = saved_buf_len | | sge->FlagsLength = saved_buf_len | | ||||
((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||||
MPI2_SGE_FLAGS_END_OF_BUFFER | | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||||
MPI2_SGE_FLAGS_LAST_ELEMENT | | MPI2_SGE_FLAGS_LAST_ELEMENT | | ||||
MPI2_SGE_FLAGS_END_OF_LIST | | MPI2_SGE_FLAGS_END_OF_LIST | | ||||
Show All 10 Lines | mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len, | ||||
} | } | ||||
sge->Address.Low = saved_address_low; | sge->Address.Low = saved_address_low; | ||||
sge->Address.High = saved_address_high; | sge->Address.High = saved_address_high; | ||||
cm->cm_sglsize -= len; | cm->cm_sglsize -= len; | ||||
/* Endian Safe code */ | /* Endian Safe code */ | ||||
sge_flags = sge->FlagsLength; | sge_flags = sge->FlagsLength; | ||||
sge->FlagsLength = htole32(sge_flags); | sge->FlagsLength = htole32(sge_flags); | ||||
sge->Address.High = htole32(sge->Address.High); | |||||
sge->Address.Low = htole32(sge->Address.Low); | |||||
bcopy(sge, cm->cm_sge, len); | bcopy(sge, cm->cm_sge, len); | ||||
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len); | cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Add one IEEE scatter-gather element (chain or simple) to the IEEE scatter- | * Add one IEEE scatter-gather element (chain or simple) to the IEEE scatter- | ||||
* gather list for a command. Maintain cm_sglsize and cm_sge as the | * gather list for a command. Maintain cm_sglsize and cm_sge as the | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | if (segsleft == 1) { | ||||
if (cm->cm_out_len) { | if (cm->cm_out_len) { | ||||
sge->Length = cm->cm_out_len; | sge->Length = cm->cm_out_len; | ||||
sge->Flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | | sge->Flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | | ||||
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR); | MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR); | ||||
cm->cm_sglsize -= ieee_sge_size; | cm->cm_sglsize -= ieee_sge_size; | ||||
/* Endian Safe code */ | /* Endian Safe code */ | ||||
sge_length = sge->Length; | sge_length = sge->Length; | ||||
sge->Length = htole32(sge_length); | sge->Length = htole32(sge_length); | ||||
sge->Address.High = htole32(sge->Address.High); | |||||
sge->Address.Low = htole32(sge->Address.Low); | |||||
bcopy(sgep, cm->cm_sge, ieee_sge_size); | bcopy(sgep, cm->cm_sge, ieee_sge_size); | ||||
cm->cm_sge = | cm->cm_sge = | ||||
(MPI25_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + | (MPI25_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + | ||||
ieee_sge_size); | ieee_sge_size); | ||||
} | } | ||||
sge->Length = saved_buf_len; | sge->Length = saved_buf_len; | ||||
sge->Flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | | sge->Flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | | ||||
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | | MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | | ||||
MPI25_IEEE_SGE_FLAGS_END_OF_LIST); | MPI25_IEEE_SGE_FLAGS_END_OF_LIST); | ||||
sge->Address.Low = saved_address_low; | sge->Address.Low = saved_address_low; | ||||
sge->Address.High = saved_address_high; | sge->Address.High = saved_address_high; | ||||
} | } | ||||
cm->cm_sglsize -= ieee_sge_size; | cm->cm_sglsize -= ieee_sge_size; | ||||
/* Endian Safe code */ | /* Endian Safe code */ | ||||
sge_length = sge->Length; | sge_length = sge->Length; | ||||
sge->Length = htole32(sge_length); | sge->Length = htole32(sge_length); | ||||
sge->Address.High = htole32(sge->Address.High); | |||||
sge->Address.Low = htole32(sge->Address.Low); | |||||
bcopy(sgep, cm->cm_sge, ieee_sge_size); | bcopy(sgep, cm->cm_sge, ieee_sge_size); | ||||
cm->cm_sge = (MPI25_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + | cm->cm_sge = (MPI25_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + | ||||
ieee_sge_size); | ieee_sge_size); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Add one dma segment to the scatter-gather list for a command. | * Add one dma segment to the scatter-gather list for a command. | ||||
▲ Show 20 Lines • Show All 416 Lines • Show Last 20 Lines |
Why data16[0] is not converted with le16toh() while the other elements of data16[] are?