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