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
13 #include "./constants.h"
14 #include "./can_sysdep.h"
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
23 * This structure is used to store CAN messages in the CAN FIFO queue.
25 struct canque_slot_t {
26 struct canque_slot_t *next;
27 unsigned long slot_flags;
31 #define CAN_SLOTF_CMD 0x00ff /* */
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
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
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).
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 */
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
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)
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)
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.
113 * Return Value: The function returns negative value if there is no
114 * free slot in the FIFO queue.
117 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
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);
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);
135 slot->slot_flags=cmd&CAN_SLOTF_CMD;
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().
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.
148 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
151 can_spin_irqflags_t flags;
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");
156 fifo->tail=&slot->next;
158 if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
159 ret=CAN_FIFOF_EMPTY; /* Fifo has been empty before put */
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);
167 * canque_fifo_abort_inslot - release and abort slot
168 * @fifo: pointer to the FIFO structure
169 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
171 * Return Value: The nonzero value indicates, that fifo was full
174 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
177 can_spin_irqflags_t flags;
178 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
179 slot->next=fifo->flist;
181 if(canque_fifo_test_and_clear_fl(fifo,FULL))
183 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
188 * canque_fifo_test_outslot - test and get ready slot from the FIFO
189 * @fifo: pointer to the FIFO structure
190 * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
192 * Return Value: The negative value indicates, that queue is empty.
193 * The positive or zero value represents command stored into slot by
194 * the call to the function canque_fifo_get_inslot().
195 * The successfully acquired FIFO output slot has to be released by
196 * the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
199 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
201 can_spin_irqflags_t flags;
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);
211 if(!(fifo->head=slot->next))
212 fifo->tail=&fifo->head;
213 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
216 cmd=slot->slot_flags;
217 return cmd&CAN_SLOTF_CMD;
222 * canque_fifo_free_outslot - free processed FIFO slot
223 * @fifo: pointer to the FIFO structure
224 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
226 * Return Value: The returned value informs about FIFO state change.
227 * The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
228 * the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
229 * has been processed.
232 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
235 can_spin_irqflags_t flags;
236 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
237 slot->next=fifo->flist;
239 if(canque_fifo_test_and_clear_fl(fifo,FULL))
242 canque_fifo_set_fl(fifo,EMPTY);
243 ret|=CAN_FIFOF_EMPTY;
245 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
250 * canque_fifo_again_outslot - interrupt and postpone processing of the slot
251 * @fifo: pointer to the FIFO structure
252 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
254 * Return Value: The function cannot fail..
257 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
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;
264 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
268 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
270 int canque_fifo_init_slots(struct canque_fifo_t *fifo);
272 #define CANQUEUE_PRIO_NR 3
274 /* Forward declarations for external types */
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
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.
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;
317 struct list_head pending_peers;
318 unsigned long pending_inops;
319 unsigned long pending_outops;
320 #endif /*CAN_WITH_RTL*/
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
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
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);
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*/
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;
382 #endif /*CAN_WITH_RTL*/
384 struct msgobj_t *msgobj;
385 struct canchip_t *chip;
387 wait_queue_head_t daemonq;
388 #else /*CAN_WITH_RTL*/
389 pthread_t worker_thread;
390 #endif /*CAN_WITH_RTL*/
393 struct list_head dead_peers;
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 */
409 #define CAN_ENDSF_DEAD (1<<0)
410 #define CAN_ENDSF_MEM_RTL (1<<1)
413 * canque_notify_inends - request to send notification to the input ends
414 * @qedge: pointer to the edge structure
415 * @what: notification type
418 void canque_notify_inends(struct canque_edge_t *qedge, int what)
421 if(qedge->inends->notify)
422 qedge->inends->notify(qedge->inends,qedge,what);
426 * canque_notify_outends - request to send notification to the output ends
427 * @qedge: pointer to the edge structure
428 * @what: notification type
431 void canque_notify_outends(struct canque_edge_t *qedge, int what)
434 if(qedge->outends->notify)
435 qedge->outends->notify(qedge->outends,qedge,what);
439 * canque_notify_bothends - request to send notification to the both ends
440 * @qedge: pointer to the edge structure
441 * @what: notification type
444 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
446 canque_notify_inends(qedge, what);
447 canque_notify_outends(qedge, what);
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
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.
460 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
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]);
473 can_spin_unlock(&qedge->fifo.fifo_lock);
474 can_spin_unlock_irqrestore(&outends->ends_lock, flags);
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
483 * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
486 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
488 filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
489 filtflags += filtflags&MSG_RTR;
490 return (id&MSG_ID_MASK) | (filtflags<<28);
493 int canque_get_inslot(struct canque_ends_t *qends,
494 struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
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);
500 int canque_put_inslot(struct canque_ends_t *qends,
501 struct canque_edge_t *qedge, struct canque_slot_t *slot);
503 int canque_abort_inslot(struct canque_ends_t *qends,
504 struct canque_edge_t *qedge, struct canque_slot_t *slot);
506 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
508 int canque_test_outslot(struct canque_ends_t *qends,
509 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
511 int canque_free_outslot(struct canque_ends_t *qends,
512 struct canque_edge_t *qedge, struct canque_slot_t *slot);
514 int canque_again_outslot(struct canque_ends_t *qends,
515 struct canque_edge_t *qedge, struct canque_slot_t *slot);
517 int canque_set_filt(struct canque_edge_t *qedge,
518 unsigned long filtid, unsigned long filtmask, int flags);
520 int canque_flush(struct canque_edge_t *qedge);
522 int canqueue_disconnect_edge(struct canque_edge_t *qedge);
524 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
526 int canqueue_ends_init_gen(struct canque_ends_t *qends);
528 void canqueue_block_inlist(struct canque_ends_t *qends);
530 void canqueue_block_outlist(struct canque_ends_t *qends);
532 int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest);
534 int canqueue_ends_kill_outlist(struct canque_ends_t *qends);
536 int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt);
538 int canqueue_ends_flush_inlist(struct canque_ends_t *qends);
540 int canqueue_ends_flush_outlist(struct canque_ends_t *qends);
542 /* edge reference and traversal functions */
544 void canque_edge_do_dead(struct canque_edge_t *edge);
547 * canque_edge_incref - increments edge reference count
548 * @edge: pointer to the edge structure
551 void canque_edge_incref(struct canque_edge_t *edge)
553 atomic_inc(&edge->edge_used);
557 can_spin_irqflags_t canque_edge_lock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends)
559 can_spin_irqflags_t flags;
561 can_spin_lock_irqsave(&inends->ends_lock, flags);
562 can_spin_lock(&outends->ends_lock);
564 can_spin_lock_irqsave(&outends->ends_lock, flags);
565 if(outends!=inends) can_spin_lock(&inends->ends_lock);
571 void canque_edge_unlock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends, can_spin_irqflags_t flags)
573 if(outends!=inends) can_spin_unlock(&outends->ends_lock);
574 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
577 /* Non-inlined version of edge reference decrement */
578 void __canque_edge_decref(struct canque_edge_t *edge);
581 void __canque_edge_decref_body(struct canque_edge_t *edge)
583 can_spin_irqflags_t flags;
585 struct canque_ends_t *inends=edge->inends;
586 struct canque_ends_t *outends=edge->outends;
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 :-) */
595 canque_edge_unlock_both_ends(inends, outends, flags);
596 if(dead_fl) canque_edge_do_dead(edge);
599 #ifndef CAN_HAVE_ARCH_CMPXCHG
601 * canque_edge_decref - decrements edge reference count
602 * @edge: pointer to the edge structure
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()
609 void canque_edge_decref(struct canque_edge_t *edge)
611 __canque_edge_decref_body(edge);
615 void canque_edge_decref(struct canque_edge_t *edge)
619 x = atomic_read(&edge->edge_used);
622 return __canque_edge_decref(edge);
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 */
634 struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
636 can_spin_irqflags_t flags;
637 struct list_head *entry;
638 struct canque_edge_t *edge;
640 can_spin_lock_irqsave(&qends->ends_lock, flags);
641 entry=qends->inlist.next;
643 if(entry != &qends->inlist) {
644 edge=list_entry(entry,struct canque_edge_t,inpeers);
645 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
649 canque_edge_incref(edge);
653 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
659 struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
661 can_spin_irqflags_t flags;
662 struct list_head *entry;
663 struct canque_edge_t *next;
665 can_spin_lock_irqsave(&qends->ends_lock, flags);
666 entry=edge->inpeers.next;
668 if(entry != &qends->inlist) {
669 next=list_entry(entry,struct canque_edge_t,inpeers);
670 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
674 canque_edge_incref(next);
678 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
679 canque_edge_decref(edge);
683 #define canque_for_each_inedge(qends, edge) \
684 for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
687 struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends)
689 can_spin_irqflags_t flags;
690 struct list_head *entry;
691 struct canque_edge_t *edge;
693 can_spin_lock_irqsave(&qends->ends_lock, flags);
694 entry=qends->outlist.next;
696 if(entry != &qends->outlist) {
697 edge=list_entry(entry,struct canque_edge_t,outpeers);
698 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
702 canque_edge_incref(edge);
706 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
712 struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
714 can_spin_irqflags_t flags;
715 struct list_head *entry;
716 struct canque_edge_t *next;
718 can_spin_lock_irqsave(&qends->ends_lock, flags);
719 entry=edge->outpeers.next;
721 if(entry != &qends->outlist) {
722 next=list_entry(entry,struct canque_edge_t,outpeers);
723 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
727 canque_edge_incref(next);
731 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
732 canque_edge_decref(edge);
736 #define canque_for_each_outedge(qends, edge) \
737 for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge))
739 /* Linux kernel specific functions */
741 int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr);
743 int canque_fifo_done_kern(struct canque_fifo_t *fifo);
745 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
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);
751 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
752 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
754 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
756 int canqueue_ends_init_kern(struct canque_ends_t *qends);
758 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
760 void canqueue_ends_dispose_postpone(struct canque_ends_t *qends);
762 void canqueue_kern_initialize(void);
766 extern struct tasklet_struct canque_dead_tl; /*publication required only for RTL*/
768 /* RT-Linux specific functions and variables */
770 extern int canqueue_rtl_irq;
772 extern unsigned long canqueue_rtl2lin_pend;
774 #define CAN_RTL2LIN_PEND_DEAD_b 0
776 void canqueue_rtl_initialize(void);
777 void canqueue_rtl_done(void);
779 int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
780 struct canque_edge_t *qedge, int what);
782 struct canque_edge_t *canque_new_edge_rtl(int slotsnr);
784 void canque_dispose_edge_rtl(struct canque_edge_t *qedge);
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);
790 int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
791 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
793 int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge);
795 void canque_ends_free_rtl(struct canque_ends_t *qends);
797 int canqueue_ends_init_rtl(struct canque_ends_t *qends);
799 int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync);
801 #else /*CAN_WITH_RTL*/
803 static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
804 struct canque_edge_t *qedge, int what) { return 0; }
806 #endif /*CAN_WITH_RTL*/
809 #endif /*_CAN_QUEUE_H*/