diff options
-rw-r--r-- | arch/x86/include/asm/xen/pci.h | 7 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 135 | ||||
-rw-r--r-- | drivers/xen/events.c | 13 | ||||
-rw-r--r-- | include/xen/interface/physdev.h | 10 |
4 files changed, 165 insertions, 0 deletions
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index f89a42aff284..2329b3eaf8d3 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h | |||
@@ -13,6 +13,13 @@ static inline int pci_xen_hvm_init(void) | |||
13 | return -1; | 13 | return -1; |
14 | } | 14 | } |
15 | #endif | 15 | #endif |
16 | #if defined(CONFIG_XEN_DOM0) | ||
17 | void __init xen_setup_pirqs(void); | ||
18 | #else | ||
19 | static inline void __init xen_setup_pirqs(void) | ||
20 | { | ||
21 | } | ||
22 | #endif | ||
16 | 23 | ||
17 | #if defined(CONFIG_PCI_MSI) | 24 | #if defined(CONFIG_PCI_MSI) |
18 | #if defined(CONFIG_PCI_XEN) | 25 | #if defined(CONFIG_PCI_XEN) |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index b5bd6420851e..dd0b5fdb27b9 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -257,3 +257,138 @@ int __init pci_xen_hvm_init(void) | |||
257 | #endif | 257 | #endif |
258 | return 0; | 258 | return 0; |
259 | } | 259 | } |
260 | |||
261 | #ifdef CONFIG_XEN_DOM0 | ||
262 | static int xen_register_pirq(u32 gsi, int triggering) | ||
263 | { | ||
264 | int rc, irq; | ||
265 | struct physdev_map_pirq map_irq; | ||
266 | int shareable = 0; | ||
267 | char *name; | ||
268 | |||
269 | if (!xen_pv_domain()) | ||
270 | return -1; | ||
271 | |||
272 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
273 | shareable = 0; | ||
274 | name = "ioapic-edge"; | ||
275 | } else { | ||
276 | shareable = 1; | ||
277 | name = "ioapic-level"; | ||
278 | } | ||
279 | |||
280 | irq = xen_allocate_pirq(gsi, shareable, name); | ||
281 | |||
282 | printk(KERN_DEBUG "xen: --> irq=%d\n", irq); | ||
283 | |||
284 | if (irq < 0) | ||
285 | goto out; | ||
286 | |||
287 | map_irq.domid = DOMID_SELF; | ||
288 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
289 | map_irq.index = gsi; | ||
290 | map_irq.pirq = irq; | ||
291 | |||
292 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
293 | if (rc) { | ||
294 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
295 | return -1; | ||
296 | } | ||
297 | |||
298 | out: | ||
299 | return irq; | ||
300 | } | ||
301 | |||
302 | static int xen_register_gsi(u32 gsi, int triggering, int polarity) | ||
303 | { | ||
304 | int rc, irq; | ||
305 | struct physdev_setup_gsi setup_gsi; | ||
306 | |||
307 | if (!xen_pv_domain()) | ||
308 | return -1; | ||
309 | |||
310 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
311 | gsi, triggering, polarity); | ||
312 | |||
313 | irq = xen_register_pirq(gsi, triggering); | ||
314 | |||
315 | setup_gsi.gsi = gsi; | ||
316 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
317 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
318 | |||
319 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
320 | if (rc == -EEXIST) | ||
321 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
322 | else if (rc) { | ||
323 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
324 | gsi, rc); | ||
325 | } | ||
326 | |||
327 | return irq; | ||
328 | } | ||
329 | |||
330 | static __init void xen_setup_acpi_sci(void) | ||
331 | { | ||
332 | int rc; | ||
333 | int trigger, polarity; | ||
334 | int gsi = acpi_sci_override_gsi; | ||
335 | |||
336 | if (!gsi) | ||
337 | return; | ||
338 | |||
339 | rc = acpi_get_override_irq(gsi, &trigger, &polarity); | ||
340 | if (rc) { | ||
341 | printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi" | ||
342 | " sci, rc=%d\n", rc); | ||
343 | return; | ||
344 | } | ||
345 | trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||
346 | polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||
347 | |||
348 | printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " | ||
349 | "polarity=%d\n", gsi, trigger, polarity); | ||
350 | |||
351 | gsi = xen_register_gsi(gsi, trigger, polarity); | ||
352 | printk(KERN_INFO "xen: acpi sci %d\n", gsi); | ||
353 | |||
354 | return; | ||
355 | } | ||
356 | |||
357 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
358 | int trigger, int polarity) | ||
359 | { | ||
360 | return xen_register_gsi(gsi, trigger, polarity); | ||
361 | } | ||
362 | |||
363 | static int __init pci_xen_initial_domain(void) | ||
364 | { | ||
365 | xen_setup_acpi_sci(); | ||
366 | __acpi_register_gsi = acpi_register_gsi_xen; | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | void __init xen_setup_pirqs(void) | ||
372 | { | ||
373 | int irq; | ||
374 | |||
375 | pci_xen_initial_domain(); | ||
376 | |||
377 | if (0 == nr_ioapics) { | ||
378 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) | ||
379 | xen_allocate_pirq(irq, 0, "xt-pic"); | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | /* Pre-allocate legacy irqs */ | ||
384 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { | ||
385 | int trigger, polarity; | ||
386 | |||
387 | if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) | ||
388 | continue; | ||
389 | |||
390 | xen_register_pirq(irq, | ||
391 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); | ||
392 | } | ||
393 | } | ||
394 | #endif | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index efa683ee8840..c649ac0aaeef 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -681,6 +681,8 @@ out: | |||
681 | int xen_destroy_irq(int irq) | 681 | int xen_destroy_irq(int irq) |
682 | { | 682 | { |
683 | struct irq_desc *desc; | 683 | struct irq_desc *desc; |
684 | struct physdev_unmap_pirq unmap_irq; | ||
685 | struct irq_info *info = info_for_irq(irq); | ||
684 | int rc = -ENOENT; | 686 | int rc = -ENOENT; |
685 | 687 | ||
686 | spin_lock(&irq_mapping_update_lock); | 688 | spin_lock(&irq_mapping_update_lock); |
@@ -689,6 +691,15 @@ int xen_destroy_irq(int irq) | |||
689 | if (!desc) | 691 | if (!desc) |
690 | goto out; | 692 | goto out; |
691 | 693 | ||
694 | if (xen_initial_domain()) { | ||
695 | unmap_irq.pirq = info->u.pirq.gsi; | ||
696 | unmap_irq.domid = DOMID_SELF; | ||
697 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | ||
698 | if (rc) { | ||
699 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | ||
700 | goto out; | ||
701 | } | ||
702 | } | ||
692 | irq_info[irq] = mk_unbound_info(); | 703 | irq_info[irq] = mk_unbound_info(); |
693 | 704 | ||
694 | irq_free_desc(irq); | 705 | irq_free_desc(irq); |
@@ -1425,5 +1436,7 @@ void __init xen_init_IRQ(void) | |||
1425 | pci_xen_hvm_init(); | 1436 | pci_xen_hvm_init(); |
1426 | } else { | 1437 | } else { |
1427 | irq_ctx_init(smp_processor_id()); | 1438 | irq_ctx_init(smp_processor_id()); |
1439 | if (xen_initial_domain()) | ||
1440 | xen_setup_pirqs(); | ||
1428 | } | 1441 | } |
1429 | } | 1442 | } |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 69a72b96a6cb..a85d76c2e360 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
@@ -151,6 +151,16 @@ struct physdev_op { | |||
151 | } u; | 151 | } u; |
152 | }; | 152 | }; |
153 | 153 | ||
154 | #define PHYSDEVOP_setup_gsi 21 | ||
155 | struct physdev_setup_gsi { | ||
156 | int gsi; | ||
157 | /* IN */ | ||
158 | uint8_t triggering; | ||
159 | /* IN */ | ||
160 | uint8_t polarity; | ||
161 | /* IN */ | ||
162 | }; | ||
163 | |||
154 | #define PHYSDEVOP_get_nr_pirqs 22 | 164 | #define PHYSDEVOP_get_nr_pirqs 22 |
155 | struct physdev_nr_pirqs { | 165 | struct physdev_nr_pirqs { |
156 | /* OUT */ | 166 | /* OUT */ |