diff options
author | venkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com> | 2008-09-05 21:02:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:53:07 -0400 |
commit | 58ac1e76ce77d515bd5cb65dbc465a040da341c6 (patch) | |
tree | e1bd9e60aaaa5098ea368c04043adf2a79fca604 /arch/x86/kernel/io_apic.c | |
parent | b40d575bf0679c45aaf9e1161fc51a6b041b7210 (diff) |
x86: HPET_MSI Basic HPET_MSI setup code
Basic HPET MSI setup code. Routines to perform basic MSI read write
in HPET memory map and setting up irq_chip for HPET MSI.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/io_apic.c')
-rw-r--r-- | arch/x86/kernel/io_apic.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index d22fecf828b8..77fa155becf6 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #endif | 41 | #endif |
42 | #include <linux/bootmem.h> | 42 | #include <linux/bootmem.h> |
43 | #include <linux/dmar.h> | 43 | #include <linux/dmar.h> |
44 | #include <linux/hpet.h> | ||
44 | 45 | ||
45 | #include <asm/idle.h> | 46 | #include <asm/idle.h> |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
@@ -56,6 +57,7 @@ | |||
56 | #include <asm/hypertransport.h> | 57 | #include <asm/hypertransport.h> |
57 | #include <asm/setup.h> | 58 | #include <asm/setup.h> |
58 | #include <asm/irq_remapping.h> | 59 | #include <asm/irq_remapping.h> |
60 | #include <asm/hpet.h> | ||
59 | 61 | ||
60 | #include <mach_ipi.h> | 62 | #include <mach_ipi.h> |
61 | #include <mach_apic.h> | 63 | #include <mach_apic.h> |
@@ -3522,6 +3524,68 @@ int arch_setup_dmar_msi(unsigned int irq) | |||
3522 | } | 3524 | } |
3523 | #endif | 3525 | #endif |
3524 | 3526 | ||
3527 | #ifdef CONFIG_HPET_TIMER | ||
3528 | |||
3529 | #ifdef CONFIG_SMP | ||
3530 | static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask) | ||
3531 | { | ||
3532 | struct irq_cfg *cfg; | ||
3533 | struct irq_desc *desc; | ||
3534 | struct msi_msg msg; | ||
3535 | unsigned int dest; | ||
3536 | cpumask_t tmp; | ||
3537 | |||
3538 | cpus_and(tmp, mask, cpu_online_map); | ||
3539 | if (cpus_empty(tmp)) | ||
3540 | return; | ||
3541 | |||
3542 | if (assign_irq_vector(irq, mask)) | ||
3543 | return; | ||
3544 | |||
3545 | cfg = irq_cfg(irq); | ||
3546 | cpus_and(tmp, cfg->domain, mask); | ||
3547 | dest = cpu_mask_to_apicid(tmp); | ||
3548 | |||
3549 | hpet_msi_read(irq, &msg); | ||
3550 | |||
3551 | msg.data &= ~MSI_DATA_VECTOR_MASK; | ||
3552 | msg.data |= MSI_DATA_VECTOR(cfg->vector); | ||
3553 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; | ||
3554 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | ||
3555 | |||
3556 | hpet_msi_write(irq, &msg); | ||
3557 | desc = irq_to_desc(irq); | ||
3558 | desc->affinity = mask; | ||
3559 | } | ||
3560 | #endif /* CONFIG_SMP */ | ||
3561 | |||
3562 | struct irq_chip hpet_msi_type = { | ||
3563 | .name = "HPET_MSI", | ||
3564 | .unmask = hpet_msi_unmask, | ||
3565 | .mask = hpet_msi_mask, | ||
3566 | .ack = ack_apic_edge, | ||
3567 | #ifdef CONFIG_SMP | ||
3568 | .set_affinity = hpet_msi_set_affinity, | ||
3569 | #endif | ||
3570 | .retrigger = ioapic_retrigger_irq, | ||
3571 | }; | ||
3572 | |||
3573 | int arch_setup_hpet_msi(unsigned int irq) | ||
3574 | { | ||
3575 | int ret; | ||
3576 | struct msi_msg msg; | ||
3577 | |||
3578 | ret = msi_compose_msg(NULL, irq, &msg); | ||
3579 | if (ret < 0) | ||
3580 | return ret; | ||
3581 | |||
3582 | hpet_msi_write(irq, &msg); | ||
3583 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq, | ||
3584 | "edge"); | ||
3585 | return 0; | ||
3586 | } | ||
3587 | #endif | ||
3588 | |||
3525 | #endif /* CONFIG_PCI_MSI */ | 3589 | #endif /* CONFIG_PCI_MSI */ |
3526 | /* | 3590 | /* |
3527 | * Hypertransport interrupt support | 3591 | * Hypertransport interrupt support |