Merge tag 'x86-irq-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 irq updates from Thomas Gleixner: "Surgery of the MSI interrupt handling to prepare the support of upcoming devices which require non-PCI based MSI handling: - Cleanup historical leftovers all over the place - Rework the code to utilize more core functionality - Wrap XEN PCI/MSI interrupts into an irqdomain to make irqdomain assignment to PCI devices possible. - Assign irqdomains to PCI devices at initialization time which allows to utilize the full functionality of hierarchical irqdomains. - Remove arch_.*_msi_irq() functions from X86 and utilize the irqdomain which is assigned to the device for interrupt management. - Make the arch_.*_msi_irq() support conditional on a config switch and let the last few users select it" * tag 'x86-irq-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (40 commits) PCI: MSI: Fix Kconfig dependencies for PCI_MSI_ARCH_FALLBACKS x86/apic/msi: Unbreak DMAR and HPET MSI iommu/amd: Remove domain search for PCI/MSI iommu/vt-d: Remove domain search for PCI/MSI[X] x86/irq: Make most MSI ops XEN private x86/irq: Cleanup the arch_*_msi_irqs() leftovers PCI/MSI: Make arch_.*_msi_irq[s] fallbacks selectable x86/pci: Set default irq domain in pcibios_add_device() iommm/amd: Store irq domain in struct device iommm/vt-d: Store irq domain in struct device x86/xen: Wrap XEN MSI management into irqdomain irqdomain/msi: Allow to override msi_domain_alloc/free_irqs() x86/xen: Consolidate XEN-MSI init x86/xen: Rework MSI teardown x86/xen: Make xen_msi_init() static and rename it to xen_hvm_msi_init() PCI/MSI: Provide pci_dev_has_special_msi_domain() helper PCI_vmd_Mark_VMD_irqdomain_with_DOMAIN_BUS_VMD_MSI irqdomain/msi: Provide DOMAIN_BUS_VMD_MSI x86/irq: Initialize PCI/MSI domain at PCI init time x86/pci: Reducde #ifdeffery in PCI init code ...
This commit is contained in:
@@ -1568,18 +1568,17 @@ EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent);
|
||||
*/
|
||||
int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
||||
{
|
||||
struct irq_data *pos = NULL;
|
||||
struct irq_data *pos;
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
for (; data; data = data->parent_data)
|
||||
#endif
|
||||
for (pos = NULL; !pos && data; data = irqd_get_parent_data(data)) {
|
||||
if (data->chip && data->chip->irq_compose_msi_msg)
|
||||
pos = data;
|
||||
}
|
||||
|
||||
if (!pos)
|
||||
return -ENOSYS;
|
||||
|
||||
pos->chip->irq_compose_msi_msg(pos, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -473,6 +473,15 @@ static inline void irq_domain_deactivate_irq(struct irq_data *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline struct irq_data *irqd_get_parent_data(struct irq_data *irqd)
|
||||
{
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
return irqd->parent_data;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
|
@@ -187,7 +187,6 @@ static const struct irq_domain_ops msi_domain_ops = {
|
||||
.deactivate = msi_domain_deactivate,
|
||||
};
|
||||
|
||||
#ifdef GENERIC_MSI_DOMAIN_OPS
|
||||
static irq_hw_number_t msi_domain_ops_get_hwirq(struct msi_domain_info *info,
|
||||
msi_alloc_info_t *arg)
|
||||
{
|
||||
@@ -206,11 +205,6 @@ static void msi_domain_ops_set_desc(msi_alloc_info_t *arg,
|
||||
{
|
||||
arg->desc = desc;
|
||||
}
|
||||
#else
|
||||
#define msi_domain_ops_get_hwirq NULL
|
||||
#define msi_domain_ops_prepare NULL
|
||||
#define msi_domain_ops_set_desc NULL
|
||||
#endif /* !GENERIC_MSI_DOMAIN_OPS */
|
||||
|
||||
static int msi_domain_ops_init(struct irq_domain *domain,
|
||||
struct msi_domain_info *info,
|
||||
@@ -235,11 +229,13 @@ static int msi_domain_ops_check(struct irq_domain *domain,
|
||||
}
|
||||
|
||||
static struct msi_domain_ops msi_domain_ops_default = {
|
||||
.get_hwirq = msi_domain_ops_get_hwirq,
|
||||
.msi_init = msi_domain_ops_init,
|
||||
.msi_check = msi_domain_ops_check,
|
||||
.msi_prepare = msi_domain_ops_prepare,
|
||||
.set_desc = msi_domain_ops_set_desc,
|
||||
.get_hwirq = msi_domain_ops_get_hwirq,
|
||||
.msi_init = msi_domain_ops_init,
|
||||
.msi_check = msi_domain_ops_check,
|
||||
.msi_prepare = msi_domain_ops_prepare,
|
||||
.set_desc = msi_domain_ops_set_desc,
|
||||
.domain_alloc_irqs = __msi_domain_alloc_irqs,
|
||||
.domain_free_irqs = __msi_domain_free_irqs,
|
||||
};
|
||||
|
||||
static void msi_domain_update_dom_ops(struct msi_domain_info *info)
|
||||
@@ -251,6 +247,14 @@ static void msi_domain_update_dom_ops(struct msi_domain_info *info)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ops->domain_alloc_irqs == NULL)
|
||||
ops->domain_alloc_irqs = msi_domain_ops_default.domain_alloc_irqs;
|
||||
if (ops->domain_free_irqs == NULL)
|
||||
ops->domain_free_irqs = msi_domain_ops_default.domain_free_irqs;
|
||||
|
||||
if (!(info->flags & MSI_FLAG_USE_DEF_DOM_OPS))
|
||||
return;
|
||||
|
||||
if (ops->get_hwirq == NULL)
|
||||
ops->get_hwirq = msi_domain_ops_default.get_hwirq;
|
||||
if (ops->msi_init == NULL)
|
||||
@@ -284,8 +288,7 @@ struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
|
||||
{
|
||||
struct irq_domain *domain;
|
||||
|
||||
if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
|
||||
msi_domain_update_dom_ops(info);
|
||||
msi_domain_update_dom_ops(info);
|
||||
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
|
||||
msi_domain_update_chip_ops(info);
|
||||
|
||||
@@ -370,8 +373,13 @@ static bool msi_check_reservation_mode(struct irq_domain *domain,
|
||||
{
|
||||
struct msi_desc *desc;
|
||||
|
||||
if (domain->bus_token != DOMAIN_BUS_PCI_MSI)
|
||||
switch(domain->bus_token) {
|
||||
case DOMAIN_BUS_PCI_MSI:
|
||||
case DOMAIN_BUS_VMD_MSI:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(info->flags & MSI_FLAG_MUST_REACTIVATE))
|
||||
return false;
|
||||
@@ -387,17 +395,8 @@ static bool msi_check_reservation_mode(struct irq_domain *domain,
|
||||
return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
|
||||
* @domain: The domain to allocate from
|
||||
* @dev: Pointer to device struct of the device for which the interrupts
|
||||
* are allocated
|
||||
* @nvec: The number of interrupts to allocate
|
||||
*
|
||||
* Returns 0 on success or an error code.
|
||||
*/
|
||||
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,
|
||||
int nvec)
|
||||
{
|
||||
struct msi_domain_info *info = domain->host_data;
|
||||
struct msi_domain_ops *ops = info->ops;
|
||||
@@ -491,12 +490,24 @@ cleanup:
|
||||
}
|
||||
|
||||
/**
|
||||
* msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated tp @dev
|
||||
* @domain: The domain to managing the interrupts
|
||||
* msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
|
||||
* @domain: The domain to allocate from
|
||||
* @dev: Pointer to device struct of the device for which the interrupts
|
||||
* are free
|
||||
* are allocated
|
||||
* @nvec: The number of interrupts to allocate
|
||||
*
|
||||
* Returns 0 on success or an error code.
|
||||
*/
|
||||
void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
|
||||
int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
|
||||
int nvec)
|
||||
{
|
||||
struct msi_domain_info *info = domain->host_data;
|
||||
struct msi_domain_ops *ops = info->ops;
|
||||
|
||||
return ops->domain_alloc_irqs(domain, dev, nvec);
|
||||
}
|
||||
|
||||
void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
|
||||
{
|
||||
struct msi_desc *desc;
|
||||
|
||||
@@ -513,6 +524,20 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated tp @dev
|
||||
* @domain: The domain to managing the interrupts
|
||||
* @dev: Pointer to device struct of the device for which the interrupts
|
||||
* are free
|
||||
*/
|
||||
void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
|
||||
{
|
||||
struct msi_domain_info *info = domain->host_data;
|
||||
struct msi_domain_ops *ops = info->ops;
|
||||
|
||||
return ops->domain_free_irqs(domain, dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* msi_get_domain_info - Get the MSI interrupt domain info for @domain
|
||||
* @domain: The interrupt domain to retrieve data from
|
||||
|
Reference in New Issue
Block a user