]> git.ipfire.org Git - people/ms/linux.git/blame - arch/x86/pci/irq.c
Importing "grsecurity-3.1-3.19.2-201503201903.patch"
[people/ms/linux.git] / arch / x86 / pci / irq.c
CommitLineData
1da177e4
LT
1/*
2 * Low-Level PCI Support for PC -- Routing of Interrupts
3 *
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5 */
6
1da177e4
LT
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
1da177e4 11#include <linux/interrupt.h>
1da177e4 12#include <linux/dmi.h>
7058b061
PC
13#include <linux/io.h>
14#include <linux/smp.h>
1da177e4 15#include <asm/io_apic.h>
b33fa1f3 16#include <linux/irq.h>
1da177e4 17#include <linux/acpi.h>
82487711 18#include <asm/pci_x86.h>
1da177e4
LT
19
20#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
21#define PIRQ_VERSION 0x0100
22
23static int broken_hp_bios_irq9;
24static int acer_tm360_irqrouting;
25
26static struct irq_routing_table *pirq_table;
27
28static int pirq_enable_irq(struct pci_dev *dev);
c03b3b07 29static void pirq_disable_irq(struct pci_dev *dev);
1da177e4
LT
30
31/*
32 * Never use: 0, 1, 2 (timer, keyboard, and cascade)
33 * Avoid using: 13, 14 and 15 (FP error and IDE).
34 * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
35 */
36unsigned int pcibios_irq_mask = 0xfff8;
37
38static int pirq_penalty[16] = {
39 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
40 0, 0, 0, 0, 1000, 100000, 100000, 100000
41};
42
43struct irq_router {
44 char *name;
45 u16 vendor, device;
46 int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
273c1127
MV
47 int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq,
48 int new);
1da177e4
LT
49};
50
51struct irq_router_handler {
52 u16 vendor;
53 int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
63d9c273 54} __do_const;
1da177e4 55
ab3b3793 56int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
c03b3b07 57void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;
1da177e4 58
120bb424 59/*
60 * Check passed address for the PCI IRQ Routing Table signature
61 * and perform checksum verification.
62 */
63
7058b061 64static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
120bb424 65{
66 struct irq_routing_table *rt;
67 int i;
68 u8 sum;
69
70 rt = (struct irq_routing_table *) addr;
71 if (rt->signature != PIRQ_SIGNATURE ||
72 rt->version != PIRQ_VERSION ||
73 rt->size % 16 ||
74 rt->size < sizeof(struct irq_routing_table))
75 return NULL;
76 sum = 0;
7058b061 77 for (i = 0; i < rt->size; i++)
120bb424 78 sum += addr[i];
79 if (!sum) {
273c1127
MV
80 DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n",
81 rt);
120bb424 82 return rt;
83 }
84 return NULL;
85}
86
87
88
1da177e4
LT
89/*
90 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
91 */
92
93static struct irq_routing_table * __init pirq_find_routing_table(void)
94{
95 u8 *addr;
96 struct irq_routing_table *rt;
1da177e4 97
120bb424 98 if (pirq_table_addr) {
99 rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
100 if (rt)
101 return rt;
102 printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
103 }
7058b061 104 for (addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
120bb424 105 rt = pirq_check_routing_table(addr);
106 if (rt)
1da177e4 107 return rt;
1da177e4
LT
108 }
109 return NULL;
110}
111
112/*
113 * If we have a IRQ routing table, use it to search for peer host
114 * bridges. It's a gross hack, but since there are no other known
115 * ways how to get a list of buses, we have to go this way.
116 */
117
118static void __init pirq_peer_trick(void)
119{
120 struct irq_routing_table *rt = pirq_table;
121 u8 busmap[256];
122 int i;
123 struct irq_info *e;
124
125 memset(busmap, 0, sizeof(busmap));
7058b061 126 for (i = 0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
1da177e4
LT
127 e = &rt->slots[i];
128#ifdef DEBUG
129 {
130 int j;