summaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index cd504092299..7016a734257 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -582,7 +582,9 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
goto out; /* XXX need refcount? */
}
- if (identity_mapped_irq(gsi)) {
+ /* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore
+ * we are using the !xen_initial_domain() to drop in the function.*/
+ if (identity_mapped_irq(gsi) || !xen_initial_domain()) {
irq = gsi;
irq_to_desc_alloc_node(irq, 0);
dynamic_irq_init(irq);
@@ -593,7 +595,13 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
handle_level_irq, name);
irq_op.irq = irq;
- if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+ irq_op.vector = 0;
+
+ /* Only the privileged domain can do this. For non-priv, the pcifront
+ * driver provides a PCI bus that does the call to do exactly
+ * this in the priv domain. */
+ if (xen_initial_domain() &&
+ HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
dynamic_irq_cleanup(irq);
irq = -ENOSPC;
goto out;
@@ -608,6 +616,26 @@ out:
return irq;
}
+int xen_destroy_irq(int irq)
+{
+ struct irq_desc *desc;
+ int rc = -ENOENT;
+
+ spin_lock(&irq_mapping_update_lock);
+
+ desc = irq_to_desc(irq);
+ if (!desc)
+ goto out;
+
+ irq_info[irq] = mk_unbound_info();
+
+ dynamic_irq_cleanup(irq);
+
+out:
+ spin_unlock(&irq_mapping_update_lock);
+ return rc;
+}
+
int xen_vector_from_irq(unsigned irq)
{
return vector_from_irq(irq);