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); |
