nvme: Add handling for bar5
The NVMe spec allows the Table BIR (TBIR) and PBA DIR (PBIR) to be 0, 4, or 5. The existing NVMe driver basically only has support for 4, perhaps under the assumption that BAR4 is 64-bit and also occupies BAR5. This change adds support for BAR5, covering the case where BAR4 and BAR5 might both be present and 32-bit, where the Table BIR might be 4 and the PBA BIR might be 5, or vice versa. The NVMe spec (in the SR-IOV section) also permits VFs to use BIR=2, so I haven't added stricter checks on which BIR will be permitted by the driver. This enables FreeBSD on Google Compute Engine C4 Machines. MFC after: 3 days Reviewed by: imp Sponsored by: Google Co-authored-by: Matt Delco <delco@google.com> Signed-off-by: Jasper Tran O'Leary <jtranoleary@google.com> Differential Revision: https://reviews.freebsd.org/D53140
This commit is contained in:
committed by
Alexander Ziaee
parent
9b9c726df1
commit
7b32f4f0a7
@@ -1762,9 +1762,14 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev)
|
||||
bus_release_resource(ctrlr->dev, SYS_RES_IRQ,
|
||||
rman_get_rid(ctrlr->res), ctrlr->res);
|
||||
|
||||
if (ctrlr->bar4_resource != NULL) {
|
||||
if (ctrlr->msix_table_resource != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
ctrlr->bar4_resource_id, ctrlr->bar4_resource);
|
||||
ctrlr->msix_table_resource_id, ctrlr->msix_table_resource);
|
||||
}
|
||||
|
||||
if (ctrlr->msix_pba_resource != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
ctrlr->msix_pba_resource_id, ctrlr->msix_pba_resource);
|
||||
}
|
||||
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
|
||||
+37
-11
@@ -152,11 +152,15 @@ static int
|
||||
nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
|
||||
{
|
||||
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;
|
||||
|
||||
ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY,
|
||||
&ctrlr->resource_id, RF_ACTIVE);
|
||||
|
||||
if(ctrlr->resource == NULL) {
|
||||
if (ctrlr->resource == NULL) {
|
||||
nvme_printf(ctrlr, "unable to allocate pci resource\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
@@ -166,15 +170,32 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
|
||||
ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle;
|
||||
|
||||
/*
|
||||
* The NVMe spec allows for the MSI-X table to be placed behind
|
||||
* BAR 4/5, separate from the control/doorbell registers. Always
|
||||
* try to map this bar, because it must be mapped prior to calling
|
||||
* pci_alloc_msix(). If the table isn't behind BAR 4/5,
|
||||
* bus_alloc_resource() will just return NULL which is OK.
|
||||
* The NVMe spec allows for the MSI-X tables to be placed behind
|
||||
* BAR 4 and/or 5, separate from the control/doorbell registers.
|
||||
*/
|
||||
ctrlr->bar4_resource_id = PCIR_BAR(4);
|
||||
ctrlr->bar4_resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY,
|
||||
&ctrlr->bar4_resource_id, RF_ACTIVE);
|
||||
|
||||
ctrlr->msix_table_resource_id = pci_msix_table_bar(ctrlr->dev);
|
||||
ctrlr->msix_pba_resource_id = pci_msix_pba_bar(ctrlr->dev);
|
||||
|
||||
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);
|
||||
if (ctrlr->msix_table_resource == NULL) {
|
||||
nvme_printf(ctrlr, "unable to allocate msi-x table resource\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
if (ctrlr->msix_pba_resource_id >= 0 &&
|
||||
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);
|
||||
if (ctrlr->msix_pba_resource == NULL) {
|
||||
nvme_printf(ctrlr, "unable to allocate msi-x pba resource\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -200,9 +221,14 @@ nvme_pci_attach(device_t dev)
|
||||
ctrlr->resource_id, ctrlr->resource);
|
||||
}
|
||||
|
||||
if (ctrlr->bar4_resource != NULL) {
|
||||
if (ctrlr->msix_table_resource != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
ctrlr->bar4_resource_id, ctrlr->bar4_resource);
|
||||
ctrlr->msix_table_resource_id, ctrlr->msix_table_resource);
|
||||
}
|
||||
|
||||
if (ctrlr->msix_pba_resource != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
ctrlr->msix_pba_resource_id, ctrlr->msix_pba_resource);
|
||||
}
|
||||
|
||||
if (ctrlr->tag)
|
||||
|
||||
@@ -235,8 +235,10 @@ struct nvme_controller {
|
||||
* separate from the control registers which are in BAR 0/1. These
|
||||
* members track the mapping of BAR 4/5 for that reason.
|
||||
*/
|
||||
int bar4_resource_id;
|
||||
struct resource *bar4_resource;
|
||||
int msix_table_resource_id;
|
||||
struct resource *msix_table_resource;
|
||||
int msix_pba_resource_id;
|
||||
struct resource *msix_pba_resource;
|
||||
|
||||
int msi_count;
|
||||
uint32_t enable_aborts;
|
||||
|
||||
Reference in New Issue
Block a user