diff options
| author | Scott Long <scottl@FreeBSD.org> | 2017-09-11 01:51:27 +0000 |
|---|---|---|
| committer | Scott Long <scottl@FreeBSD.org> | 2017-09-11 01:51:27 +0000 |
| commit | 3c5ac992c76786af01081721995ae377131b3edc (patch) | |
| tree | 9c2b8ace5c8fb0c275d0677870e24c9006aa5001 /sys/dev/mpr | |
| parent | 5e66298138a2243c9de66734e678ec0c3ff2ec08 (diff) | |
Notes
Diffstat (limited to 'sys/dev/mpr')
| -rw-r--r-- | sys/dev/mpr/mpr.c | 109 | ||||
| -rw-r--r-- | sys/dev/mpr/mpr_pci.c | 37 | ||||
| -rw-r--r-- | sys/dev/mpr/mpr_sas.c | 3 | ||||
| -rw-r--r-- | sys/dev/mpr/mprvar.h | 17 |
4 files changed, 140 insertions, 26 deletions
diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index b34630d955ba..c5df73003715 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -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, diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index 0ac3e5ce8413..9430db5925de 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -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; } } diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index c646eb1743d2..e683e508db7d 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -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); diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index a33c2a0bf16c..0e97d6fefca4 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -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; }; |
