aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/acpi.c32
-rw-r--r--arch/x86/pci/ce4100.c2
-rw-r--r--arch/x86/pci/common.c14
-rw-r--r--arch/x86/pci/direct.c6
-rw-r--r--arch/x86/pci/mmconfig-shared.c3
-rw-r--r--arch/x86/pci/numaq_32.c2
-rw-r--r--arch/x86/pci/olpc.c4
-rw-r--r--arch/x86/pci/pcbios.c2
-rw-r--r--arch/x86/pci/visws.c2
-rw-r--r--arch/x86/pci/xen.c401
10 files changed, 238 insertions, 230 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 68c3c1395202..404f21a3ff9e 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
@@ -246,10 +257,9 @@ static void add_resources(struct pci_root_info *info)
246 257
247 conflict = insert_resource_conflict(root, res); 258 conflict = insert_resource_conflict(root, res);
248 if (conflict) 259 if (conflict)
249 dev_err(&info->bridge->dev, 260 dev_info(&info->bridge->dev,
250 "address space collision: host bridge window %pR " 261 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
251 "conflicts with %s %pR\n", 262 res, conflict->name, conflict);
252 res, conflict->name, conflict);
253 else 263 else
254 pci_bus_add_resource(info->bus, res, 0); 264 pci_bus_add_resource(info->bus, res, 0);
255 } 265 }
@@ -361,6 +371,20 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
361 } 371 }
362 } 372 }
363 373
374 /* After the PCI-E bus has been walked and all devices discovered,
375 * configure any settings of the fabric that might be necessary.
376 */
377 if (bus) {
378 struct pci_bus *child;
379 list_for_each_entry(child, &bus->children, node) {
380 struct pci_dev *self = child->self;
381 if (!self)
382 continue;
383
384 pcie_bus_configure_settings(child, self->pcie_mpss);
385 }
386 }
387
364 if (!bus) 388 if (!bus)
365 kfree(sd); 389 kfree(sd);
366 390
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 67858be4b52b..99176094500b 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 5fe75026ecc2..92df322e0b57 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 e6fd8473fb7b..4f2c70439d7f 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 750c346ef50a..301e325992f6 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 5c9e2458df4e..512a88c41501 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 13700ec8e2e4..5262603b04d9 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,
264static int pci_olpc_write(unsigned int seg, unsigned int bus, 266static 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 a5f7d0d63de0..f68553551467 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 03008f72eb04..6f2f8eeed171 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
25unsigned int pci_bus0, pci_bus1; 25unsigned int pci_bus0, pci_bus1;
26 26
27static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 27static 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 f567965c0620..492ade8c978e 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
27static 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
23static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, 59static 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);
97out:
98 return irq;
99}
100
101static 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
112static 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
140static 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,45 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
65struct xen_pci_frontend_ops *xen_pci_frontend; 152struct xen_pci_frontend_ops *xen_pci_frontend;
66EXPORT_SYMBOL_GPL(xen_pci_frontend); 153EXPORT_SYMBOL_GPL(xen_pci_frontend);
67 154
155static 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 ret = irq;
180 goto free;
181 }
182 i++;
183 }
184 kfree(v);
185 return 0;
186
187error:
188 dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
189free:
190 kfree(v);
191 return ret;
192}
193
68#define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ 194#define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \
69 MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) 195 MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
70 196
@@ -97,8 +223,10 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
97 if (msg.data != XEN_PIRQ_MSI_DATA || 223 if (msg.data != XEN_PIRQ_MSI_DATA ||
98 xen_irq_from_pirq(pirq) < 0) { 224 xen_irq_from_pirq(pirq) < 0) {
99 pirq = xen_allocate_pirq_msi(dev, msidesc); 225 pirq = xen_allocate_pirq_msi(dev, msidesc);
100 if (pirq < 0) 226 if (pirq < 0) {
227 irq = -ENODEV;
101 goto error; 228 goto error;
229 }
102 xen_msi_compose_msg(dev, pirq, &msg); 230 xen_msi_compose_msg(dev, pirq, &msg);
103 __write_msi_msg(msidesc, &msg); 231 __write_msi_msg(msidesc, &msg);
104 dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); 232 dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
@@ -120,71 +248,12 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
120error: 248error:
121 dev_err(&dev->dev, 249 dev_err(&dev->dev,
122 "Xen PCI frontend has not registered MSI/MSI-X support!\n"); 250 "Xen PCI frontend has not registered MSI/MSI-X support!\n");
123 return -ENODEV; 251 return irq;
124}
125
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
131static 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
161error:
162 dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
163free:
164 kfree(v);
165 return ret;
166}
167
168static 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
182static void xen_teardown_msi_irq(unsigned int irq)
183{
184 xen_destroy_irq(irq);
185} 252}
186 253
187#ifdef CONFIG_XEN_DOM0 254#ifdef CONFIG_XEN_DOM0
255static bool __read_mostly pci_seg_supported = true;
256
188static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 257static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
189{ 258{
190 int ret = 0; 259 int ret = 0;
@@ -202,10 +271,11 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
202 271
203 memset(&map_irq, 0, sizeof(map_irq)); 272 memset(&map_irq, 0, sizeof(map_irq));
204 map_irq.domid = domid; 273 map_irq.domid = domid;
205 map_irq.type = MAP_PIRQ_TYPE_MSI; 274 map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
206 map_irq.index = -1; 275 map_irq.index = -1;
207 map_irq.pirq = -1; 276 map_irq.pirq = -1;
208 map_irq.bus = dev->bus->number; 277 map_irq.bus = dev->bus->number |
278 (pci_domain_nr(dev->bus) << 16);
209 map_irq.devfn = dev->devfn; 279 map_irq.devfn = dev->devfn;
210 280
211 if (type == PCI_CAP_ID_MSIX) { 281 if (type == PCI_CAP_ID_MSIX) {
@@ -222,7 +292,20 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
222 map_irq.entry_nr = msidesc->msi_attrib.entry_nr; 292 map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
223 } 293 }
224 294
225 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 295 ret = -EINVAL;
296 if (pci_seg_supported)
297 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
298 &map_irq);
299 if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
300 map_irq.type = MAP_PIRQ_TYPE_MSI;
301 map_irq.index = -1;
302 map_irq.pirq = -1;
303 map_irq.bus = dev->bus->number;
304 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
305 &map_irq);
306 if (ret != -EINVAL)
307 pci_seg_supported = false;
308 }
226 if (ret) { 309 if (ret) {
227 dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n", 310 dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
228 ret, domid); 311 ret, domid);
@@ -242,45 +325,28 @@ out:
242 return ret; 325 return ret;
243} 326}
244#endif 327#endif
245#endif
246 328
247static int xen_pcifront_enable_irq(struct pci_dev *dev) 329static void xen_teardown_msi_irqs(struct pci_dev *dev)
248{ 330{
249 int rc; 331 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 332
269 if (gsi < NR_IRQS_LEGACY) 333 msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
270 share = 0; 334 if (msidesc->msi_attrib.is_msix)
335 xen_pci_frontend_disable_msix(dev);
336 else
337 xen_pci_frontend_disable_msi(dev);
271 338
272 rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); 339 /* Free the IRQ's and the msidesc using the generic code. */
273 if (rc < 0) { 340 default_teardown_msi_irqs(dev);
274 dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", 341}
275 gsi, pirq, rc);
276 return rc;
277 }
278 342
279 dev->irq = rc; 343static 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); 344{
281 return 0; 345 xen_destroy_irq(irq);
282} 346}
283 347
348#endif
349
284int __init pci_xen_init(void) 350int __init pci_xen_init(void)
285{ 351{
286 if (!xen_pv_domain() || xen_initial_domain()) 352 if (!xen_pv_domain() || xen_initial_domain())
@@ -327,79 +393,6 @@ int __init pci_xen_hvm_init(void)
327} 393}
328 394
329#ifdef CONFIG_XEN_DOM0 395#ifdef CONFIG_XEN_DOM0
330static 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
371out:
372 return irq;
373}
374
375static 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
403static __init void xen_setup_acpi_sci(void) 396static __init void xen_setup_acpi_sci(void)
404{ 397{
405 int rc; 398 int rc;
@@ -419,7 +412,7 @@ static __init void xen_setup_acpi_sci(void)
419 } 412 }
420 trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; 413 trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
421 polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; 414 polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
422 415
423 printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " 416 printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
424 "polarity=%d\n", gsi, trigger, polarity); 417 "polarity=%d\n", gsi, trigger, polarity);
425 418
@@ -434,10 +427,9 @@ static __init void xen_setup_acpi_sci(void)
434 * the ACPI interpreter and keels over since IRQ 9 has not been 427 * the ACPI interpreter and keels over since IRQ 9 has not been
435 * setup as we had setup IRQ 20 for it). 428 * setup as we had setup IRQ 20 for it).
436 */ 429 */
437 /* Check whether the GSI != IRQ */
438 if (acpi_gsi_to_irq(gsi, &irq) == 0) { 430 if (acpi_gsi_to_irq(gsi, &irq) == 0) {
439 if (irq >= 0 && irq != gsi) 431 /* Use the provided value if it's valid. */
440 /* Bugger, we MUST have that IRQ. */ 432 if (irq >= 0)
441 gsi_override = irq; 433 gsi_override = irq;
442 } 434 }
443 435
@@ -447,41 +439,16 @@ static __init void xen_setup_acpi_sci(void)
447 return; 439 return;
448} 440}
449 441
450static int acpi_register_gsi_xen(struct device *dev, u32 gsi, 442int __init pci_xen_initial_domain(void)
451 int trigger, int polarity)
452{ 443{
453 return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); 444 int irq;
454}
455 445
456static int __init pci_xen_initial_domain(void)
457{
458#ifdef CONFIG_PCI_MSI 446#ifdef CONFIG_PCI_MSI
459 x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; 447 x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
460 x86_msi.teardown_msi_irq = xen_teardown_msi_irq; 448 x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
461#endif 449#endif
462 xen_setup_acpi_sci(); 450 xen_setup_acpi_sci();
463 __acpi_register_gsi = acpi_register_gsi_xen; 451 __acpi_register_gsi = acpi_register_gsi_xen;
464
465 return 0;
466}
467
468void __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 */ 452 /* Pre-allocate legacy irqs */
486 for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { 453 for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
487 int trigger, polarity; 454 int trigger, polarity;
@@ -490,12 +457,16 @@ void __init xen_setup_pirqs(void)
490 continue; 457 continue;
491 458
492 xen_register_pirq(irq, -1 /* no GSI override */, 459 xen_register_pirq(irq, -1 /* no GSI override */,
493 trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); 460 trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE,
461 true /* Map GSI to PIRQ */);
494 } 462 }
463 if (0 == nr_ioapics) {
464 for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
465 xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
466 }
467 return 0;
495} 468}
496#endif
497 469
498#ifdef CONFIG_XEN_DOM0
499struct xen_device_domain_owner { 470struct xen_device_domain_owner {
500 domid_t domain; 471 domid_t domain;
501 struct pci_dev *dev; 472 struct pci_dev *dev;