Add support for the Broadcom (Avago/LSI) 9305 16 and 24 port HBA's.

Reviewed by:    ken, scottl, ambrisko, asomers
Approved by:	ken, scottl, ambrisko
MFC after:      1 week
Relnotes:       yes
Differential Revision: https://reviews.freebsd.org/D6098
This commit is contained in:
slm 2016-05-09 16:19:13 +00:00
parent 9b9ab04340
commit 1f91a62e29
5 changed files with 69 additions and 11 deletions

View File

@ -441,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) ||
@ -1188,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 */
@ -1246,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++;
}
@ -2169,7 +2192,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;
/*
@ -2191,8 +2214,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.
@ -2218,13 +2239,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 |
@ -2233,10 +2255,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);
}

View File

@ -110,6 +110,18 @@ struct mpr_ident {
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3316_1" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3316_2" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_1,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_1" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_2" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3216" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3224" },
{ 0, 0, 0, 0, 0, NULL }
};

View File

@ -704,6 +704,7 @@ mprsas_register_events(struct mpr_softc *sc)
setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK);
setbit(events, MPI2_EVENT_IR_OPERATION_STATUS);
setbit(events, MPI2_EVENT_TEMP_THRESHOLD);
setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
mpr_register_events(sc, events, mprsas_evt_handler, NULL,
&sc->sassc->mprsas_eh);
@ -2048,6 +2049,9 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio,
case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
desc_ioc_state = "eedp app tag error";
break;
case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
desc_ioc_state = "insufficient power";
break;
default:
desc_ioc_state = "unknown";
break;

View File

@ -645,6 +645,23 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
}
break;
}
case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
{
pMpi26EventDataActiveCableExcept_t ace_event_data;
ace_event_data =
(pMpi26EventDataActiveCableExcept_t)fw_event->event_data;
if (ace_event_data->ReasonCode ==
MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
mpr_printf(sc, "Currently an active cable with "
"ReceptacleID %d cannot be powered and device "
"connected to this active cable will not be seen. "
"This active cable requires %d mW of power.\n",
ace_event_data->ReceptacleID,
ace_event_data->ActiveCablePowerRequirement);
}
break;
}
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
default:

View File

@ -46,6 +46,8 @@
#define MPR_SGE64_SIZE 12
#define MPR_SGE32_SIZE 8
#define MPR_SGC_SIZE 8
#define MPR_DEFAULT_CHAIN_SEG_SIZE 8
#define MPR_MAX_CHAIN_ELEMENT_SIZE 16
#define MPR_FUNCTRACE(sc) \
mpr_dprint((sc), MPR_TRACE, "%s\n", __func__)
@ -263,6 +265,8 @@ struct mpr_softc {
int chain_free;
int max_chains;
int chain_free_lowwater;
uint32_t chain_frame_size;
uint16_t chain_seg_size;
u_int enable_ssu;
int spinup_wait_time;
uint64_t chain_alloc_fail;