]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/include/can_queue.h
107074c8c83e6ab3b1925390eaf4f833e823d49d
[lincan.git] / lincan / include / can_queue.h
1 #ifndef _CAN_QUEUE_H
2 #define _CAN_QUEUE_H
3
4 #include "./canmsg.h"
5 #include "./constants.h"
6 #include "./can_sysdep.h"
7
8 /**
9  * struct canque_slot_t - one CAN message slot in the CAN FIFO queue 
10  * @next: pointer to the next/younger slot
11  * @slot_flags: space for flags and optional command describing action
12  *      associated with slot data
13  * @msg: space for one CAN message
14  *
15  * This structure is used to store CAN messages in the CAN FIFO queue.
16  */
17  struct canque_slot_t {
18         struct canque_slot_t *next;
19         unsigned long slot_flags;
20         struct canmsg_t msg;
21 };
22
23 #define CAN_SLOTF_CMD   0x00ff  /*  */
24
25 /**
26  * struct canque_fifo_t - CAN FIFO queue representation
27  * @fifo_flags: this field holds global flags describing state of the FIFO.
28  *      %CAN_FIFOF_ERROR is set when some error condition occurs.
29  *      %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
30  *      %CAN_FIFOF_BLOCK state blocks insertion of the next messages. 
31  *      %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full. 
32  *      %CAN_FIFOF_FULL indicates FIFO full state. 
33  *      %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
34  *      %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
35  * @error_code: futher description of error condition
36  * @head: pointer to the FIFO head, oldest slot
37  * @tail: pointer to the location, where pointer to newly inserted slot
38  *      should be added
39  * @flist: pointer to list of the free slots associated with queue
40  * @entry: pointer to the memory allocated for the list slots.
41  * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
42  * @slotsnr:  number of allocated slots
43  *
44  * This structure represents CAN FIFO queue. It is implemented as 
45  * a single linked list of slots prepared for processing. The empty slots
46  * are stored in single linked list (@flist).
47  */
48 struct canque_fifo_t {
49         unsigned long fifo_flags;
50         unsigned long error_code;
51         struct canque_slot_t *head;     /* points to the oldest entry */
52         struct canque_slot_t **tail;    /* points to NULL pointer for chaining */
53         struct canque_slot_t *flist;    /* points the first entry in the free list */
54         struct canque_slot_t *entry;    /* points to first allocated entry */
55         can_spinlock_t fifo_lock;       /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
56         int    slotsnr;
57 };
58
59 #define CAN_FIFOF_DESTROY_b     15
60 #define CAN_FIFOF_ERROR_b       14
61 #define CAN_FIFOF_ERR2BLOCK_b   13
62 #define CAN_FIFOF_BLOCK_b       12
63 #define CAN_FIFOF_OVERRUN_b     11
64 #define CAN_FIFOF_FULL_b        10
65 #define CAN_FIFOF_EMPTY_b       9
66 #define CAN_FIFOF_DEAD_b        8
67 #define CAN_FIFOF_INACTIVE_b    7
68 #define CAN_FIFOF_FREEONEMPTY_b 6
69 #define CAN_FIFOF_READY_b       5
70 #define CAN_FIFOF_NOTIFYPEND_b  4
71 #define CAN_FIFOF_RTL_MEM_b     3
72
73 #define CAN_FIFOF_DESTROY       (1<<CAN_FIFOF_DESTROY_b)
74 #define CAN_FIFOF_ERROR         (1<<CAN_FIFOF_ERROR_b)
75 #define CAN_FIFOF_ERR2BLOCK     (1<<CAN_FIFOF_ERR2BLOCK_b)
76 #define CAN_FIFOF_BLOCK         (1<<CAN_FIFOF_BLOCK_b)
77 #define CAN_FIFOF_OVERRUN       (1<<CAN_FIFOF_OVERRUN_b)
78 #define CAN_FIFOF_FULL          (1<<CAN_FIFOF_FULL_b)
79 #define CAN_FIFOF_EMPTY         (1<<CAN_FIFOF_EMPTY_b)
80 #define CAN_FIFOF_DEAD          (1<<CAN_FIFOF_DEAD_b)
81 #define CAN_FIFOF_INACTIVE      (1<<CAN_FIFOF_INACTIVE_b)
82 #define CAN_FIFOF_FREEONEMPTY   (1<<CAN_FIFOF_FREEONEMPTY_b)
83 #define CAN_FIFOF_READY         (1<<CAN_FIFOF_READY_b)
84 #define CAN_FIFOF_NOTIFYPEND    (1<<CAN_FIFOF_NOTIFYPEND_b)
85 #define CAN_FIFOF_RTL_MEM       (1<<CAN_FIFOF_RTL_MEM_b)
86
87 #define canque_fifo_test_fl(fifo,fifo_fl) \
88   test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
89 #define canque_fifo_set_fl(fifo,fifo_fl) \
90   set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
91 #define canque_fifo_clear_fl(fifo,fifo_fl) \
92   clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
93 #define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
94   test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
95 #define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
96   test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
97
98
99 /**
100  * canque_fifo_get_inslot - allocate slot for the input of one CAN message 
101  * @fifo: pointer to the FIFO structure
102  * @slotp: pointer to location to store pointer to the allocated slot.
103  * @cmd: optional command associated with allocated slot.
104  *
105  * Return Value: The function returns negative value if there is no
106  *      free slot in the FIFO queue.
107  */
108 static inline
109 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
110 {
111         can_spin_irqflags_t flags;
112         struct canque_slot_t *slot;
113         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
114         /* get the first free slot slot from flist */
115         if(!(slot=fifo->flist)) {
116                 canque_fifo_set_fl(fifo,OVERRUN);
117                 canque_fifo_set_fl(fifo,FULL);
118                 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
119                 *slotp=NULL;
120                 return -1;
121         }
122         /* adjust free slot list */
123         if(!(fifo->flist=slot->next))
124                 canque_fifo_set_fl(fifo,FULL);
125         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
126         *slotp=slot;
127         slot->slot_flags=cmd&CAN_SLOTF_CMD;
128         return 1;
129 }
130
131 /**
132  * canque_fifo_put_inslot - releases slot to further processing
133  * @fifo: pointer to the FIFO structure
134  * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
135  *
136  * Return Value: The nonzero return value indicates, that the queue was empty
137  *      before call to the function. The caller should wake-up output side of the queue.
138  */
139 static inline
140 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
141 {
142         int ret;
143         can_spin_irqflags_t flags;
144         slot->next=NULL;
145         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
146         if(*fifo->tail) can_printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
147         *fifo->tail=slot;
148         fifo->tail=&slot->next;
149         ret=0;
150         if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
151           ret=CAN_FIFOF_EMPTY;  /* Fifo has been empty before put */
152         if(canque_fifo_test_and_clear_fl(fifo,INACTIVE))
153           ret=CAN_FIFOF_INACTIVE; /* Fifo has been empty before put */
154         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
155         return ret;
156 }
157
158 /**
159  * canque_fifo_abort_inslot - release and abort slot
160  * @fifo: pointer to the FIFO structure
161  * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
162  *
163  * Return Value: The nonzero value indicates, that fifo was full
164  */
165 static inline
166 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
167 {
168         int ret=0;
169         can_spin_irqflags_t flags;
170         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
171         slot->next=fifo->flist;
172         fifo->flist=slot;
173         if(canque_fifo_test_and_clear_fl(fifo,FULL))
174                 ret=CAN_FIFOF_FULL;
175         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
176         return ret;
177 }
178
179 /**
180  * canque_fifo_test_outslot - test and get ready slot from the FIFO
181  * @fifo: pointer to the FIFO structure
182  * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
183  *
184  * Return Value: The negative value indicates, that queue is empty.
185  *      The positive or zero value represents command stored into slot by
186  *      the call to the function canque_fifo_get_inslot().
187  *      The successfully acquired FIFO output slot has to be released by
188  *      the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
189  */
190 static inline
191 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
192 {
193         can_spin_irqflags_t flags;
194         int cmd;
195         struct canque_slot_t *slot;
196         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
197         if(!(slot=fifo->head)){;
198                 canque_fifo_set_fl(fifo,EMPTY);
199                 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
200                 *slotp=NULL;
201                 return -1;
202         }
203         if(!(fifo->head=slot->next))
204                 fifo->tail=&fifo->head;
205         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
206
207         *slotp=slot;
208         cmd=slot->slot_flags;
209         return cmd&CAN_SLOTF_CMD;
210 }
211
212
213 /**
214  * canque_fifo_free_outslot - free processed FIFO slot
215  * @fifo: pointer to the FIFO structure
216  * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
217  *
218  * Return Value: The returned value informs about FIFO state change.
219  *      The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
220  *      the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
221  *      has been processed.
222  */
223 static inline
224 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
225 {
226         int ret=0;
227         can_spin_irqflags_t flags;
228         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
229         slot->next=fifo->flist;
230         fifo->flist=slot;
231         if(canque_fifo_test_and_clear_fl(fifo,FULL))
232                 ret=CAN_FIFOF_FULL;
233         if(!(fifo->head)){
234                 canque_fifo_set_fl(fifo,EMPTY);
235                 ret|=CAN_FIFOF_EMPTY;
236         }
237         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
238         return ret;
239 }
240
241 /**
242  * canque_fifo_again_outslot - interrupt and postpone processing of the slot
243  * @fifo: pointer to the FIFO structure
244  * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
245  *
246  * Return Value: The function cannot fail..
247  */
248 static inline
249 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
250 {
251         can_spin_irqflags_t flags;
252         can_spin_lock_irqsave(&fifo->fifo_lock, flags);
253         if(!(slot->next=fifo->head))
254                 fifo->tail=&slot->next;
255         fifo->head=slot;
256         can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
257         return 1;
258 }
259
260 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
261
262 int canque_fifo_init_slots(struct canque_fifo_t *fifo);
263
264 #define CANQUEUE_PRIO_NR  3
265
266 /* Forward declarations for external types */
267 struct msgobj_t;
268 struct chip_t;
269
270 /**
271  * struct canque_edge_t - CAN message delivery subsystem graph edge
272  * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
273  * @filtid: the possible CAN message identifiers filter.
274  * @filtmask: the filter mask, the comparison considers only
275  *      @filtid bits corresponding to set bits in the @filtmask field.
276  * @inpeers: the lists of all peers FIFOs connected by their
277  *      input side (@inends) to the same terminal (@struct canque_ends_t).
278  * @outpeers: the lists of all peers FIFOs connected by their
279  *      output side (@outends) to the same terminal (@struct canque_ends_t).
280  * @activepeers: the lists of peers FIFOs connected by their
281  *      output side (@outends) to the same terminal (@struct canque_ends_t)
282  *      with same priority and active state.
283  * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
284  * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
285  * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
286  * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
287  * @edge_num: edge sequential number intended for debugging purposes only
288  * @pending_peers: edges with pending delayed events (RTL->Linux calls)
289  * @pending_inops: bitmask of pending operations
290  * @pending_outops: bitmask of pending operations
291  *
292  * This structure represents one direction connection from messages source 
293  * (@inends) to message consumer (@outends) fifo ends hub. The edge contains
294  * &struct canque_fifo_t for message fifo implementation.
295  */
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 list_head activepeers;
303         struct canque_ends_t *inends;
304         struct canque_ends_t *outends;
305         atomic_t edge_used;
306         int edge_prio;
307         int edge_num;
308     #ifdef CAN_WITH_RTL
309         struct list_head pending_peers;
310         unsigned long pending_inops;
311         unsigned long pending_outops;
312     #endif /*CAN_WITH_RTL*/
313 };
314
315 /**
316  * struct canque_ends_t - CAN message delivery subsystem graph vertex (FIFO ends)
317  * @ends_flags: this field holds flags describing state of the ENDS structure.
318  * @active: the array of the lists of active edges directed to the ends structure
319  *      with ready messages. The array is indexed by the edges priorities. 
320  * @idle: the list of the edges directed to the ends structure with empty FIFOs.
321  * @inlist: the list of outgoing edges input sides.
322  * @outlist: the list of all incoming edges output sides. Each of there edges
323  *      is listed on one of @active or @idle lists.
324  * @ends_lock: the lock synchronizing operations between threads accessing
325  *      same ends structure.
326  * @notify: pointer to notify procedure. The next state changes are notified.
327  *      %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side. 
328  *      %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
329  *      %CANQUEUE_NOTIFY_PROC  (in->out call) - empty state negated => out side is requested to process slots.
330  *      %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
331  *              called with some lock to prevent edge disappear.
332  *      %CANQUEUE_NOTIFY_DEAD  (both) - edge is in progress of deletion.
333  *      %CANQUEUE_NOTIFY_ATACH (both) - new edge has been attached to end.
334  *      %CANQUEUE_NOTIFY_FILTCH (out->in call) - edge filter rules changed
335  *      %CANQUEUE_NOTIFY_ERROR  (out->in call) - error in messages processing.
336  * @context: space to store ends user specific information
337  * @endinfo: space to store some other ends usage specific informations
338  *      mainly for waking-up by the notify calls.
339  * @dead_peers: used to chain ends wanting for postponed destruction
340  *
341  * Structure represents place to connect edges to for CAN communication entity.
342  * The zero, one or more incoming and outgoing edges can be connected to
343  * this structure.
344  */
345 struct canque_ends_t {
346         unsigned long ends_flags;
347         struct list_head active[CANQUEUE_PRIO_NR];
348         struct list_head idle;
349         struct list_head inlist;
350         struct list_head outlist;
351         can_spinlock_t ends_lock;       /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
352         void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
353         void *context;
354         union {
355                 struct {
356                         wait_queue_head_t readq;
357                         wait_queue_head_t writeq;
358                         wait_queue_head_t emptyq;
359                     #ifdef CAN_ENABLE_KERN_FASYNC
360                         struct fasync_struct *fasync;
361                     #endif /*CAN_ENABLE_KERN_FASYNC*/
362                 } fileinfo;
363             #ifdef CAN_WITH_RTL
364                 struct {
365                         rtl_spinlock_t rtl_lock;
366                         rtl_wait_t rtl_readq;
367                         atomic_t   rtl_readq_age;
368                         rtl_wait_t rtl_writeq;
369                         atomic_t   rtl_writeq_age;
370                         rtl_wait_t rtl_emptyq;
371                         atomic_t   rtl_emptyq_age;
372                         unsigned long pend_flags;
373                 } rtlinfo;
374             #endif /*CAN_WITH_RTL*/
375                 struct {
376                         struct msgobj_t *msgobj;
377                         struct chip_t *chip;
378                     #ifndef CAN_WITH_RTL
379                         wait_queue_head_t daemonq;
380                     #else /*CAN_WITH_RTL*/
381                         pthread_t worker_thread;
382                     #endif /*CAN_WITH_RTL*/
383                 } chipinfo;
384         } endinfo;
385         struct list_head dead_peers;
386 };
387
388 #define CANQUEUE_NOTIFY_EMPTY  1 /* out -> in - all slots are processed by FIFO out side */
389 #define CANQUEUE_NOTIFY_SPACE  2 /* out -> in - full state negated => there is space for new message */
390 #define CANQUEUE_NOTIFY_PROC   3 /* in -> out - empty state negated => out side is requested to process slots */
391 #define CANQUEUE_NOTIFY_NOUSR  4 /* called with some lock to prevent edge disappear */
392 #define CANQUEUE_NOTIFY_DEAD   5 /*  */
393 #define CANQUEUE_NOTIFY_DEAD_WANTED 6 /*  */
394 #define CANQUEUE_NOTIFY_ATTACH 7 /*  */
395 #define CANQUEUE_NOTIFY_FILTCH 8 /* filter changed */
396 #define CANQUEUE_NOTIFY_ERROR      0x10000 /* error notifiers */
397 #define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
398 #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
399 #define CANQUEUE_NOTIFY_ERRTX_BUS  0x11003 /* tx bus error */
400
401 #define CAN_ENDSF_DEAD    (1<<0)
402 #define CAN_ENDSF_MEM_RTL (1<<1)
403
404 /**
405  * canque_notify_inends - request to send notification to the input ends
406  * @qedge: pointer to the edge structure
407  * @what: notification type
408  */
409 static inline
410 void canque_notify_inends(struct canque_edge_t *qedge, int what)
411 {
412         if(qedge->inends)
413                 if(qedge->inends->notify)
414                         qedge->inends->notify(qedge->inends,qedge,what);
415 }
416
417 /**
418  * canque_notify_outends - request to send notification to the output ends
419  * @qedge: pointer to the edge structure
420  * @what: notification type
421  */
422 static inline
423 void canque_notify_outends(struct canque_edge_t *qedge, int what)
424 {
425         if(qedge->outends)
426                 if(qedge->outends->notify)
427                         qedge->outends->notify(qedge->outends,qedge,what);
428 }
429
430 /**
431  * canque_notify_bothends - request to send notification to the both ends
432  * @qedge: pointer to the edge structure
433  * @what: notification type
434  */
435 static inline
436 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
437 {
438         canque_notify_inends(qedge, what);
439         canque_notify_outends(qedge, what);
440 }
441
442 /**
443  * canque_activate_edge - mark output end of the edge as active
444  * @qedge: pointer to the edge structure
445  * @inends: input side of the edge
446  *
447  * Function call moves output side of the edge from idle onto active edges
448  * list.
449  */
450 static inline
451 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
452 {
453         can_spin_irqflags_t flags;
454         struct canque_ends_t *outends;
455         if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
456                 qedge->edge_prio=CANQUEUE_PRIO_NR-1;
457         can_spin_lock_irqsave(&inends->ends_lock, flags);
458         if((outends=qedge->outends)){
459                 can_spin_lock(&outends->ends_lock);
460                 can_spin_lock(&qedge->fifo.fifo_lock);
461                 if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
462                         list_del(&qedge->activepeers);
463                         list_add_tail(&qedge->activepeers,&outends->active[qedge->edge_prio]);
464                 }
465                 can_spin_unlock(&qedge->fifo.fifo_lock);
466                 can_spin_unlock(&outends->ends_lock);
467
468         }
469         can_spin_unlock_irqrestore(&inends->ends_lock, flags);
470 }
471
472 /**
473  * canque_filtid2internal - converts message ID and filter flags into internal format
474  * @id: CAN message 11 or 29 bit identifier
475  * @filtflags: CAN message flags
476  *
477  * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
478  */
479 static inline
480 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
481 {
482         filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
483         filtflags += filtflags&MSG_RTR;
484         return (id&MSG_ID_MASK) | (filtflags<<28);
485 }
486
487 int canque_get_inslot(struct canque_ends_t *qends,
488         struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
489         
490 int canque_get_inslot4id(struct canque_ends_t *qends,
491         struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
492         int cmd, unsigned long id, int prio);
493         
494 int canque_put_inslot(struct canque_ends_t *qends,
495         struct canque_edge_t *qedge, struct canque_slot_t *slot);
496
497 int canque_abort_inslot(struct canque_ends_t *qends,
498         struct canque_edge_t *qedge, struct canque_slot_t *slot);
499
500 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
501
502 int canque_test_outslot(struct canque_ends_t *qends,
503         struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
504
505 int canque_free_outslot(struct canque_ends_t *qends,
506         struct canque_edge_t *qedge, struct canque_slot_t *slot);
507
508 int canque_again_outslot(struct canque_ends_t *qends,
509         struct canque_edge_t *qedge, struct canque_slot_t *slot);
510
511 int canque_set_filt(struct canque_edge_t *qedge,
512         unsigned long filtid, unsigned long filtmask, int flags);
513         
514 int canque_flush(struct canque_edge_t *qedge);
515
516 int canqueue_disconnect_edge(struct canque_edge_t *qedge);
517
518 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
519
520 int canqueue_ends_init_gen(struct canque_ends_t *qends);
521
522 void canqueue_block_inlist(struct canque_ends_t *qends);
523
524 void canqueue_block_outlist(struct canque_ends_t *qends);
525
526 int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest);
527
528 int canqueue_ends_kill_outlist(struct canque_ends_t *qends);
529
530 int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt);
531
532 int canqueue_ends_flush_inlist(struct canque_ends_t *qends);
533
534 int canqueue_ends_flush_outlist(struct canque_ends_t *qends);
535
536 /* edge reference and traversal functions */
537
538 void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl);
539
540 static inline
541 void canque_edge_incref(struct canque_edge_t *edge)
542 {
543         atomic_inc(&edge->edge_used);
544 }
545
546 static inline
547 void canque_edge_decref(struct canque_edge_t *edge)
548 {
549         can_spin_irqflags_t flags;
550         struct canque_ends_t *inends=edge->inends;
551         struct canque_ends_t *outends=edge->outends;
552         int dead_fl;
553         
554         can_spin_lock_irqsave(&inends->ends_lock, flags);
555         can_spin_lock(&outends->ends_lock);
556         if(atomic_dec_and_test(&edge->edge_used)) {
557                 dead_fl=canque_fifo_test_and_set_fl(&edge->fifo,DEAD);
558                 /* Because of former evolution of edge references 
559                    management notify of CANQUEUE_NOTIFY_NOUSR could
560                    be moved to canque_edge_do_dead :-) */
561                 can_spin_unlock(&outends->ends_lock);
562                 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
563                 canque_edge_do_dead(edge, dead_fl);
564         } else {
565                 can_spin_unlock(&outends->ends_lock);
566                 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
567         }
568 }
569
570 static inline
571 struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
572 {
573         can_spin_irqflags_t flags;
574         struct list_head *entry;
575         struct canque_edge_t *edge;
576         
577         can_spin_lock_irqsave(&qends->ends_lock, flags);
578         entry=qends->inlist.next;
579     skip_dead:
580         if(entry != &qends->inlist) {
581                 edge=list_entry(entry,struct canque_edge_t,inpeers);
582                 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
583                         entry=entry->next;
584                         goto skip_dead;
585                 }
586                 canque_edge_incref(edge);
587         } else {
588                 edge=NULL;
589         }
590         can_spin_unlock_irqrestore(&qends->ends_lock, flags);
591         return edge;
592 }
593
594
595 static inline
596 struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
597 {
598         can_spin_irqflags_t flags;
599         struct list_head *entry;
600         struct canque_edge_t *next;
601         
602         can_spin_lock_irqsave(&qends->ends_lock, flags);
603         entry=edge->inpeers.next;
604     skip_dead:
605         if(entry != &qends->inlist) {
606                 next=list_entry(entry,struct canque_edge_t,inpeers);
607                 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
608                         entry=entry->next;
609                         goto skip_dead;
610                 }
611                 canque_edge_incref(next);
612         } else {
613                 next=NULL;
614         }
615         can_spin_unlock_irqrestore(&qends->ends_lock, flags);
616         canque_edge_decref(edge);
617         return next;
618 }
619
620 #define canque_for_each_inedge(qends, edge) \
621             for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
622
623 static inline
624 struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends)
625 {
626         can_spin_irqflags_t flags;
627         struct list_head *entry;
628         struct canque_edge_t *edge;
629         
630         can_spin_lock_irqsave(&qends->ends_lock, flags);
631         entry=qends->outlist.next;
632     skip_dead:
633         if(entry != &qends->outlist) {
634                 edge=list_entry(entry,struct canque_edge_t,outpeers);
635                 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
636                         entry=entry->next;
637                         goto skip_dead;
638                 }
639                 canque_edge_incref(edge);
640         } else {
641                 edge=NULL;
642         }
643         can_spin_unlock_irqrestore(&qends->ends_lock, flags);
644         return edge;
645 }
646
647
648 static inline
649 struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
650 {
651         can_spin_irqflags_t flags;
652         struct list_head *entry;
653         struct canque_edge_t *next;
654         
655         can_spin_lock_irqsave(&qends->ends_lock, flags);
656         entry=edge->outpeers.next;
657     skip_dead:
658         if(entry != &qends->outlist) {
659                 next=list_entry(entry,struct canque_edge_t,outpeers);
660                 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
661                         entry=entry->next;
662                         goto skip_dead;
663                 }
664                 canque_edge_incref(next);
665         } else {
666                 next=NULL;
667         }
668         can_spin_unlock_irqrestore(&qends->ends_lock, flags);
669         canque_edge_decref(edge);
670         return next;
671 }
672
673 #define canque_for_each_outedge(qends, edge) \
674             for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge))
675
676 /* Linux kernel specific functions */
677
678 int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr);
679
680 int canque_fifo_done_kern(struct canque_fifo_t *fifo);
681
682 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
683
684 int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
685         struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
686         int cmd, unsigned long id, int prio);
687
688 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
689         struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
690
691 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
692
693 int canqueue_ends_init_kern(struct canque_ends_t *qends);
694
695 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
696
697 void canqueue_ends_dispose_postpone(struct canque_ends_t *qends);
698
699 void canqueue_kern_initialize(void);
700
701 #ifdef CAN_WITH_RTL
702
703 extern struct tasklet_struct canque_dead_tl;    /*publication required only for RTL*/
704
705 /* RT-Linux specific functions and variables */
706
707 extern int canqueue_rtl_irq;
708
709 extern unsigned long canqueue_rtl2lin_pend;
710
711 #define CAN_RTL2LIN_PEND_DEAD_b 0
712
713 void canqueue_rtl_initialize(void);
714 void canqueue_rtl_done(void);
715
716 int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
717                          struct canque_edge_t *qedge, int what);
718
719 struct canque_edge_t *canque_new_edge_rtl(int slotsnr);
720
721 void canque_dispose_edge_rtl(struct canque_edge_t *qedge);
722
723 int canque_get_inslot4id_wait_rtl(struct canque_ends_t *qends,
724         struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
725         int cmd, unsigned long id, int prio);
726
727 int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
728         struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
729
730 int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge);
731
732 void canque_ends_free_rtl(struct canque_ends_t *qends);
733
734 int canqueue_ends_init_rtl(struct canque_ends_t *qends);
735
736 int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync);
737
738 #else /*CAN_WITH_RTL*/
739
740 static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
741                         struct canque_edge_t *qedge, int what) { return 0; }
742
743 #endif /*CAN_WITH_RTL*/
744
745
746 #endif /*_CAN_QUEUE_H*/