From 84ee36132b941a179dee2b7de76c71d3a6d57d28 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 16 Jan 2012 18:41:49 +0800 Subject: [PATCH] msix: Remove MSI-X allocation, step 3/many Add alloc_msix_vector pci method, which allocate one MSI-X at the specified position on the target CPU --- sys/bus/pci/pci.c | 161 ++++++++------------------------------ sys/bus/pci/pci_if.m | 8 +- sys/bus/pci/pci_private.h | 2 +- sys/bus/pci/pcivar.h | 5 +- 4 files changed, 41 insertions(+), 135 deletions(-) diff --git a/sys/bus/pci/pci.c b/sys/bus/pci/pci.c index a5f297e43e..7d50fb96b8 100644 --- a/sys/bus/pci/pci.c +++ b/sys/bus/pci/pci.c @@ -173,7 +173,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), DEVMETHOD(pci_find_extcap, pci_find_extcap_method), DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method), - DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method), + DEVMETHOD(pci_alloc_msix_vector, pci_alloc_msix_vector_method), DEVMETHOD(pci_release_msi, pci_release_msi_method), DEVMETHOD(pci_msi_count, pci_msi_count_method), DEVMETHOD(pci_msix_count, pci_msix_count_method), @@ -1463,149 +1463,52 @@ pci_resume_msix(device_t dev) } /* - * Attempt to allocate *count MSI-X messages. The actual number allocated is - * returned in *count. After this function returns, each message will be - * available to the driver as SYS_RES_IRQ resources starting at rid 1. + * Attempt to allocate one MSI-X message at the specified vector on cpuid. + * + * After this function returns, the MSI-X's rid will be saved in rid0. */ int -pci_alloc_msix_method(device_t dev, device_t child, int *count) +pci_alloc_msix_vector_method(device_t dev, device_t child, u_int vector, + int *rid0, int cpuid) { struct pci_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; + struct pcicfg_msix *msix = &dinfo->cfg.msix; struct resource_list_entry *rle; - int actual, error, i, irq, max; - - /* Don't let count == 0 get us into trouble. */ - if (*count == 0) - return (EINVAL); - - /* If rid 0 is allocated, then fail. */ - rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 0); - if (rle != NULL && rle->res != NULL) - return (ENXIO); - - /* Already have allocated messages? */ - if (cfg->msi.msi_alloc != 0 || cfg->msix.msix_alloc != 0) - return (ENXIO); - - /* If MSI is blacklisted for this system, fail. */ - if (pci_msi_blacklisted()) - return (ENXIO); - - /* MSI-X capability present? */ - if (cfg->msix.msix_location == 0 || !pci_do_msix) - return (ENODEV); + int error, irq, rid; - /* Make sure the appropriate BARs are mapped. */ - rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, - cfg->msix.msix_table_bar); - if (rle == NULL || rle->res == NULL || - !(rman_get_flags(rle->res) & RF_ACTIVE)) - return (ENXIO); - cfg->msix.msix_table_res = rle->res; - if (cfg->msix.msix_pba_bar != cfg->msix.msix_table_bar) { - rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, - cfg->msix.msix_pba_bar); - if (rle == NULL || rle->res == NULL || - !(rman_get_flags(rle->res) & RF_ACTIVE)) - return (ENXIO); - } - cfg->msix.msix_pba_res = rle->res; + KASSERT(msix->msix_table_res != NULL && + msix->msix_pba_res != NULL, ("MSI-X is not setup yet\n")); + KASSERT(cpuid >= 0 && cpuid < ncpus, ("invalid cpuid %d\n", cpuid)); + KASSERT(vector < msix->msix_msgnum, + ("invalid MSI-X vector %u, total %d\n", vector, msix->msix_msgnum)); - if (bootverbose) + if (bootverbose) { device_printf(child, - "attempting to allocate %d MSI-X vectors (%d supported)\n", - *count, cfg->msix.msix_msgnum); - max = min(*count, cfg->msix.msix_msgnum); - for (i = 0; i < max; i++) { - /* Allocate a message. */ - error = PCIB_ALLOC_MSIX(device_get_parent(dev), child, &irq, - -1 /* XXX */); - if (error) - break; - resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1, irq, - irq, 1, -1); + "attempting to allocate MSI-X #%u vector (%d supported)\n", + vector, msix->msix_msgnum); } - actual = i; - if (actual == 0) { - if (bootverbose) { - device_printf(child, - "could not allocate any MSI-X vectors\n"); - } - return (ENXIO); - } - - if (bootverbose) { - rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 1); - if (actual == 1) - device_printf(child, "using IRQ %lu for MSI-X\n", - rle->start); - else { - int run; - - /* - * Be fancy and try to print contiguous runs of - * IRQ values as ranges. 'irq' is the previous IRQ. - * 'run' is true if we are in a range. - */ - device_printf(child, "using IRQs %lu", rle->start); - irq = rle->start; - run = 0; - for (i = 1; i < actual; i++) { - rle = resource_list_find(&dinfo->resources, - SYS_RES_IRQ, i + 1); - - /* Still in a run? */ - if (rle->start == irq + 1) { - run = 1; - irq++; - continue; - } - - /* Finish previous range. */ - if (run) { - kprintf("-%d", irq); - run = 0; - } + /* Set rid according to vector number */ + rid = vector + 1; - /* Start new range. */ - kprintf(",%lu", rle->start); - irq = rle->start; - } - - /* Unfinished range? */ - if (run) - kprintf("-%d", irq); - kprintf(" for MSI-X\n"); - } - } - - /* Mask all vectors. */ - for (i = 0; i < cfg->msix.msix_msgnum; i++) - pci_mask_msix_vector(child, i); + /* Allocate a message. */ + error = PCIB_ALLOC_MSIX(device_get_parent(dev), child, &irq, cpuid); + if (error) + return error; + resource_list_add(&dinfo->resources, SYS_RES_IRQ, rid, + irq, irq, 1, cpuid); - /* Allocate and initialize vector data and virtual table. */ - cfg->msix.msix_vectors = kmalloc(sizeof(struct msix_vector) * actual, - M_DEVBUF, M_WAITOK | M_ZERO); - cfg->msix.msix_table = kmalloc(sizeof(struct msix_table_entry) * actual, - M_DEVBUF, M_WAITOK | M_ZERO); - for (i = 0; i < actual; i++) { - rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); - cfg->msix.msix_vectors[i].mv_irq = rle->start; - cfg->msix.msix_table[i].mte_vector = i + 1; + if (bootverbose) { + rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid); + device_printf(child, "using IRQ %lu for MSI-X on cpu%d\n", + rle->start, cpuid); } - /* Update control register to enable MSI-X. */ - cfg->msix.msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; - pci_write_config(child, cfg->msix.msix_location + PCIR_MSIX_CTRL, - cfg->msix.msix_ctrl, 2); - /* Update counts of alloc'd messages. */ - cfg->msix.msix_alloc = actual; - cfg->msix.msix_table_len = actual; - *count = actual; - return (0); + msix->msix_alloc++; + + *rid0 = rid; + return 0; } #ifdef notyet diff --git a/sys/bus/pci/pci_if.m b/sys/bus/pci/pci_if.m index ff86239112..d902b761c6 100644 --- a/sys/bus/pci/pci_if.m +++ b/sys/bus/pci/pci_if.m @@ -120,15 +120,17 @@ METHOD int alloc_msi { int cpuid; }; -METHOD int alloc_msix { +METHOD int release_msi { device_t dev; device_t child; - int *count; }; -METHOD int release_msi { +METHOD int alloc_msix_vector { device_t dev; device_t child; + u_int vector; + int *rid; + int cpuid; }; METHOD int msi_count { diff --git a/sys/bus/pci/pci_private.h b/sys/bus/pci/pci_private.h index 49413c010c..d5944a30a0 100644 --- a/sys/bus/pci/pci_private.h +++ b/sys/bus/pci/pci_private.h @@ -73,7 +73,7 @@ int pci_disable_io_method(device_t dev, device_t child, int space); int pci_find_extcap_method(device_t dev, device_t child, int capability, int *capreg); int pci_alloc_msi_method(device_t dev, device_t child, int *rid, int count, int cpuid); -int pci_alloc_msix_method(device_t dev, device_t child, int *count); +int pci_alloc_msix_vector_method(device_t dev, device_t child, u_int vector, int *rid, int cpuid); int pci_release_msi_method(device_t dev, device_t child); int pci_msi_count_method(device_t dev, device_t child); int pci_msix_count_method(device_t dev, device_t child); diff --git a/sys/bus/pci/pcivar.h b/sys/bus/pci/pcivar.h index b7298f587c..ac682f16c7 100644 --- a/sys/bus/pci/pcivar.h +++ b/sys/bus/pci/pcivar.h @@ -471,9 +471,10 @@ pci_alloc_msi(device_t dev, int *rid, int count, int cpuid) } static __inline int -pci_alloc_msix(device_t dev, int *count) +pci_alloc_msix_vector(device_t dev, u_int vector, int *rid, int cpuid) { - return (PCI_ALLOC_MSIX(device_get_parent(dev), dev, count)); + return (PCI_ALLOC_MSIX_VECTOR(device_get_parent(dev), dev, vector, rid, + cpuid)); } static __inline int -- 2.41.0