[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [patch 01/10] genirq/msi: Add range argument to alloc/free MSI domain ops
In preparation for supporting range allocations for MSI-X, add a range argument to the MSI domain alloc/free function pointers and fixup all affected places. The range is supplied via a pointer to a struct msi_range which contains the first and last MSI index and the number of vectors to allocate/free. To support the sparse MSI-X allocations via pci_enable_msix_range() and pci_enable_msix_exact() the number of vectors can be smaller than the range defined by the first and last MSI index. This can be cleaned up later once the code is converted by converting these sparse allocations to an initial allocation on enable and expansion of the vector space at the required indices. Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> --- arch/powerpc/platforms/pseries/msi.c | 6 +++--- arch/x86/pci/xen.c | 10 +++++----- include/linux/msi.h | 30 +++++++++++++++++++++++------- kernel/irq/msi.c | 12 ++++++------ 4 files changed, 37 insertions(+), 21 deletions(-) --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -450,13 +450,13 @@ static void pseries_msi_ops_msi_free(str * RTAS can not disable one MSI at a time. It's all or nothing. Do it * at the end after all IRQs have been freed. */ -static void pseries_msi_domain_free_irqs(struct irq_domain *domain, - struct device *dev) +static void pseries_msi_domain_free_irqs(struct irq_domain *domain, struct device *dev, + struct msi_range *range) { if (WARN_ON_ONCE(!dev_is_pci(dev))) return; - __msi_domain_free_irqs(domain, dev); + __msi_domain_free_irqs(domain, dev, range); rtas_disable_msi(to_pci_dev(dev)); } --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -407,8 +407,8 @@ static void xen_pv_teardown_msi_irqs(str xen_teardown_msi_irqs(dev); } -static int xen_msi_domain_alloc_irqs(struct irq_domain *domain, - struct device *dev, int nvec) +static int xen_msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, + struct msi_range *range) { int type; @@ -420,11 +420,11 @@ static int xen_msi_domain_alloc_irqs(str else type = PCI_CAP_ID_MSI; - return xen_msi_ops.setup_msi_irqs(to_pci_dev(dev), nvec, type); + return xen_msi_ops.setup_msi_irqs(to_pci_dev(dev), range->ndesc, type); } -static void xen_msi_domain_free_irqs(struct irq_domain *domain, - struct device *dev) +static void xen_msi_domain_free_irqs(struct irq_domain *domain, struct device *dev, + struct msi_range *range) { if (WARN_ON_ONCE(!dev_is_pci(dev))) return; --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -191,6 +191,23 @@ struct msi_device_data { enum msi_desc_filter __iter_filter; }; +/** + * msi_range - Descriptor for a MSI index range + * @first: First index + * @last: Last index (inclusive) + * @ndesc: Number of descriptors for allocations + * + * @first = 0 and @last = UINT_MAX is the full range for an operation. + * + * Note: @ndesc can be less than the range defined by @first and @last to + * support sparse allocations from PCI/MSI-X. + */ +struct msi_range { + unsigned int first; + unsigned int last; + unsigned int ndesc; +}; + int msi_setup_device_data(struct device *dev); /* MSI device properties */ @@ -415,10 +432,10 @@ struct msi_domain_ops { msi_alloc_info_t *arg); void (*set_desc)(msi_alloc_info_t *arg, struct msi_desc *desc); - int (*domain_alloc_irqs)(struct irq_domain *domain, - struct device *dev, int nvec); - void (*domain_free_irqs)(struct irq_domain *domain, - struct device *dev); + int (*domain_alloc_irqs)(struct irq_domain *domain, struct device *dev, + struct msi_range *range); + void (*domain_free_irqs)(struct irq_domain *domain, struct device *dev, + struct msi_range *range); }; /** @@ -484,13 +501,12 @@ int msi_domain_set_affinity(struct irq_d struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); -int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, - int nvec); +int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, struct msi_range *range); int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev, int nvec); int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec); -void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); +void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev, struct msi_range *range); void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev); void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain); --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -869,8 +869,7 @@ static int msi_init_virq(struct irq_doma return 0; } -int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, - int nvec) +int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, struct msi_range *range) { struct msi_domain_info *info = domain->host_data; struct msi_domain_ops *ops = info->ops; @@ -880,7 +879,7 @@ int __msi_domain_alloc_irqs(struct irq_d int allocated = 0; int i, ret, virq; - ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); + ret = msi_domain_prepare_irqs(domain, dev, range->ndesc, &arg); if (ret) return ret; @@ -960,6 +959,7 @@ int msi_domain_alloc_irqs_descs_locked(s int nvec) { struct msi_domain_info *info = domain->host_data; + struct msi_range range = { .ndesc = nvec }; struct msi_domain_ops *ops = info->ops; int ret; @@ -969,7 +969,7 @@ int msi_domain_alloc_irqs_descs_locked(s if (ret) return ret; - ret = ops->domain_alloc_irqs(domain, dev, nvec); + ret = ops->domain_alloc_irqs(domain, dev, &range); if (ret) msi_domain_free_irqs_descs_locked(domain, dev); return ret; @@ -994,7 +994,7 @@ int msi_domain_alloc_irqs(struct irq_dom return ret; } -void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) +void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev, struct msi_range *range) { struct msi_domain_info *info = domain->host_data; struct irq_data *irqd; @@ -1041,7 +1041,7 @@ void msi_domain_free_irqs_descs_locked(s lockdep_assert_held(&dev->msi.data->mutex); - ops->domain_free_irqs(domain, dev); + ops->domain_free_irqs(domain, dev, NULL); msi_domain_free_msi_descs(info, dev); }
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |