diff options
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/amd_bus.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/ce4100.c | 7 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 159 |
3 files changed, 93 insertions, 75 deletions
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index e27dffbbb1a7..026e4931d162 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
@@ -350,7 +350,7 @@ static int __init early_fill_mp_bus_info(void) | |||
350 | 350 | ||
351 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) | 351 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) |
352 | 352 | ||
353 | static void enable_pci_io_ecs(void *unused) | 353 | static void __cpuinit enable_pci_io_ecs(void *unused) |
354 | { | 354 | { |
355 | u64 reg; | 355 | u64 reg; |
356 | rdmsrl(MSR_AMD64_NB_CFG, reg); | 356 | rdmsrl(MSR_AMD64_NB_CFG, reg); |
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index c63c6d3dd8e8..67858be4b52b 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | 36 | ||
37 | #include <asm/ce4100.h> | ||
37 | #include <asm/pci_x86.h> | 38 | #include <asm/pci_x86.h> |
38 | 39 | ||
39 | struct sim_reg { | 40 | struct sim_reg { |
@@ -306,10 +307,10 @@ struct pci_raw_ops ce4100_pci_conf = { | |||
306 | .write = ce4100_conf_write, | 307 | .write = ce4100_conf_write, |
307 | }; | 308 | }; |
308 | 309 | ||
309 | static int __init ce4100_pci_init(void) | 310 | int __init ce4100_pci_init(void) |
310 | { | 311 | { |
311 | init_sim_regs(); | 312 | init_sim_regs(); |
312 | raw_pci_ops = &ce4100_pci_conf; | 313 | raw_pci_ops = &ce4100_pci_conf; |
313 | return 0; | 314 | /* Indicate caller that it should invoke pci_legacy_init() */ |
315 | return 1; | ||
314 | } | 316 | } |
315 | subsys_initcall(ce4100_pci_init); | ||
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 25cd4a07d09f..8c4085a95ef1 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include <asm/xen/pci.h> | 20 | #include <asm/xen/pci.h> |
21 | 21 | ||
22 | #ifdef CONFIG_ACPI | 22 | #ifdef CONFIG_ACPI |
23 | static int xen_hvm_register_pirq(u32 gsi, int triggering) | 23 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, |
24 | int trigger, int polarity) | ||
24 | { | 25 | { |
25 | int rc, irq; | 26 | int rc, irq; |
26 | struct physdev_map_pirq map_irq; | 27 | struct physdev_map_pirq map_irq; |
@@ -41,7 +42,7 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) | |||
41 | return -1; | 42 | return -1; |
42 | } | 43 | } |
43 | 44 | ||
44 | if (triggering == ACPI_EDGE_SENSITIVE) { | 45 | if (trigger == ACPI_EDGE_SENSITIVE) { |
45 | shareable = 0; | 46 | shareable = 0; |
46 | name = "ioapic-edge"; | 47 | name = "ioapic-edge"; |
47 | } else { | 48 | } else { |
@@ -55,12 +56,6 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) | |||
55 | 56 | ||
56 | return irq; | 57 | return irq; |
57 | } | 58 | } |
58 | |||
59 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | ||
60 | int trigger, int polarity) | ||
61 | { | ||
62 | return xen_hvm_register_pirq(gsi, trigger); | ||
63 | } | ||
64 | #endif | 59 | #endif |
65 | 60 | ||
66 | #if defined(CONFIG_PCI_MSI) | 61 | #if defined(CONFIG_PCI_MSI) |
@@ -91,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, | |||
91 | 86 | ||
92 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 87 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
93 | { | 88 | { |
94 | int irq, pirq, ret = 0; | 89 | int irq, pirq; |
95 | struct msi_desc *msidesc; | 90 | struct msi_desc *msidesc; |
96 | struct msi_msg msg; | 91 | struct msi_msg msg; |
97 | 92 | ||
@@ -99,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
99 | __read_msi_msg(msidesc, &msg); | 94 | __read_msi_msg(msidesc, &msg); |
100 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | | 95 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | |
101 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); | 96 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); |
102 | if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { | 97 | if (msg.data != XEN_PIRQ_MSI_DATA || |
103 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 98 | xen_irq_from_pirq(pirq) < 0) { |
104 | "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ); | 99 | pirq = xen_allocate_pirq_msi(dev, msidesc); |
105 | if (irq < 0) | 100 | if (pirq < 0) |
106 | goto error; | 101 | goto error; |
107 | ret = set_irq_msi(irq, msidesc); | 102 | xen_msi_compose_msg(dev, pirq, &msg); |
108 | if (ret < 0) | 103 | __write_msi_msg(msidesc, &msg); |
109 | goto error_while; | 104 | dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); |
110 | printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" | 105 | } else { |
111 | " pirq=%d\n", irq, pirq); | 106 | dev_dbg(&dev->dev, |
112 | return 0; | 107 | "xen: msi already bound to pirq=%d\n", pirq); |
113 | } | 108 | } |
114 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, |
115 | "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ)); | 110 | (type == PCI_CAP_ID_MSIX) ? |
116 | if (irq < 0 || pirq < 0) | 111 | "msi-x" : "msi"); |
112 | if (irq < 0) | ||
117 | goto error; | 113 | goto error; |
118 | printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); | 114 | dev_dbg(&dev->dev, |
119 | xen_msi_compose_msg(dev, pirq, &msg); | 115 | "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq); |
120 | ret = set_irq_msi(irq, msidesc); | ||
121 | if (ret < 0) | ||
122 | goto error_while; | ||
123 | write_msi_msg(irq, &msg); | ||
124 | } | 116 | } |
125 | return 0; | 117 | return 0; |
126 | 118 | ||
127 | error_while: | ||
128 | unbind_from_irqhandler(irq, NULL); | ||
129 | error: | 119 | error: |
130 | if (ret == -ENODEV) | 120 | dev_err(&dev->dev, |
131 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | 121 | "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
132 | " MSI/MSI-X support!\n"); | 122 | return -ENODEV; |
133 | |||
134 | return ret; | ||
135 | } | 123 | } |
136 | 124 | ||
137 | /* | 125 | /* |
@@ -150,35 +138,26 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
150 | return -ENOMEM; | 138 | return -ENOMEM; |
151 | 139 | ||
152 | if (type == PCI_CAP_ID_MSIX) | 140 | if (type == PCI_CAP_ID_MSIX) |
153 | ret = xen_pci_frontend_enable_msix(dev, &v, nvec); | 141 | ret = xen_pci_frontend_enable_msix(dev, v, nvec); |
154 | else | 142 | else |
155 | ret = xen_pci_frontend_enable_msi(dev, &v); | 143 | ret = xen_pci_frontend_enable_msi(dev, v); |
156 | if (ret) | 144 | if (ret) |
157 | goto error; | 145 | goto error; |
158 | i = 0; | 146 | i = 0; |
159 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 147 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
160 | irq = xen_allocate_pirq(v[i], 0, /* not sharable */ | 148 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, |
161 | (type == PCI_CAP_ID_MSIX) ? | 149 | (type == PCI_CAP_ID_MSIX) ? |
162 | "pcifront-msi-x" : "pcifront-msi"); | 150 | "pcifront-msi-x" : |
163 | if (irq < 0) { | 151 | "pcifront-msi"); |
164 | ret = -1; | 152 | if (irq < 0) |
165 | goto free; | 153 | goto free; |
166 | } | ||
167 | |||
168 | ret = set_irq_msi(irq, msidesc); | ||
169 | if (ret) | ||
170 | goto error_while; | ||
171 | i++; | 154 | i++; |
172 | } | 155 | } |
173 | kfree(v); | 156 | kfree(v); |
174 | return 0; | 157 | return 0; |
175 | 158 | ||
176 | error_while: | ||
177 | unbind_from_irqhandler(irq, NULL); | ||
178 | error: | 159 | error: |
179 | if (ret == -ENODEV) | 160 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
180 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | ||
181 | " MSI/MSI-X support!\n"); | ||
182 | free: | 161 | free: |
183 | kfree(v); | 162 | kfree(v); |
184 | return ret; | 163 | return ret; |
@@ -193,6 +172,9 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) | |||
193 | xen_pci_frontend_disable_msix(dev); | 172 | xen_pci_frontend_disable_msix(dev); |
194 | else | 173 | else |
195 | xen_pci_frontend_disable_msi(dev); | 174 | xen_pci_frontend_disable_msi(dev); |
175 | |||
176 | /* Free the IRQ's and the msidesc using the generic code. */ | ||
177 | default_teardown_msi_irqs(dev); | ||
196 | } | 178 | } |
197 | 179 | ||
198 | static void xen_teardown_msi_irq(unsigned int irq) | 180 | static void xen_teardown_msi_irq(unsigned int irq) |
@@ -200,47 +182,82 @@ static void xen_teardown_msi_irq(unsigned int irq) | |||
200 | xen_destroy_irq(irq); | 182 | xen_destroy_irq(irq); |
201 | } | 183 | } |
202 | 184 | ||
185 | #ifdef CONFIG_XEN_DOM0 | ||
203 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 186 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
204 | { | 187 | { |
205 | int irq, ret; | 188 | int ret = 0; |
206 | struct msi_desc *msidesc; | 189 | struct msi_desc *msidesc; |
207 | 190 | ||
208 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 191 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
209 | irq = xen_create_msi_irq(dev, msidesc, type); | 192 | struct physdev_map_pirq map_irq; |
210 | if (irq < 0) | ||
211 | return -1; | ||
212 | 193 | ||
213 | ret = set_irq_msi(irq, msidesc); | 194 | memset(&map_irq, 0, sizeof(map_irq)); |
214 | if (ret) | 195 | map_irq.domid = DOMID_SELF; |
215 | goto error; | 196 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
216 | } | 197 | map_irq.index = -1; |
217 | return 0; | 198 | map_irq.pirq = -1; |
199 | map_irq.bus = dev->bus->number; | ||
200 | map_irq.devfn = dev->devfn; | ||
218 | 201 | ||
219 | error: | 202 | if (type == PCI_CAP_ID_MSIX) { |
220 | xen_destroy_irq(irq); | 203 | int pos; |
204 | u32 table_offset, bir; | ||
205 | |||
206 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
207 | |||
208 | pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, | ||
209 | &table_offset); | ||
210 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
211 | |||
212 | map_irq.table_base = pci_resource_start(dev, bir); | ||
213 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
214 | } | ||
215 | |||
216 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
217 | if (ret) { | ||
218 | dev_warn(&dev->dev, "xen map irq failed %d\n", ret); | ||
219 | goto out; | ||
220 | } | ||
221 | |||
222 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | ||
223 | map_irq.pirq, map_irq.index, | ||
224 | (type == PCI_CAP_ID_MSIX) ? | ||
225 | "msi-x" : "msi"); | ||
226 | if (ret < 0) | ||
227 | goto out; | ||
228 | } | ||
229 | ret = 0; | ||
230 | out: | ||
221 | return ret; | 231 | return ret; |
222 | } | 232 | } |
223 | #endif | 233 | #endif |
234 | #endif | ||
224 | 235 | ||
225 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | 236 | static int xen_pcifront_enable_irq(struct pci_dev *dev) |
226 | { | 237 | { |
227 | int rc; | 238 | int rc; |
228 | int share = 1; | 239 | int share = 1; |
240 | u8 gsi; | ||
229 | 241 | ||
230 | dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq); | 242 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); |
231 | 243 | if (rc < 0) { | |
232 | if (dev->irq < 0) | 244 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", |
233 | return -EINVAL; | 245 | rc); |
246 | return rc; | ||
247 | } | ||
234 | 248 | ||
235 | if (dev->irq < NR_IRQS_LEGACY) | 249 | if (gsi < NR_IRQS_LEGACY) |
236 | share = 0; | 250 | share = 0; |
237 | 251 | ||
238 | rc = xen_allocate_pirq(dev->irq, share, "pcifront"); | 252 | rc = xen_allocate_pirq(gsi, share, "pcifront"); |
239 | if (rc < 0) { | 253 | if (rc < 0) { |
240 | dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n", | 254 | dev_warn(&dev->dev, "Xen PCI: failed to register GSI%d: %d\n", |
241 | dev->irq, rc); | 255 | gsi, rc); |
242 | return rc; | 256 | return rc; |
243 | } | 257 | } |
258 | |||
259 | dev->irq = rc; | ||
260 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | ||
244 | return 0; | 261 | return 0; |
245 | } | 262 | } |
246 | 263 | ||