0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/sched.h>
0012 #include <linux/slab.h>
0013 #include "ibmasm.h"
0014 #include "lowlevel.h"
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 static void wake_up_event_readers(struct service_processor *sp)
0027 {
0028 struct event_reader *reader;
0029
0030 list_for_each_entry(reader, &sp->event_buffer->readers, node)
0031 wake_up_interruptible(&reader->wait);
0032 }
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size)
0044 {
0045 struct event_buffer *buffer = sp->event_buffer;
0046 struct ibmasm_event *event;
0047 unsigned long flags;
0048
0049 data_size = min(data_size, IBMASM_EVENT_MAX_SIZE);
0050
0051 spin_lock_irqsave(&sp->lock, flags);
0052
0053 event = &buffer->events[buffer->next_index];
0054 memcpy_fromio(event->data, data, data_size);
0055 event->data_size = data_size;
0056 event->serial_number = buffer->next_serial_number;
0057
0058
0059 buffer->next_index = (buffer->next_index + 1) % IBMASM_NUM_EVENTS;
0060 buffer->next_serial_number++;
0061 spin_unlock_irqrestore(&sp->lock, flags);
0062
0063 wake_up_event_readers(sp);
0064 }
0065
0066 static inline int event_available(struct event_buffer *b, struct event_reader *r)
0067 {
0068 return (r->next_serial_number < b->next_serial_number);
0069 }
0070
0071
0072
0073
0074
0075
0076
0077 int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader)
0078 {
0079 struct event_buffer *buffer = sp->event_buffer;
0080 struct ibmasm_event *event;
0081 unsigned int index;
0082 unsigned long flags;
0083
0084 reader->cancelled = 0;
0085
0086 if (wait_event_interruptible(reader->wait,
0087 event_available(buffer, reader) || reader->cancelled))
0088 return -ERESTARTSYS;
0089
0090 if (!event_available(buffer, reader))
0091 return 0;
0092
0093 spin_lock_irqsave(&sp->lock, flags);
0094
0095 index = buffer->next_index;
0096 event = &buffer->events[index];
0097 while (event->serial_number < reader->next_serial_number) {
0098 index = (index + 1) % IBMASM_NUM_EVENTS;
0099 event = &buffer->events[index];
0100 }
0101 memcpy(reader->data, event->data, event->data_size);
0102 reader->data_size = event->data_size;
0103 reader->next_serial_number = event->serial_number + 1;
0104
0105 spin_unlock_irqrestore(&sp->lock, flags);
0106
0107 return event->data_size;
0108 }
0109
0110 void ibmasm_cancel_next_event(struct event_reader *reader)
0111 {
0112 reader->cancelled = 1;
0113 wake_up_interruptible(&reader->wait);
0114 }
0115
0116 void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader)
0117 {
0118 unsigned long flags;
0119
0120 reader->next_serial_number = sp->event_buffer->next_serial_number;
0121 init_waitqueue_head(&reader->wait);
0122 spin_lock_irqsave(&sp->lock, flags);
0123 list_add(&reader->node, &sp->event_buffer->readers);
0124 spin_unlock_irqrestore(&sp->lock, flags);
0125 }
0126
0127 void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader)
0128 {
0129 unsigned long flags;
0130
0131 spin_lock_irqsave(&sp->lock, flags);
0132 list_del(&reader->node);
0133 spin_unlock_irqrestore(&sp->lock, flags);
0134 }
0135
0136 int ibmasm_event_buffer_init(struct service_processor *sp)
0137 {
0138 struct event_buffer *buffer;
0139 struct ibmasm_event *event;
0140 int i;
0141
0142 buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL);
0143 if (!buffer)
0144 return -ENOMEM;
0145
0146 buffer->next_index = 0;
0147 buffer->next_serial_number = 1;
0148
0149 event = buffer->events;
0150 for (i=0; i<IBMASM_NUM_EVENTS; i++, event++)
0151 event->serial_number = 0;
0152
0153 INIT_LIST_HEAD(&buffer->readers);
0154
0155 sp->event_buffer = buffer;
0156
0157 return 0;
0158 }
0159
0160 void ibmasm_event_buffer_exit(struct service_processor *sp)
0161 {
0162 kfree(sp->event_buffer);
0163 }