4 #include <linux/version.h>
5 #include <linux/wait.h>
6 #include <linux/list.h>
8 #include <asm/atomic.h>
10 #include "./constants.h"
12 /* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2
13 kernels need next definitions too */
14 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)) /* may need correction */
15 #define wait_queue_head_t struct wait_queue *
16 #define wait_queue_t struct wait_queue
17 #define init_waitqueue_head(queue_head) (*queue_head=NULL)
18 #define init_waitqueue_entry(qentry,qtask) \
19 (qentry->next=NULL,qentry->task=qtask)
20 #define DECLARE_WAIT_QUEUE_HEAD(name) \
21 struct wait_queue * name=NULL
22 #define DECLARE_WAITQUEUE(wait, current) \
23 struct wait_queue wait = { current, NULL }
24 #define init_MUTEX(sem) (*sem=MUTEX)
25 #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
30 * struct canque_slot_t - one CAN message slot in the CAN FIFO queue
31 * @next: pointer to the next/younger slot
32 * @mrs_do_inp: space for flags and optional command describing action
33 * associated with slot data
34 * @msg: space for one CAN message
36 * This structure is used to store CAN messages in the CAN FIFO queue.
38 struct canque_slot_t {
39 struct canque_slot_t *next;
40 unsigned long slot_flags;
44 #define CAN_SLOTF_CMD 0x00ff /* */
47 * struct canque_fifo_t - CAN FIFO queue representation
48 * @fifo_flags: this field holds global flags describing state of the FIFO.
49 * %CAN_FIFOF_ERROR is set when some error condition occurs.
50 * %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
51 * %CAN_FIFOF_BLOCK state blocks insertion of the next messages.
52 * %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full.
53 * %CAN_FIFOF_FULL indicates FIFO full state.
54 * %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
55 * %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
56 * @error_code: futher description of error condition
57 * @head: pointer to the FIFO head, oldest slot
58 * @tail: pointer to the location, where pointer to newly inserted slot
60 * @tail: pointer to the location, where pointer to newly inserted slot
61 * @entry: pointer to the memory allocated for the list slots.
62 * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
64 * This structure represents CAN FIFO queue. It is implemented as
65 * a single linked list of slots prepared for processing. The empty slots
66 * are stored in single linked list (@flist).
68 struct canque_fifo_t {
69 unsigned long fifo_flags;
70 unsigned long error_code;
71 struct canque_slot_t *head; /* points to the oldest entry */
72 struct canque_slot_t **tail; /* points to NULL pointer for chaining */
73 struct canque_slot_t *flist; /* points the first entry in the free list */
74 struct canque_slot_t *entry; /* points to first allocated entry */
75 spinlock_t fifo_lock; /* spin_lock_irqsave / spin_lock_irqrestore */
78 #define CAN_FIFOF_DESTROY_b 15
79 #define CAN_FIFOF_ERROR_b 14
80 #define CAN_FIFOF_ERR2BLOCK_b 13
81 #define CAN_FIFOF_BLOCK_b 12
82 #define CAN_FIFOF_OVERRUN_b 11
83 #define CAN_FIFOF_FULL_b 10
84 #define CAN_FIFOF_EMPTY_b 9
85 #define CAN_FIFOF_DEAD_b 8
87 #define CAN_FIFOF_DESTROY (1<<CAN_FIFOF_DESTROY_b)
88 #define CAN_FIFOF_ERROR (1<<CAN_FIFOF_ERROR_b)
89 #define CAN_FIFOF_ERR2BLOCK (1<<CAN_FIFOF_ERR2BLOCK_b)
90 #define CAN_FIFOF_BLOCK (1<<CAN_FIFOF_BLOCK_b)
91 #define CAN_FIFOF_OVERRUN (1<<CAN_FIFOF_OVERRUN_b)
92 #define CAN_FIFOF_FULL (1<<CAN_FIFOF_FULL_b)
93 #define CAN_FIFOF_EMPTY (1<<CAN_FIFOF_EMPTY_b)
94 #define CAN_FIFOF_DEAD (1<<CAN_FIFOF_DEAD_b)
96 #define canque_fifo_test_fl(fifo,fifo_fl) \
97 test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
98 #define canque_fifo_set_fl(fifo,fifo_fl) \
99 set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
100 #define canque_fifo_clear_fl(fifo,fifo_fl) \
101 clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
102 #define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
103 test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
104 #define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
105 test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
109 * canque_fifo_get_inslot - allocate slot for the input of one CAN message
110 * @fifo: pointer to the FIFO structure
111 * @slotp: pointer to location to store pointer to the allocated slot.
112 * @cmd: optional command associated with allocated slot.
114 * Return Value: The function returns negative value if there is no
115 * free slot in the FIFO queue.
118 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
121 struct canque_slot_t *slot;
122 spin_lock_irqsave(&fifo->fifo_lock, flags);
123 /* get the first free slot slot from flist */
124 if(!(slot=fifo->flist)) {
125 canque_fifo_set_fl(fifo,OVERRUN);
126 canque_fifo_set_fl(fifo,FULL);
127 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
131 /* adjust free slot list */
132 if(!(fifo->flist=slot->next))
133 canque_fifo_set_fl(fifo,FULL);
134 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
136 slot->slot_flags=cmd&CAN_SLOTF_CMD;
141 * canque_fifo_put_inslot - releases slot to further processing
142 * @fifo: pointer to the FIFO structure
143 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
145 * Return Value: The nonzero return value indicates, that the queue was empty
146 * before call to the function. The caller should wake-up output side of the queue.
149 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
154 spin_lock_irqsave(&fifo->fifo_lock, flags);
155 if(*fifo->tail) printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
157 fifo->tail=&slot->next;
158 if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
159 ret=CAN_FIFOF_EMPTY; /* Fifo has been empty before put */
162 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
167 * canque_fifo_abort_inslot - release and abort slot
168 * @fifo: pointer to the FIFO structure
169 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
171 * Return Value: The nonzero value indicates, that fifo was full
174 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
178 spin_lock_irqsave(&fifo->fifo_lock, flags);
179 slot->next=fifo->flist;
181 if(canque_fifo_test_and_clear_fl(fifo,FULL))
183 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
188 * canque_fifo_test_outslot - test and get ready slot from the FIFO
189 * @fifo: pointer to the FIFO structure
190 * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
192 * Return Value: The negative value indicates, that queue is empty.
193 * The positive or zero value represents command stored into slot by
194 * the call to the function canque_fifo_get_inslot().
195 * The successfully acquired FIFO output slot has to be released by
196 * the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
199 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
203 struct canque_slot_t *slot;
204 spin_lock_irqsave(&fifo->fifo_lock, flags);
205 if(!(slot=fifo->head)){;
206 canque_fifo_set_fl(fifo,EMPTY);
207 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
211 if(!(fifo->head=slot->next))
212 fifo->tail=&fifo->head;
213 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
216 cmd=slot->slot_flags;
217 return cmd&CAN_SLOTF_CMD;
222 * canque_fifo_free_outslot - free processed FIFO slot
223 * @fifo: pointer to the FIFO structure
224 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
226 * Return Value: The returned value informs about FIFO state change.
227 * The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
228 * the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
229 * has been processed.
232 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
236 spin_lock_irqsave(&fifo->fifo_lock, flags);
237 slot->next=fifo->flist;
239 if(canque_fifo_test_and_clear_fl(fifo,FULL))
242 canque_fifo_set_fl(fifo,EMPTY);
243 ret|=CAN_FIFOF_EMPTY;
245 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
250 * canque_fifo_again_outslot - interrupt and postpone processing of the slot
251 * @fifo: pointer to the FIFO structure
252 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
254 * Return Value: The function cannot fail..
257 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
260 spin_lock_irqsave(&fifo->fifo_lock, flags);
261 if(!(slot->next=fifo->head))
262 fifo->tail=&slot->next;
264 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
268 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
270 int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr);
272 int canque_fifo_done(struct canque_fifo_t *fifo);
274 #define CANQUEUE_PRIO_NR 3
276 /* Forward declarations for external types */
281 * canque_edge_t - CAN message delivery subsystem graph edge
282 * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
283 * @filtid: the possible CAN message identifiers filter.
284 * @filtmask: the filter mask, the comparison considers only
285 * @filtid bits corresponding to set bits in the @filtmask field.
286 * @inpeers: the lists of all peer FIFOs connected by their
287 * input side (@inends) to the same terminal (@struct canque_ends_t).
288 * @outpeers: the lists of all peer FIFOs connected by their
289 * output side (@outends) to the same terminal (@struct canque_ends_t).
290 * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
291 * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
292 * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
293 * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
294 * @edge_num: edge sequential number intended for debugging purposes only
296 struct canque_edge_t {
297 struct canque_fifo_t fifo;
298 unsigned long filtid;
299 unsigned long filtmask;
300 struct list_head inpeers;
301 struct list_head outpeers;
302 struct canque_ends_t *inends;
303 struct canque_ends_t *outends;
310 * canque_edge_t - CAN message delivery subsystem graph vertex (FIFO ends)
311 * @active: the array of the lists of active edges directed to the ends structure
312 * with ready messages. The array is indexed by the edges priorities.
313 * @idle: the list of the edges directed to the ends structure with empty FIFOs.
314 * @inlist: the list of outgoing edges input sides.
315 * @ends_lock: the lock synchronizing operations between threads accessing
316 * same ends structure.
317 * @notify: pointer to notify procedure. The next state changes are notified.
318 * %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side.
319 * %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
320 * %CANQUEUE_NOTIFY_PROC (in->out call) - empty state negated => out side is requested to process slots.
321 * %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
322 * called with some lock to prevent edge disappear.
323 * @context: space to store ends user specific information
324 * @endinfo: space to store some other ends usage specific informations
325 * mainly for waking-up by the notify calls.
327 struct canque_ends_t {
328 struct list_head active[CANQUEUE_PRIO_NR];
329 struct list_head idle;
330 struct list_head inlist;
331 spinlock_t ends_lock; /* spin_lock_irqsave / spin_lock_irqrestore */
332 void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
336 wait_queue_head_t readq;
337 wait_queue_head_t writeq;
338 wait_queue_head_t emptyq;
341 wait_queue_head_t daemonq;
342 struct msgobj_t *msgobj;
348 #define CANQUEUE_NOTIFY_EMPTY 1 /* out -> in - all slots are processed by FIFO out side */
349 #define CANQUEUE_NOTIFY_SPACE 2 /* out -> in - full state negated => there is space for new message */
350 #define CANQUEUE_NOTIFY_PROC 3 /* in -> out - empty state negated => out side is requested to process slots */
351 #define CANQUEUE_NOTIFY_NOUSR 4 /* called with some lock to prevent edge disappear */
352 #define CANQUEUE_NOTIFY_DEAD 5 /* */
353 #define CANQUEUE_NOTIFY_ATACH 6 /* */
354 #define CANQUEUE_NOTIFY_FILTCH 7 /* filter changed */
355 #define CANQUEUE_NOTIFY_ERROR 0x10000 /* error notifiers */
356 #define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
357 #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
358 #define CANQUEUE_NOTIFY_ERRTX_BUS 0x11003 /* tx bus error */
361 void canque_notify_inends(struct canque_edge_t *qedge, int what)
364 if(qedge->inends->notify)
365 qedge->inends->notify(qedge->inends,qedge,what);
369 void canque_notify_outends(struct canque_edge_t *qedge, int what)
372 if(qedge->outends->notify)
373 qedge->outends->notify(qedge->outends,qedge,what);
377 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
379 canque_notify_inends(qedge, what);
380 canque_notify_outends(qedge, what);
384 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
387 struct canque_ends_t *outends;
388 if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
389 qedge->edge_prio=CANQUEUE_PRIO_NR-1;
390 spin_lock_irqsave(&inends->ends_lock, flags);
391 if((outends=qedge->outends)){
392 spin_lock(&outends->ends_lock);
393 spin_lock(&qedge->fifo.fifo_lock);
394 if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
395 list_del(&qedge->outpeers);
396 list_add_tail(&qedge->outpeers,&outends->active[qedge->edge_prio]);
398 spin_unlock(&qedge->fifo.fifo_lock);
399 spin_unlock(&outends->ends_lock);
402 spin_unlock_irqrestore(&inends->ends_lock, flags);
405 int canque_get_inslot(struct canque_ends_t *qends,
406 struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
408 int canque_get_inslot4id(struct canque_ends_t *qends,
409 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
410 int cmd, unsigned long id, int prio);
412 int canque_put_inslot(struct canque_ends_t *qends,
413 struct canque_edge_t *qedge, struct canque_slot_t *slot);
415 int canque_abort_inslot(struct canque_ends_t *qends,
416 struct canque_edge_t *qedge, struct canque_slot_t *slot);
418 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
420 int canque_test_outslot(struct canque_ends_t *qends,
421 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
423 int canque_free_outslot(struct canque_ends_t *qends,
424 struct canque_edge_t *qedge, struct canque_slot_t *slot);
426 int canque_again_outslot(struct canque_ends_t *qends,
427 struct canque_edge_t *qedge, struct canque_slot_t *slot);
429 int canque_set_filt(struct canque_edge_t *qedge,
430 unsigned long filtid, unsigned long filtmask);
432 int canque_flush(struct canque_edge_t *qedge);
434 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
436 int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
437 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
438 int cmd, unsigned long id, int prio);
440 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
441 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
443 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
445 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
447 int canqueue_ends_init_gen(struct canque_ends_t *qends);
449 int canqueue_ends_init_kern(struct canque_ends_t *qends);
451 int canqueue_ends_done_kern(struct canque_ends_t *qends, int sync);
453 #endif /*_CAN_QUEUE_H*/