mpi3mr: configure larger max I/O size if the HBA firmware supports it
The max I/O size that an mpi3mr HBA supports is reported in the IOCFacts structure (with 0 representing the legacy max I/O size of 1 MB). By default, set the max I/O size of devices attached to mpi3mr controllers to the smaller of the HBA's max I/O size and the kernel's maxphys. Allow this default to be overriden by a global tunable "hw.mpi3mr.max_sgl_entries" or by a per-controller tunable "dev.mpi3mr.N.max_sgl_entries". Sponsored by: Netflix Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D49090
This commit is contained in:
@@ -1617,6 +1617,7 @@ static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc,
|
|||||||
(facts_data->MaxPCIeSwitches);
|
(facts_data->MaxPCIeSwitches);
|
||||||
sc->facts.max_sasexpanders =
|
sc->facts.max_sasexpanders =
|
||||||
(facts_data->MaxSASExpanders);
|
(facts_data->MaxSASExpanders);
|
||||||
|
sc->facts.max_data_length = facts_data->MaxDataLength;
|
||||||
sc->facts.max_sasinitiators =
|
sc->facts.max_sasinitiators =
|
||||||
(facts_data->MaxSASInitiators);
|
(facts_data->MaxSASInitiators);
|
||||||
sc->facts.max_enclosures = (facts_data->MaxEnclosures);
|
sc->facts.max_enclosures = (facts_data->MaxEnclosures);
|
||||||
@@ -1651,6 +1652,10 @@ static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc,
|
|||||||
sc->facts.io_throttle_low = facts_data->IOThrottleLow;
|
sc->facts.io_throttle_low = facts_data->IOThrottleLow;
|
||||||
sc->facts.io_throttle_high = facts_data->IOThrottleHigh;
|
sc->facts.io_throttle_high = facts_data->IOThrottleHigh;
|
||||||
|
|
||||||
|
if (sc->facts.max_data_length == MPI3_IOCFACTS_MAX_DATA_LENGTH_NOT_REPORTED)
|
||||||
|
sc->facts.max_data_length = MPI3MR_DEFAULT_MAX_IO_SIZE;
|
||||||
|
else
|
||||||
|
sc->facts.max_data_length *= MPI3MR_PAGE_SIZE_4K;
|
||||||
/*Store in 512b block count*/
|
/*Store in 512b block count*/
|
||||||
if (sc->facts.io_throttle_data_length)
|
if (sc->facts.io_throttle_data_length)
|
||||||
sc->io_throttle_data_length =
|
sc->io_throttle_data_length =
|
||||||
@@ -2511,7 +2516,9 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc)
|
|||||||
goto out_failed;
|
goto out_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = MPI3MR_CHAINSGE_SIZE;
|
if (sc->max_sgl_entries > sc->facts.max_data_length / PAGE_SIZE)
|
||||||
|
sc->max_sgl_entries = sc->facts.max_data_length / PAGE_SIZE;
|
||||||
|
sz = sc->max_sgl_entries * sizeof(Mpi3SGESimple_t);
|
||||||
|
|
||||||
if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
|
if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
|
||||||
4096, 0, /* algnmnt, boundary */
|
4096, 0, /* algnmnt, boundary */
|
||||||
@@ -4961,7 +4968,7 @@ mpi3mr_alloc_requests(struct mpi3mr_softc *sc)
|
|||||||
struct mpi3mr_cmd *cmd;
|
struct mpi3mr_cmd *cmd;
|
||||||
int i, j, nsegs, ret;
|
int i, j, nsegs, ret;
|
||||||
|
|
||||||
nsegs = MPI3MR_SG_DEPTH;
|
nsegs = sc->max_sgl_entries;
|
||||||
ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */
|
ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */
|
||||||
1, 0, /* algnmnt, boundary */
|
1, 0, /* algnmnt, boundary */
|
||||||
sc->dma_loaddr, /* lowaddr */
|
sc->dma_loaddr, /* lowaddr */
|
||||||
|
|||||||
@@ -95,10 +95,11 @@
|
|||||||
#define MPI3MR_NAME_LENGTH 32
|
#define MPI3MR_NAME_LENGTH 32
|
||||||
#define IOCNAME "%s: "
|
#define IOCNAME "%s: "
|
||||||
|
|
||||||
|
#define MPI3MR_DEFAULT_MAX_IO_SIZE (1 * 1024 * 1024)
|
||||||
|
|
||||||
#define SAS4116_CHIP_REV_A0 0
|
#define SAS4116_CHIP_REV_A0 0
|
||||||
#define SAS4116_CHIP_REV_B0 1
|
#define SAS4116_CHIP_REV_B0 1
|
||||||
|
|
||||||
#define MPI3MR_SG_DEPTH (MPI3MR_4K_PGSZ/sizeof(Mpi3SGESimple_t))
|
|
||||||
#define MPI3MR_MAX_SECTORS 2048
|
#define MPI3MR_MAX_SECTORS 2048
|
||||||
#define MPI3MR_MAX_CMDS_LUN 7
|
#define MPI3MR_MAX_CMDS_LUN 7
|
||||||
#define MPI3MR_MAX_CDB_LENGTH 16
|
#define MPI3MR_MAX_CDB_LENGTH 16
|
||||||
@@ -109,7 +110,12 @@
|
|||||||
#define MPI3MR_RAID_QDEPTH 128
|
#define MPI3MR_RAID_QDEPTH 128
|
||||||
#define MPI3MR_NVME_QDEPTH 128
|
#define MPI3MR_NVME_QDEPTH 128
|
||||||
|
|
||||||
|
/* Definitions for internal SGL and Chain SGL buffers */
|
||||||
#define MPI3MR_4K_PGSZ 4096
|
#define MPI3MR_4K_PGSZ 4096
|
||||||
|
#define MPI3MR_PAGE_SIZE_4K 4096
|
||||||
|
#define MPI3MR_DEFAULT_SGL_ENTRIES 256
|
||||||
|
#define MPI3MR_MAX_SGL_ENTRIES 2048
|
||||||
|
|
||||||
#define MPI3MR_AREQQ_SIZE (2 * MPI3MR_4K_PGSZ)
|
#define MPI3MR_AREQQ_SIZE (2 * MPI3MR_4K_PGSZ)
|
||||||
#define MPI3MR_AREPQ_SIZE (4 * MPI3MR_4K_PGSZ)
|
#define MPI3MR_AREPQ_SIZE (4 * MPI3MR_4K_PGSZ)
|
||||||
#define MPI3MR_AREQ_FRAME_SZ 128
|
#define MPI3MR_AREQ_FRAME_SZ 128
|
||||||
@@ -125,8 +131,6 @@
|
|||||||
|
|
||||||
#define MPI3MR_THRESHOLD_REPLY_COUNT 100
|
#define MPI3MR_THRESHOLD_REPLY_COUNT 100
|
||||||
|
|
||||||
#define MPI3MR_CHAINSGE_SIZE MPI3MR_4K_PGSZ
|
|
||||||
|
|
||||||
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
|
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
|
||||||
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
|
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
|
||||||
MPI3_SGE_FLAGS_END_OF_LIST)
|
MPI3_SGE_FLAGS_END_OF_LIST)
|
||||||
@@ -335,6 +339,7 @@ struct mpi3mr_ioc_facts
|
|||||||
U16 max_perids;
|
U16 max_perids;
|
||||||
U16 max_pds;
|
U16 max_pds;
|
||||||
U16 max_sasexpanders;
|
U16 max_sasexpanders;
|
||||||
|
U32 max_data_length;
|
||||||
U16 max_sasinitiators;
|
U16 max_sasinitiators;
|
||||||
U16 max_enclosures;
|
U16 max_enclosures;
|
||||||
U16 max_pcieswitches;
|
U16 max_pcieswitches;
|
||||||
@@ -671,6 +676,7 @@ struct mpi3mr_softc {
|
|||||||
struct mtx target_lock;
|
struct mtx target_lock;
|
||||||
|
|
||||||
U16 max_host_ios;
|
U16 max_host_ios;
|
||||||
|
U32 max_sgl_entries;
|
||||||
bus_dma_tag_t chain_sgl_list_tag;
|
bus_dma_tag_t chain_sgl_list_tag;
|
||||||
struct mpi3mr_chain *chain_sgl_list;
|
struct mpi3mr_chain *chain_sgl_list;
|
||||||
U16 chain_bitmap_sz;
|
U16 chain_bitmap_sz;
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ static void mpi3mr_prepare_sgls(void *arg,
|
|||||||
bus_dmamap_sync(sc->buffer_dmat, cm->dmamap,
|
bus_dmamap_sync(sc->buffer_dmat, cm->dmamap,
|
||||||
BUS_DMASYNC_PREWRITE);
|
BUS_DMASYNC_PREWRITE);
|
||||||
|
|
||||||
KASSERT(nsegs <= MPI3MR_SG_DEPTH && nsegs > 0,
|
KASSERT(nsegs <= sc->max_sgl_entries && nsegs > 0,
|
||||||
("%s: bad SGE count: %d\n", device_get_nameunit(sc->mpi3mr_dev), nsegs));
|
("%s: bad SGE count: %d\n", device_get_nameunit(sc->mpi3mr_dev), nsegs));
|
||||||
KASSERT(scsiio_req->DataLength != 0,
|
KASSERT(scsiio_req->DataLength != 0,
|
||||||
("%s: Data segments (%d), but DataLength == 0\n",
|
("%s: Data segments (%d), but DataLength == 0\n",
|
||||||
@@ -218,7 +218,7 @@ static void mpi3mr_prepare_sgls(void *arg,
|
|||||||
|
|
||||||
chain = chain_req->buf;
|
chain = chain_req->buf;
|
||||||
chain_dma = chain_req->buf_phys;
|
chain_dma = chain_req->buf_phys;
|
||||||
memset(chain_req->buf, 0, PAGE_SIZE);
|
memset(chain_req->buf, 0, sc->max_sgl_entries * sizeof(Mpi3SGESimple_t));
|
||||||
sges_in_segment = sges_left;
|
sges_in_segment = sges_left;
|
||||||
chain_length = sges_in_segment * sizeof(Mpi3SGESimple_t);
|
chain_length = sges_in_segment * sizeof(Mpi3SGESimple_t);
|
||||||
|
|
||||||
@@ -1154,7 +1154,7 @@ mpi3mr_action_scsiio(struct mpi3mr_cam_softc *cam_sc, union ccb *ccb)
|
|||||||
return;
|
return;
|
||||||
case CAM_DATA_VADDR:
|
case CAM_DATA_VADDR:
|
||||||
case CAM_DATA_BIO:
|
case CAM_DATA_BIO:
|
||||||
if (csio->dxfer_len > (MPI3MR_SG_DEPTH * MPI3MR_4K_PGSZ)) {
|
if (csio->dxfer_len > (sc->max_sgl_entries * PAGE_SIZE)) {
|
||||||
mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG);
|
mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG);
|
||||||
mpi3mr_release_command(cm);
|
mpi3mr_release_command(cm);
|
||||||
xpt_done(ccb);
|
xpt_done(ccb);
|
||||||
@@ -1305,8 +1305,10 @@ mpi3mr_cam_action(struct cam_sim *sim, union ccb *ccb)
|
|||||||
{
|
{
|
||||||
struct mpi3mr_cam_softc *cam_sc;
|
struct mpi3mr_cam_softc *cam_sc;
|
||||||
struct mpi3mr_target *targ;
|
struct mpi3mr_target *targ;
|
||||||
|
struct mpi3mr_softc *sc;
|
||||||
|
|
||||||
cam_sc = cam_sim_softc(sim);
|
cam_sc = cam_sim_softc(sim);
|
||||||
|
sc = cam_sc->sc;
|
||||||
|
|
||||||
mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "ccb func_code 0x%x target id: 0x%x\n",
|
mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "ccb func_code 0x%x target id: 0x%x\n",
|
||||||
ccb->ccb_h.func_code, ccb->ccb_h.target_id);
|
ccb->ccb_h.func_code, ccb->ccb_h.target_id);
|
||||||
@@ -1357,7 +1359,7 @@ mpi3mr_cam_action(struct cam_sim *sim, union ccb *ccb)
|
|||||||
"PCI device target_id: %u max io size: %u\n",
|
"PCI device target_id: %u max io size: %u\n",
|
||||||
ccb->ccb_h.target_id, cpi->maxio);
|
ccb->ccb_h.target_id, cpi->maxio);
|
||||||
} else {
|
} else {
|
||||||
cpi->maxio = PAGE_SIZE * (MPI3MR_SG_DEPTH - 1);
|
cpi->maxio = PAGE_SIZE * (sc->max_sgl_entries - 1);
|
||||||
}
|
}
|
||||||
mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
|
mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -178,12 +178,15 @@ mpi3mr_get_tunables(struct mpi3mr_softc *sc)
|
|||||||
sc->reset_in_progress = 0;
|
sc->reset_in_progress = 0;
|
||||||
sc->reset.type = 0;
|
sc->reset.type = 0;
|
||||||
sc->iot_enable = 1;
|
sc->iot_enable = 1;
|
||||||
|
sc->max_sgl_entries = maxphys / PAGE_SIZE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab the global variables.
|
* Grab the global variables.
|
||||||
*/
|
*/
|
||||||
TUNABLE_INT_FETCH("hw.mpi3mr.debug_level", &sc->mpi3mr_debug);
|
TUNABLE_INT_FETCH("hw.mpi3mr.debug_level", &sc->mpi3mr_debug);
|
||||||
TUNABLE_INT_FETCH("hw.mpi3mr.ctrl_reset", &sc->reset.type);
|
TUNABLE_INT_FETCH("hw.mpi3mr.ctrl_reset", &sc->reset.type);
|
||||||
TUNABLE_INT_FETCH("hw.mpi3mr.iot_enable", &sc->iot_enable);
|
TUNABLE_INT_FETCH("hw.mpi3mr.iot_enable", &sc->iot_enable);
|
||||||
|
TUNABLE_INT_FETCH("hw.mpi3mr.max_sgl_entries", &sc->max_sgl_entries);
|
||||||
|
|
||||||
/* Grab the unit-instance variables */
|
/* Grab the unit-instance variables */
|
||||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.debug_level",
|
snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.debug_level",
|
||||||
@@ -197,6 +200,10 @@ mpi3mr_get_tunables(struct mpi3mr_softc *sc)
|
|||||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.iot_enable",
|
snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.iot_enable",
|
||||||
device_get_unit(sc->mpi3mr_dev));
|
device_get_unit(sc->mpi3mr_dev));
|
||||||
TUNABLE_INT_FETCH(tmpstr, &sc->iot_enable);
|
TUNABLE_INT_FETCH(tmpstr, &sc->iot_enable);
|
||||||
|
|
||||||
|
snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.max_sgl_entries",
|
||||||
|
device_get_unit(sc->mpi3mr_dev));
|
||||||
|
TUNABLE_INT_FETCH(tmpstr, &sc->max_sgl_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mpi3mr_ident *
|
static struct mpi3mr_ident *
|
||||||
@@ -444,6 +451,15 @@ mpi3mr_pci_attach(device_t dev)
|
|||||||
sc->mpi3mr_dev = dev;
|
sc->mpi3mr_dev = dev;
|
||||||
mpi3mr_get_tunables(sc);
|
mpi3mr_get_tunables(sc);
|
||||||
|
|
||||||
|
if (sc->max_sgl_entries > MPI3MR_MAX_SGL_ENTRIES)
|
||||||
|
sc->max_sgl_entries = MPI3MR_MAX_SGL_ENTRIES;
|
||||||
|
else if (sc->max_sgl_entries < MPI3MR_DEFAULT_SGL_ENTRIES)
|
||||||
|
sc->max_sgl_entries = MPI3MR_DEFAULT_SGL_ENTRIES;
|
||||||
|
else {
|
||||||
|
sc->max_sgl_entries /= MPI3MR_DEFAULT_SGL_ENTRIES;
|
||||||
|
sc->max_sgl_entries *= MPI3MR_DEFAULT_SGL_ENTRIES;
|
||||||
|
}
|
||||||
|
|
||||||
if ((error = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_INIT)) != 0) {
|
if ((error = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_INIT)) != 0) {
|
||||||
mpi3mr_dprint(sc, MPI3MR_ERROR, "FW initialization failed\n");
|
mpi3mr_dprint(sc, MPI3MR_ERROR, "FW initialization failed\n");
|
||||||
goto load_failed;
|
goto load_failed;
|
||||||
|
|||||||
Reference in New Issue
Block a user