diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-04 05:16:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:29 -0400 |
commit | 8b955b0dddb35e398b07e217a81f8bd49400796f (patch) | |
tree | 6fc307371b6889ac08fa5a7187cde1c137c8d765 | |
parent | e78d01693be38bf93dd6bb49b86e143da450de86 (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>
-rw-r--r-- | arch/i386/kernel/io_apic.c | 90 | ||||
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 96 | ||||
-rw-r--r-- | drivers/pci/Kconfig | 9 | ||||
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/htirq.c | 189 | ||||
-rw-r--r-- | include/asm-i386/hypertransport.h | 42 | ||||
-rw-r--r-- | include/asm-x86_64/hypertransport.h | 42 | ||||
-rw-r--r-- | include/linux/pci.h | 17 |
8 files changed, 486 insertions, 0 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 03e7606be6e6..100406b453b8 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/i8259.h> | 40 | #include <asm/i8259.h> |
41 | #include <asm/nmi.h> | 41 | #include <asm/nmi.h> |
42 | #include <asm/msidef.h> | 42 | #include <asm/msidef.h> |
43 | #include <asm/hypertransport.h> | ||
43 | 44 | ||
44 | #include <mach_apic.h> | 45 | #include <mach_apic.h> |
45 | #include <mach_apicdef.h> | 46 | #include <mach_apicdef.h> |
@@ -2518,6 +2519,95 @@ struct msi_ops arch_msi_ops = { | |||
2518 | 2519 | ||
2519 | #endif /* CONFIG_PCI_MSI */ | 2520 | #endif /* CONFIG_PCI_MSI */ |
2520 | 2521 | ||
2522 | /* | ||
2523 | * Hypertransport interrupt support | ||
2524 | */ | ||
2525 | #ifdef CONFIG_HT_IRQ | ||
2526 | |||
2527 | #ifdef CONFIG_SMP | ||
2528 | |||
2529 | static void target_ht_irq(unsigned int irq, unsigned int dest) | ||
2530 | { | ||
2531 | u32 low, high; | ||
2532 | low = read_ht_irq_low(irq); | ||
2533 | high = read_ht_irq_high(irq); | ||
2534 | |||
2535 | low &= ~(HT_IRQ_LOW_DEST_ID_MASK); | ||
2536 | high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
2537 | |||
2538 | low |= HT_IRQ_LOW_DEST_ID(dest); | ||
2539 | high |= HT_IRQ_HIGH_DEST_ID(dest); | ||
2540 | |||
2541 | write_ht_irq_low(irq, low); | ||
2542 | write_ht_irq_high(irq, high); | ||
2543 | } | ||
2544 | |||
2545 | static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) | ||
2546 | { | ||
2547 | unsigned int dest; | ||
2548 | cpumask_t tmp; | ||
2549 | |||
2550 | cpus_and(tmp, mask, cpu_online_map); | ||
2551 | if (cpus_empty(tmp)) | ||
2552 | tmp = TARGET_CPUS; | ||
2553 | |||
2554 | cpus_and(mask, tmp, CPU_MASK_ALL); | ||
2555 | |||
2556 | dest = cpu_mask_to_apicid(mask); | ||
2557 | |||
2558 | target_ht_irq(irq, dest); | ||
2559 | set_native_irq_info(irq, mask); | ||
2560 | } | ||
2561 | #endif | ||
2562 | |||
2563 | static struct hw_interrupt_type ht_irq_chip = { | ||
2564 | .name = "PCI-HT", | ||
2565 | .mask = mask_ht_irq, | ||
2566 | .unmask = unmask_ht_irq, | ||
2567 | .ack = ack_ioapic_irq, | ||
2568 | #ifdef CONFIG_SMP | ||
2569 | .set_affinity = set_ht_irq_affinity, | ||
2570 | #endif | ||
2571 | .retrigger = ioapic_retrigger_irq, | ||
2572 | }; | ||
2573 | |||
2574 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | ||
2575 | { | ||
2576 | int vector; | ||
2577 | |||
2578 | vector = assign_irq_vector(irq); | ||
2579 | if (vector >= 0) { | ||
2580 | u32 low, high; | ||
2581 | unsigned dest; | ||
2582 | cpumask_t tmp; | ||
2583 | |||
2584 | cpus_clear(tmp); | ||
2585 | cpu_set(vector >> 8, tmp); | ||
2586 | dest = cpu_mask_to_apicid(tmp); | ||
2587 | |||
2588 | high = HT_IRQ_HIGH_DEST_ID(dest); | ||
2589 | |||
2590 | low = HT_IRQ_LOW_BASE | | ||
2591 | HT_IRQ_LOW_DEST_ID(dest) | | ||
2592 | HT_IRQ_LOW_VECTOR(vector) | | ||
2593 | ((INT_DEST_MODE == 0) ? | ||
2594 | HT_IRQ_LOW_DM_PHYSICAL : | ||
2595 | HT_IRQ_LOW_DM_LOGICAL) | | ||
2596 | HT_IRQ_LOW_RQEOI_EDGE | | ||
2597 | ((INT_DELIVERY_MODE != dest_LowestPrio) ? | ||
2598 | HT_IRQ_LOW_MT_FIXED : | ||
2599 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
2600 | HT_IRQ_LOW_IRQ_MASKED; | ||
2601 | |||
2602 | write_ht_irq_low(irq, low); | ||
2603 | write_ht_irq_high(irq, high); | ||
2604 | |||
2605 | set_irq_chip_and_handler(irq, &ht_irq_chip, handle_edge_irq); | ||
2606 | } | ||
2607 | return vector; | ||
2608 | } | ||
2609 | #endif /* CONFIG_HT_IRQ */ | ||
2610 | |||
2521 | /* -------------------------------------------------------------------------- | 2611 | /* -------------------------------------------------------------------------- |
2522 | ACPI-based IOAPIC Configuration | 2612 | ACPI-based IOAPIC Configuration |
2523 | -------------------------------------------------------------------------- */ | 2613 | -------------------------------------------------------------------------- */ |
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 | ||
47 | static int assign_irq_vector(int irq, cpumask_t mask); | 48 | static 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 | |||
1783 | static 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 | |||
1799 | static 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 | |||
1824 | static 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 | |||
1835 | int 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 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index c27e782e6df9..0af6d7288415 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -52,3 +52,12 @@ config PCI_DEBUG | |||
52 | 52 | ||
53 | When in doubt, say N. | 53 | When in doubt, say N. |
54 | 54 | ||
55 | config HT_IRQ | ||
56 | bool "Interrupts on hypertransport devices" | ||
57 | default y | ||
58 | depends on PCI_MSI | ||
59 | depends on X86_LOCAL_APIC && X86_IO_APIC | ||
60 | help | ||
61 | This allows native hypertransport devices to use interrupts. | ||
62 | |||
63 | If unsure say Y. | ||
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 983d0f86aa33..2752c57ecf01 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_PPC32) += setup-irq.o | |||
26 | obj-$(CONFIG_PPC64) += setup-bus.o | 26 | obj-$(CONFIG_PPC64) += setup-bus.o |
27 | obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o | 27 | obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o |
28 | obj-$(CONFIG_X86_VISWS) += setup-irq.o | 28 | obj-$(CONFIG_X86_VISWS) += setup-irq.o |
29 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
29 | 30 | ||
30 | msiobj-y := msi.o | 31 | msiobj-y := msi.o |
31 | msiobj-$(CONFIG_IA64) += msi-apic.o | 32 | msiobj-$(CONFIG_IA64) += msi-apic.o |
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c new file mode 100644 index 000000000000..4ba46359d367 --- /dev/null +++ b/drivers/pci/htirq.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * File: htirq.c | ||
3 | * Purpose: Hypertransport Interrupt Capability | ||
4 | * | ||
5 | * Copyright (C) 2006 Linux Networx | ||
6 | * Copyright (C) Eric Biederman <ebiederman@lnxi.com> | ||
7 | */ | ||
8 | |||
9 | #include <linux/irq.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/gfp.h> | ||
14 | |||
15 | /* Global ht irq lock. | ||
16 | * | ||
17 | * This is needed to serialize access to the data port in hypertransport | ||
18 | * irq capability. | ||
19 | * | ||
20 | * With multiple simultaneous hypertransport irq devices it might pay | ||
21 | * to make this more fine grained. But start with simple, stupid, and correct. | ||
22 | */ | ||
23 | static DEFINE_SPINLOCK(ht_irq_lock); | ||
24 | |||
25 | struct ht_irq_cfg { | ||
26 | struct pci_dev *dev; | ||
27 | unsigned pos; | ||
28 | unsigned idx; | ||
29 | }; | ||
30 | |||
31 | void write_ht_irq_low(unsigned int irq, u32 data) | ||
32 | { | ||
33 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
34 | unsigned long flags; | ||
35 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
36 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
37 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
38 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
39 | } | ||
40 | |||
41 | void write_ht_irq_high(unsigned int irq, u32 data) | ||
42 | { | ||
43 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
44 | unsigned long flags; | ||
45 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
46 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
47 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
48 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
49 | } | ||
50 | |||
51 | u32 read_ht_irq_low(unsigned int irq) | ||
52 | { | ||
53 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
54 | unsigned long flags; | ||
55 | u32 data; | ||
56 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
57 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
58 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
59 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
60 | return data; | ||
61 | } | ||
62 | |||
63 | u32 read_ht_irq_high(unsigned int irq) | ||
64 | { | ||
65 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
66 | unsigned long flags; | ||
67 | u32 data; | ||
68 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
69 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
70 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
71 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
72 | return data; | ||
73 | } | ||
74 | |||
75 | void mask_ht_irq(unsigned int irq) | ||
76 | { | ||
77 | struct ht_irq_cfg *cfg; | ||
78 | unsigned long flags; | ||
79 | u32 data; | ||
80 | |||
81 | cfg = get_irq_data(irq); | ||
82 | |||
83 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
84 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
85 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
86 | data |= 1; | ||
87 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
88 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
89 | } | ||
90 | |||
91 | void unmask_ht_irq(unsigned int irq) | ||
92 | { | ||
93 | struct ht_irq_cfg *cfg; | ||
94 | unsigned long flags; | ||
95 | u32 data; | ||
96 | |||
97 | cfg = get_irq_data(irq); | ||
98 | |||
99 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
100 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
101 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
102 | data &= ~1; | ||
103 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
104 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * ht_create_irq - create an irq and attach it to a device. | ||
109 | * @dev: The hypertransport device to find the irq capability on. | ||
110 | * @idx: Which of the possible irqs to attach to. | ||
111 | * | ||
112 | * ht_create_irq is needs to be called for all hypertransport devices | ||
113 | * that generate irqs. | ||
114 | * | ||
115 | * The irq number of the new irq or a negative error value is returned. | ||
116 | */ | ||
117 | int ht_create_irq(struct pci_dev *dev, int idx) | ||
118 | { | ||
119 | struct ht_irq_cfg *cfg; | ||
120 | unsigned long flags; | ||
121 | u32 data; | ||
122 | int max_irq; | ||
123 | int pos; | ||
124 | int irq; | ||
125 | |||
126 | pos = pci_find_capability(dev, PCI_CAP_ID_HT); | ||
127 | while (pos) { | ||
128 | u8 subtype; | ||
129 | pci_read_config_byte(dev, pos + 3, &subtype); | ||
130 | if (subtype == HT_CAPTYPE_IRQ) | ||
131 | break; | ||
132 | pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT); | ||
133 | } | ||
134 | if (!pos) | ||
135 | return -EINVAL; | ||
136 | |||
137 | /* Verify the idx I want to use is in range */ | ||
138 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
139 | pci_write_config_byte(dev, pos + 2, 1); | ||
140 | pci_read_config_dword(dev, pos + 4, &data); | ||
141 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
142 | |||
143 | max_irq = (data >> 16) & 0xff; | ||
144 | if ( idx > max_irq) | ||
145 | return -EINVAL; | ||
146 | |||
147 | cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); | ||
148 | if (!cfg) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | cfg->dev = dev; | ||
152 | cfg->pos = pos; | ||
153 | cfg->idx = 0x10 + (idx * 2); | ||
154 | |||
155 | irq = create_irq(); | ||
156 | if (irq < 0) { | ||
157 | kfree(cfg); | ||
158 | return -EBUSY; | ||
159 | } | ||
160 | set_irq_data(irq, cfg); | ||
161 | |||
162 | if (arch_setup_ht_irq(irq, dev) < 0) { | ||
163 | ht_destroy_irq(irq); | ||
164 | return -EBUSY; | ||
165 | } | ||
166 | |||
167 | return irq; | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * ht_destroy_irq - destroy an irq created with ht_create_irq | ||
172 | * | ||
173 | * This reverses ht_create_irq removing the specified irq from | ||
174 | * existence. The irq should be free before this happens. | ||
175 | */ | ||
176 | void ht_destroy_irq(unsigned int irq) | ||
177 | { | ||
178 | struct ht_irq_cfg *cfg; | ||
179 | |||
180 | cfg = get_irq_data(irq); | ||
181 | set_irq_chip(irq, NULL); | ||
182 | set_irq_data(irq, NULL); | ||
183 | destroy_irq(irq); | ||
184 | |||
185 | kfree(cfg); | ||
186 | } | ||
187 | |||
188 | EXPORT_SYMBOL(ht_create_irq); | ||
189 | EXPORT_SYMBOL(ht_destroy_irq); | ||
diff --git a/include/asm-i386/hypertransport.h b/include/asm-i386/hypertransport.h new file mode 100644 index 000000000000..c16c6ff4bdd7 --- /dev/null +++ b/include/asm-i386/hypertransport.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef ASM_HYPERTRANSPORT_H | ||
2 | #define ASM_HYPERTRANSPORT_H | ||
3 | |||
4 | /* | ||
5 | * Constants for x86 Hypertransport Interrupts. | ||
6 | */ | ||
7 | |||
8 | #define HT_IRQ_LOW_BASE 0xf8000000 | ||
9 | |||
10 | #define HT_IRQ_LOW_VECTOR_SHIFT 16 | ||
11 | #define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000 | ||
12 | #define HT_IRQ_LOW_VECTOR(v) (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK) | ||
13 | |||
14 | #define HT_IRQ_LOW_DEST_ID_SHIFT 8 | ||
15 | #define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00 | ||
16 | #define HT_IRQ_LOW_DEST_ID(v) (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK) | ||
17 | |||
18 | #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000 | ||
19 | #define HT_IRQ_LOW_DM_LOGICAL 0x0000040 | ||
20 | |||
21 | #define HT_IRQ_LOW_RQEOI_EDGE 0x0000000 | ||
22 | #define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020 | ||
23 | |||
24 | |||
25 | #define HT_IRQ_LOW_MT_FIXED 0x0000000 | ||
26 | #define HT_IRQ_LOW_MT_ARBITRATED 0x0000004 | ||
27 | #define HT_IRQ_LOW_MT_SMI 0x0000008 | ||
28 | #define HT_IRQ_LOW_MT_NMI 0x000000c | ||
29 | #define HT_IRQ_LOW_MT_INIT 0x0000010 | ||
30 | #define HT_IRQ_LOW_MT_STARTUP 0x0000014 | ||
31 | #define HT_IRQ_LOW_MT_EXTINT 0x0000018 | ||
32 | #define HT_IRQ_LOW_MT_LINT1 0x000008c | ||
33 | #define HT_IRQ_LOW_MT_LINT0 0x0000098 | ||
34 | |||
35 | #define HT_IRQ_LOW_IRQ_MASKED 0x0000001 | ||
36 | |||
37 | |||
38 | #define HT_IRQ_HIGH_DEST_ID_SHIFT 0 | ||
39 | #define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff | ||
40 | #define HT_IRQ_HIGH_DEST_ID(v) ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) | ||
41 | |||
42 | #endif /* ASM_HYPERTRANSPORT_H */ | ||
diff --git a/include/asm-x86_64/hypertransport.h b/include/asm-x86_64/hypertransport.h new file mode 100644 index 000000000000..c16c6ff4bdd7 --- /dev/null +++ b/include/asm-x86_64/hypertransport.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef ASM_HYPERTRANSPORT_H | ||
2 | #define ASM_HYPERTRANSPORT_H | ||
3 | |||
4 | /* | ||
5 | * Constants for x86 Hypertransport Interrupts. | ||
6 | */ | ||
7 | |||
8 | #define HT_IRQ_LOW_BASE 0xf8000000 | ||
9 | |||
10 | #define HT_IRQ_LOW_VECTOR_SHIFT 16 | ||
11 | #define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000 | ||
12 | #define HT_IRQ_LOW_VECTOR(v) (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK) | ||
13 | |||
14 | #define HT_IRQ_LOW_DEST_ID_SHIFT 8 | ||
15 | #define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00 | ||
16 | #define HT_IRQ_LOW_DEST_ID(v) (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK) | ||
17 | |||
18 | #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000 | ||
19 | #define HT_IRQ_LOW_DM_LOGICAL 0x0000040 | ||
20 | |||
21 | #define HT_IRQ_LOW_RQEOI_EDGE 0x0000000 | ||
22 | #define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020 | ||
23 | |||
24 | |||
25 | #define HT_IRQ_LOW_MT_FIXED 0x0000000 | ||
26 | #define HT_IRQ_LOW_MT_ARBITRATED 0x0000004 | ||
27 | #define HT_IRQ_LOW_MT_SMI 0x0000008 | ||
28 | #define HT_IRQ_LOW_MT_NMI 0x000000c | ||
29 | #define HT_IRQ_LOW_MT_INIT 0x0000010 | ||
30 | #define HT_IRQ_LOW_MT_STARTUP 0x0000014 | ||
31 | #define HT_IRQ_LOW_MT_EXTINT 0x0000018 | ||
32 | #define HT_IRQ_LOW_MT_LINT1 0x000008c | ||
33 | #define HT_IRQ_LOW_MT_LINT0 0x0000098 | ||
34 | |||
35 | #define HT_IRQ_LOW_IRQ_MASKED 0x0000001 | ||
36 | |||
37 | |||
38 | #define HT_IRQ_HIGH_DEST_ID_SHIFT 0 | ||
39 | #define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff | ||
40 | #define HT_IRQ_HIGH_DEST_ID(v) ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) | ||
41 | |||
42 | #endif /* ASM_HYPERTRANSPORT_H */ | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 2aabe90f1cd2..9b34bc8f34e4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -681,6 +681,23 @@ extern int msi_register(struct msi_ops *ops); | |||
681 | 681 | ||
682 | #endif | 682 | #endif |
683 | 683 | ||
684 | #ifdef CONFIG_HT_IRQ | ||
685 | /* Helper functions.. */ | ||
686 | void write_ht_irq_low(unsigned int irq, u32 data); | ||
687 | void write_ht_irq_high(unsigned int irq, u32 data); | ||
688 | u32 read_ht_irq_low(unsigned int irq); | ||
689 | u32 read_ht_irq_high(unsigned int irq); | ||
690 | void mask_ht_irq(unsigned int irq); | ||
691 | void unmask_ht_irq(unsigned int irq); | ||
692 | |||
693 | /* The functions a driver should call */ | ||
694 | int ht_create_irq(struct pci_dev *dev, int idx); | ||
695 | void ht_destroy_irq(unsigned int irq); | ||
696 | |||
697 | /* The arch hook for getting things started */ | ||
698 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); | ||
699 | #endif /* CONFIG_HT_IRQ */ | ||
700 | |||
684 | extern void pci_block_user_cfg_access(struct pci_dev *dev); | 701 | extern void pci_block_user_cfg_access(struct pci_dev *dev); |
685 | extern void pci_unblock_user_cfg_access(struct pci_dev *dev); | 702 | extern void pci_unblock_user_cfg_access(struct pci_dev *dev); |
686 | 703 | ||