diff options
author | Max Asbock <masbock@us.ibm.com> | 2005-06-21 20:16:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 22:07:34 -0400 |
commit | b8acb808468a88a188d7c5aba3681c583a5785f9 (patch) | |
tree | 7a4e5367e05cc52bc8008baaa8c35ed05989ec60 /drivers/misc/ibmasm | |
parent | f5ccc842318efcd7c05dee3203dfdbbafae47bd6 (diff) |
[PATCH] ibmasm driver: correctly wake up sleeping threads
Due to my incomplete understanding of the wait_event_interruptible() function
threads waiting for service processor events were not woken up. This patch
fixes that problem.
Signed-off-by: Max Asbock <masbock@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/misc/ibmasm')
-rw-r--r-- | drivers/misc/ibmasm/event.c | 18 | ||||
-rw-r--r-- | drivers/misc/ibmasm/ibmasm.h | 2 | ||||
-rw-r--r-- | drivers/misc/ibmasm/ibmasmfs.c | 34 |
3 files changed, 40 insertions, 14 deletions
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c index e100f34f1587..fe1e819235a4 100644 --- a/drivers/misc/ibmasm/event.c +++ b/drivers/misc/ibmasm/event.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "ibmasm.h" | 25 | #include "ibmasm.h" |
26 | #include "lowlevel.h" | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * ASM service processor event handling routines. | 29 | * ASM service processor event handling routines. |
@@ -34,7 +35,6 @@ | |||
34 | * circular buffer. | 35 | * circular buffer. |
35 | */ | 36 | */ |
36 | 37 | ||
37 | |||
38 | static void wake_up_event_readers(struct service_processor *sp) | 38 | static void wake_up_event_readers(struct service_processor *sp) |
39 | { | 39 | { |
40 | struct event_reader *reader; | 40 | struct event_reader *reader; |
@@ -63,7 +63,7 @@ void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int | |||
63 | spin_lock_irqsave(&sp->lock, flags); | 63 | spin_lock_irqsave(&sp->lock, flags); |
64 | /* copy the event into the next slot in the circular buffer */ | 64 | /* copy the event into the next slot in the circular buffer */ |
65 | event = &buffer->events[buffer->next_index]; | 65 | event = &buffer->events[buffer->next_index]; |
66 | memcpy(event->data, data, data_size); | 66 | memcpy_fromio(event->data, data, data_size); |
67 | event->data_size = data_size; | 67 | event->data_size = data_size; |
68 | event->serial_number = buffer->next_serial_number; | 68 | event->serial_number = buffer->next_serial_number; |
69 | 69 | ||
@@ -93,7 +93,10 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea | |||
93 | unsigned int index; | 93 | unsigned int index; |
94 | unsigned long flags; | 94 | unsigned long flags; |
95 | 95 | ||
96 | if (wait_event_interruptible(reader->wait, event_available(buffer, reader))) | 96 | reader->cancelled = 0; |
97 | |||
98 | if (wait_event_interruptible(reader->wait, | ||
99 | event_available(buffer, reader) || reader->cancelled)) | ||
97 | return -ERESTARTSYS; | 100 | return -ERESTARTSYS; |
98 | 101 | ||
99 | if (!event_available(buffer, reader)) | 102 | if (!event_available(buffer, reader)) |
@@ -116,6 +119,12 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea | |||
116 | return event->data_size; | 119 | return event->data_size; |
117 | } | 120 | } |
118 | 121 | ||
122 | void ibmasm_cancel_next_event(struct event_reader *reader) | ||
123 | { | ||
124 | reader->cancelled = 1; | ||
125 | wake_up_interruptible(&reader->wait); | ||
126 | } | ||
127 | |||
119 | void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader) | 128 | void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader) |
120 | { | 129 | { |
121 | unsigned long flags; | 130 | unsigned long flags; |
@@ -131,8 +140,6 @@ void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_r | |||
131 | { | 140 | { |
132 | unsigned long flags; | 141 | unsigned long flags; |
133 | 142 | ||
134 | wake_up_interruptible(&reader->wait); | ||
135 | |||
136 | spin_lock_irqsave(&sp->lock, flags); | 143 | spin_lock_irqsave(&sp->lock, flags); |
137 | list_del(&reader->node); | 144 | list_del(&reader->node); |
138 | spin_unlock_irqrestore(&sp->lock, flags); | 145 | spin_unlock_irqrestore(&sp->lock, flags); |
@@ -164,6 +171,5 @@ int ibmasm_event_buffer_init(struct service_processor *sp) | |||
164 | 171 | ||
165 | void ibmasm_event_buffer_exit(struct service_processor *sp) | 172 | void ibmasm_event_buffer_exit(struct service_processor *sp) |
166 | { | 173 | { |
167 | wake_up_event_readers(sp); | ||
168 | kfree(sp->event_buffer); | 174 | kfree(sp->event_buffer); |
169 | } | 175 | } |
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index 1e83406382e7..35c4def5af18 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h | |||
@@ -108,6 +108,7 @@ struct event_buffer { | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct event_reader { | 110 | struct event_reader { |
111 | int cancelled; | ||
111 | unsigned int next_serial_number; | 112 | unsigned int next_serial_number; |
112 | wait_queue_head_t wait; | 113 | wait_queue_head_t wait; |
113 | struct list_head node; | 114 | struct list_head node; |
@@ -185,6 +186,7 @@ extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsi | |||
185 | extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); | 186 | extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); |
186 | extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); | 187 | extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); |
187 | extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); | 188 | extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); |
189 | extern void ibmasm_cancel_next_event(struct event_reader *reader); | ||
188 | 190 | ||
189 | /* heartbeat - from SP to OS */ | 191 | /* heartbeat - from SP to OS */ |
190 | extern void ibmasm_register_panic_notifier(void); | 192 | extern void ibmasm_register_panic_notifier(void); |
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 866e867e68f2..c87ef7d82b70 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c | |||
@@ -374,6 +374,7 @@ static int event_file_open(struct inode *inode, struct file *file) | |||
374 | ibmasm_event_reader_register(sp, &event_data->reader); | 374 | ibmasm_event_reader_register(sp, &event_data->reader); |
375 | 375 | ||
376 | event_data->sp = sp; | 376 | event_data->sp = sp; |
377 | event_data->active = 0; | ||
377 | file->private_data = event_data; | 378 | file->private_data = event_data; |
378 | return 0; | 379 | return 0; |
379 | } | 380 | } |
@@ -391,7 +392,9 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count | |||
391 | { | 392 | { |
392 | struct ibmasmfs_event_data *event_data = file->private_data; | 393 | struct ibmasmfs_event_data *event_data = file->private_data; |
393 | struct event_reader *reader = &event_data->reader; | 394 | struct event_reader *reader = &event_data->reader; |
395 | struct service_processor *sp = event_data->sp; | ||
394 | int ret; | 396 | int ret; |
397 | unsigned long flags; | ||
395 | 398 | ||
396 | if (*offset < 0) | 399 | if (*offset < 0) |
397 | return -EINVAL; | 400 | return -EINVAL; |
@@ -400,17 +403,32 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count | |||
400 | if (*offset != 0) | 403 | if (*offset != 0) |
401 | return 0; | 404 | return 0; |
402 | 405 | ||
403 | ret = ibmasm_get_next_event(event_data->sp, reader); | 406 | spin_lock_irqsave(&sp->lock, flags); |
407 | if (event_data->active) { | ||
408 | spin_unlock_irqrestore(&sp->lock, flags); | ||
409 | return -EBUSY; | ||
410 | } | ||
411 | event_data->active = 1; | ||
412 | spin_unlock_irqrestore(&sp->lock, flags); | ||
413 | |||
414 | ret = ibmasm_get_next_event(sp, reader); | ||
404 | if (ret <= 0) | 415 | if (ret <= 0) |
405 | return ret; | 416 | goto out; |
406 | 417 | ||
407 | if (count < reader->data_size) | 418 | if (count < reader->data_size) { |
408 | return -EINVAL; | 419 | ret = -EINVAL; |
420 | goto out; | ||
421 | } | ||
409 | 422 | ||
410 | if (copy_to_user(buf, reader->data, reader->data_size)) | 423 | if (copy_to_user(buf, reader->data, reader->data_size)) { |
411 | return -EFAULT; | 424 | ret = -EFAULT; |
425 | goto out; | ||
426 | } | ||
427 | ret = reader->data_size; | ||
412 | 428 | ||
413 | return reader->data_size; | 429 | out: |
430 | event_data->active = 0; | ||
431 | return ret; | ||
414 | } | 432 | } |
415 | 433 | ||
416 | static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) | 434 | static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) |
@@ -424,7 +442,7 @@ static ssize_t event_file_write(struct file *file, const char __user *buf, size_ | |||
424 | if (*offset != 0) | 442 | if (*offset != 0) |
425 | return 0; | 443 | return 0; |
426 | 444 | ||
427 | wake_up_interruptible(&event_data->reader.wait); | 445 | ibmasm_cancel_next_event(&event_data->reader); |
428 | return 0; | 446 | return 0; |
429 | } | 447 | } |
430 | 448 | ||