5 #include "./constants.h"
6 #include "./can_sysdep.h"
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
15 * This structure is used to store CAN messages in the CAN FIFO queue.
17 struct canque_slot_t {
18 struct canque_slot_t *next;
19 unsigned long slot_flags;
23 #define CAN_SLOTF_CMD 0x00ff /* */
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
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
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).
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 */
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
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)
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)
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.
105 * Return Value: The function returns negative value if there is no
106 * free slot in the FIFO queue.
109 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
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);
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);
127 slot->slot_flags=cmd&CAN_SLOTF_CMD;
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().
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.
140 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
143 can_spin_irqflags_t flags;
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");
148 fifo->tail=&slot->next;
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);
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().
163 * Return Value: The nonzero value indicates, that fifo was full
166 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
169 can_spin_irqflags_t flags;
170 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
171 slot->next=fifo->flist;
173 if(canque_fifo_test_and_clear_fl(fifo,FULL))
175 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
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.
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().
191 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
193 can_spin_irqflags_t flags;
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);
203 if(!(fifo->head=slot->next))
204 fifo->tail=&fifo->head;
205 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
208 cmd=slot->slot_flags;
209 return cmd&CAN_SLOTF_CMD;
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().
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.
224 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
227 can_spin_irqflags_t flags;
228 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
229 slot->next=fifo->flist;
231 if(canque_fifo_test_and_clear_fl(fifo,FULL))
234 canque_fifo_set_fl(fifo,EMPTY);
235 ret|=CAN_FIFOF_EMPTY;
237 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
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().
246 * Return Value: The function cannot fail..
249 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
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;
256 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
260 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
262 int canque_fifo_init_slots(struct canque_fifo_t *fifo);
264 #define CANQUEUE_PRIO_NR 3
266 /* Forward declarations for external types */
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
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.
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;
309 struct list_head pending_peers;
310 unsigned long pending_inops;
311 unsigned long pending_outops;
312 #endif /*CAN_WITH_RTL*/
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
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
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);
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*/
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;
374 #endif /*CAN_WITH_RTL*/
376 struct msgobj_t *msgobj;
379 wait_queue_head_t daemonq;
380 #else /*CAN_WITH_RTL*/
381 pthread_t worker_thread;
382 #endif /*CAN_WITH_RTL*/
385 struct list_head dead_peers;
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 */
401 #define CAN_ENDSF_DEAD (1<<0)
402 #define CAN_ENDSF_MEM_RTL (1<<1)
405 * canque_notify_inends - request to send notification to the input ends
406 * @qedge: pointer to the edge structure
407 * @what: notification type
410 void canque_notify_inends(struct canque_edge_t *qedge, int what)
413 if(qedge->inends->notify)
414 qedge->inends->notify(qedge->inends,qedge,what);
418 * canque_notify_outends - request to send notification to the output ends
419 * @qedge: pointer to the edge structure
420 * @what: notification type
423 void canque_notify_outends(struct canque_edge_t *qedge, int what)
426 if(qedge->outends->notify)
427 qedge->outends->notify(qedge->outends,qedge,what);
431 * canque_notify_bothends - request to send notification to the both ends
432 * @qedge: pointer to the edge structure
433 * @what: notification type
436 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
438 canque_notify_inends(qedge, what);
439 canque_notify_outends(qedge, what);
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
447 * Function call moves output side of the edge from idle onto active edges
451 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
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]);
465 can_spin_unlock(&qedge->fifo.fifo_lock);
466 can_spin_unlock(&outends->ends_lock);
469 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
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
477 * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
480 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
482 filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
483 filtflags += filtflags&MSG_RTR;
484 return (id&MSG_ID_MASK) | (filtflags<<28);
487 int canque_get_inslot(struct canque_ends_t *qends,
488 struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
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);
494 int canque_put_inslot(struct canque_ends_t *qends,
495 struct canque_edge_t *qedge, struct canque_slot_t *slot);
497 int canque_abort_inslot(struct canque_ends_t *qends,
498 struct canque_edge_t *qedge, struct canque_slot_t *slot);
500 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
502 int canque_test_outslot(struct canque_ends_t *qends,
503 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
505 int canque_free_outslot(struct canque_ends_t *qends,
506 struct canque_edge_t *qedge, struct canque_slot_t *slot);
508 int canque_again_outslot(struct canque_ends_t *qends,
509 struct canque_edge_t *qedge, struct canque_slot_t *slot);
511 int canque_set_filt(struct canque_edge_t *qedge,
512 unsigned long filtid, unsigned long filtmask, int flags);
514 int canque_flush(struct canque_edge_t *qedge);
516 int canqueue_disconnect_edge(struct canque_edge_t *qedge);
518 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
520 int canqueue_ends_init_gen(struct canque_ends_t *qends);
522 void canqueue_block_inlist(struct canque_ends_t *qends);
524 void canqueue_block_outlist(struct canque_ends_t *qends);
526 int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest);
528 int canqueue_ends_kill_outlist(struct canque_ends_t *qends);
530 int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt);
532 int canqueue_ends_flush_inlist(struct canque_ends_t *qends);
534 int canqueue_ends_flush_outlist(struct canque_ends_t *qends);
536 /* edge reference and traversal functions */
538 void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl);
541 void canque_edge_incref(struct canque_edge_t *edge)
543 atomic_inc(&edge->edge_used);
547 void canque_edge_decref(struct canque_edge_t *edge)
549 can_spin_irqflags_t flags;
550 struct canque_ends_t *inends=edge->inends;
551 struct canque_ends_t *outends=edge->outends;
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);
565 can_spin_unlock(&outends->ends_lock);
566 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
571 struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
573 can_spin_irqflags_t flags;
574 struct list_head *entry;
575 struct canque_edge_t *edge;
577 can_spin_lock_irqsave(&qends->ends_lock, flags);
578 entry=qends->inlist.next;
580 if(entry != &qends->inlist) {
581 edge=list_entry(entry,struct canque_edge_t,inpeers);
582 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
586 canque_edge_incref(edge);
590 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
596 struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
598 can_spin_irqflags_t flags;
599 struct list_head *entry;
600 struct canque_edge_t *next;
602 can_spin_lock_irqsave(&qends->ends_lock, flags);
603 entry=edge->inpeers.next;
605 if(entry != &qends->inlist) {
606 next=list_entry(entry,struct canque_edge_t,inpeers);
607 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
611 canque_edge_incref(next);
615 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
616 canque_edge_decref(edge);
620 #define canque_for_each_inedge(qends, edge) \
621 for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
624 struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends)
626 can_spin_irqflags_t flags;
627 struct list_head *entry;
628 struct canque_edge_t *edge;
630 can_spin_lock_irqsave(&qends->ends_lock, flags);
631 entry=qends->outlist.next;
633 if(entry != &qends->outlist) {
634 edge=list_entry(entry,struct canque_edge_t,outpeers);
635 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
639 canque_edge_incref(edge);
643 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
649 struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
651 can_spin_irqflags_t flags;
652 struct list_head *entry;
653 struct canque_edge_t *next;
655 can_spin_lock_irqsave(&qends->ends_lock, flags);
656 entry=edge->outpeers.next;
658 if(entry != &qends->outlist) {
659 next=list_entry(entry,struct canque_edge_t,outpeers);
660 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
664 canque_edge_incref(next);
668 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
669 canque_edge_decref(edge);
673 #define canque_for_each_outedge(qends, edge) \
674 for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge))
676 /* Linux kernel specific functions */
678 int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr);
680 int canque_fifo_done_kern(struct canque_fifo_t *fifo);
682 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
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);
688 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
689 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
691 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
693 int canqueue_ends_init_kern(struct canque_ends_t *qends);
695 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
697 void canqueue_ends_dispose_postpone(struct canque_ends_t *qends);
699 void canqueue_kern_initialize(void);
703 extern struct tasklet_struct canque_dead_tl; /*publication required only for RTL*/
705 /* RT-Linux specific functions and variables */
707 extern int canqueue_rtl_irq;
709 extern unsigned long canqueue_rtl2lin_pend;
711 #define CAN_RTL2LIN_PEND_DEAD_b 0
713 void canqueue_rtl_initialize(void);
714 void canqueue_rtl_done(void);
716 int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
717 struct canque_edge_t *qedge, int what);
719 struct canque_edge_t *canque_new_edge_rtl(int slotsnr);
721 void canque_dispose_edge_rtl(struct canque_edge_t *qedge);
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);
727 int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
728 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
730 int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge);
732 void canque_ends_free_rtl(struct canque_ends_t *qends);
734 int canqueue_ends_init_rtl(struct canque_ends_t *qends);
736 int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync);
738 #else /*CAN_WITH_RTL*/
740 static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
741 struct canque_edge_t *qedge, int what) { return 0; }
743 #endif /*CAN_WITH_RTL*/
746 #endif /*_CAN_QUEUE_H*/