aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/ibmasm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/ibmasm')
-rw-r--r--drivers/misc/ibmasm/event.c18
-rw-r--r--drivers/misc/ibmasm/ibmasm.h2
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c34
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
38static void wake_up_event_readers(struct service_processor *sp) 38static 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
122void ibmasm_cancel_next_event(struct event_reader *reader)
123{
124 reader->cancelled = 1;
125 wake_up_interruptible(&reader->wait);
126}
127
119void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader) 128void 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
165void ibmasm_event_buffer_exit(struct service_processor *sp) 172void 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
110struct event_reader { 110struct 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
185extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); 186extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
186extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); 187extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
187extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); 188extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
189extern void ibmasm_cancel_next_event(struct event_reader *reader);
188 190
189/* heartbeat - from SP to OS */ 191/* heartbeat - from SP to OS */
190extern void ibmasm_register_panic_notifier(void); 192extern 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; 429out:
430 event_data->active = 0;
431 return ret;
414} 432}
415 433
416static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 434static 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