aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 212a5c871bf4..7a55b292bf39 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -873,11 +873,32 @@ static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
873 return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); 873 return err ? : bind_evtchn_to_irq(bind_interdomain.local_port);
874} 874}
875 875
876static int find_virq(unsigned int virq, unsigned int cpu)
877{
878 struct evtchn_status status;
879 int port, rc = -ENOENT;
880
881 memset(&status, 0, sizeof(status));
882 for (port = 0; port <= NR_EVENT_CHANNELS; port++) {
883 status.dom = DOMID_SELF;
884 status.port = port;
885 rc = HYPERVISOR_event_channel_op(EVTCHNOP_status, &status);
886 if (rc < 0)
887 continue;
888 if (status.status != EVTCHNSTAT_virq)
889 continue;
890 if (status.u.virq == virq && status.vcpu == cpu) {
891 rc = port;
892 break;
893 }
894 }
895 return rc;
896}
876 897
877int bind_virq_to_irq(unsigned int virq, unsigned int cpu) 898int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
878{ 899{
879 struct evtchn_bind_virq bind_virq; 900 struct evtchn_bind_virq bind_virq;
880 int evtchn, irq; 901 int evtchn, irq, ret;
881 902
882 mutex_lock(&irq_mapping_update_lock); 903 mutex_lock(&irq_mapping_update_lock);
883 904
@@ -893,10 +914,16 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
893 914
894 bind_virq.virq = virq; 915 bind_virq.virq = virq;
895 bind_virq.vcpu = cpu; 916 bind_virq.vcpu = cpu;
896 if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, 917 ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
897 &bind_virq) != 0) 918 &bind_virq);
898 BUG(); 919 if (ret == 0)
899 evtchn = bind_virq.port; 920 evtchn = bind_virq.port;
921 else {
922 if (ret == -EEXIST)
923 ret = find_virq(virq, cpu);
924 BUG_ON(ret < 0);
925 evtchn = ret;
926 }
900 927
901 xen_irq_info_virq_init(cpu, irq, evtchn, virq); 928 xen_irq_info_virq_init(cpu, irq, evtchn, virq);
902 929