Add infrastructure for allocating multiple MSI-X interrupts. Also
add more fine-tuned controls for allocating requests and replies. Sponsored by: Netflix
This commit is contained in:
parent
5e66298138
commit
3c5ac992c7
@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag);
|
||||
static int mpr_init_queues(struct mpr_softc *sc);
|
||||
static void mpr_resize_queues(struct mpr_softc *sc);
|
||||
static int mpr_message_unit_reset(struct mpr_softc *sc, int sleep_flag);
|
||||
static int mpr_transition_operational(struct mpr_softc *sc);
|
||||
static int mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching);
|
||||
@ -374,6 +375,46 @@ mpr_transition_operational(struct mpr_softc *sc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
mpr_resize_queues(struct mpr_softc *sc)
|
||||
{
|
||||
int reqcr, prireqcr;
|
||||
|
||||
/*
|
||||
* Size the queues. Since the reply queues always need one free
|
||||
* entry, we'll deduct one reply message here. The LSI documents
|
||||
* suggest instead to add a count to the request queue, but I think
|
||||
* that it's better to deduct from reply queue.
|
||||
*/
|
||||
prireqcr = MAX(1, sc->max_prireqframes);
|
||||
prireqcr = MIN(prireqcr, sc->facts->HighPriorityCredit);
|
||||
|
||||
reqcr = MAX(2, sc->max_reqframes);
|
||||
reqcr = MIN(reqcr, sc->facts->RequestCredit);
|
||||
|
||||
sc->num_reqs = prireqcr + reqcr;
|
||||
sc->num_replies = MIN(sc->max_replyframes + sc->max_evtframes,
|
||||
sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
|
||||
|
||||
/*
|
||||
* Figure out the number of MSIx-based queues. If the firmware or
|
||||
* user has done something crazy and not allowed enough credit for
|
||||
* the queues to be useful then don't enable multi-queue.
|
||||
*/
|
||||
if (sc->facts->MaxMSIxVectors < 2)
|
||||
sc->msi_msgs = 1;
|
||||
|
||||
if (sc->msi_msgs > 1) {
|
||||
sc->msi_msgs = MIN(sc->msi_msgs, mp_ncpus);
|
||||
sc->msi_msgs = MIN(sc->msi_msgs, sc->facts->MaxMSIxVectors);
|
||||
if (sc->num_reqs / sc->msi_msgs < 2)
|
||||
sc->msi_msgs = 1;
|
||||
}
|
||||
|
||||
mpr_dprint(sc, MPR_INIT, "Sized queues to q=%d reqs=%d replies=%d\n",
|
||||
sc->msi_msgs, sc->num_reqs, sc->num_replies);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called during attach and when re-initializing due to a Diag Reset.
|
||||
* IOC Facts is used to allocate many of the structures needed by the driver.
|
||||
@ -530,13 +571,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ)
|
||||
sc->atomic_desc_capable = TRUE;
|
||||
|
||||
/*
|
||||
* Size the queues. Since the reply queues always need one free
|
||||
* entry, we'll just deduct one reply message here.
|
||||
*/
|
||||
sc->num_reqs = MIN(MPR_REQ_FRAMES, sc->facts->RequestCredit);
|
||||
sc->num_replies = MIN(MPR_REPLY_FRAMES + MPR_EVT_REPLY_FRAMES,
|
||||
sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
|
||||
mpr_resize_queues(sc);
|
||||
|
||||
/*
|
||||
* Initialize all Tail Queues
|
||||
@ -1146,11 +1181,11 @@ mpr_alloc_queues(struct mpr_softc *sc)
|
||||
struct mpr_queue *q;
|
||||
int nq, i;
|
||||
|
||||
nq = MIN(sc->msi_msgs, mp_ncpus);
|
||||
sc->msi_msgs = nq;
|
||||
nq = sc->msi_msgs;
|
||||
mpr_dprint(sc, MPR_INIT|MPR_XINFO, "Allocating %d I/O queues\n", nq);
|
||||
|
||||
sc->queues = malloc(sizeof(struct mpr_queue) * nq, M_MPR, M_NOWAIT|M_ZERO);
|
||||
sc->queues = malloc(sizeof(struct mpr_queue) * nq, M_MPR,
|
||||
M_NOWAIT|M_ZERO);
|
||||
if (sc->queues == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -1562,11 +1597,16 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
sc->mpr_debug = MPR_INFO | MPR_FAULT;
|
||||
sc->disable_msix = 0;
|
||||
sc->disable_msi = 0;
|
||||
sc->max_msix = MPR_MSIX_MAX;
|
||||
sc->max_chains = MPR_CHAIN_FRAMES;
|
||||
sc->max_io_pages = MPR_MAXIO_PAGES;
|
||||
sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
|
||||
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
|
||||
sc->use_phynum = 1;
|
||||
sc->max_reqframes = MPR_REQ_FRAMES;
|
||||
sc->max_prireqframes = MPR_PRI_REQ_FRAMES;
|
||||
sc->max_replyframes = MPR_REPLY_FRAMES;
|
||||
sc->max_evtframes = MPR_EVT_REPLY_FRAMES;
|
||||
|
||||
/*
|
||||
* Grab the global variables.
|
||||
@ -1574,11 +1614,16 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
TUNABLE_INT_FETCH("hw.mpr.debug_level", &sc->mpr_debug);
|
||||
TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix);
|
||||
TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_msix", &sc->max_msix);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_io_pages", &sc->max_io_pages);
|
||||
TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu);
|
||||
TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time);
|
||||
TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_reqframes", &sc->max_reqframes);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_prireqframes", &sc->max_prireqframes);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_replyframes", &sc->max_replyframes);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_evtframes", &sc->max_evtframes);
|
||||
|
||||
/* Grab the unit-instance variables */
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
|
||||
@ -1593,6 +1638,10 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->disable_msi);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_msix",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_msix);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_chains",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_chains);
|
||||
@ -1617,6 +1666,22 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.use_phy_num",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_reqframes",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_reqframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_prireqframes",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_prireqframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_replyframes",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_replyframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_evtframes",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_evtframes);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1658,8 +1723,28 @@ mpr_setup_sysctl(struct mpr_softc *sc)
|
||||
"Disable the use of MSI-X interrupts");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "disable_msi", CTLFLAG_RD, &sc->disable_msi, 0,
|
||||
"Disable the use of MSI interrupts");
|
||||
OID_AUTO, "max_msix", CTLFLAG_RD, &sc->max_msix, 0,
|
||||
"User-defined maximum number of MSIX queues");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "msix_msgs", CTLFLAG_RD, &sc->msi_msgs, 0,
|
||||
"Negotiated number of MSIX queues");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_reqframes", CTLFLAG_RD, &sc->max_reqframes, 0,
|
||||
"Total number of allocated request frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_prireqframes", CTLFLAG_RD, &sc->max_prireqframes, 0,
|
||||
"Total number of allocated high priority request frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_replyframes", CTLFLAG_RD, &sc->max_replyframes, 0,
|
||||
"Total number of allocated reply frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_evtframes", CTLFLAG_RD, &sc->max_evtframes, 0,
|
||||
"Total number of event frames allocated");
|
||||
|
||||
SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "firmware_version", CTLFLAG_RW, sc->fw_version,
|
||||
|
@ -262,23 +262,38 @@ mpr_pci_alloc_interrupts(struct mpr_softc *sc)
|
||||
error = 0;
|
||||
msgs = 0;
|
||||
|
||||
if ((sc->disable_msix == 0) &&
|
||||
((msgs = pci_msix_count(dev)) >= MPR_MSI_COUNT))
|
||||
error = mpr_alloc_msix(sc, MPR_MSI_COUNT);
|
||||
if ((error != 0) && (sc->disable_msi == 0) &&
|
||||
((msgs = pci_msi_count(dev)) >= MPR_MSI_COUNT))
|
||||
error = mpr_alloc_msi(sc, MPR_MSI_COUNT);
|
||||
if (error != 0) {
|
||||
if (sc->disable_msix == 0) {
|
||||
msgs = pci_msix_count(dev);
|
||||
mpr_dprint(sc, MPR_INIT, "Counted %d MSI-X messages\n", msgs);
|
||||
msgs = min(msgs, sc->max_msix);
|
||||
msgs = min(msgs, MPR_MSIX_MAX);
|
||||
msgs = min(msgs, 1); /* XXX */
|
||||
if (msgs != 0) {
|
||||
mpr_dprint(sc, MPR_INIT, "Attempting to allocate %d MSI-X "
|
||||
"messages\n", msgs);
|
||||
error = mpr_alloc_msix(sc, msgs);
|
||||
}
|
||||
}
|
||||
if (((error != 0) || (msgs == 0)) && (sc->disable_msi == 0)) {
|
||||
msgs = pci_msi_count(dev);
|
||||
mpr_dprint(sc, MPR_INIT, "Counted %d MSI messages\n", msgs);
|
||||
msgs = min(msgs, MPR_MSI_MAX);
|
||||
if (msgs != 0) {
|
||||
mpr_dprint(sc, MPR_INIT, "Attempting to allocated %d MSI "
|
||||
"messages\n", MPR_MSI_MAX);
|
||||
error = mpr_alloc_msi(sc, MPR_MSI_MAX);
|
||||
}
|
||||
}
|
||||
if ((error != 0) || (msgs == 0)) {
|
||||
/*
|
||||
* If neither MSI or MSI-X are available, assume legacy INTx.
|
||||
* This also implies that there will be only 1 queue.
|
||||
*/
|
||||
mpr_dprint(sc, MPR_INIT, "Falling back to legacy INTx\n");
|
||||
sc->mpr_flags |= MPR_FLAGS_INTX;
|
||||
msgs = 1;
|
||||
} else {
|
||||
} else
|
||||
sc->mpr_flags |= MPR_FLAGS_MSI;
|
||||
msgs = MPR_MSI_COUNT; /* XXX */
|
||||
}
|
||||
|
||||
sc->msi_msgs = msgs;
|
||||
mpr_dprint(sc, MPR_INIT, "Allocated %d interrupts\n", msgs);
|
||||
@ -318,6 +333,7 @@ mpr_pci_setup_interrupts(struct mpr_softc *sc)
|
||||
if (q->irq == NULL) {
|
||||
mpr_dprint(sc, MPR_ERROR|MPR_INIT,
|
||||
"Cannot allocate interrupt RID %d\n", rid);
|
||||
sc->msi_msgs = i;
|
||||
break;
|
||||
}
|
||||
error = bus_setup_intr(dev, q->irq,
|
||||
@ -326,6 +342,7 @@ mpr_pci_setup_interrupts(struct mpr_softc *sc)
|
||||
if (error) {
|
||||
mpr_dprint(sc, MPR_ERROR|MPR_INIT,
|
||||
"Cannot setup interrupt RID %d\n", rid);
|
||||
sc->msi_msgs = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -924,6 +924,9 @@ mpr_detach_sas(struct mpr_softc *sc)
|
||||
/* Make sure CAM doesn't wedge if we had to bail out early. */
|
||||
mpr_lock(sc);
|
||||
|
||||
while (sassc->startup_refcount != 0)
|
||||
mprsas_startup_decrement(sassc);
|
||||
|
||||
/* Deregister our async handler */
|
||||
if (sassc->path != NULL) {
|
||||
xpt_register_async(0, mprsas_async, sc, sassc->path);
|
||||
|
@ -37,13 +37,15 @@
|
||||
|
||||
#define MPR_DB_MAX_WAIT 2500
|
||||
|
||||
#define MPR_REQ_FRAMES 1024
|
||||
#define MPR_REQ_FRAMES 2048
|
||||
#define MPR_PRI_REQ_FRAMES 128
|
||||
#define MPR_EVT_REPLY_FRAMES 32
|
||||
#define MPR_REPLY_FRAMES MPR_REQ_FRAMES
|
||||
#define MPR_CHAIN_FRAMES 2048
|
||||
#define MPR_MAXIO_PAGES (-1)
|
||||
#define MPR_SENSE_LEN SSD_FULL_SIZE
|
||||
#define MPR_MSI_COUNT 1
|
||||
#define MPR_MSI_MAX 1
|
||||
#define MPR_MSIX_MAX 96
|
||||
#define MPR_SGE64_SIZE 12
|
||||
#define MPR_SGE32_SIZE 8
|
||||
#define MPR_SGC_SIZE 8
|
||||
@ -296,8 +298,6 @@ struct mpr_softc {
|
||||
#define MPR_FLAGS_GEN35_IOC (1 << 6)
|
||||
#define MPR_FLAGS_REALLOCATED (1 << 7)
|
||||
u_int mpr_debug;
|
||||
u_int disable_msix;
|
||||
u_int disable_msi;
|
||||
int msi_msgs;
|
||||
u_int atomic_desc_capable;
|
||||
int tm_cmds_active;
|
||||
@ -446,7 +446,16 @@ struct mpr_softc {
|
||||
uint32_t SSU_refcount;
|
||||
uint8_t SSU_started;
|
||||
|
||||
/* Configuration tunables */
|
||||
u_int disable_msix;
|
||||
u_int disable_msi;
|
||||
u_int max_msix;
|
||||
u_int max_reqframes;
|
||||
u_int max_prireqframes;
|
||||
u_int max_replyframes;
|
||||
u_int max_evtframes;
|
||||
char exclude_ids[80];
|
||||
|
||||
struct timeval lastfail;
|
||||
};
|
||||
|
||||
|
@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static int mps_diag_reset(struct mps_softc *sc, int sleep_flag);
|
||||
static int mps_init_queues(struct mps_softc *sc);
|
||||
static void mps_resize_queues(struct mps_softc *sc);
|
||||
static int mps_message_unit_reset(struct mps_softc *sc, int sleep_flag);
|
||||
static int mps_transition_operational(struct mps_softc *sc);
|
||||
static int mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching);
|
||||
@ -368,6 +369,46 @@ mps_transition_operational(struct mps_softc *sc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
mps_resize_queues(struct mps_softc *sc)
|
||||
{
|
||||
int reqcr, prireqcr;
|
||||
|
||||
/*
|
||||
* Size the queues. Since the reply queues always need one free
|
||||
* entry, we'll deduct one reply message here. The LSI documents
|
||||
* suggest instead to add a count to the request queue, but I think
|
||||
* that it's better to deduct from reply queue.
|
||||
*/
|
||||
prireqcr = MAX(1, sc->max_prireqframes);
|
||||
prireqcr = MIN(prireqcr, sc->facts->HighPriorityCredit);
|
||||
|
||||
reqcr = MAX(2, sc->max_reqframes);
|
||||
reqcr = MIN(reqcr, sc->facts->RequestCredit);
|
||||
|
||||
sc->num_reqs = prireqcr + reqcr;
|
||||
sc->num_replies = MIN(sc->max_replyframes + sc->max_evtframes,
|
||||
sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
|
||||
|
||||
/*
|
||||
* Figure out the number of MSIx-based queues. If the firmware or
|
||||
* user has done something crazy and not allowed enough credit for
|
||||
* the queues to be useful then don't enable multi-queue.
|
||||
*/
|
||||
if (sc->facts->MaxMSIxVectors < 2)
|
||||
sc->msi_msgs = 1;
|
||||
|
||||
if (sc->msi_msgs > 1) {
|
||||
sc->msi_msgs = MIN(sc->msi_msgs, mp_ncpus);
|
||||
sc->msi_msgs = MIN(sc->msi_msgs, sc->facts->MaxMSIxVectors);
|
||||
if (sc->num_reqs / sc->msi_msgs < 2)
|
||||
sc->msi_msgs = 1;
|
||||
}
|
||||
|
||||
mps_dprint(sc, MPS_INIT, "Sized queues to q=%d reqs=%d replies=%d\n",
|
||||
sc->msi_msgs, sc->num_reqs, sc->num_replies);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called during attach and when re-initializing due to a Diag Reset.
|
||||
* IOC Facts is used to allocate many of the structures needed by the driver.
|
||||
@ -518,13 +559,7 @@ mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching)
|
||||
if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
|
||||
sc->control_TLR = TRUE;
|
||||
|
||||
/*
|
||||
* Size the queues. Since the reply queues always need one free
|
||||
* entry, we'll just deduct one reply message here.
|
||||
*/
|
||||
sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
|
||||
sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
|
||||
sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
|
||||
mps_resize_queues(sc);
|
||||
|
||||
/*
|
||||
* Initialize all Tail Queues
|
||||
@ -1121,11 +1156,11 @@ mps_alloc_queues(struct mps_softc *sc)
|
||||
struct mps_queue *q;
|
||||
int nq, i;
|
||||
|
||||
nq = MIN(sc->msi_msgs, mp_ncpus);
|
||||
sc->msi_msgs = nq;
|
||||
nq = sc->msi_msgs;
|
||||
mps_dprint(sc, MPS_INIT|MPS_XINFO, "Allocating %d I/O queues\n", nq);
|
||||
|
||||
sc->queues = malloc(sizeof(struct mps_queue) * nq, M_MPT2, M_NOWAIT|M_ZERO);
|
||||
sc->queues = malloc(sizeof(struct mps_queue) * nq, M_MPT2,
|
||||
M_NOWAIT|M_ZERO);
|
||||
if (sc->queues == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -1423,11 +1458,16 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
sc->mps_debug = MPS_INFO|MPS_FAULT;
|
||||
sc->disable_msix = 0;
|
||||
sc->disable_msi = 0;
|
||||
sc->max_msix = MPS_MSIX_MAX;
|
||||
sc->max_chains = MPS_CHAIN_FRAMES;
|
||||
sc->max_io_pages = MPS_MAXIO_PAGES;
|
||||
sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
|
||||
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
|
||||
sc->use_phynum = 1;
|
||||
sc->max_reqframes = MPS_REQ_FRAMES;
|
||||
sc->max_prireqframes = MPS_PRI_REQ_FRAMES;
|
||||
sc->max_replyframes = MPS_REPLY_FRAMES;
|
||||
sc->max_evtframes = MPS_EVT_REPLY_FRAMES;
|
||||
|
||||
/*
|
||||
* Grab the global variables.
|
||||
@ -1435,11 +1475,16 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
TUNABLE_INT_FETCH("hw.mps.debug_level", &sc->mps_debug);
|
||||
TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix);
|
||||
TUNABLE_INT_FETCH("hw.mps.disable_msi", &sc->disable_msi);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_msix", &sc->max_msix);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_chains", &sc->max_chains);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_io_pages", &sc->max_io_pages);
|
||||
TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu);
|
||||
TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time);
|
||||
TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_reqframes", &sc->max_reqframes);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_prireqframes", &sc->max_prireqframes);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_replyframes", &sc->max_replyframes);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_evtframes", &sc->max_evtframes);
|
||||
|
||||
/* Grab the unit-instance variables */
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
|
||||
@ -1454,6 +1499,10 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->disable_msi);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_msix",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_msix);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_chains",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_chains);
|
||||
@ -1478,6 +1527,23 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.use_phy_num",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_reqframes",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_reqframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_prireqframes",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_prireqframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_replyframes",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_replyframes);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_evtframes",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->max_evtframes);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1522,6 +1588,30 @@ mps_setup_sysctl(struct mps_softc *sc)
|
||||
OID_AUTO, "disable_msi", CTLFLAG_RD, &sc->disable_msi, 0,
|
||||
"Disable the use of MSI interrupts");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_msix", CTLFLAG_RD, &sc->max_msix, 0,
|
||||
"User-defined maximum number of MSIX queues");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "msix_msgs", CTLFLAG_RD, &sc->msi_msgs, 0,
|
||||
"Negotiated number of MSIX queues");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_reqframes", CTLFLAG_RD, &sc->max_reqframes, 0,
|
||||
"Total number of allocated request frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_prireqframes", CTLFLAG_RD, &sc->max_prireqframes, 0,
|
||||
"Total number of allocated high priority request frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_replyframes", CTLFLAG_RD, &sc->max_replyframes, 0,
|
||||
"Total number of allocated reply frames");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "max_evtframes", CTLFLAG_RD, &sc->max_evtframes, 0,
|
||||
"Total number of event frames allocated");
|
||||
|
||||
SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "firmware_version", CTLFLAG_RW, sc->fw_version,
|
||||
strlen(sc->fw_version), "firmware version");
|
||||
|
@ -247,23 +247,38 @@ mps_pci_alloc_interrupts(struct mps_softc *sc)
|
||||
error = 0;
|
||||
msgs = 0;
|
||||
|
||||
if ((sc->disable_msix == 0) &&
|
||||
((msgs = pci_msix_count(dev)) >= MPS_MSI_COUNT))
|
||||
error = mps_alloc_msix(sc, MPS_MSI_COUNT);
|
||||
if ((error != 0) && (sc->disable_msi == 0) &&
|
||||
((msgs = pci_msi_count(dev)) >= MPS_MSI_COUNT))
|
||||
error = mps_alloc_msi(sc, MPS_MSI_COUNT);
|
||||
if (error != 0) {
|
||||
if (sc->disable_msix == 0) {
|
||||
msgs = pci_msix_count(dev);
|
||||
mps_dprint(sc, MPS_INIT, "Counted %d MSI-X messages\n", msgs);
|
||||
msgs = min(msgs, sc->max_msix);
|
||||
msgs = min(msgs, MPS_MSIX_MAX);
|
||||
msgs = min(msgs, 1); /* XXX */
|
||||
if (msgs != 0) {
|
||||
mps_dprint(sc, MPS_INIT, "Attempting to allocate %d MSI-X "
|
||||
"messages\n", msgs);
|
||||
error = mps_alloc_msix(sc, msgs);
|
||||
}
|
||||
}
|
||||
if (((error != 0) || (msgs == 0)) && (sc->disable_msi == 0)) {
|
||||
msgs = pci_msi_count(dev);
|
||||
mps_dprint(sc, MPS_INIT, "Counted %d MSI messages\n", msgs);
|
||||
msgs = min(msgs, MPS_MSI_MAX);
|
||||
if (msgs != 0) {
|
||||
mps_dprint(sc, MPS_INIT, "Attempting to allocate %d MSI "
|
||||
"messages\n", MPS_MSI_MAX);
|
||||
error = mps_alloc_msi(sc, MPS_MSI_MAX);
|
||||
}
|
||||
}
|
||||
if ((error != 0) || (msgs == 0)) {
|
||||
/*
|
||||
* If neither MSI or MSI-X are avaiable, assume legacy INTx.
|
||||
* This also implies that there will be only 1 queue.
|
||||
*/
|
||||
mps_dprint(sc, MPS_INIT, "Falling back to legacy INTx\n");
|
||||
sc->mps_flags |= MPS_FLAGS_INTX;
|
||||
msgs = 1;
|
||||
} else {
|
||||
} else
|
||||
sc->mps_flags |= MPS_FLAGS_MSI;
|
||||
msgs = 1; /* XXX */
|
||||
}
|
||||
|
||||
sc->msi_msgs = msgs;
|
||||
mps_dprint(sc, MPS_INIT, "Allocated %d interrupts\n", msgs);
|
||||
@ -302,7 +317,8 @@ mps_pci_setup_interrupts(struct mps_softc *sc)
|
||||
&q->irq_rid, RF_ACTIVE);
|
||||
if (q->irq == NULL) {
|
||||
mps_dprint(sc, MPS_ERROR|MPS_INIT,
|
||||
"Cannot allocate interrupt RID%d\n", rid);
|
||||
"Cannot allocate interrupt RID %d\n", rid);
|
||||
sc->msi_msgs = i;
|
||||
break;
|
||||
}
|
||||
error = bus_setup_intr(dev, q->irq,
|
||||
@ -311,6 +327,7 @@ mps_pci_setup_interrupts(struct mps_softc *sc)
|
||||
if (error) {
|
||||
mps_dprint(sc, MPS_ERROR|MPS_INIT,
|
||||
"Cannot setup interrupt RID %d\n", rid);
|
||||
sc->msi_msgs = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -871,6 +871,9 @@ mps_detach_sas(struct mps_softc *sc)
|
||||
/* Make sure CAM doesn't wedge if we had to bail out early. */
|
||||
mps_lock(sc);
|
||||
|
||||
while (sassc->startup_refcount != 0)
|
||||
mpssas_startup_decrement(sassc);
|
||||
|
||||
/* Deregister our async handler */
|
||||
if (sassc->path != NULL) {
|
||||
xpt_register_async(0, mpssas_async, sc, sassc->path);
|
||||
|
@ -37,13 +37,15 @@
|
||||
|
||||
#define MPS_DB_MAX_WAIT 2500
|
||||
|
||||
#define MPS_REQ_FRAMES 1024
|
||||
#define MPS_REQ_FRAMES 2048
|
||||
#define MPS_PRI_REQ_FRAMES 128
|
||||
#define MPS_EVT_REPLY_FRAMES 32
|
||||
#define MPS_REPLY_FRAMES MPS_REQ_FRAMES
|
||||
#define MPS_CHAIN_FRAMES 2048
|
||||
#define MPS_MAXIO_PAGES (-1)
|
||||
#define MPS_SENSE_LEN SSD_FULL_SIZE
|
||||
#define MPS_MSI_COUNT 1
|
||||
#define MPS_MSI_MAX 1
|
||||
#define MPS_MSIX_MAX 16
|
||||
#define MPS_SGE64_SIZE 12
|
||||
#define MPS_SGE32_SIZE 8
|
||||
#define MPS_SGC_SIZE 8
|
||||
@ -292,8 +294,6 @@ struct mps_softc {
|
||||
#define MPS_FLAGS_WD_AVAILABLE (1 << 6)
|
||||
#define MPS_FLAGS_REALLOCATED (1 << 7)
|
||||
u_int mps_debug;
|
||||
u_int disable_msix;
|
||||
u_int disable_msi;
|
||||
u_int msi_msgs;
|
||||
int tm_cmds_active;
|
||||
int io_cmds_active;
|
||||
@ -437,12 +437,21 @@ struct mps_softc {
|
||||
uint64_t DD_max_lba;
|
||||
struct mps_column_map DD_column_map[MPS_MAX_DISKS_IN_VOL];
|
||||
|
||||
char exclude_ids[80];
|
||||
struct timeval lastfail;
|
||||
|
||||
/* StartStopUnit command handling at shutdown */
|
||||
uint32_t SSU_refcount;
|
||||
uint8_t SSU_started;
|
||||
|
||||
/* Configuration tunables */
|
||||
u_int disable_msix;
|
||||
u_int disable_msi;
|
||||
u_int max_msix;
|
||||
u_int max_reqframes;
|
||||
u_int max_prireqframes;
|
||||
u_int max_replyframes;
|
||||
u_int max_evtframes;
|
||||
char exclude_ids[80];
|
||||
|
||||
struct timeval lastfail;
|
||||
};
|
||||
|
||||
struct mps_config_params {
|
||||
|
Loading…
Reference in New Issue
Block a user