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