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