diff options
Diffstat (limited to 'sys/dev/mpr/mpr.c')
-rw-r--r-- | sys/dev/mpr/mpr.c | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 07e73c5..f5fe216 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,14 +92,11 @@ static __inline void mpr_complete_command(struct mpr_softc *sc, struct mpr_command *cm); static void mpr_dispatch_event(struct mpr_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *reply); -static void mpr_config_complete(struct mpr_softc *sc, - struct mpr_command *cm); +static void mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm); static void mpr_periodic(void *); static int mpr_reregister_events(struct mpr_softc *sc); -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 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_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag); SYSCTL_NODE(_hw, OID_AUTO, mpr, CTLFLAG_RD, 0, "MPR Driver Parameters"); @@ -444,6 +441,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) || (saved_facts.IOCRequestFrameSize != sc->facts->IOCRequestFrameSize) || + (saved_facts.IOCMaxChainSegmentSize != + sc->facts->IOCMaxChainSegmentSize) || (saved_facts.MaxTargets != sc->facts->MaxTargets) || (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) || (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) || @@ -550,8 +549,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) error = mpr_transition_operational(sc); if (error != 0) { if (attaching) { - mpr_printf(sc, "%s failed to transition to " - "operational with error %d\n", __func__, error); + mpr_printf(sc, "%s failed to transition to operational " + "with error %d\n", __func__, error); mpr_free(sc); return (error); } else { @@ -685,7 +684,7 @@ mpr_reinit(struct mpr_softc *sc) if (sc->mpr_flags & MPR_FLAGS_DIAGRESET) { mpr_dprint(sc, MPR_INIT, "%s reset already in progress\n", - __func__); + __func__); return 0; } @@ -1191,7 +1190,28 @@ mpr_alloc_requests(struct mpr_softc *sc) bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize, 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 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 */ 16, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ @@ -1249,9 +1269,9 @@ mpr_alloc_requests(struct mpr_softc *sc) for (i = 0; i < sc->max_chains; i++) { chain = &sc->chains[i]; 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 + - i * sc->facts->IOCRequestFrameSize * 4; + i * sc->chain_frame_size; mpr_free_chain(sc, chain); sc->chain_free_lowwater++; } @@ -1714,9 +1734,9 @@ mpr_complete_command(struct mpr_softc *sc, struct mpr_command *cm) if (cm->cm_complete != NULL) { mpr_dprint(sc, MPR_TRACE, - "%s cm %p calling cm_complete %p data %p reply %p\n", - __func__, cm, cm->cm_complete, cm->cm_complete_data, - cm->cm_reply); + "%s cm %p calling cm_complete %p data %p reply %p\n", + __func__, cm, cm->cm_complete, cm->cm_complete_data, + cm->cm_reply); cm->cm_complete(sc, cm); } @@ -1773,10 +1793,9 @@ mpr_sas_log_info(struct mpr_softc *sc , u32 log_info) break; } - mpr_dprint(sc, MPR_INFO, "log_info(0x%08x): originator(%s), " - "code(0x%02x), sub_code(0x%04x)\n", log_info, - originator_str, sas_loginfo.dw.code, - sas_loginfo.dw.subcode); + mpr_dprint(sc, MPR_LOG, "log_info(0x%08x): originator(%s), " + "code(0x%02x), sub_code(0x%04x)\n", log_info, originator_str, + sas_loginfo.dw.code, sas_loginfo.dw.subcode); } static void @@ -1925,9 +1944,10 @@ mpr_intr_locked(void *data) */ rel_rep = (MPI2_DIAG_RELEASE_REPLY *)reply; - if (le16toh(rel_rep->IOCStatus) == + if ((le16toh(rel_rep->IOCStatus) & + MPI2_IOCSTATUS_MASK) == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) - { + { pBuffer = &sc->fw_diag_buffer_list[ rel_rep->BufferType]; @@ -2175,7 +2195,7 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) MPI2_REQUEST_HEADER *req; MPI25_IEEE_SGE_CHAIN64 *ieee_sgc; 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; /* @@ -2197,8 +2217,6 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) if (chain == NULL) return (ENOBUFS); - space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4; - /* * Note: a double-linked list is used to make it easier to walk for * debugging. @@ -2224,13 +2242,14 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) */ current_segs = (cm->cm_sglsize / sgc_size) - 1; 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) { next_chain_offset = segs_per_frame - 1; } } 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); ieee_sgc->NextChainOffset = next_chain_offset; ieee_sgc->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | @@ -2239,10 +2258,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) ieee_sgc->Address.High = htole32(chain->chain_busaddr >> 32); cm->cm_sge = &((MPI25_SGE_IO_UNION *)chain->chain)->IeeeSimple; req = (MPI2_REQUEST_HEADER *)cm->cm_req; - req->ChainOffset = ((sc->facts->IOCRequestFrameSize * 4) - - sgc_size) >> 4; + req->ChainOffset = (sc->chain_frame_size - sgc_size) >> 4; - cm->cm_sglsize = space; + cm->cm_sglsize = sc->chain_frame_size; return (0); } @@ -2465,10 +2483,9 @@ mpr_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) * user they did the wrong thing. */ if ((cm->cm_max_segs != 0) && (nsegs > cm->cm_max_segs)) { - mpr_dprint(sc, MPR_ERROR, - "%s: warning: busdma returned %d segments, " - "more than the %d allowed\n", __func__, nsegs, - cm->cm_max_segs); + mpr_dprint(sc, MPR_ERROR, "%s: warning: busdma returned %d " + "segments, more than the %d allowed\n", __func__, nsegs, + cm->cm_max_segs); } /* @@ -2665,8 +2682,8 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) if (error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); - mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? - "success" : "failed"); + mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" : + "failed"); } return (error); } |