aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/io_apic.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:29 -0400
commit8b955b0dddb35e398b07e217a81f8bd49400796f (patch)
tree6fc307371b6889ac08fa5a7187cde1c137c8d765 /arch/x86_64/kernel/io_apic.c
parente78d01693be38bf93dd6bb49b86e143da450de86 (diff)
[PATCH] Initial generic hypertransport interrupt support
This patch implements two functions ht_create_irq and ht_destroy_irq for use by drivers. Several other functions are implemented as helpers for arch specific irq_chip handlers. The driver for the card I tested this on isn't yet ready to be merged. However this code is and hypertransport irqs are in use in a few other places in the kernel. Not that any of this will get merged before 2.6.19 Because the ipath-ht400 is slightly out of spec this code will need to be generalized to work there. I think all of the powerpc uses are for a plain interrupt controller in a chipset so support for native hypertransport devices is a little less interesting. However I think this is a half way decent model on how to separate arch specific and generic helper code, and I think this is a functional model of how to get the architecture dependencies out of the msi code. [akpm@osdl.org: Kconfig fix] Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Greg KH <greg@kroah.com> Cc: Andi Kleen <ak@muc.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r--arch/x86_64/kernel/io_apic.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 7cc29b50b0c1..31c270fee337 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -43,6 +43,7 @@
43#include <asm/dma.h> 43#include <asm/dma.h>
44#include <asm/nmi.h> 44#include <asm/nmi.h>
45#include <asm/msidef.h> 45#include <asm/msidef.h>
46#include <asm/hypertransport.h>
46 47
47static int assign_irq_vector(int irq, cpumask_t mask); 48static int assign_irq_vector(int irq, cpumask_t mask);
48 49
@@ -1772,6 +1773,101 @@ struct msi_ops arch_msi_ops = {
1772 1773
1773#endif 1774#endif
1774 1775
1776/*
1777 * Hypertransport interrupt support
1778 */
1779#ifdef CONFIG_HT_IRQ
1780
1781#ifdef CONFIG_SMP
1782
1783static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
1784{
1785 u32 low, high;
1786 low = read_ht_irq_low(irq);
1787 high = read_ht_irq_high(irq);
1788
1789 low &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
1790 high &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
1791
1792 low |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
1793 high |= HT_IRQ_HIGH_DEST_ID(dest);
1794
1795 write_ht_irq_low(irq, low);
1796 write_ht_irq_high(irq, high);
1797}
1798
1799static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
1800{
1801 unsigned int dest;
1802 cpumask_t tmp;
1803 int vector;
1804
1805 cpus_and(tmp, mask, cpu_online_map);
1806 if (cpus_empty(tmp))
1807 tmp = TARGET_CPUS;
1808
1809 cpus_and(mask, tmp, CPU_MASK_ALL);
1810
1811 vector = assign_irq_vector(irq, mask);
1812 if (vector < 0)
1813 return;
1814
1815 cpus_clear(tmp);
1816 cpu_set(vector >> 8, tmp);
1817 dest = cpu_mask_to_apicid(tmp);
1818
1819 target_ht_irq(irq, dest, vector & 0xff);
1820 set_native_irq_info(irq, mask);
1821}
1822#endif
1823
1824static struct hw_interrupt_type ht_irq_chip = {
1825 .name = "PCI-HT",
1826 .mask = mask_ht_irq,
1827 .unmask = unmask_ht_irq,
1828 .ack = ack_apic_edge,
1829#ifdef CONFIG_SMP
1830 .set_affinity = set_ht_irq_affinity,
1831#endif
1832 .retrigger = ioapic_retrigger_irq,
1833};
1834
1835int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
1836{
1837 int vector;
1838
1839 vector = assign_irq_vector(irq, TARGET_CPUS);
1840 if (vector >= 0) {
1841 u32 low, high;
1842 unsigned dest;
1843 cpumask_t tmp;
1844
1845 cpus_clear(tmp);
1846 cpu_set(vector >> 8, tmp);
1847 dest = cpu_mask_to_apicid(tmp);
1848
1849 high = HT_IRQ_HIGH_DEST_ID(dest);
1850
1851 low = HT_IRQ_LOW_BASE |
1852 HT_IRQ_LOW_DEST_ID(dest) |
1853 HT_IRQ_LOW_VECTOR(vector) |
1854 ((INT_DEST_MODE == 0) ?
1855 HT_IRQ_LOW_DM_PHYSICAL :
1856 HT_IRQ_LOW_DM_LOGICAL) |
1857 HT_IRQ_LOW_RQEOI_EDGE |
1858 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
1859 HT_IRQ_LOW_MT_FIXED :
1860 HT_IRQ_LOW_MT_ARBITRATED);
1861
1862 write_ht_irq_low(irq, low);
1863 write_ht_irq_high(irq, high);
1864
1865 set_irq_chip_and_handler(irq, &ht_irq_chip, handle_edge_irq);
1866 }
1867 return vector;
1868}
1869#endif /* CONFIG_HT_IRQ */
1870
1775/* -------------------------------------------------------------------------- 1871/* --------------------------------------------------------------------------
1776 ACPI-based IOAPIC Configuration 1872 ACPI-based IOAPIC Configuration
1777 -------------------------------------------------------------------------- */ 1873 -------------------------------------------------------------------------- */