diff options
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/Makefile | 3 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 50 | ||||
-rw-r--r-- | arch/x86/pci/amd_bus.c | 42 | ||||
-rw-r--r-- | arch/x86/pci/ce4100.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 14 | ||||
-rw-r--r-- | arch/x86/pci/direct.c | 6 | ||||
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 3 | ||||
-rw-r--r-- | arch/x86/pci/numaq_32.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/olpc.c | 4 | ||||
-rw-r--r-- | arch/x86/pci/pcbios.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/visws.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 371 |
12 files changed, 242 insertions, 259 deletions
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index 6b8759f7634..d24d3da7292 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -18,8 +18,9 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | |||
18 | obj-$(CONFIG_X86_MRST) += mrst.o | 18 | obj-$(CONFIG_X86_MRST) += mrst.o |
19 | 19 | ||
20 | obj-y += common.o early.o | 20 | obj-y += common.o early.o |
21 | obj-y += amd_bus.o bus_numa.o | 21 | obj-y += bus_numa.o |
22 | 22 | ||
23 | obj-$(CONFIG_AMD_NB) += amd_bus.o | ||
23 | obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o | 24 | obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o |
24 | 25 | ||
25 | ifeq ($(CONFIG_PCI_DEBUG),y) | 26 | ifeq ($(CONFIG_PCI_DEBUG),y) |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 68c3c139520..f8348ab1032 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -43,6 +43,17 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = { | |||
43 | DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"), | 43 | DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"), |
44 | }, | 44 | }, |
45 | }, | 45 | }, |
46 | /* https://bugzilla.kernel.org/show_bug.cgi?id=30552 */ | ||
47 | /* 2006 AMD HT/VIA system with two host bridges */ | ||
48 | { | ||
49 | .callback = set_use_crs, | ||
50 | .ident = "ASUS M2V-MX SE", | ||
51 | .matches = { | ||
52 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
53 | DMI_MATCH(DMI_BOARD_NAME, "M2V-MX SE"), | ||
54 | DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), | ||
55 | }, | ||
56 | }, | ||
46 | {} | 57 | {} |
47 | }; | 58 | }; |
48 | 59 | ||
@@ -138,7 +149,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
138 | struct acpi_resource_address64 addr; | 149 | struct acpi_resource_address64 addr; |
139 | acpi_status status; | 150 | acpi_status status; |
140 | unsigned long flags; | 151 | unsigned long flags; |
141 | u64 start, end; | 152 | u64 start, orig_end, end; |
142 | 153 | ||
143 | status = resource_to_addr(acpi_res, &addr); | 154 | status = resource_to_addr(acpi_res, &addr); |
144 | if (!ACPI_SUCCESS(status)) | 155 | if (!ACPI_SUCCESS(status)) |
@@ -154,7 +165,21 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
154 | return AE_OK; | 165 | return AE_OK; |
155 | 166 | ||
156 | start = addr.minimum + addr.translation_offset; | 167 | start = addr.minimum + addr.translation_offset; |
157 | end = addr.maximum + addr.translation_offset; | 168 | orig_end = end = addr.maximum + addr.translation_offset; |
169 | |||
170 | /* Exclude non-addressable range or non-addressable portion of range */ | ||
171 | end = min(end, (u64)iomem_resource.end); | ||
172 | if (end <= start) { | ||
173 | dev_info(&info->bridge->dev, | ||
174 | "host bridge window [%#llx-%#llx] " | ||
175 | "(ignored, not CPU addressable)\n", start, orig_end); | ||
176 | return AE_OK; | ||
177 | } else if (orig_end != end) { | ||
178 | dev_info(&info->bridge->dev, | ||
179 | "host bridge window [%#llx-%#llx] " | ||
180 | "([%#llx-%#llx] ignored, not CPU addressable)\n", | ||
181 | start, orig_end, end + 1, orig_end); | ||
182 | } | ||
158 | 183 | ||
159 | res = &info->res[info->res_num]; | 184 | res = &info->res[info->res_num]; |
160 | res->name = info->name; | 185 | res->name = info->name; |
@@ -246,10 +271,9 @@ static void add_resources(struct pci_root_info *info) | |||
246 | 271 | ||
247 | conflict = insert_resource_conflict(root, res); | 272 | conflict = insert_resource_conflict(root, res); |
248 | if (conflict) | 273 | if (conflict) |
249 | dev_err(&info->bridge->dev, | 274 | dev_info(&info->bridge->dev, |
250 | "address space collision: host bridge window %pR " | 275 | "ignoring host bridge window %pR (conflicts with %s %pR)\n", |
251 | "conflicts with %s %pR\n", | 276 | res, conflict->name, conflict); |
252 | res, conflict->name, conflict); | ||
253 | else | 277 | else |
254 | pci_bus_add_resource(info->bus, res, 0); | 278 | pci_bus_add_resource(info->bus, res, 0); |
255 | } | 279 | } |
@@ -361,6 +385,20 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) | |||
361 | } | 385 | } |
362 | } | 386 | } |
363 | 387 | ||
388 | /* After the PCI-E bus has been walked and all devices discovered, | ||
389 | * configure any settings of the fabric that might be necessary. | ||
390 | */ | ||
391 | if (bus) { | ||
392 | struct pci_bus *child; | ||
393 | list_for_each_entry(child, &bus->children, node) { | ||
394 | struct pci_dev *self = child->self; | ||
395 | if (!self) | ||
396 | continue; | ||
397 | |||
398 | pcie_bus_configure_settings(child, self->pcie_mpss); | ||
399 | } | ||
400 | } | ||
401 | |||
364 | if (!bus) | 402 | if (!bus) |
365 | kfree(sd); | 403 | kfree(sd); |
366 | 404 | ||
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 026e4931d16..385a940b542 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
@@ -30,34 +30,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = { | |||
30 | { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, | 30 | { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static u64 __initdata fam10h_mmconf_start; | ||
34 | static u64 __initdata fam10h_mmconf_end; | ||
35 | static void __init get_pci_mmcfg_amd_fam10h_range(void) | ||
36 | { | ||
37 | u32 address; | ||
38 | u64 base, msr; | ||
39 | unsigned segn_busn_bits; | ||
40 | |||
41 | /* assume all cpus from fam10h have mmconf */ | ||
42 | if (boot_cpu_data.x86 < 0x10) | ||
43 | return; | ||
44 | |||
45 | address = MSR_FAM10H_MMIO_CONF_BASE; | ||
46 | rdmsrl(address, msr); | ||
47 | |||
48 | /* mmconfig is not enable */ | ||
49 | if (!(msr & FAM10H_MMIO_CONF_ENABLE)) | ||
50 | return; | ||
51 | |||
52 | base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); | ||
53 | |||
54 | segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & | ||
55 | FAM10H_MMIO_CONF_BUSRANGE_MASK; | ||
56 | |||
57 | fam10h_mmconf_start = base; | ||
58 | fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1; | ||
59 | } | ||
60 | |||
61 | #define RANGE_NUM 16 | 33 | #define RANGE_NUM 16 |
62 | 34 | ||
63 | /** | 35 | /** |
@@ -85,6 +57,9 @@ static int __init early_fill_mp_bus_info(void) | |||
85 | u64 val; | 57 | u64 val; |
86 | u32 address; | 58 | u32 address; |
87 | bool found; | 59 | bool found; |
60 | struct resource fam10h_mmconf_res, *fam10h_mmconf; | ||
61 | u64 fam10h_mmconf_start; | ||
62 | u64 fam10h_mmconf_end; | ||
88 | 63 | ||
89 | if (!early_pci_allowed()) | 64 | if (!early_pci_allowed()) |
90 | return -1; | 65 | return -1; |
@@ -211,12 +186,17 @@ static int __init early_fill_mp_bus_info(void) | |||
211 | subtract_range(range, RANGE_NUM, 0, end); | 186 | subtract_range(range, RANGE_NUM, 0, end); |
212 | 187 | ||
213 | /* get mmconfig */ | 188 | /* get mmconfig */ |
214 | get_pci_mmcfg_amd_fam10h_range(); | 189 | fam10h_mmconf = amd_get_mmconfig_range(&fam10h_mmconf_res); |
215 | /* need to take out mmconf range */ | 190 | /* need to take out mmconf range */ |
216 | if (fam10h_mmconf_end) { | 191 | if (fam10h_mmconf) { |
217 | printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end); | 192 | printk(KERN_DEBUG "Fam 10h mmconf %pR\n", fam10h_mmconf); |
193 | fam10h_mmconf_start = fam10h_mmconf->start; | ||
194 | fam10h_mmconf_end = fam10h_mmconf->end; | ||
218 | subtract_range(range, RANGE_NUM, fam10h_mmconf_start, | 195 | subtract_range(range, RANGE_NUM, fam10h_mmconf_start, |
219 | fam10h_mmconf_end + 1); | 196 | fam10h_mmconf_end + 1); |
197 | } else { | ||
198 | fam10h_mmconf_start = 0; | ||
199 | fam10h_mmconf_end = 0; | ||
220 | } | 200 | } |
221 | 201 | ||
222 | /* mmio resource */ | 202 | /* mmio resource */ |
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index 67858be4b52..99176094500 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c | |||
@@ -257,6 +257,7 @@ static int ce4100_conf_read(unsigned int seg, unsigned int bus, | |||
257 | { | 257 | { |
258 | int i; | 258 | int i; |
259 | 259 | ||
260 | WARN_ON(seg); | ||
260 | if (bus == 1) { | 261 | if (bus == 1) { |
261 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | 262 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { |
262 | if (bus1_fixups[i].dev_func == devfn && | 263 | if (bus1_fixups[i].dev_func == devfn && |
@@ -282,6 +283,7 @@ static int ce4100_conf_write(unsigned int seg, unsigned int bus, | |||
282 | { | 283 | { |
283 | int i; | 284 | int i; |
284 | 285 | ||
286 | WARN_ON(seg); | ||
285 | if (bus == 1) { | 287 | if (bus == 1) { |
286 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | 288 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { |
287 | if (bus1_fixups[i].dev_func == devfn && | 289 | if (bus1_fixups[i].dev_func == devfn && |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 5fe75026ecc..92df322e0b5 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -247,13 +247,6 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { | |||
247 | }, | 247 | }, |
248 | #endif /* __i386__ */ | 248 | #endif /* __i386__ */ |
249 | { | 249 | { |
250 | .callback = find_sort_method, | ||
251 | .ident = "Dell System", | ||
252 | .matches = { | ||
253 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | ||
254 | }, | ||
255 | }, | ||
256 | { | ||
257 | .callback = set_bf_sort, | 250 | .callback = set_bf_sort, |
258 | .ident = "Dell PowerEdge 1950", | 251 | .ident = "Dell PowerEdge 1950", |
259 | .matches = { | 252 | .matches = { |
@@ -294,6 +287,13 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { | |||
294 | }, | 287 | }, |
295 | }, | 288 | }, |
296 | { | 289 | { |
290 | .callback = find_sort_method, | ||
291 | .ident = "Dell System", | ||
292 | .matches = { | ||
293 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | ||
294 | }, | ||
295 | }, | ||
296 | { | ||
297 | .callback = set_bf_sort, | 297 | .callback = set_bf_sort, |
298 | .ident = "HP ProLiant BL20p G3", | 298 | .ident = "HP ProLiant BL20p G3", |
299 | .matches = { | 299 | .matches = { |
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c index e6fd8473fb7..4f2c70439d7 100644 --- a/arch/x86/pci/direct.c +++ b/arch/x86/pci/direct.c | |||
@@ -22,7 +22,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus, | |||
22 | { | 22 | { |
23 | unsigned long flags; | 23 | unsigned long flags; |
24 | 24 | ||
25 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) { | 25 | if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) { |
26 | *value = -1; | 26 | *value = -1; |
27 | return -EINVAL; | 27 | return -EINVAL; |
28 | } | 28 | } |
@@ -53,7 +53,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus, | |||
53 | { | 53 | { |
54 | unsigned long flags; | 54 | unsigned long flags; |
55 | 55 | ||
56 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) | 56 | if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) |
57 | return -EINVAL; | 57 | return -EINVAL; |
58 | 58 | ||
59 | raw_spin_lock_irqsave(&pci_config_lock, flags); | 59 | raw_spin_lock_irqsave(&pci_config_lock, flags); |
@@ -97,6 +97,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus, | |||
97 | unsigned long flags; | 97 | unsigned long flags; |
98 | int dev, fn; | 98 | int dev, fn; |
99 | 99 | ||
100 | WARN_ON(seg); | ||
100 | if ((bus > 255) || (devfn > 255) || (reg > 255)) { | 101 | if ((bus > 255) || (devfn > 255) || (reg > 255)) { |
101 | *value = -1; | 102 | *value = -1; |
102 | return -EINVAL; | 103 | return -EINVAL; |
@@ -138,6 +139,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus, | |||
138 | unsigned long flags; | 139 | unsigned long flags; |
139 | int dev, fn; | 140 | int dev, fn; |
140 | 141 | ||
142 | WARN_ON(seg); | ||
141 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | 143 | if ((bus > 255) || (devfn > 255) || (reg > 255)) |
142 | return -EINVAL; | 144 | return -EINVAL; |
143 | 145 | ||
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 750c346ef50..301e325992f 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -519,7 +519,8 @@ static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, | |||
519 | if (cfg->address < 0xFFFFFFFF) | 519 | if (cfg->address < 0xFFFFFFFF) |
520 | return 0; | 520 | return 0; |
521 | 521 | ||
522 | if (!strcmp(mcfg->header.oem_id, "SGI")) | 522 | if (!strcmp(mcfg->header.oem_id, "SGI") || |
523 | !strcmp(mcfg->header.oem_id, "SGI2")) | ||
523 | return 0; | 524 | return 0; |
524 | 525 | ||
525 | if (mcfg->header.revision >= 1) { | 526 | if (mcfg->header.revision >= 1) { |
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c index 5c9e2458df4..512a88c4150 100644 --- a/arch/x86/pci/numaq_32.c +++ b/arch/x86/pci/numaq_32.c | |||
@@ -34,6 +34,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, | |||
34 | unsigned long flags; | 34 | unsigned long flags; |
35 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | 35 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); |
36 | 36 | ||
37 | WARN_ON(seg); | ||
37 | if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | 38 | if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) |
38 | return -EINVAL; | 39 | return -EINVAL; |
39 | 40 | ||
@@ -73,6 +74,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, | |||
73 | unsigned long flags; | 74 | unsigned long flags; |
74 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | 75 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); |
75 | 76 | ||
77 | WARN_ON(seg); | ||
76 | if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | 78 | if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) |
77 | return -EINVAL; | 79 | return -EINVAL; |
78 | 80 | ||
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c index 13700ec8e2e..5262603b04d 100644 --- a/arch/x86/pci/olpc.c +++ b/arch/x86/pci/olpc.c | |||
@@ -206,6 +206,8 @@ static int pci_olpc_read(unsigned int seg, unsigned int bus, | |||
206 | { | 206 | { |
207 | uint32_t *addr; | 207 | uint32_t *addr; |
208 | 208 | ||
209 | WARN_ON(seg); | ||
210 | |||
209 | /* Use the hardware mechanism for non-simulated devices */ | 211 | /* Use the hardware mechanism for non-simulated devices */ |
210 | if (!is_simulated(bus, devfn)) | 212 | if (!is_simulated(bus, devfn)) |
211 | return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); | 213 | return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); |
@@ -264,6 +266,8 @@ static int pci_olpc_read(unsigned int seg, unsigned int bus, | |||
264 | static int pci_olpc_write(unsigned int seg, unsigned int bus, | 266 | static int pci_olpc_write(unsigned int seg, unsigned int bus, |
265 | unsigned int devfn, int reg, int len, uint32_t value) | 267 | unsigned int devfn, int reg, int len, uint32_t value) |
266 | { | 268 | { |
269 | WARN_ON(seg); | ||
270 | |||
267 | /* Use the hardware mechanism for non-simulated devices */ | 271 | /* Use the hardware mechanism for non-simulated devices */ |
268 | if (!is_simulated(bus, devfn)) | 272 | if (!is_simulated(bus, devfn)) |
269 | return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); | 273 | return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); |
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index a5f7d0d63de..f6855355146 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c | |||
@@ -181,6 +181,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, | |||
181 | unsigned long flags; | 181 | unsigned long flags; |
182 | unsigned long bx = (bus << 8) | devfn; | 182 | unsigned long bx = (bus << 8) | devfn; |
183 | 183 | ||
184 | WARN_ON(seg); | ||
184 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) | 185 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) |
185 | return -EINVAL; | 186 | return -EINVAL; |
186 | 187 | ||
@@ -247,6 +248,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, | |||
247 | unsigned long flags; | 248 | unsigned long flags; |
248 | unsigned long bx = (bus << 8) | devfn; | 249 | unsigned long bx = (bus << 8) | devfn; |
249 | 250 | ||
251 | WARN_ON(seg); | ||
250 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | 252 | if ((bus > 255) || (devfn > 255) || (reg > 255)) |
251 | return -EINVAL; | 253 | return -EINVAL; |
252 | 254 | ||
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c index 03008f72eb0..6f2f8eeed17 100644 --- a/arch/x86/pci/visws.c +++ b/arch/x86/pci/visws.c | |||
@@ -24,7 +24,7 @@ static void pci_visws_disable_irq(struct pci_dev *dev) { } | |||
24 | 24 | ||
25 | unsigned int pci_bus0, pci_bus1; | 25 | unsigned int pci_bus0, pci_bus1; |
26 | 26 | ||
27 | static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | 27 | static int __init visws_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
28 | { | 28 | { |
29 | int irq, bus = dev->bus->number; | 29 | int irq, bus = dev->bus->number; |
30 | 30 | ||
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index f567965c062..1017c7bee38 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -1,8 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux | 2 | * Xen PCI - handle PCI (INTx) and MSI infrastructure calls for PV, HVM and |
3 | * x86 PCI core to support the Xen PCI Frontend | 3 | * initial domain support. We also handle the DSDT _PRT callbacks for GSI's |
4 | * used in HVM and initial domain mode (PV does not parse ACPI, so it has no | ||
5 | * concept of GSIs). Under PV we hook under the pnbbios API for IRQs and | ||
6 | * 0xcf8 PCI configuration read/write. | ||
4 | * | 7 | * |
5 | * Author: Ryan Wilson <hap9@epoch.ncsc.mil> | 8 | * Author: Ryan Wilson <hap9@epoch.ncsc.mil> |
9 | * Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | ||
10 | * Stefano Stabellini <stefano.stabellini@eu.citrix.com> | ||
6 | */ | 11 | */ |
7 | #include <linux/module.h> | 12 | #include <linux/module.h> |
8 | #include <linux/init.h> | 13 | #include <linux/init.h> |
@@ -19,22 +24,53 @@ | |||
19 | #include <xen/events.h> | 24 | #include <xen/events.h> |
20 | #include <asm/xen/pci.h> | 25 | #include <asm/xen/pci.h> |
21 | 26 | ||
27 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | ||
28 | { | ||
29 | int rc; | ||
30 | int share = 1; | ||
31 | int pirq; | ||
32 | u8 gsi; | ||
33 | |||
34 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); | ||
35 | if (rc < 0) { | ||
36 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", | ||
37 | rc); | ||
38 | return rc; | ||
39 | } | ||
40 | /* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/ | ||
41 | pirq = gsi; | ||
42 | |||
43 | if (gsi < NR_IRQS_LEGACY) | ||
44 | share = 0; | ||
45 | |||
46 | rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); | ||
47 | if (rc < 0) { | ||
48 | dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", | ||
49 | gsi, pirq, rc); | ||
50 | return rc; | ||
51 | } | ||
52 | |||
53 | dev->irq = rc; | ||
54 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
22 | #ifdef CONFIG_ACPI | 58 | #ifdef CONFIG_ACPI |
23 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | 59 | static int xen_register_pirq(u32 gsi, int gsi_override, int triggering, |
24 | int trigger, int polarity) | 60 | bool set_pirq) |
25 | { | 61 | { |
26 | int rc, irq; | 62 | int rc, pirq = -1, irq = -1; |
27 | struct physdev_map_pirq map_irq; | 63 | struct physdev_map_pirq map_irq; |
28 | int shareable = 0; | 64 | int shareable = 0; |
29 | char *name; | 65 | char *name; |
30 | 66 | ||
31 | if (!xen_hvm_domain()) | 67 | if (set_pirq) |
32 | return -1; | 68 | pirq = gsi; |
33 | 69 | ||
34 | map_irq.domid = DOMID_SELF; | 70 | map_irq.domid = DOMID_SELF; |
35 | map_irq.type = MAP_PIRQ_TYPE_GSI; | 71 | map_irq.type = MAP_PIRQ_TYPE_GSI; |
36 | map_irq.index = gsi; | 72 | map_irq.index = gsi; |
37 | map_irq.pirq = -1; | 73 | map_irq.pirq = pirq; |
38 | 74 | ||
39 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | 75 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); |
40 | if (rc) { | 76 | if (rc) { |
@@ -42,7 +78,7 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
42 | return -1; | 78 | return -1; |
43 | } | 79 | } |
44 | 80 | ||
45 | if (trigger == ACPI_EDGE_SENSITIVE) { | 81 | if (triggering == ACPI_EDGE_SENSITIVE) { |
46 | shareable = 0; | 82 | shareable = 0; |
47 | name = "ioapic-edge"; | 83 | name = "ioapic-edge"; |
48 | } else { | 84 | } else { |
@@ -50,12 +86,63 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
50 | name = "ioapic-level"; | 86 | name = "ioapic-level"; |
51 | } | 87 | } |
52 | 88 | ||
89 | if (gsi_override >= 0) | ||
90 | gsi = gsi_override; | ||
91 | |||
53 | irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name); | 92 | irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name); |
93 | if (irq < 0) | ||
94 | goto out; | ||
95 | |||
96 | printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", map_irq.pirq, irq, gsi); | ||
97 | out: | ||
98 | return irq; | ||
99 | } | ||
100 | |||
101 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | ||
102 | int trigger, int polarity) | ||
103 | { | ||
104 | if (!xen_hvm_domain()) | ||
105 | return -1; | ||
54 | 106 | ||
55 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); | 107 | return xen_register_pirq(gsi, -1 /* no GSI override */, trigger, |
108 | false /* no mapping of GSI to PIRQ */); | ||
109 | } | ||
110 | |||
111 | #ifdef CONFIG_XEN_DOM0 | ||
112 | static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity) | ||
113 | { | ||
114 | int rc, irq; | ||
115 | struct physdev_setup_gsi setup_gsi; | ||
116 | |||
117 | if (!xen_pv_domain()) | ||
118 | return -1; | ||
119 | |||
120 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
121 | gsi, triggering, polarity); | ||
122 | |||
123 | irq = xen_register_pirq(gsi, gsi_override, triggering, true); | ||
124 | |||
125 | setup_gsi.gsi = gsi; | ||
126 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
127 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
128 | |||
129 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
130 | if (rc == -EEXIST) | ||
131 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
132 | else if (rc) { | ||
133 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
134 | gsi, rc); | ||
135 | } | ||
56 | 136 | ||
57 | return irq; | 137 | return irq; |
58 | } | 138 | } |
139 | |||
140 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
141 | int trigger, int polarity) | ||
142 | { | ||
143 | return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); | ||
144 | } | ||
145 | #endif | ||
59 | #endif | 146 | #endif |
60 | 147 | ||
61 | #if defined(CONFIG_PCI_MSI) | 148 | #if defined(CONFIG_PCI_MSI) |
@@ -65,6 +152,43 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
65 | struct xen_pci_frontend_ops *xen_pci_frontend; | 152 | struct xen_pci_frontend_ops *xen_pci_frontend; |
66 | EXPORT_SYMBOL_GPL(xen_pci_frontend); | 153 | EXPORT_SYMBOL_GPL(xen_pci_frontend); |
67 | 154 | ||
155 | static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
156 | { | ||
157 | int irq, ret, i; | ||
158 | struct msi_desc *msidesc; | ||
159 | int *v; | ||
160 | |||
161 | v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); | ||
162 | if (!v) | ||
163 | return -ENOMEM; | ||
164 | |||
165 | if (type == PCI_CAP_ID_MSIX) | ||
166 | ret = xen_pci_frontend_enable_msix(dev, v, nvec); | ||
167 | else | ||
168 | ret = xen_pci_frontend_enable_msi(dev, v); | ||
169 | if (ret) | ||
170 | goto error; | ||
171 | i = 0; | ||
172 | list_for_each_entry(msidesc, &dev->msi_list, list) { | ||
173 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | ||
174 | (type == PCI_CAP_ID_MSIX) ? | ||
175 | "pcifront-msi-x" : | ||
176 | "pcifront-msi", | ||
177 | DOMID_SELF); | ||
178 | if (irq < 0) | ||
179 | goto free; | ||
180 | i++; | ||
181 | } | ||
182 | kfree(v); | ||
183 | return 0; | ||
184 | |||
185 | error: | ||
186 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); | ||
187 | free: | ||
188 | kfree(v); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
68 | #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ | 192 | #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ |
69 | MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) | 193 | MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) |
70 | 194 | ||
@@ -123,67 +247,6 @@ error: | |||
123 | return -ENODEV; | 247 | return -ENODEV; |
124 | } | 248 | } |
125 | 249 | ||
126 | /* | ||
127 | * For MSI interrupts we have to use drivers/xen/event.s functions to | ||
128 | * allocate an irq_desc and setup the right */ | ||
129 | |||
130 | |||
131 | static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
132 | { | ||
133 | int irq, ret, i; | ||
134 | struct msi_desc *msidesc; | ||
135 | int *v; | ||
136 | |||
137 | v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); | ||
138 | if (!v) | ||
139 | return -ENOMEM; | ||
140 | |||
141 | if (type == PCI_CAP_ID_MSIX) | ||
142 | ret = xen_pci_frontend_enable_msix(dev, v, nvec); | ||
143 | else | ||
144 | ret = xen_pci_frontend_enable_msi(dev, v); | ||
145 | if (ret) | ||
146 | goto error; | ||
147 | i = 0; | ||
148 | list_for_each_entry(msidesc, &dev->msi_list, list) { | ||
149 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | ||
150 | (type == PCI_CAP_ID_MSIX) ? | ||
151 | "pcifront-msi-x" : | ||
152 | "pcifront-msi", | ||
153 | DOMID_SELF); | ||
154 | if (irq < 0) | ||
155 | goto free; | ||
156 | i++; | ||
157 | } | ||
158 | kfree(v); | ||
159 | return 0; | ||
160 | |||
161 | error: | ||
162 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); | ||
163 | free: | ||
164 | kfree(v); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static void xen_teardown_msi_irqs(struct pci_dev *dev) | ||
169 | { | ||
170 | struct msi_desc *msidesc; | ||
171 | |||
172 | msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); | ||
173 | if (msidesc->msi_attrib.is_msix) | ||
174 | xen_pci_frontend_disable_msix(dev); | ||
175 | else | ||
176 | xen_pci_frontend_disable_msi(dev); | ||
177 | |||
178 | /* Free the IRQ's and the msidesc using the generic code. */ | ||
179 | default_teardown_msi_irqs(dev); | ||
180 | } | ||
181 | |||
182 | static void xen_teardown_msi_irq(unsigned int irq) | ||
183 | { | ||
184 | xen_destroy_irq(irq); | ||
185 | } | ||
186 | |||
187 | #ifdef CONFIG_XEN_DOM0 | 250 | #ifdef CONFIG_XEN_DOM0 |
188 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 251 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
189 | { | 252 | { |
@@ -242,45 +305,28 @@ out: | |||
242 | return ret; | 305 | return ret; |
243 | } | 306 | } |
244 | #endif | 307 | #endif |
245 | #endif | ||
246 | 308 | ||
247 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | 309 | static void xen_teardown_msi_irqs(struct pci_dev *dev) |
248 | { | 310 | { |
249 | int rc; | 311 | struct msi_desc *msidesc; |
250 | int share = 1; | ||
251 | int pirq; | ||
252 | u8 gsi; | ||
253 | |||
254 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); | ||
255 | if (rc < 0) { | ||
256 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", | ||
257 | rc); | ||
258 | return rc; | ||
259 | } | ||
260 | |||
261 | rc = xen_allocate_pirq_gsi(gsi); | ||
262 | if (rc < 0) { | ||
263 | dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n", | ||
264 | gsi, rc); | ||
265 | return rc; | ||
266 | } | ||
267 | pirq = rc; | ||
268 | 312 | ||
269 | if (gsi < NR_IRQS_LEGACY) | 313 | msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); |
270 | share = 0; | 314 | if (msidesc->msi_attrib.is_msix) |
315 | xen_pci_frontend_disable_msix(dev); | ||
316 | else | ||
317 | xen_pci_frontend_disable_msi(dev); | ||
271 | 318 | ||
272 | rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); | 319 | /* Free the IRQ's and the msidesc using the generic code. */ |
273 | if (rc < 0) { | 320 | default_teardown_msi_irqs(dev); |
274 | dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", | 321 | } |
275 | gsi, pirq, rc); | ||
276 | return rc; | ||
277 | } | ||
278 | 322 | ||
279 | dev->irq = rc; | 323 | static void xen_teardown_msi_irq(unsigned int irq) |
280 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | 324 | { |
281 | return 0; | 325 | xen_destroy_irq(irq); |
282 | } | 326 | } |
283 | 327 | ||
328 | #endif | ||
329 | |||
284 | int __init pci_xen_init(void) | 330 | int __init pci_xen_init(void) |
285 | { | 331 | { |
286 | if (!xen_pv_domain() || xen_initial_domain()) | 332 | if (!xen_pv_domain() || xen_initial_domain()) |
@@ -327,79 +373,6 @@ int __init pci_xen_hvm_init(void) | |||
327 | } | 373 | } |
328 | 374 | ||
329 | #ifdef CONFIG_XEN_DOM0 | 375 | #ifdef CONFIG_XEN_DOM0 |
330 | static int xen_register_pirq(u32 gsi, int gsi_override, int triggering) | ||
331 | { | ||
332 | int rc, pirq, irq = -1; | ||
333 | struct physdev_map_pirq map_irq; | ||
334 | int shareable = 0; | ||
335 | char *name; | ||
336 | |||
337 | if (!xen_pv_domain()) | ||
338 | return -1; | ||
339 | |||
340 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
341 | shareable = 0; | ||
342 | name = "ioapic-edge"; | ||
343 | } else { | ||
344 | shareable = 1; | ||
345 | name = "ioapic-level"; | ||
346 | } | ||
347 | pirq = xen_allocate_pirq_gsi(gsi); | ||
348 | if (pirq < 0) | ||
349 | goto out; | ||
350 | |||
351 | if (gsi_override >= 0) | ||
352 | irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name); | ||
353 | else | ||
354 | irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); | ||
355 | if (irq < 0) | ||
356 | goto out; | ||
357 | |||
358 | printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi); | ||
359 | |||
360 | map_irq.domid = DOMID_SELF; | ||
361 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
362 | map_irq.index = gsi; | ||
363 | map_irq.pirq = pirq; | ||
364 | |||
365 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
366 | if (rc) { | ||
367 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
368 | return -1; | ||
369 | } | ||
370 | |||
371 | out: | ||
372 | return irq; | ||
373 | } | ||
374 | |||
375 | static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity) | ||
376 | { | ||
377 | int rc, irq; | ||
378 | struct physdev_setup_gsi setup_gsi; | ||
379 | |||
380 | if (!xen_pv_domain()) | ||
381 | return -1; | ||
382 | |||
383 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
384 | gsi, triggering, polarity); | ||
385 | |||
386 | irq = xen_register_pirq(gsi, gsi_override, triggering); | ||
387 | |||
388 | setup_gsi.gsi = gsi; | ||
389 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
390 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
391 | |||
392 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
393 | if (rc == -EEXIST) | ||
394 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
395 | else if (rc) { | ||
396 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
397 | gsi, rc); | ||
398 | } | ||
399 | |||
400 | return irq; | ||
401 | } | ||
402 | |||
403 | static __init void xen_setup_acpi_sci(void) | 376 | static __init void xen_setup_acpi_sci(void) |
404 | { | 377 | { |
405 | int rc; | 378 | int rc; |
@@ -419,7 +392,7 @@ static __init void xen_setup_acpi_sci(void) | |||
419 | } | 392 | } |
420 | trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | 393 | trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; |
421 | polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | 394 | polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; |
422 | 395 | ||
423 | printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " | 396 | printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " |
424 | "polarity=%d\n", gsi, trigger, polarity); | 397 | "polarity=%d\n", gsi, trigger, polarity); |
425 | 398 | ||
@@ -434,10 +407,9 @@ static __init void xen_setup_acpi_sci(void) | |||
434 | * the ACPI interpreter and keels over since IRQ 9 has not been | 407 | * the ACPI interpreter and keels over since IRQ 9 has not been |
435 | * setup as we had setup IRQ 20 for it). | 408 | * setup as we had setup IRQ 20 for it). |
436 | */ | 409 | */ |
437 | /* Check whether the GSI != IRQ */ | ||
438 | if (acpi_gsi_to_irq(gsi, &irq) == 0) { | 410 | if (acpi_gsi_to_irq(gsi, &irq) == 0) { |
439 | if (irq >= 0 && irq != gsi) | 411 | /* Use the provided value if it's valid. */ |
440 | /* Bugger, we MUST have that IRQ. */ | 412 | if (irq >= 0) |
441 | gsi_override = irq; | 413 | gsi_override = irq; |
442 | } | 414 | } |
443 | 415 | ||
@@ -447,41 +419,16 @@ static __init void xen_setup_acpi_sci(void) | |||
447 | return; | 419 | return; |
448 | } | 420 | } |
449 | 421 | ||
450 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | 422 | int __init pci_xen_initial_domain(void) |
451 | int trigger, int polarity) | ||
452 | { | 423 | { |
453 | return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); | 424 | int irq; |
454 | } | ||
455 | 425 | ||
456 | static int __init pci_xen_initial_domain(void) | ||
457 | { | ||
458 | #ifdef CONFIG_PCI_MSI | 426 | #ifdef CONFIG_PCI_MSI |
459 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; | 427 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; |
460 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 428 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; |
461 | #endif | 429 | #endif |
462 | xen_setup_acpi_sci(); | 430 | xen_setup_acpi_sci(); |
463 | __acpi_register_gsi = acpi_register_gsi_xen; | 431 | __acpi_register_gsi = acpi_register_gsi_xen; |
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | void __init xen_setup_pirqs(void) | ||
469 | { | ||
470 | int pirq, irq; | ||
471 | |||
472 | pci_xen_initial_domain(); | ||
473 | |||
474 | if (0 == nr_ioapics) { | ||
475 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { | ||
476 | pirq = xen_allocate_pirq_gsi(irq); | ||
477 | if (WARN(pirq < 0, | ||
478 | "Could not allocate PIRQ for legacy interrupt\n")) | ||
479 | break; | ||
480 | irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic"); | ||
481 | } | ||
482 | return; | ||
483 | } | ||
484 | |||
485 | /* Pre-allocate legacy irqs */ | 432 | /* Pre-allocate legacy irqs */ |
486 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { | 433 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { |
487 | int trigger, polarity; | 434 | int trigger, polarity; |
@@ -490,12 +437,16 @@ void __init xen_setup_pirqs(void) | |||
490 | continue; | 437 | continue; |
491 | 438 | ||
492 | xen_register_pirq(irq, -1 /* no GSI override */, | 439 | xen_register_pirq(irq, -1 /* no GSI override */, |
493 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); | 440 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE, |
441 | true /* Map GSI to PIRQ */); | ||
494 | } | 442 | } |
443 | if (0 == nr_ioapics) { | ||
444 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) | ||
445 | xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic"); | ||
446 | } | ||
447 | return 0; | ||
495 | } | 448 | } |
496 | #endif | ||
497 | 449 | ||
498 | #ifdef CONFIG_XEN_DOM0 | ||
499 | struct xen_device_domain_owner { | 450 | struct xen_device_domain_owner { |
500 | domid_t domain; | 451 | domid_t domain; |
501 | struct pci_dev *dev; | 452 | struct pci_dev *dev; |