From cbd4db21b013f4570cc2866fe0c04e72640c9d96 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 25 Aug 2011 18:30:48 +0200 Subject: [PATCH] --- yaml --- r: 264443 b: refs/heads/master c: 62cc5fc7b2e0218144e162afb8191db9b924b5e6 h: refs/heads/master i: 264441: f089d46d3ab3a3f113fdc47b770909d04a8195df 264439: afde7340be53420aa80be5d33433fe9a62190fdb v: v3 --- [refs] | 2 +- trunk/drivers/xen/events.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 6b3aac4cc994..31055237b18f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c4c303c7c5679b4b368e12f41124aee29c325b76 +refs/heads/master: 62cc5fc7b2e0218144e162afb8191db9b924b5e6 diff --git a/trunk/drivers/xen/events.c b/trunk/drivers/xen/events.c index 30df85d8fca8..31493e906bbd 100644 --- a/trunk/drivers/xen/events.c +++ b/trunk/drivers/xen/events.c @@ -877,11 +877,32 @@ static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); } +static int find_virq(unsigned int virq, unsigned int cpu) +{ + struct evtchn_status status; + int port, rc = -ENOENT; + + memset(&status, 0, sizeof(status)); + for (port = 0; port <= NR_EVENT_CHANNELS; port++) { + status.dom = DOMID_SELF; + status.port = port; + rc = HYPERVISOR_event_channel_op(EVTCHNOP_status, &status); + if (rc < 0) + continue; + if (status.status != EVTCHNSTAT_virq) + continue; + if (status.u.virq == virq && status.vcpu == cpu) { + rc = port; + break; + } + } + return rc; +} int bind_virq_to_irq(unsigned int virq, unsigned int cpu) { struct evtchn_bind_virq bind_virq; - int evtchn, irq; + int evtchn, irq, ret; spin_lock(&irq_mapping_update_lock); @@ -897,10 +918,16 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) bind_virq.virq = virq; bind_virq.vcpu = cpu; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, - &bind_virq) != 0) - BUG(); - evtchn = bind_virq.port; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + &bind_virq); + if (ret == 0) + evtchn = bind_virq.port; + else { + if (ret == -EEXIST) + ret = find_virq(virq, cpu); + BUG_ON(ret < 0); + evtchn = ret; + } xen_irq_info_virq_init(cpu, irq, evtchn, virq);