aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/nvme
diff options
context:
space:
mode:
authorJim Harris <jimharris@FreeBSD.org>2016-01-07 16:12:42 +0000
committerJim Harris <jimharris@FreeBSD.org>2016-01-07 16:12:42 +0000
commitd400f790b12fc5a8b945b6dfbde3b90e723a5632 (patch)
tree855fa01ee101852247a822aa6fd57fdd58199be1 /sys/dev/nvme
parente5af5854ff3b396ed514c3231463b7ef654ca0bb (diff)
downloadsrc-d400f790b12fc5a8b945b6dfbde3b90e723a5632.tar.gz
src-d400f790b12fc5a8b945b6dfbde3b90e723a5632.zip
nvme: break out interrupt setup code into a separate function
MFC after: 3 days Sponsored by: Intel
Notes
Notes: svn path=/head/; revision=293327
Diffstat (limited to 'sys/dev/nvme')
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c129
1 files changed, 63 insertions, 66 deletions
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 35ee07b2b7e4..76f9fb3ec996 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
static void nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
struct nvme_async_event_request *aer);
+static void nvme_ctrlr_setup_interrupts(struct nvme_controller *ctrlr);
static int
nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
@@ -777,6 +778,7 @@ static int
nvme_ctrlr_configure_intx(struct nvme_controller *ctrlr)
{
+ ctrlr->msix_enabled = 0;
ctrlr->num_io_queues = 1;
ctrlr->rid = 0;
ctrlr->res = bus_alloc_resource_any(ctrlr->dev, SYS_RES_IRQ,
@@ -924,80 +926,35 @@ static struct cdevsw nvme_ctrlr_cdevsw = {
.d_ioctl = nvme_ctrlr_ioctl
};
-int
-nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
+static void
+nvme_ctrlr_setup_interrupts(struct nvme_controller *ctrlr)
{
- union cap_lo_register cap_lo;
- union cap_hi_register cap_hi;
- int per_cpu_io_queues;
- int num_vectors_requested, num_vectors_allocated;
- int status, timeout_period;
-
- ctrlr->dev = dev;
-
- mtx_init(&ctrlr->lock, "nvme ctrlr lock", NULL, MTX_DEF);
-
- status = nvme_ctrlr_allocate_bar(ctrlr);
-
- if (status != 0)
- return (status);
-
- /*
- * Software emulators may set the doorbell stride to something
- * other than zero, but this driver is not set up to handle that.
- */
- cap_hi.raw = nvme_mmio_read_4(ctrlr, cap_hi);
- if (cap_hi.bits.dstrd != 0)
- return (ENXIO);
-
- ctrlr->min_page_size = 1 << (12 + cap_hi.bits.mpsmin);
-
- /* Get ready timeout value from controller, in units of 500ms. */
- cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo);
- ctrlr->ready_timeout_in_ms = cap_lo.bits.to * 500;
-
- timeout_period = NVME_DEFAULT_TIMEOUT_PERIOD;
- TUNABLE_INT_FETCH("hw.nvme.timeout_period", &timeout_period);
- timeout_period = min(timeout_period, NVME_MAX_TIMEOUT_PERIOD);
- timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
- ctrlr->timeout_period = timeout_period;
-
- nvme_retry_count = NVME_DEFAULT_RETRY_COUNT;
- TUNABLE_INT_FETCH("hw.nvme.retry_count", &nvme_retry_count);
+ device_t dev;
+ int per_cpu_io_queues;
+ int num_vectors_requested, num_vectors_allocated;
+ dev = ctrlr->dev;
per_cpu_io_queues = 1;
TUNABLE_INT_FETCH("hw.nvme.per_cpu_io_queues", &per_cpu_io_queues);
- if (per_cpu_io_queues)
- ctrlr->num_io_queues = mp_ncpus;
- else
- ctrlr->num_io_queues = 1;
-
ctrlr->force_intx = 0;
TUNABLE_INT_FETCH("hw.nvme.force_intx", &ctrlr->force_intx);
- ctrlr->enable_aborts = 0;
- TUNABLE_INT_FETCH("hw.nvme.enable_aborts", &ctrlr->enable_aborts);
+ if (ctrlr->force_intx || pci_msix_count(dev) < 2) {
+ nvme_ctrlr_configure_intx(ctrlr);
+ return;
+ }
ctrlr->msix_enabled = 1;
- if (ctrlr->force_intx) {
- ctrlr->msix_enabled = 0;
- goto intx;
- }
+ if (per_cpu_io_queues)
+ ctrlr->num_io_queues = mp_ncpus;
+ else
+ ctrlr->num_io_queues = 1;
/* One vector per IO queue, plus one vector for admin queue. */
num_vectors_requested = ctrlr->num_io_queues + 1;
- /*
- * If we cannot even allocate 2 vectors (one for admin, one for
- * I/O), then revert to INTx.
- */
- if (pci_msix_count(dev) < 2) {
- ctrlr->msix_enabled = 0;
- goto intx;
- }
-
if (pci_msix_count(dev) < num_vectors_requested) {
ctrlr->num_io_queues = 1;
num_vectors_requested = 2; /* one for admin, one for I/O */
@@ -1005,15 +962,15 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
num_vectors_allocated = num_vectors_requested;
if (pci_alloc_msix(dev, &num_vectors_allocated) != 0) {
- ctrlr->msix_enabled = 0;
- goto intx;
+ nvme_ctrlr_configure_intx(ctrlr);
+ return;
}
if (num_vectors_allocated < num_vectors_requested) {
if (num_vectors_allocated < 2) {
pci_release_msi(dev);
- ctrlr->msix_enabled = 0;
- goto intx;
+ nvme_ctrlr_configure_intx(ctrlr);
+ return;
}
ctrlr->num_io_queues = 1;
@@ -1029,11 +986,51 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
if (num_vectors_allocated != 2)
panic("could not reallocate 2 vectors\n");
}
+}
+
+int
+nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
+{
+ union cap_lo_register cap_lo;
+ union cap_hi_register cap_hi;
+ int status, timeout_period;
-intx:
+ ctrlr->dev = dev;
- if (!ctrlr->msix_enabled)
- nvme_ctrlr_configure_intx(ctrlr);
+ mtx_init(&ctrlr->lock, "nvme ctrlr lock", NULL, MTX_DEF);
+
+ status = nvme_ctrlr_allocate_bar(ctrlr);
+
+ if (status != 0)
+ return (status);
+
+ /*
+ * Software emulators may set the doorbell stride to something
+ * other than zero, but this driver is not set up to handle that.
+ */
+ cap_hi.raw = nvme_mmio_read_4(ctrlr, cap_hi);
+ if (cap_hi.bits.dstrd != 0)
+ return (ENXIO);
+
+ ctrlr->min_page_size = 1 << (12 + cap_hi.bits.mpsmin);
+
+ /* Get ready timeout value from controller, in units of 500ms. */
+ cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo);
+ ctrlr->ready_timeout_in_ms = cap_lo.bits.to * 500;
+
+ timeout_period = NVME_DEFAULT_TIMEOUT_PERIOD;
+ TUNABLE_INT_FETCH("hw.nvme.timeout_period", &timeout_period);
+ timeout_period = min(timeout_period, NVME_MAX_TIMEOUT_PERIOD);
+ timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
+ ctrlr->timeout_period = timeout_period;
+
+ nvme_retry_count = NVME_DEFAULT_RETRY_COUNT;
+ TUNABLE_INT_FETCH("hw.nvme.retry_count", &nvme_retry_count);
+
+ ctrlr->enable_aborts = 0;
+ TUNABLE_INT_FETCH("hw.nvme.enable_aborts", &ctrlr->enable_aborts);
+
+ nvme_ctrlr_setup_interrupts(ctrlr);
ctrlr->max_xfer_size = NVME_MAX_XFER_SIZE;
nvme_ctrlr_construct_admin_qpair(ctrlr);