diff options
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c0b4468683f9..d5d498fbee4b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3267,7 +3267,8 @@ void destroy_irq(unsigned int irq) | |||
3267 | * MSI message composition | 3267 | * MSI message composition |
3268 | */ | 3268 | */ |
3269 | #ifdef CONFIG_PCI_MSI | 3269 | #ifdef CONFIG_PCI_MSI |
3270 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | 3270 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, |
3271 | struct msi_msg *msg, u8 hpet_id) | ||
3271 | { | 3272 | { |
3272 | struct irq_cfg *cfg; | 3273 | struct irq_cfg *cfg; |
3273 | int err; | 3274 | int err; |
@@ -3301,7 +3302,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms | |||
3301 | irte.dest_id = IRTE_DEST(dest); | 3302 | irte.dest_id = IRTE_DEST(dest); |
3302 | 3303 | ||
3303 | /* Set source-id of interrupt request */ | 3304 | /* Set source-id of interrupt request */ |
3304 | set_msi_sid(&irte, pdev); | 3305 | if (pdev) |
3306 | set_msi_sid(&irte, pdev); | ||
3307 | else | ||
3308 | set_hpet_sid(&irte, hpet_id); | ||
3305 | 3309 | ||
3306 | modify_irte(irq, &irte); | 3310 | modify_irte(irq, &irte); |
3307 | 3311 | ||
@@ -3466,7 +3470,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) | |||
3466 | int ret; | 3470 | int ret; |
3467 | struct msi_msg msg; | 3471 | struct msi_msg msg; |
3468 | 3472 | ||
3469 | ret = msi_compose_msg(dev, irq, &msg); | 3473 | ret = msi_compose_msg(dev, irq, &msg, -1); |
3470 | if (ret < 0) | 3474 | if (ret < 0) |
3471 | return ret; | 3475 | return ret; |
3472 | 3476 | ||
@@ -3599,7 +3603,7 @@ int arch_setup_dmar_msi(unsigned int irq) | |||
3599 | int ret; | 3603 | int ret; |
3600 | struct msi_msg msg; | 3604 | struct msi_msg msg; |
3601 | 3605 | ||
3602 | ret = msi_compose_msg(NULL, irq, &msg); | 3606 | ret = msi_compose_msg(NULL, irq, &msg, -1); |
3603 | if (ret < 0) | 3607 | if (ret < 0) |
3604 | return ret; | 3608 | return ret; |
3605 | dmar_msi_write(irq, &msg); | 3609 | dmar_msi_write(irq, &msg); |
@@ -3639,6 +3643,19 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3639 | 3643 | ||
3640 | #endif /* CONFIG_SMP */ | 3644 | #endif /* CONFIG_SMP */ |
3641 | 3645 | ||
3646 | static struct irq_chip ir_hpet_msi_type = { | ||
3647 | .name = "IR-HPET_MSI", | ||
3648 | .unmask = hpet_msi_unmask, | ||
3649 | .mask = hpet_msi_mask, | ||
3650 | #ifdef CONFIG_INTR_REMAP | ||
3651 | .ack = ir_ack_apic_edge, | ||
3652 | #ifdef CONFIG_SMP | ||
3653 | .set_affinity = ir_set_msi_irq_affinity, | ||
3654 | #endif | ||
3655 | #endif | ||
3656 | .retrigger = ioapic_retrigger_irq, | ||
3657 | }; | ||
3658 | |||
3642 | static struct irq_chip hpet_msi_type = { | 3659 | static struct irq_chip hpet_msi_type = { |
3643 | .name = "HPET_MSI", | 3660 | .name = "HPET_MSI", |
3644 | .unmask = hpet_msi_unmask, | 3661 | .unmask = hpet_msi_unmask, |
@@ -3650,20 +3667,36 @@ static struct irq_chip hpet_msi_type = { | |||
3650 | .retrigger = ioapic_retrigger_irq, | 3667 | .retrigger = ioapic_retrigger_irq, |
3651 | }; | 3668 | }; |
3652 | 3669 | ||
3653 | int arch_setup_hpet_msi(unsigned int irq) | 3670 | int arch_setup_hpet_msi(unsigned int irq, unsigned int id) |
3654 | { | 3671 | { |
3655 | int ret; | 3672 | int ret; |
3656 | struct msi_msg msg; | 3673 | struct msi_msg msg; |
3657 | struct irq_desc *desc = irq_to_desc(irq); | 3674 | struct irq_desc *desc = irq_to_desc(irq); |
3658 | 3675 | ||
3659 | ret = msi_compose_msg(NULL, irq, &msg); | 3676 | if (intr_remapping_enabled) { |
3677 | struct intel_iommu *iommu = map_hpet_to_ir(id); | ||
3678 | int index; | ||
3679 | |||
3680 | if (!iommu) | ||
3681 | return -1; | ||
3682 | |||
3683 | index = alloc_irte(iommu, irq, 1); | ||
3684 | if (index < 0) | ||
3685 | return -1; | ||
3686 | } | ||
3687 | |||
3688 | ret = msi_compose_msg(NULL, irq, &msg, id); | ||
3660 | if (ret < 0) | 3689 | if (ret < 0) |
3661 | return ret; | 3690 | return ret; |
3662 | 3691 | ||
3663 | hpet_msi_write(irq, &msg); | 3692 | hpet_msi_write(irq, &msg); |
3664 | desc->status |= IRQ_MOVE_PCNTXT; | 3693 | desc->status |= IRQ_MOVE_PCNTXT; |
3665 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq, | 3694 | if (irq_remapped(irq)) |
3666 | "edge"); | 3695 | set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type, |
3696 | handle_edge_irq, "edge"); | ||
3697 | else | ||
3698 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, | ||
3699 | handle_edge_irq, "edge"); | ||
3667 | 3700 | ||
3668 | return 0; | 3701 | return 0; |
3669 | } | 3702 | } |