diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-08-04 15:07:09 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-08-27 17:33:20 -0400 |
commit | c8bc6f3c806f1fcbfdbf0b1ff6c52dba59192d3b (patch) | |
tree | 072f772308c44eb0223fbfb45c8a055918c70502 /arch/x86/kernel/apic | |
parent | 20f3097bfe5fb5ced0b14f9ea2620c4039bf1dde (diff) |
x86: arch specific support for remapping HPET MSIs
x86 arch support for remapping HPET MSI's by associating the HPET timer block
with the interrupt-remapping HW unit and setting up appropriate irq_chip
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Jay Fenlason <fenlason@redhat.com>
LKML-Reference: <20090804190729.630510000@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/apic')
-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 d2ed6c5ddc80..d9c6f14d3b32 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3254,7 +3254,8 @@ void destroy_irq(unsigned int irq) | |||
3254 | * MSI message composition | 3254 | * MSI message composition |
3255 | */ | 3255 | */ |
3256 | #ifdef CONFIG_PCI_MSI | 3256 | #ifdef CONFIG_PCI_MSI |
3257 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | 3257 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, |
3258 | struct msi_msg *msg, u8 hpet_id) | ||
3258 | { | 3259 | { |
3259 | struct irq_cfg *cfg; | 3260 | struct irq_cfg *cfg; |
3260 | int err; | 3261 | int err; |
@@ -3288,7 +3289,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms | |||
3288 | irte.dest_id = IRTE_DEST(dest); | 3289 | irte.dest_id = IRTE_DEST(dest); |
3289 | 3290 | ||
3290 | /* Set source-id of interrupt request */ | 3291 | /* Set source-id of interrupt request */ |
3291 | set_msi_sid(&irte, pdev); | 3292 | if (pdev) |
3293 | set_msi_sid(&irte, pdev); | ||
3294 | else | ||
3295 | set_hpet_sid(&irte, hpet_id); | ||
3292 | 3296 | ||
3293 | modify_irte(irq, &irte); | 3297 | modify_irte(irq, &irte); |
3294 | 3298 | ||
@@ -3453,7 +3457,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) | |||
3453 | int ret; | 3457 | int ret; |
3454 | struct msi_msg msg; | 3458 | struct msi_msg msg; |
3455 | 3459 | ||
3456 | ret = msi_compose_msg(dev, irq, &msg); | 3460 | ret = msi_compose_msg(dev, irq, &msg, -1); |
3457 | if (ret < 0) | 3461 | if (ret < 0) |
3458 | return ret; | 3462 | return ret; |
3459 | 3463 | ||
@@ -3586,7 +3590,7 @@ int arch_setup_dmar_msi(unsigned int irq) | |||
3586 | int ret; | 3590 | int ret; |
3587 | struct msi_msg msg; | 3591 | struct msi_msg msg; |
3588 | 3592 | ||
3589 | ret = msi_compose_msg(NULL, irq, &msg); | 3593 | ret = msi_compose_msg(NULL, irq, &msg, -1); |
3590 | if (ret < 0) | 3594 | if (ret < 0) |
3591 | return ret; | 3595 | return ret; |
3592 | dmar_msi_write(irq, &msg); | 3596 | dmar_msi_write(irq, &msg); |
@@ -3626,6 +3630,19 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3626 | 3630 | ||
3627 | #endif /* CONFIG_SMP */ | 3631 | #endif /* CONFIG_SMP */ |
3628 | 3632 | ||
3633 | static struct irq_chip ir_hpet_msi_type = { | ||
3634 | .name = "IR-HPET_MSI", | ||
3635 | .unmask = hpet_msi_unmask, | ||
3636 | .mask = hpet_msi_mask, | ||
3637 | #ifdef CONFIG_INTR_REMAP | ||
3638 | .ack = ir_ack_apic_edge, | ||
3639 | #ifdef CONFIG_SMP | ||
3640 | .set_affinity = ir_set_msi_irq_affinity, | ||
3641 | #endif | ||
3642 | #endif | ||
3643 | .retrigger = ioapic_retrigger_irq, | ||
3644 | }; | ||
3645 | |||
3629 | static struct irq_chip hpet_msi_type = { | 3646 | static struct irq_chip hpet_msi_type = { |
3630 | .name = "HPET_MSI", | 3647 | .name = "HPET_MSI", |
3631 | .unmask = hpet_msi_unmask, | 3648 | .unmask = hpet_msi_unmask, |
@@ -3637,20 +3654,36 @@ static struct irq_chip hpet_msi_type = { | |||
3637 | .retrigger = ioapic_retrigger_irq, | 3654 | .retrigger = ioapic_retrigger_irq, |
3638 | }; | 3655 | }; |
3639 | 3656 | ||
3640 | int arch_setup_hpet_msi(unsigned int irq) | 3657 | int arch_setup_hpet_msi(unsigned int irq, unsigned int id) |
3641 | { | 3658 | { |
3642 | int ret; | 3659 | int ret; |
3643 | struct msi_msg msg; | 3660 | struct msi_msg msg; |
3644 | struct irq_desc *desc = irq_to_desc(irq); | 3661 | struct irq_desc *desc = irq_to_desc(irq); |
3645 | 3662 | ||
3646 | ret = msi_compose_msg(NULL, irq, &msg); | 3663 | if (intr_remapping_enabled) { |
3664 | struct intel_iommu *iommu = map_hpet_to_ir(id); | ||
3665 | int index; | ||
3666 | |||
3667 | if (!iommu) | ||
3668 | return -1; | ||
3669 | |||
3670 | index = alloc_irte(iommu, irq, 1); | ||
3671 | if (index < 0) | ||
3672 | return -1; | ||
3673 | } | ||
3674 | |||
3675 | ret = msi_compose_msg(NULL, irq, &msg, id); | ||
3647 | if (ret < 0) | 3676 | if (ret < 0) |
3648 | return ret; | 3677 | return ret; |
3649 | 3678 | ||
3650 | hpet_msi_write(irq, &msg); | 3679 | hpet_msi_write(irq, &msg); |
3651 | desc->status |= IRQ_MOVE_PCNTXT; | 3680 | desc->status |= IRQ_MOVE_PCNTXT; |
3652 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq, | 3681 | if (irq_remapped(irq)) |
3653 | "edge"); | 3682 | set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type, |
3683 | handle_edge_irq, "edge"); | ||
3684 | else | ||
3685 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, | ||
3686 | handle_edge_irq, "edge"); | ||
3654 | 3687 | ||
3655 | return 0; | 3688 | return 0; |
3656 | } | 3689 | } |