Changeset View
Changeset View
Standalone View
Standalone View
mpr.c
Show First 20 Lines • Show All 438 Lines • ▼ Show 20 Lines | if ((!attaching) && | ||||
((saved_facts.MsgVersion != sc->facts->MsgVersion) || | ((saved_facts.MsgVersion != sc->facts->MsgVersion) || | ||||
(saved_facts.HeaderVersion != sc->facts->HeaderVersion) || | (saved_facts.HeaderVersion != sc->facts->HeaderVersion) || | ||||
(saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) || | (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) || | ||||
(saved_facts.RequestCredit != sc->facts->RequestCredit) || | (saved_facts.RequestCredit != sc->facts->RequestCredit) || | ||||
(saved_facts.ProductID != sc->facts->ProductID) || | (saved_facts.ProductID != sc->facts->ProductID) || | ||||
(saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) || | (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) || | ||||
(saved_facts.IOCRequestFrameSize != | (saved_facts.IOCRequestFrameSize != | ||||
sc->facts->IOCRequestFrameSize) || | sc->facts->IOCRequestFrameSize) || | ||||
(saved_facts.IOCMaxChainSegmentSize != | |||||
sc->facts->IOCMaxChainSegmentSize) || | |||||
(saved_facts.MaxTargets != sc->facts->MaxTargets) || | (saved_facts.MaxTargets != sc->facts->MaxTargets) || | ||||
(saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) || | (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) || | ||||
(saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) || | (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) || | ||||
(saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) || | (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) || | ||||
(saved_facts.MaxReplyDescriptorPostQueueDepth != | (saved_facts.MaxReplyDescriptorPostQueueDepth != | ||||
sc->facts->MaxReplyDescriptorPostQueueDepth) || | sc->facts->MaxReplyDescriptorPostQueueDepth) || | ||||
(saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) || | (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) || | ||||
(saved_facts.MaxVolumes != sc->facts->MaxVolumes) || | (saved_facts.MaxVolumes != sc->facts->MaxVolumes) || | ||||
▲ Show 20 Lines • Show All 731 Lines • ▼ Show 20 Lines | return (ENOMEM); | ||||
BUS_DMA_NOWAIT, &sc->req_map)) { | BUS_DMA_NOWAIT, &sc->req_map)) { | ||||
device_printf(sc->mpr_dev, "Cannot allocate request memory\n"); | device_printf(sc->mpr_dev, "Cannot allocate request memory\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
bzero(sc->req_frames, rsize); | bzero(sc->req_frames, rsize); | ||||
bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize, | bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize, | ||||
mpr_memaddr_cb, &sc->req_busaddr, 0); | mpr_memaddr_cb, &sc->req_busaddr, 0); | ||||
rsize = sc->facts->IOCRequestFrameSize * sc->max_chains * 4; | /* | ||||
* Gen3 and beyond uses the IOCMaxChainSegmentSize from IOC Facts to | |||||
* get the size of a Chain Frame. Previous versions use the same size | |||||
* as a Request Frame for the Chain Frame size. If | |||||
* IOCMaxChainSegmentSize is 0, use the default value. The | |||||
* IOCMaxChainSegmentSize is the number of 16-byte elelements that can | |||||
* fit in a Chain Frame, which is the size of an IEEE Simple SGE. | |||||
*/ | |||||
if (sc->facts->MsgVersion >= MPI2_VERSION_02_05) { | |||||
sc->chain_seg_size = | |||||
htole16(sc->facts->IOCMaxChainSegmentSize); | |||||
if (sc->chain_seg_size == 0) { | |||||
sc->chain_frame_size = MPR_DEFAULT_CHAIN_SEG_SIZE * | |||||
MPR_MAX_CHAIN_ELEMENT_SIZE; | |||||
} else { | |||||
sc->chain_frame_size = sc->chain_seg_size * | |||||
MPR_MAX_CHAIN_ELEMENT_SIZE; | |||||
} | |||||
} else { | |||||
sc->chain_frame_size = sc->facts->IOCRequestFrameSize * 4; | |||||
} | |||||
rsize = sc->chain_frame_size * sc->max_chains; | |||||
if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */ | if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */ | ||||
16, 0, /* algnmnt, boundary */ | 16, 0, /* algnmnt, boundary */ | ||||
BUS_SPACE_MAXADDR, /* lowaddr */ | BUS_SPACE_MAXADDR, /* lowaddr */ | ||||
BUS_SPACE_MAXADDR, /* highaddr */ | BUS_SPACE_MAXADDR, /* highaddr */ | ||||
NULL, NULL, /* filter, filterarg */ | NULL, NULL, /* filter, filterarg */ | ||||
rsize, /* maxsize */ | rsize, /* maxsize */ | ||||
1, /* nsegments */ | 1, /* nsegments */ | ||||
rsize, /* maxsegsize */ | rsize, /* maxsegsize */ | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | mpr_alloc_requests(struct mpr_softc *sc) | ||||
if (!sc->chains) { | if (!sc->chains) { | ||||
device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", | device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", | ||||
__func__, __LINE__); | __func__, __LINE__); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
for (i = 0; i < sc->max_chains; i++) { | for (i = 0; i < sc->max_chains; i++) { | ||||
chain = &sc->chains[i]; | chain = &sc->chains[i]; | ||||
chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames + | chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames + | ||||
i * sc->facts->IOCRequestFrameSize * 4); | i * sc->chain_frame_size); | ||||
chain->chain_busaddr = sc->chain_busaddr + | chain->chain_busaddr = sc->chain_busaddr + | ||||
i * sc->facts->IOCRequestFrameSize * 4; | i * sc->chain_frame_size; | ||||
mpr_free_chain(sc, chain); | mpr_free_chain(sc, chain); | ||||
sc->chain_free_lowwater++; | sc->chain_free_lowwater++; | ||||
} | } | ||||
/* XXX Need to pick a more precise value */ | /* XXX Need to pick a more precise value */ | ||||
nsegs = (MAXPHYS / PAGE_SIZE) + 1; | nsegs = (MAXPHYS / PAGE_SIZE) + 1; | ||||
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 */ | ||||
▲ Show 20 Lines • Show All 905 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
mpr_add_chain(struct mpr_command *cm, int segsleft) | mpr_add_chain(struct mpr_command *cm, int segsleft) | ||||
{ | { | ||||
struct mpr_softc *sc = cm->cm_sc; | struct mpr_softc *sc = cm->cm_sc; | ||||
MPI2_REQUEST_HEADER *req; | MPI2_REQUEST_HEADER *req; | ||||
MPI25_IEEE_SGE_CHAIN64 *ieee_sgc; | MPI25_IEEE_SGE_CHAIN64 *ieee_sgc; | ||||
struct mpr_chain *chain; | struct mpr_chain *chain; | ||||
int space, sgc_size, current_segs, rem_segs, segs_per_frame; | int sgc_size, current_segs, rem_segs, segs_per_frame; | ||||
uint8_t next_chain_offset = 0; | uint8_t next_chain_offset = 0; | ||||
/* | /* | ||||
* Fail if a command is requesting a chain for SIMPLE SGE's. For SAS3 | * Fail if a command is requesting a chain for SIMPLE SGE's. For SAS3 | ||||
* only IEEE commands should be requesting chains. Return some error | * only IEEE commands should be requesting chains. Return some error | ||||
* code other than 0. | * code other than 0. | ||||
*/ | */ | ||||
if (cm->cm_flags & MPR_CM_FLAGS_SGE_SIMPLE) { | if (cm->cm_flags & MPR_CM_FLAGS_SGE_SIMPLE) { | ||||
mpr_dprint(sc, MPR_ERROR, "A chain element cannot be added to " | mpr_dprint(sc, MPR_ERROR, "A chain element cannot be added to " | ||||
"an MPI SGL.\n"); | "an MPI SGL.\n"); | ||||
return(ENOBUFS); | return(ENOBUFS); | ||||
} | } | ||||
sgc_size = sizeof(MPI25_IEEE_SGE_CHAIN64); | sgc_size = sizeof(MPI25_IEEE_SGE_CHAIN64); | ||||
if (cm->cm_sglsize < sgc_size) | if (cm->cm_sglsize < sgc_size) | ||||
panic("MPR: Need SGE Error Code\n"); | panic("MPR: Need SGE Error Code\n"); | ||||
chain = mpr_alloc_chain(cm->cm_sc); | chain = mpr_alloc_chain(cm->cm_sc); | ||||
if (chain == NULL) | if (chain == NULL) | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4; | |||||
/* | /* | ||||
* Note: a double-linked list is used to make it easier to walk for | * Note: a double-linked list is used to make it easier to walk for | ||||
* debugging. | * debugging. | ||||
*/ | */ | ||||
TAILQ_INSERT_TAIL(&cm->cm_chain_list, chain, chain_link); | TAILQ_INSERT_TAIL(&cm->cm_chain_list, chain, chain_link); | ||||
/* | /* | ||||
* Need to know if the number of frames left is more than 1 or not. If | * Need to know if the number of frames left is more than 1 or not. If | ||||
Show All 9 Lines | if (cm->cm_sglsize < (sgc_size * segsleft)) { | ||||
* the chain element. To know if more than one more frame is | * the chain element. To know if more than one more frame is | ||||
* required, just check if there will be a remainder after using | * required, just check if there will be a remainder after using | ||||
* the current frame (with this chain) and the next frame. If | * the current frame (with this chain) and the next frame. If | ||||
* so the NextChainOffset must be the last element of the next | * so the NextChainOffset must be the last element of the next | ||||
* frame. | * frame. | ||||
*/ | */ | ||||
current_segs = (cm->cm_sglsize / sgc_size) - 1; | current_segs = (cm->cm_sglsize / sgc_size) - 1; | ||||
rem_segs = segsleft - current_segs; | rem_segs = segsleft - current_segs; | ||||
segs_per_frame = space / sgc_size; | segs_per_frame = sc->chain_frame_size / sgc_size; | ||||
if (rem_segs > segs_per_frame) { | if (rem_segs > segs_per_frame) { | ||||
next_chain_offset = segs_per_frame - 1; | next_chain_offset = segs_per_frame - 1; | ||||
} | } | ||||
} | } | ||||
ieee_sgc = &((MPI25_SGE_IO_UNION *)cm->cm_sge)->IeeeChain; | ieee_sgc = &((MPI25_SGE_IO_UNION *)cm->cm_sge)->IeeeChain; | ||||
ieee_sgc->Length = next_chain_offset ? htole32((uint32_t)space) : | ieee_sgc->Length = next_chain_offset ? | ||||
htole32((uint32_t)sc->chain_frame_size) : | |||||
htole32((uint32_t)rem_segs * (uint32_t)sgc_size); | htole32((uint32_t)rem_segs * (uint32_t)sgc_size); | ||||
ieee_sgc->NextChainOffset = next_chain_offset; | ieee_sgc->NextChainOffset = next_chain_offset; | ||||
ieee_sgc->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | | ieee_sgc->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | | ||||
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR); | MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR); | ||||
ieee_sgc->Address.Low = htole32(chain->chain_busaddr); | ieee_sgc->Address.Low = htole32(chain->chain_busaddr); | ||||
ieee_sgc->Address.High = htole32(chain->chain_busaddr >> 32); | ieee_sgc->Address.High = htole32(chain->chain_busaddr >> 32); | ||||
cm->cm_sge = &((MPI25_SGE_IO_UNION *)chain->chain)->IeeeSimple; | cm->cm_sge = &((MPI25_SGE_IO_UNION *)chain->chain)->IeeeSimple; | ||||
req = (MPI2_REQUEST_HEADER *)cm->cm_req; | req = (MPI2_REQUEST_HEADER *)cm->cm_req; | ||||
req->ChainOffset = ((sc->facts->IOCRequestFrameSize * 4) - | req->ChainOffset = (sc->chain_frame_size - sgc_size) >> 4; | ||||
sgc_size) >> 4; | |||||
cm->cm_sglsize = space; | cm->cm_sglsize = sc->chain_frame_size; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Add one scatter-gather element to the scatter-gather list for a command. | * Add one scatter-gather element to the scatter-gather list for a command. | ||||
* Maintain cm_sglsize and cm_sge as the remaining size and pointer to the | * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the | ||||
* next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a | * next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a | ||||
* chain, so don't consider any chain additions. | * chain, so don't consider any chain additions. | ||||
▲ Show 20 Lines • Show All 550 Lines • Show Last 20 Lines |