iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit
Refine the interfaces to create IRQ for DMAR unit. It's a preparation for converting DMAR IRQ to hierarchical irqdomain on x86. It also moves dmar_alloc_hwirq()/dmar_free_hwirq() from irq_remapping.h to dmar.h. They are not irq_remapping specific. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: David Cohen <david.a.cohen@linux.intel.com> Cc: Sander Eikelenboom <linux@eikelenboom.it> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: iommu@lists.linux-foundation.org Cc: Vinod Koul <vinod.koul@intel.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dimitri Sivanich <sivanich@sgi.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Link: http://lkml.kernel.org/r/1428905519-23704-20-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
b1855c752e
commit
34742db8ea
|
@ -1,6 +1,4 @@
|
||||||
#ifndef __IA64_INTR_REMAPPING_H
|
#ifndef __IA64_INTR_REMAPPING_H
|
||||||
#define __IA64_INTR_REMAPPING_H
|
#define __IA64_INTR_REMAPPING_H
|
||||||
#define irq_remapping_enabled 0
|
#define irq_remapping_enabled 0
|
||||||
#define dmar_alloc_hwirq create_irq
|
|
||||||
#define dmar_free_hwirq destroy_irq
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -165,7 +165,7 @@ static struct irq_chip dmar_msi_type = {
|
||||||
.irq_retrigger = ia64_msi_retrigger_irq,
|
.irq_retrigger = ia64_msi_retrigger_irq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static void
|
||||||
msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
|
msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
|
||||||
{
|
{
|
||||||
struct irq_cfg *cfg = irq_cfg + irq;
|
struct irq_cfg *cfg = irq_cfg + irq;
|
||||||
|
@ -186,21 +186,29 @@ msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
|
||||||
MSI_DATA_LEVEL_ASSERT |
|
MSI_DATA_LEVEL_ASSERT |
|
||||||
MSI_DATA_DELIVERY_FIXED |
|
MSI_DATA_DELIVERY_FIXED |
|
||||||
MSI_DATA_VECTOR(cfg->vector);
|
MSI_DATA_VECTOR(cfg->vector);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_setup_dmar_msi(unsigned int irq)
|
int dmar_alloc_hwirq(int id, int node, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int irq;
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
|
|
||||||
ret = msi_compose_msg(NULL, irq, &msg);
|
irq = create_irq();
|
||||||
if (ret < 0)
|
if (irq > 0) {
|
||||||
return ret;
|
irq_set_handler_data(irq, arg);
|
||||||
dmar_msi_write(irq, &msg);
|
irq_set_chip_and_handler_name(irq, &dmar_msi_type,
|
||||||
irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
|
handle_edge_irq, "edge");
|
||||||
"edge");
|
msi_compose_msg(NULL, irq, &msg);
|
||||||
return 0;
|
dmar_msi_write(irq, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dmar_free_hwirq(int irq)
|
||||||
|
{
|
||||||
|
irq_set_handler_data(irq, NULL);
|
||||||
|
destroy_irq(irq);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_INTEL_IOMMU */
|
#endif /* CONFIG_INTEL_IOMMU */
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,4 @@ irq_remapping_get_irq_domain(struct irq_alloc_info *info)
|
||||||
|
|
||||||
#define irq_remapping_print_chip NULL
|
#define irq_remapping_print_chip NULL
|
||||||
#endif /* CONFIG_IRQ_REMAP */
|
#endif /* CONFIG_IRQ_REMAP */
|
||||||
|
|
||||||
extern int dmar_alloc_hwirq(void);
|
|
||||||
extern void dmar_free_hwirq(int irq);
|
|
||||||
|
|
||||||
#endif /* __X86_IRQ_REMAPPING_H */
|
#endif /* __X86_IRQ_REMAPPING_H */
|
||||||
|
|
|
@ -228,25 +228,27 @@ static struct irq_chip dmar_msi_type = {
|
||||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||||
};
|
};
|
||||||
|
|
||||||
int arch_setup_dmar_msi(unsigned int irq)
|
int dmar_alloc_hwirq(int id, int node, void *arg)
|
||||||
{
|
{
|
||||||
|
int irq;
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
struct irq_cfg *cfg = irq_cfg(irq);
|
|
||||||
|
|
||||||
native_compose_msi_msg(cfg, &msg);
|
irq = irq_domain_alloc_irqs(NULL, 1, node, NULL);
|
||||||
dmar_msi_write(irq, &msg);
|
if (irq > 0) {
|
||||||
irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
|
irq_set_handler_data(irq, arg);
|
||||||
"edge");
|
irq_set_chip_and_handler_name(irq, &dmar_msi_type,
|
||||||
return 0;
|
handle_edge_irq, "edge");
|
||||||
}
|
native_compose_msi_msg(irq_cfg(irq), &msg);
|
||||||
|
dmar_msi_write(irq, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
int dmar_alloc_hwirq(void)
|
return irq;
|
||||||
{
|
|
||||||
return irq_domain_alloc_irqs(NULL, 1, NUMA_NO_NODE, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dmar_free_hwirq(int irq)
|
void dmar_free_hwirq(int irq)
|
||||||
{
|
{
|
||||||
|
irq_set_handler_data(irq, NULL);
|
||||||
|
irq_set_handler(irq, NULL);
|
||||||
irq_domain_free_irqs(irq, 1);
|
irq_domain_free_irqs(irq, 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1087,8 +1087,8 @@ static void free_iommu(struct intel_iommu *iommu)
|
||||||
|
|
||||||
if (iommu->irq) {
|
if (iommu->irq) {
|
||||||
free_irq(iommu->irq, iommu);
|
free_irq(iommu->irq, iommu);
|
||||||
irq_set_handler_data(iommu->irq, NULL);
|
|
||||||
dmar_free_hwirq(iommu->irq);
|
dmar_free_hwirq(iommu->irq);
|
||||||
|
iommu->irq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iommu->qi) {
|
if (iommu->qi) {
|
||||||
|
@ -1642,23 +1642,14 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
|
||||||
if (iommu->irq)
|
if (iommu->irq)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
irq = dmar_alloc_hwirq();
|
irq = dmar_alloc_hwirq(iommu->seq_id, iommu->node, iommu);
|
||||||
if (irq <= 0) {
|
if (irq > 0) {
|
||||||
|
iommu->irq = irq;
|
||||||
|
} else {
|
||||||
pr_err("IOMMU: no free vectors\n");
|
pr_err("IOMMU: no free vectors\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_set_handler_data(irq, iommu);
|
|
||||||
iommu->irq = irq;
|
|
||||||
|
|
||||||
ret = arch_setup_dmar_msi(irq);
|
|
||||||
if (ret) {
|
|
||||||
irq_set_handler_data(irq, NULL);
|
|
||||||
iommu->irq = 0;
|
|
||||||
dmar_free_hwirq(irq);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
|
ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_err("IOMMU: can't request irq\n");
|
pr_err("IOMMU: can't request irq\n");
|
||||||
|
|
|
@ -227,6 +227,7 @@ extern void dmar_msi_read(int irq, struct msi_msg *msg);
|
||||||
extern void dmar_msi_write(int irq, struct msi_msg *msg);
|
extern void dmar_msi_write(int irq, struct msi_msg *msg);
|
||||||
extern int dmar_set_interrupt(struct intel_iommu *iommu);
|
extern int dmar_set_interrupt(struct intel_iommu *iommu);
|
||||||
extern irqreturn_t dmar_fault(int irq, void *dev_id);
|
extern irqreturn_t dmar_fault(int irq, void *dev_id);
|
||||||
extern int arch_setup_dmar_msi(unsigned int irq);
|
extern int dmar_alloc_hwirq(int id, int node, void *arg);
|
||||||
|
extern void dmar_free_hwirq(int irq);
|
||||||
|
|
||||||
#endif /* __DMAR_H__ */
|
#endif /* __DMAR_H__ */
|
||||||
|
|
Loading…
Reference in New Issue