diff options
Diffstat (limited to 'drivers/xen/events/events_fifo.c')
-rw-r--r-- | drivers/xen/events/events_fifo.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 96109a9972b6..84b4bfb84344 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c | |||
@@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue); | |||
66 | static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; | 66 | static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; |
67 | static unsigned event_array_pages __read_mostly; | 67 | static unsigned event_array_pages __read_mostly; |
68 | 68 | ||
69 | /* | ||
70 | * sync_set_bit() and friends must be unsigned long aligned on non-x86 | ||
71 | * platforms. | ||
72 | */ | ||
73 | #if !defined(CONFIG_X86) && BITS_PER_LONG > 32 | ||
74 | |||
75 | #define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) | ||
76 | #define EVTCHN_FIFO_BIT(b, w) \ | ||
77 | (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b) | ||
78 | |||
79 | #else | ||
80 | |||
69 | #define BM(w) ((unsigned long *)(w)) | 81 | #define BM(w) ((unsigned long *)(w)) |
82 | #define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b | ||
83 | |||
84 | #endif | ||
70 | 85 | ||
71 | static inline event_word_t *event_word_from_port(unsigned port) | 86 | static inline event_word_t *event_word_from_port(unsigned port) |
72 | { | 87 | { |
@@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu) | |||
161 | static void evtchn_fifo_clear_pending(unsigned port) | 176 | static void evtchn_fifo_clear_pending(unsigned port) |
162 | { | 177 | { |
163 | event_word_t *word = event_word_from_port(port); | 178 | event_word_t *word = event_word_from_port(port); |
164 | sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word)); | 179 | sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
165 | } | 180 | } |
166 | 181 | ||
167 | static void evtchn_fifo_set_pending(unsigned port) | 182 | static void evtchn_fifo_set_pending(unsigned port) |
168 | { | 183 | { |
169 | event_word_t *word = event_word_from_port(port); | 184 | event_word_t *word = event_word_from_port(port); |
170 | sync_set_bit(EVTCHN_FIFO_PENDING, BM(word)); | 185 | sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
171 | } | 186 | } |
172 | 187 | ||
173 | static bool evtchn_fifo_is_pending(unsigned port) | 188 | static bool evtchn_fifo_is_pending(unsigned port) |
174 | { | 189 | { |
175 | event_word_t *word = event_word_from_port(port); | 190 | event_word_t *word = event_word_from_port(port); |
176 | return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)); | 191 | return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
177 | } | 192 | } |
178 | 193 | ||
179 | static bool evtchn_fifo_test_and_set_mask(unsigned port) | 194 | static bool evtchn_fifo_test_and_set_mask(unsigned port) |
180 | { | 195 | { |
181 | event_word_t *word = event_word_from_port(port); | 196 | event_word_t *word = event_word_from_port(port); |
182 | return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word)); | 197 | return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); |
183 | } | 198 | } |
184 | 199 | ||
185 | static void evtchn_fifo_mask(unsigned port) | 200 | static void evtchn_fifo_mask(unsigned port) |
186 | { | 201 | { |
187 | event_word_t *word = event_word_from_port(port); | 202 | event_word_t *word = event_word_from_port(port); |
188 | sync_set_bit(EVTCHN_FIFO_MASKED, BM(word)); | 203 | sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); |
189 | } | 204 | } |
190 | 205 | ||
206 | static bool evtchn_fifo_is_masked(unsigned port) | ||
207 | { | ||
208 | event_word_t *word = event_word_from_port(port); | ||
209 | return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); | ||
210 | } | ||
191 | /* | 211 | /* |
192 | * Clear MASKED, spinning if BUSY is set. | 212 | * Clear MASKED, spinning if BUSY is set. |
193 | */ | 213 | */ |
@@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port) | |||
211 | BUG_ON(!irqs_disabled()); | 231 | BUG_ON(!irqs_disabled()); |
212 | 232 | ||
213 | clear_masked(word); | 233 | clear_masked(word); |
214 | if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) { | 234 | if (evtchn_fifo_is_pending(port)) { |
215 | struct evtchn_unmask unmask = { .port = port }; | 235 | struct evtchn_unmask unmask = { .port = port }; |
216 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | 236 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); |
217 | } | 237 | } |
@@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port) | |||
243 | 263 | ||
244 | static void consume_one_event(unsigned cpu, | 264 | static void consume_one_event(unsigned cpu, |
245 | struct evtchn_fifo_control_block *control_block, | 265 | struct evtchn_fifo_control_block *control_block, |
246 | unsigned priority, uint32_t *ready) | 266 | unsigned priority, unsigned long *ready) |
247 | { | 267 | { |
248 | struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); | 268 | struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); |
249 | uint32_t head; | 269 | uint32_t head; |
@@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu, | |||
273 | * copy of the ready word. | 293 | * copy of the ready word. |
274 | */ | 294 | */ |
275 | if (head == 0) | 295 | if (head == 0) |
276 | clear_bit(priority, BM(ready)); | 296 | clear_bit(priority, ready); |
277 | 297 | ||
278 | if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)) | 298 | if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) |
279 | && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word))) | ||
280 | handle_irq_for_port(port); | 299 | handle_irq_for_port(port); |
281 | 300 | ||
282 | q->head[priority] = head; | 301 | q->head[priority] = head; |
@@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu, | |||
285 | static void evtchn_fifo_handle_events(unsigned cpu) | 304 | static void evtchn_fifo_handle_events(unsigned cpu) |
286 | { | 305 | { |
287 | struct evtchn_fifo_control_block *control_block; | 306 | struct evtchn_fifo_control_block *control_block; |
288 | uint32_t ready; | 307 | unsigned long ready; |
289 | unsigned q; | 308 | unsigned q; |
290 | 309 | ||
291 | control_block = per_cpu(cpu_control_block, cpu); | 310 | control_block = per_cpu(cpu_control_block, cpu); |