diff options
author | David Vrabel <david.vrabel@citrix.com> | 2013-03-14 08:49:19 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2014-01-06 10:07:43 -0500 |
commit | ab9a1cca3d172876ae9d5edb63abce7986045597 (patch) | |
tree | 1ae3ed8c8f54b7e50abf9336643c7f8110eca880 /drivers/xen/events | |
parent | 9a489f45a155fe96b9b55fbbef2b757ef7737cfc (diff) |
xen/events: add struct evtchn_ops for the low-level port operations
evtchn_ops contains the low-level operations that access the shared
data structures. This allows alternate ABIs to be supported.
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Diffstat (limited to 'drivers/xen/events')
-rw-r--r-- | drivers/xen/events/events_2l.c | 33 | ||||
-rw-r--r-- | drivers/xen/events/events_base.c | 4 | ||||
-rw-r--r-- | drivers/xen/events/events_internal.h | 63 |
3 files changed, 84 insertions, 16 deletions
diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c index a77e98d025fa..e55677cca745 100644 --- a/drivers/xen/events/events_2l.c +++ b/drivers/xen/events/events_2l.c | |||
@@ -41,43 +41,43 @@ | |||
41 | static DEFINE_PER_CPU(xen_ulong_t [NR_EVENT_CHANNELS/BITS_PER_EVTCHN_WORD], | 41 | static DEFINE_PER_CPU(xen_ulong_t [NR_EVENT_CHANNELS/BITS_PER_EVTCHN_WORD], |
42 | cpu_evtchn_mask); | 42 | cpu_evtchn_mask); |
43 | 43 | ||
44 | void xen_evtchn_port_bind_to_cpu(struct irq_info *info, int cpu) | 44 | static void evtchn_2l_bind_to_cpu(struct irq_info *info, unsigned cpu) |
45 | { | 45 | { |
46 | clear_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, info->cpu))); | 46 | clear_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, info->cpu))); |
47 | set_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, cpu))); | 47 | set_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, cpu))); |
48 | } | 48 | } |
49 | 49 | ||
50 | void clear_evtchn(int port) | 50 | static void evtchn_2l_clear_pending(unsigned port) |
51 | { | 51 | { |
52 | struct shared_info *s = HYPERVISOR_shared_info; | 52 | struct shared_info *s = HYPERVISOR_shared_info; |
53 | sync_clear_bit(port, BM(&s->evtchn_pending[0])); | 53 | sync_clear_bit(port, BM(&s->evtchn_pending[0])); |
54 | } | 54 | } |
55 | 55 | ||
56 | void set_evtchn(int port) | 56 | static void evtchn_2l_set_pending(unsigned port) |
57 | { | 57 | { |
58 | struct shared_info *s = HYPERVISOR_shared_info; | 58 | struct shared_info *s = HYPERVISOR_shared_info; |
59 | sync_set_bit(port, BM(&s->evtchn_pending[0])); | 59 | sync_set_bit(port, BM(&s->evtchn_pending[0])); |
60 | } | 60 | } |
61 | 61 | ||
62 | int test_evtchn(int port) | 62 | static bool evtchn_2l_is_pending(unsigned port) |
63 | { | 63 | { |
64 | struct shared_info *s = HYPERVISOR_shared_info; | 64 | struct shared_info *s = HYPERVISOR_shared_info; |
65 | return sync_test_bit(port, BM(&s->evtchn_pending[0])); | 65 | return sync_test_bit(port, BM(&s->evtchn_pending[0])); |
66 | } | 66 | } |
67 | 67 | ||
68 | int test_and_set_mask(int port) | 68 | static bool evtchn_2l_test_and_set_mask(unsigned port) |
69 | { | 69 | { |
70 | struct shared_info *s = HYPERVISOR_shared_info; | 70 | struct shared_info *s = HYPERVISOR_shared_info; |
71 | return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); | 71 | return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); |
72 | } | 72 | } |
73 | 73 | ||
74 | void mask_evtchn(int port) | 74 | static void evtchn_2l_mask(unsigned port) |
75 | { | 75 | { |
76 | struct shared_info *s = HYPERVISOR_shared_info; | 76 | struct shared_info *s = HYPERVISOR_shared_info; |
77 | sync_set_bit(port, BM(&s->evtchn_mask[0])); | 77 | sync_set_bit(port, BM(&s->evtchn_mask[0])); |
78 | } | 78 | } |
79 | 79 | ||
80 | void unmask_evtchn(int port) | 80 | static void evtchn_2l_unmask(unsigned port) |
81 | { | 81 | { |
82 | struct shared_info *s = HYPERVISOR_shared_info; | 82 | struct shared_info *s = HYPERVISOR_shared_info; |
83 | unsigned int cpu = get_cpu(); | 83 | unsigned int cpu = get_cpu(); |
@@ -153,7 +153,7 @@ static inline xen_ulong_t active_evtchns(unsigned int cpu, | |||
153 | * a bitset of words which contain pending event bits. The second | 153 | * a bitset of words which contain pending event bits. The second |
154 | * level is a bitset of pending events themselves. | 154 | * level is a bitset of pending events themselves. |
155 | */ | 155 | */ |
156 | void xen_evtchn_handle_events(int cpu) | 156 | static void evtchn_2l_handle_events(unsigned cpu) |
157 | { | 157 | { |
158 | int irq; | 158 | int irq; |
159 | xen_ulong_t pending_words; | 159 | xen_ulong_t pending_words; |
@@ -346,3 +346,20 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) | |||
346 | 346 | ||
347 | return IRQ_HANDLED; | 347 | return IRQ_HANDLED; |
348 | } | 348 | } |
349 | |||
350 | static const struct evtchn_ops evtchn_ops_2l = { | ||
351 | .bind_to_cpu = evtchn_2l_bind_to_cpu, | ||
352 | .clear_pending = evtchn_2l_clear_pending, | ||
353 | .set_pending = evtchn_2l_set_pending, | ||
354 | .is_pending = evtchn_2l_is_pending, | ||
355 | .test_and_set_mask = evtchn_2l_test_and_set_mask, | ||
356 | .mask = evtchn_2l_mask, | ||
357 | .unmask = evtchn_2l_unmask, | ||
358 | .handle_events = evtchn_2l_handle_events, | ||
359 | }; | ||
360 | |||
361 | void __init xen_evtchn_2l_init(void) | ||
362 | { | ||
363 | pr_info("Using 2-level ABI\n"); | ||
364 | evtchn_ops = &evtchn_ops_2l; | ||
365 | } | ||
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 8771b740e30f..7c7b744cd13d 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
@@ -61,6 +61,8 @@ | |||
61 | 61 | ||
62 | #include "events_internal.h" | 62 | #include "events_internal.h" |
63 | 63 | ||
64 | const struct evtchn_ops *evtchn_ops; | ||
65 | |||
64 | /* | 66 | /* |
65 | * This lock protects updates to the following mapping and reference-count | 67 | * This lock protects updates to the following mapping and reference-count |
66 | * arrays. The lock does not need to be acquired to read the mapping tables. | 68 | * arrays. The lock does not need to be acquired to read the mapping tables. |
@@ -1523,6 +1525,8 @@ void __init xen_init_IRQ(void) | |||
1523 | { | 1525 | { |
1524 | int i; | 1526 | int i; |
1525 | 1527 | ||
1528 | xen_evtchn_2l_init(); | ||
1529 | |||
1526 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), | 1530 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), |
1527 | GFP_KERNEL); | 1531 | GFP_KERNEL); |
1528 | BUG_ON(!evtchn_to_irq); | 1532 | BUG_ON(!evtchn_to_irq); |
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index 79ac70bbbd26..ba8142f0c635 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h | |||
@@ -54,21 +54,68 @@ struct irq_info { | |||
54 | #define PIRQ_NEEDS_EOI (1 << 0) | 54 | #define PIRQ_NEEDS_EOI (1 << 0) |
55 | #define PIRQ_SHAREABLE (1 << 1) | 55 | #define PIRQ_SHAREABLE (1 << 1) |
56 | 56 | ||
57 | struct evtchn_ops { | ||
58 | void (*bind_to_cpu)(struct irq_info *info, unsigned cpu); | ||
59 | |||
60 | void (*clear_pending)(unsigned port); | ||
61 | void (*set_pending)(unsigned port); | ||
62 | bool (*is_pending)(unsigned port); | ||
63 | bool (*test_and_set_mask)(unsigned port); | ||
64 | void (*mask)(unsigned port); | ||
65 | void (*unmask)(unsigned port); | ||
66 | |||
67 | void (*handle_events)(unsigned cpu); | ||
68 | }; | ||
69 | |||
70 | extern const struct evtchn_ops *evtchn_ops; | ||
71 | |||
57 | extern int *evtchn_to_irq; | 72 | extern int *evtchn_to_irq; |
58 | 73 | ||
59 | struct irq_info *info_for_irq(unsigned irq); | 74 | struct irq_info *info_for_irq(unsigned irq); |
60 | unsigned cpu_from_irq(unsigned irq); | 75 | unsigned cpu_from_irq(unsigned irq); |
61 | unsigned cpu_from_evtchn(unsigned int evtchn); | 76 | unsigned cpu_from_evtchn(unsigned int evtchn); |
62 | 77 | ||
63 | void xen_evtchn_port_bind_to_cpu(struct irq_info *info, int cpu); | 78 | static inline void xen_evtchn_port_bind_to_cpu(struct irq_info *info, |
79 | unsigned cpu) | ||
80 | { | ||
81 | evtchn_ops->bind_to_cpu(info, cpu); | ||
82 | } | ||
83 | |||
84 | static inline void clear_evtchn(unsigned port) | ||
85 | { | ||
86 | evtchn_ops->clear_pending(port); | ||
87 | } | ||
88 | |||
89 | static inline void set_evtchn(unsigned port) | ||
90 | { | ||
91 | evtchn_ops->set_pending(port); | ||
92 | } | ||
93 | |||
94 | static inline bool test_evtchn(unsigned port) | ||
95 | { | ||
96 | return evtchn_ops->is_pending(port); | ||
97 | } | ||
98 | |||
99 | static inline bool test_and_set_mask(unsigned port) | ||
100 | { | ||
101 | return evtchn_ops->test_and_set_mask(port); | ||
102 | } | ||
103 | |||
104 | static inline void mask_evtchn(unsigned port) | ||
105 | { | ||
106 | return evtchn_ops->mask(port); | ||
107 | } | ||
108 | |||
109 | static inline void unmask_evtchn(unsigned port) | ||
110 | { | ||
111 | return evtchn_ops->unmask(port); | ||
112 | } | ||
64 | 113 | ||
65 | void clear_evtchn(int port); | 114 | static inline void xen_evtchn_handle_events(unsigned cpu) |
66 | void set_evtchn(int port); | 115 | { |
67 | int test_evtchn(int port); | 116 | return evtchn_ops->handle_events(cpu); |
68 | int test_and_set_mask(int port); | 117 | } |
69 | void mask_evtchn(int port); | ||
70 | void unmask_evtchn(int port); | ||
71 | 118 | ||
72 | void xen_evtchn_handle_events(int cpu); | 119 | void xen_evtchn_2l_init(void); |
73 | 120 | ||
74 | #endif /* #ifndef __EVENTS_INTERNAL_H__ */ | 121 | #endif /* #ifndef __EVENTS_INTERNAL_H__ */ |