aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Delco <delco@google.com>2026-03-06 17:23:03 +0000
committerAlexander Ziaee <ziaee@FreeBSD.org>2026-03-06 17:28:41 +0000
commitb3d9e5013f3e5016ffbd3d3d6091194658af2b92 (patch)
tree78c4a19dd2e2f4ad22439b16b92e0aee9025e855
parentaf2c7d9f6452f2281a832b03375910f99230f924 (diff)
nvme: Don't active memory space until all BARs are configured
In the current current behavior the 2nd and 3rd BARs can be activated when they're configured with address zero. This change defers the activation of all BARs until after they've all been configured with an address. This enables FreeBSD on Google Compute Engine C4-LSSD Machines. Sponsored by: Google Tested by: NetApp (previous version) Reviewed by: gallatin, imp Discussed with: jrtc27 (improved error reporting) Differential Revision: https://reviews.freebsd.org/D55541
-rw-r--r--sys/dev/nvme/nvme_pci.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/sys/dev/nvme/nvme_pci.c b/sys/dev/nvme/nvme_pci.c
index 5784c6d1be96..74191df52058 100644
--- a/sys/dev/nvme/nvme_pci.c
+++ b/sys/dev/nvme/nvme_pci.c
@@ -151,24 +151,28 @@ nvme_pci_probe (device_t device)
static int
nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
{
+ int error;
+
ctrlr->resource_id = PCIR_BAR(0);
ctrlr->msix_table_resource_id = -1;
ctrlr->msix_table_resource = NULL;
ctrlr->msix_pba_resource_id = -1;
ctrlr->msix_pba_resource = NULL;
+ /*
+ * Using RF_ACTIVE will set the Memory Space bit in the PCI command register.
+ * The remaining BARs will get mapped in before they've been programmed with
+ * an address. To avoid this we'll not set this flag and instead call
+ * bus_activate_resource() after all the BARs have been programmed.
+ */
ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY,
- &ctrlr->resource_id, RF_ACTIVE);
+ &ctrlr->resource_id, 0);
if (ctrlr->resource == NULL) {
nvme_printf(ctrlr, "unable to allocate pci resource\n");
return (ENOMEM);
}
- ctrlr->bus_tag = rman_get_bustag(ctrlr->resource);
- ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource);
- ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle;
-
/*
* The NVMe spec allows for the MSI-X tables to be placed behind
* BAR 4 and/or 5, separate from the control/doorbell registers.
@@ -180,7 +184,7 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
if (ctrlr->msix_table_resource_id >= 0 &&
ctrlr->msix_table_resource_id != ctrlr->resource_id) {
ctrlr->msix_table_resource = bus_alloc_resource_any(ctrlr->dev,
- SYS_RES_MEMORY, &ctrlr->msix_table_resource_id, RF_ACTIVE);
+ SYS_RES_MEMORY, &ctrlr->msix_table_resource_id, 0);
if (ctrlr->msix_table_resource == NULL) {
nvme_printf(ctrlr, "unable to allocate msi-x table resource\n");
return (ENOMEM);
@@ -190,13 +194,39 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
ctrlr->msix_pba_resource_id != ctrlr->resource_id &&
ctrlr->msix_pba_resource_id != ctrlr->msix_table_resource_id) {
ctrlr->msix_pba_resource = bus_alloc_resource_any(ctrlr->dev,
- SYS_RES_MEMORY, &ctrlr->msix_pba_resource_id, RF_ACTIVE);
+ SYS_RES_MEMORY, &ctrlr->msix_pba_resource_id, 0);
if (ctrlr->msix_pba_resource == NULL) {
nvme_printf(ctrlr, "unable to allocate msi-x pba resource\n");
return (ENOMEM);
}
}
+ error = bus_activate_resource(ctrlr->dev, ctrlr->resource);
+ if (error) {
+ nvme_printf(ctrlr, "unable to activate pci resource: %d\n", error);
+ return (error);
+ }
+ if (ctrlr->msix_table_resource != NULL) {
+ error = bus_activate_resource(ctrlr->dev, ctrlr->msix_table_resource);
+ if (error) {
+ nvme_printf(ctrlr, "unable to activate msi-x table resource: %d\n",
+ error);
+ return (error);
+ }
+ }
+ if (ctrlr->msix_pba_resource != NULL) {
+ error = bus_activate_resource(ctrlr->dev, ctrlr->msix_pba_resource);
+ if (error) {
+ nvme_printf(ctrlr, "unable to activate msi-x pba resource: %d\n",
+ error);
+ return (error);
+ }
+ }
+
+ ctrlr->bus_tag = rman_get_bustag(ctrlr->resource);
+ ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource);
+ ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle;
+
return (0);
}