diff options
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r-- | drivers/xen/events.c | 37 |
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 | ||
876 | static 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 | ||
877 | int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | 898 | int 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 | ||