diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-07-06 10:16:21 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-07-11 13:19:25 -0400 |
commit | fef6e26208879f76bada77c11c80d56ebacb32e4 (patch) | |
tree | 7fdcd859444b21fe23217ef67364512a8f50ed9b /arch/x86/pci/xen.c | |
parent | 075d9db13183c102770dc6cefabfee1b832f9614 (diff) |
xen/pci: Shuffle code around.
The file is hard to read. Move the code around so that
the contents of it follows a uniform format:
- setup GSIs - PV, HVM, and initial domain case
- then MSI/MSI-x setup - PV, HVM and then initial domain case.
- then MSI/MSI-x teardown - same order.
- lastly, the __init functions in PV, HVM, and initial domain order.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/pci/xen.c')
-rw-r--r-- | arch/x86/pci/xen.c | 346 |
1 files changed, 173 insertions, 173 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index f567965c0620..ba4077b73047 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -19,6 +19,43 @@ | |||
19 | #include <xen/events.h> | 19 | #include <xen/events.h> |
20 | #include <asm/xen/pci.h> | 20 | #include <asm/xen/pci.h> |
21 | 21 | ||
22 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | ||
23 | { | ||
24 | int rc; | ||
25 | int share = 1; | ||
26 | int pirq; | ||
27 | u8 gsi; | ||
28 | |||
29 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); | ||
30 | if (rc < 0) { | ||
31 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", | ||
32 | rc); | ||
33 | return rc; | ||
34 | } | ||
35 | |||
36 | rc = xen_allocate_pirq_gsi(gsi); | ||
37 | if (rc < 0) { | ||
38 | dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n", | ||
39 | gsi, rc); | ||
40 | return rc; | ||
41 | } | ||
42 | pirq = rc; | ||
43 | |||
44 | if (gsi < NR_IRQS_LEGACY) | ||
45 | share = 0; | ||
46 | |||
47 | rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); | ||
48 | if (rc < 0) { | ||
49 | dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", | ||
50 | gsi, pirq, rc); | ||
51 | return rc; | ||
52 | } | ||
53 | |||
54 | dev->irq = rc; | ||
55 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | ||
56 | return 0; | ||
57 | } | ||
58 | |||
22 | #ifdef CONFIG_ACPI | 59 | #ifdef CONFIG_ACPI |
23 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | 60 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, |
24 | int trigger, int polarity) | 61 | int trigger, int polarity) |
@@ -58,6 +95,87 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
58 | } | 95 | } |
59 | #endif | 96 | #endif |
60 | 97 | ||
98 | #ifdef CONFIG_XEN_DOM0 | ||
99 | static int xen_register_pirq(u32 gsi, int gsi_override, int triggering) | ||
100 | { | ||
101 | int rc, pirq, irq = -1; | ||
102 | struct physdev_map_pirq map_irq; | ||
103 | int shareable = 0; | ||
104 | char *name; | ||
105 | |||
106 | if (!xen_pv_domain()) | ||
107 | return -1; | ||
108 | |||
109 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
110 | shareable = 0; | ||
111 | name = "ioapic-edge"; | ||
112 | } else { | ||
113 | shareable = 1; | ||
114 | name = "ioapic-level"; | ||
115 | } | ||
116 | pirq = xen_allocate_pirq_gsi(gsi); | ||
117 | if (pirq < 0) | ||
118 | goto out; | ||
119 | |||
120 | if (gsi_override >= 0) | ||
121 | irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name); | ||
122 | else | ||
123 | irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); | ||
124 | if (irq < 0) | ||
125 | goto out; | ||
126 | |||
127 | printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi); | ||
128 | |||
129 | map_irq.domid = DOMID_SELF; | ||
130 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
131 | map_irq.index = gsi; | ||
132 | map_irq.pirq = pirq; | ||
133 | |||
134 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
135 | if (rc) { | ||
136 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
137 | return -1; | ||
138 | } | ||
139 | |||
140 | out: | ||
141 | return irq; | ||
142 | } | ||
143 | |||
144 | static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity) | ||
145 | { | ||
146 | int rc, irq; | ||
147 | struct physdev_setup_gsi setup_gsi; | ||
148 | |||
149 | if (!xen_pv_domain()) | ||
150 | return -1; | ||
151 | |||
152 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
153 | gsi, triggering, polarity); | ||
154 | |||
155 | irq = xen_register_pirq(gsi, gsi_override, triggering); | ||
156 | |||
157 | setup_gsi.gsi = gsi; | ||
158 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
159 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
160 | |||
161 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
162 | if (rc == -EEXIST) | ||
163 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
164 | else if (rc) { | ||
165 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
166 | gsi, rc); | ||
167 | } | ||
168 | |||
169 | return irq; | ||
170 | } | ||
171 | |||
172 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
173 | int trigger, int polarity) | ||
174 | { | ||
175 | return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); | ||
176 | } | ||
177 | #endif | ||
178 | |||
61 | #if defined(CONFIG_PCI_MSI) | 179 | #if defined(CONFIG_PCI_MSI) |
62 | #include <linux/msi.h> | 180 | #include <linux/msi.h> |
63 | #include <asm/msidef.h> | 181 | #include <asm/msidef.h> |
@@ -65,6 +183,46 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
65 | struct xen_pci_frontend_ops *xen_pci_frontend; | 183 | struct xen_pci_frontend_ops *xen_pci_frontend; |
66 | EXPORT_SYMBOL_GPL(xen_pci_frontend); | 184 | EXPORT_SYMBOL_GPL(xen_pci_frontend); |
67 | 185 | ||
186 | /* | ||
187 | * For MSI interrupts we have to use drivers/xen/event.s functions to | ||
188 | * allocate an irq_desc and setup the right */ | ||
189 | static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
190 | { | ||
191 | int irq, ret, i; | ||
192 | struct msi_desc *msidesc; | ||
193 | int *v; | ||
194 | |||
195 | v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); | ||
196 | if (!v) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | if (type == PCI_CAP_ID_MSIX) | ||
200 | ret = xen_pci_frontend_enable_msix(dev, v, nvec); | ||
201 | else | ||
202 | ret = xen_pci_frontend_enable_msi(dev, v); | ||
203 | if (ret) | ||
204 | goto error; | ||
205 | i = 0; | ||
206 | list_for_each_entry(msidesc, &dev->msi_list, list) { | ||
207 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | ||
208 | (type == PCI_CAP_ID_MSIX) ? | ||
209 | "pcifront-msi-x" : | ||
210 | "pcifront-msi", | ||
211 | DOMID_SELF); | ||
212 | if (irq < 0) | ||
213 | goto free; | ||
214 | i++; | ||
215 | } | ||
216 | kfree(v); | ||
217 | return 0; | ||
218 | |||
219 | error: | ||
220 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); | ||
221 | free: | ||
222 | kfree(v); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
68 | #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ | 226 | #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ |
69 | MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) | 227 | MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) |
70 | 228 | ||
@@ -123,67 +281,6 @@ error: | |||
123 | return -ENODEV; | 281 | return -ENODEV; |
124 | } | 282 | } |
125 | 283 | ||
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 | 284 | #ifdef CONFIG_XEN_DOM0 |
188 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 285 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
189 | { | 286 | { |
@@ -242,44 +339,28 @@ out: | |||
242 | return ret; | 339 | return ret; |
243 | } | 340 | } |
244 | #endif | 341 | #endif |
245 | #endif | ||
246 | 342 | ||
247 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | 343 | static void xen_teardown_msi_irqs(struct pci_dev *dev) |
248 | { | 344 | { |
249 | int rc; | 345 | struct msi_desc *msidesc; |
250 | int share = 1; | ||
251 | int pirq; | ||
252 | u8 gsi; | ||
253 | 346 | ||
254 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); | 347 | msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); |
255 | if (rc < 0) { | 348 | if (msidesc->msi_attrib.is_msix) |
256 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", | 349 | xen_pci_frontend_disable_msix(dev); |
257 | rc); | 350 | else |
258 | return rc; | 351 | xen_pci_frontend_disable_msi(dev); |
259 | } | ||
260 | 352 | ||
261 | rc = xen_allocate_pirq_gsi(gsi); | 353 | /* Free the IRQ's and the msidesc using the generic code. */ |
262 | if (rc < 0) { | 354 | default_teardown_msi_irqs(dev); |
263 | dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n", | 355 | } |
264 | gsi, rc); | ||
265 | return rc; | ||
266 | } | ||
267 | pirq = rc; | ||
268 | 356 | ||
269 | if (gsi < NR_IRQS_LEGACY) | 357 | static void xen_teardown_msi_irq(unsigned int irq) |
270 | share = 0; | 358 | { |
359 | xen_destroy_irq(irq); | ||
360 | } | ||
271 | 361 | ||
272 | rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); | 362 | #endif |
273 | if (rc < 0) { | ||
274 | dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", | ||
275 | gsi, pirq, rc); | ||
276 | return rc; | ||
277 | } | ||
278 | 363 | ||
279 | dev->irq = rc; | ||
280 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | ||
281 | return 0; | ||
282 | } | ||
283 | 364 | ||
284 | int __init pci_xen_init(void) | 365 | int __init pci_xen_init(void) |
285 | { | 366 | { |
@@ -327,79 +408,6 @@ int __init pci_xen_hvm_init(void) | |||
327 | } | 408 | } |
328 | 409 | ||
329 | #ifdef CONFIG_XEN_DOM0 | 410 | #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) | 411 | static __init void xen_setup_acpi_sci(void) |
404 | { | 412 | { |
405 | int rc; | 413 | int rc; |
@@ -447,12 +455,6 @@ static __init void xen_setup_acpi_sci(void) | |||
447 | return; | 455 | return; |
448 | } | 456 | } |
449 | 457 | ||
450 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
451 | int trigger, int polarity) | ||
452 | { | ||
453 | return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); | ||
454 | } | ||
455 | |||
456 | static int __init pci_xen_initial_domain(void) | 458 | static int __init pci_xen_initial_domain(void) |
457 | { | 459 | { |
458 | #ifdef CONFIG_PCI_MSI | 460 | #ifdef CONFIG_PCI_MSI |
@@ -493,9 +495,7 @@ void __init xen_setup_pirqs(void) | |||
493 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); | 495 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); |
494 | } | 496 | } |
495 | } | 497 | } |
496 | #endif | ||
497 | 498 | ||
498 | #ifdef CONFIG_XEN_DOM0 | ||
499 | struct xen_device_domain_owner { | 499 | struct xen_device_domain_owner { |
500 | domid_t domain; | 500 | domid_t domain; |
501 | struct pci_dev *dev; | 501 | struct pci_dev *dev; |