aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2009-08-04 15:07:09 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-08-27 17:33:20 -0400
commitc8bc6f3c806f1fcbfdbf0b1ff6c52dba59192d3b (patch)
tree072f772308c44eb0223fbfb45c8a055918c70502
parent20f3097bfe5fb5ced0b14f9ea2620c4039bf1dde (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>
-rw-r--r--arch/x86/include/asm/hpet.h5
-rw-r--r--arch/x86/kernel/acpi/boot.c1
-rw-r--r--arch/x86/kernel/apic/io_apic.c49
-rw-r--r--arch/x86/kernel/hpet.c3
4 files changed, 47 insertions, 11 deletions
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index 65847c578b70..5d89fd2a3690 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -65,6 +65,7 @@
65/* hpet memory map physical address */ 65/* hpet memory map physical address */
66extern unsigned long hpet_address; 66extern unsigned long hpet_address;
67extern unsigned long force_hpet_address; 67extern unsigned long force_hpet_address;
68extern u8 hpet_blockid;
68extern int hpet_force_user; 69extern int hpet_force_user;
69extern int is_hpet_enabled(void); 70extern int is_hpet_enabled(void);
70extern int hpet_enable(void); 71extern int hpet_enable(void);
@@ -78,9 +79,9 @@ extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg);
78extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg); 79extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg);
79 80
80#ifdef CONFIG_PCI_MSI 81#ifdef CONFIG_PCI_MSI
81extern int arch_setup_hpet_msi(unsigned int irq); 82extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id);
82#else 83#else
83static inline int arch_setup_hpet_msi(unsigned int irq) 84static inline int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
84{ 85{
85 return -EINVAL; 86 return -EINVAL;
86} 87}
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 6b8ca3a0285d..eae642b0f345 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -624,6 +624,7 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
624 } 624 }
625 625
626 hpet_address = hpet_tbl->address.address; 626 hpet_address = hpet_tbl->address.address;
627 hpet_blockid = hpet_tbl->sequence;
627 628
628 /* 629 /*
629 * Some broken BIOSes advertise HPET at 0x0. We really do not 630 * Some broken BIOSes advertise HPET at 0x0. We really do not
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
3257static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 3257static 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
3633static 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
3629static struct irq_chip hpet_msi_type = { 3646static 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
3640int arch_setup_hpet_msi(unsigned int irq) 3657int 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}
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index ba575f0f2e34..7f024ff47d1d 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -33,6 +33,7 @@
33 * HPET address is set in acpi/boot.c, when an ACPI entry exists 33 * HPET address is set in acpi/boot.c, when an ACPI entry exists
34 */ 34 */
35unsigned long hpet_address; 35unsigned long hpet_address;
36u8 hpet_blockid; /* OS timer block num */
36#ifdef CONFIG_PCI_MSI 37#ifdef CONFIG_PCI_MSI
37static unsigned long hpet_num_timers; 38static unsigned long hpet_num_timers;
38#endif 39#endif
@@ -467,7 +468,7 @@ static int hpet_msi_next_event(unsigned long delta,
467 468
468static int hpet_setup_msi_irq(unsigned int irq) 469static int hpet_setup_msi_irq(unsigned int irq)
469{ 470{
470 if (arch_setup_hpet_msi(irq)) { 471 if (arch_setup_hpet_msi(irq, hpet_blockid)) {
471 destroy_irq(irq); 472 destroy_irq(irq);
472 return -EINVAL; 473 return -EINVAL;
473 } 474 }