diff options
Diffstat (limited to 'drivers/xen/events/events_base.c')
-rw-r--r-- | drivers/xen/events/events_base.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index b8cfea7812d6..41309d38f78c 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -411,7 +411,7 @@ static evtchn_port_t evtchn_from_irq(unsigned int irq) { const struct irq_info *info = NULL; - if (likely(irq < nr_irqs)) + if (likely(irq < irq_get_nr_irqs())) info = info_for_irq(irq); if (!info) return 0; @@ -722,12 +722,6 @@ static struct irq_info *xen_irq_init(unsigned int irq) INIT_RCU_WORK(&info->rwork, delayed_free_irq); set_info_for_irq(irq, info); - /* - * Interrupt affinity setting can be immediate. No point - * in delaying it until an interrupt is handled. - */ - irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); - INIT_LIST_HEAD(&info->eoi_list); list_add_tail(&info->list, &xen_irq_list_head); } @@ -923,8 +917,8 @@ static void shutdown_pirq(struct irq_data *data) return; do_mask(info, EVT_MASK_REASON_EXPLICIT); - xen_evtchn_close(evtchn); xen_irq_info_cleanup(info); + xen_evtchn_close(evtchn); } static void enable_pirq(struct irq_data *data) @@ -956,6 +950,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi); static void __unbind_from_irq(struct irq_info *info, unsigned int irq) { evtchn_port_t evtchn; + bool close_evtchn = false; if (!info) { xen_irq_free_desc(irq); @@ -975,7 +970,7 @@ static void __unbind_from_irq(struct irq_info *info, unsigned int irq) struct xenbus_device *dev; if (!info->is_static) - xen_evtchn_close(evtchn); + close_evtchn = true; switch (info->type) { case IRQT_VIRQ: @@ -995,6 +990,9 @@ static void __unbind_from_irq(struct irq_info *info, unsigned int irq) } xen_irq_info_cleanup(info); + + if (close_evtchn) + xen_evtchn_close(evtchn); } xen_free_irq(info); @@ -1186,7 +1184,7 @@ int xen_pirq_from_irq(unsigned irq) EXPORT_SYMBOL_GPL(xen_pirq_from_irq); static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip, - struct xenbus_device *dev) + struct xenbus_device *dev, bool shared) { int ret = -ENOMEM; struct irq_info *info; @@ -1220,7 +1218,8 @@ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip, */ bind_evtchn_to_cpu(info, 0, false); } else if (!WARN_ON(info->type != IRQT_EVTCHN)) { - info->refcnt++; + if (shared && !WARN_ON(info->refcnt < 0)) + info->refcnt++; } ret = info->irq; @@ -1233,13 +1232,13 @@ out: int bind_evtchn_to_irq(evtchn_port_t evtchn) { - return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL); + return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL, false); } EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn) { - return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL); + return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL, false); } EXPORT_SYMBOL_GPL(bind_evtchn_to_irq_lateeoi); @@ -1291,7 +1290,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev, evtchn_port_t remote_port, - struct irq_chip *chip) + struct irq_chip *chip, + bool shared) { struct evtchn_bind_interdomain bind_interdomain; int err; @@ -1303,14 +1303,14 @@ static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev, &bind_interdomain); return err ? : bind_evtchn_to_irq_chip(bind_interdomain.local_port, - chip, dev); + chip, dev, shared); } int bind_interdomain_evtchn_to_irq_lateeoi(struct xenbus_device *dev, evtchn_port_t remote_port) { return bind_interdomain_evtchn_to_irq_chip(dev, remote_port, - &xen_lateeoi_chip); + &xen_lateeoi_chip, false); } EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irq_lateeoi); @@ -1426,7 +1426,8 @@ static int bind_evtchn_to_irqhandler_chip(evtchn_port_t evtchn, { int irq, retval; - irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL); + irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL, + irqflags & IRQF_SHARED); if (irq < 0) return irq; retval = request_irq(irq, handler, irqflags, devname, dev_id); @@ -1467,7 +1468,8 @@ static int bind_interdomain_evtchn_to_irqhandler_chip( { int irq, retval; - irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip); + irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip, + irqflags & IRQF_SHARED); if (irq < 0) return irq; @@ -2216,7 +2218,7 @@ static __init void xen_alloc_callback_vector(void) return; pr_info("Xen HVM callback vector for event delivery is enabled\n"); - alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_xen_hvm_callback); + sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_xen_hvm_callback); } #else void xen_setup_callback_vector(void) {} |