diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | arch/i386/pci/common.c | 6 | ||||
-rw-r--r-- | arch/i386/pci/irq.c | 51 | ||||
-rw-r--r-- | arch/i386/pci/pci.h | 1 |
4 files changed, 47 insertions, 15 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f44bb5567c5b..96d924eb7b64 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1030,6 +1030,10 @@ running once the system is up. | |||
1030 | irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned | 1030 | irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned |
1031 | automatically to PCI devices. You can make the kernel | 1031 | automatically to PCI devices. You can make the kernel |
1032 | exclude IRQs of your ISA cards this way. | 1032 | exclude IRQs of your ISA cards this way. |
1033 | pirqaddr=0xAAAAA [IA-32] Specify the physical address | ||
1034 | of the PIRQ table (normally generated | ||
1035 | by the BIOS) if it is outside the | ||
1036 | F0000h-100000h range. | ||
1033 | lastbus=N [IA-32] Scan all buses till bus #N. Can be useful | 1037 | lastbus=N [IA-32] Scan all buses till bus #N. Can be useful |
1034 | if the kernel is unable to find your secondary buses | 1038 | if the kernel is unable to find your secondary buses |
1035 | and you want to tell it explicitly which ones they are. | 1039 | and you want to tell it explicitly which ones they are. |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 720975e1af50..2a2e79fbfef8 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | |||
25 | 25 | ||
26 | int pci_routeirq; | 26 | int pci_routeirq; |
27 | int pcibios_last_bus = -1; | 27 | int pcibios_last_bus = -1; |
28 | struct pci_bus *pci_root_bus = NULL; | 28 | unsigned long pirq_table_addr; |
29 | struct pci_bus *pci_root_bus; | ||
29 | struct pci_raw_ops *raw_pci_ops; | 30 | struct pci_raw_ops *raw_pci_ops; |
30 | 31 | ||
31 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | 32 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) |
@@ -188,6 +189,9 @@ char * __devinit pcibios_setup(char *str) | |||
188 | } else if (!strcmp(str, "biosirq")) { | 189 | } else if (!strcmp(str, "biosirq")) { |
189 | pci_probe |= PCI_BIOS_IRQ_SCAN; | 190 | pci_probe |= PCI_BIOS_IRQ_SCAN; |
190 | return NULL; | 191 | return NULL; |
192 | } else if (!strncmp(str, "pirqaddr=", 9)) { | ||
193 | pirq_table_addr = simple_strtoul(str+9, NULL, 0); | ||
194 | return NULL; | ||
191 | } | 195 | } |
192 | #endif | 196 | #endif |
193 | #ifdef CONFIG_PCI_DIRECT | 197 | #ifdef CONFIG_PCI_DIRECT |
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 83458f81e661..78ca1ecbb907 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c | |||
@@ -58,6 +58,35 @@ struct irq_router_handler { | |||
58 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; | 58 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * Check passed address for the PCI IRQ Routing Table signature | ||
62 | * and perform checksum verification. | ||
63 | */ | ||
64 | |||
65 | static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr) | ||
66 | { | ||
67 | struct irq_routing_table *rt; | ||
68 | int i; | ||
69 | u8 sum; | ||
70 | |||
71 | rt = (struct irq_routing_table *) addr; | ||
72 | if (rt->signature != PIRQ_SIGNATURE || | ||
73 | rt->version != PIRQ_VERSION || | ||
74 | rt->size % 16 || | ||
75 | rt->size < sizeof(struct irq_routing_table)) | ||
76 | return NULL; | ||
77 | sum = 0; | ||
78 | for (i=0; i < rt->size; i++) | ||
79 | sum += addr[i]; | ||
80 | if (!sum) { | ||
81 | DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); | ||
82 | return rt; | ||
83 | } | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | |||
88 | |||
89 | /* | ||
61 | * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. | 90 | * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. |
62 | */ | 91 | */ |
63 | 92 | ||
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void) | |||
65 | { | 94 | { |
66 | u8 *addr; | 95 | u8 *addr; |
67 | struct irq_routing_table *rt; | 96 | struct irq_routing_table *rt; |
68 | int i; | ||
69 | u8 sum; | ||
70 | 97 | ||
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 | } | ||
71 | for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { | 104 | for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { |
72 | rt = (struct irq_routing_table *) addr; | 105 | rt = pirq_check_routing_table(addr); |
73 | if (rt->signature != PIRQ_SIGNATURE || | 106 | if (rt) |
74 | rt->version != PIRQ_VERSION || | ||
75 | rt->size % 16 || | ||
76 | rt->size < sizeof(struct irq_routing_table)) | ||
77 | continue; | ||
78 | sum = 0; | ||
79 | for(i=0; i<rt->size; i++) | ||
80 | sum += addr[i]; | ||
81 | if (!sum) { | ||
82 | DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); | ||
83 | return rt; | 107 | return rt; |
84 | } | ||
85 | } | 108 | } |
86 | return NULL; | 109 | return NULL; |
87 | } | 110 | } |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index a8fc80ca69f3..a80f0f55ff51 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 | 27 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 |
28 | 28 | ||
29 | extern unsigned int pci_probe; | 29 | extern unsigned int pci_probe; |
30 | extern unsigned long pirq_table_addr; | ||
30 | 31 | ||
31 | /* pci-i386.c */ | 32 | /* pci-i386.c */ |
32 | 33 | ||