1 /**************************************************************************/
2 /* File: can_queue.h - CAN queues and message passing infrastructure */
4 /* LinCAN - (Not only) Linux CAN bus driver */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
7 /* Funded by OCERA and FRESCOR IST projects */
9 /* LinCAN is free software; you can redistribute it and/or modify it */
10 /* under terms of the GNU General Public License as published by the */
11 /* Free Software Foundation; either version 2, or (at your option) any */
12 /* later version. LinCAN is distributed in the hope that it will be */
13 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
14 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
15 /* General Public License for more details. You should have received a */
16 /* copy of the GNU General Public License along with LinCAN; see file */
17 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
18 /* Cambridge, MA 02139, USA. */
20 /* To allow use of LinCAN in the compact embedded systems firmware */
21 /* and RT-executives (RTEMS for example), main authors agree with next */
22 /* special exception: */
24 /* Including LinCAN header files in a file, instantiating LinCAN generics */
25 /* or templates, or linking other files with LinCAN objects to produce */
26 /* an application image/executable, does not by itself cause the */
27 /* resulting application image/executable to be covered by */
28 /* the GNU General Public License. */
29 /* This exception does not however invalidate any other reasons */
30 /* why the executable file might be covered by the GNU Public License. */
31 /* Publication of enhanced or derived LinCAN files is required although. */
32 /**************************************************************************/
38 #include "./constants.h"
39 #include "./can_sysdep.h"
42 * struct canque_slot_t - one CAN message slot in the CAN FIFO queue
43 * @next: pointer to the next/younger slot
44 * @slot_flags: space for flags and optional command describing action
45 * associated with slot data
46 * @msg: space for one CAN message
48 * This structure is used to store CAN messages in the CAN FIFO queue.
50 struct canque_slot_t {
51 struct canque_slot_t *next;
52 unsigned long slot_flags;
56 #define CAN_SLOTF_CMD 0x00ff /* */
59 * struct canque_fifo_t - CAN FIFO queue representation
60 * @fifo_flags: this field holds global flags describing state of the FIFO.
61 * %CAN_FIFOF_ERROR is set when some error condition occurs.
62 * %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
63 * %CAN_FIFOF_BLOCK state blocks insertion of the next messages.
64 * %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full.
65 * %CAN_FIFOF_FULL indicates FIFO full state.
66 * %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
67 * %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
68 * @error_code: futher description of error condition
69 * @head: pointer to the FIFO head, oldest slot
70 * @tail: pointer to the location, where pointer to newly inserted slot
72 * @flist: pointer to list of the free slots associated with queue
73 * @entry: pointer to the memory allocated for the list slots.
74 * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
75 * @slotsnr: number of allocated slots
77 * This structure represents CAN FIFO queue. It is implemented as
78 * a single linked list of slots prepared for processing. The empty slots
79 * are stored in single linked list (@flist).
81 struct canque_fifo_t {
82 unsigned long fifo_flags;
83 unsigned long error_code;
84 struct canque_slot_t *head; /* points to the oldest entry */
85 struct canque_slot_t **tail; /* points to NULL pointer for chaining */
86 struct canque_slot_t *flist; /* points the first entry in the free list */
87 struct canque_slot_t *entry; /* points to first allocated entry */
88 can_spinlock_t fifo_lock; /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
92 #define CAN_FIFOF_DESTROY_b 15
93 #define CAN_FIFOF_ERROR_b 14
94 #define CAN_FIFOF_ERR2BLOCK_b 13
95 #define CAN_FIFOF_BLOCK_b 12
96 #define CAN_FIFOF_OVERRUN_b 11
97 #define CAN_FIFOF_FULL_b 10
98 #define CAN_FIFOF_EMPTY_b 9
99 #define CAN_FIFOF_DEAD_b 8
100 #define CAN_FIFOF_INACTIVE_b 7
101 #define CAN_FIFOF_FREEONEMPTY_b 6
102 #define CAN_FIFOF_READY_b 5
103 #define CAN_FIFOF_NOTIFYPEND_b 4
104 #define CAN_FIFOF_RTL_MEM_b 3
106 #define CAN_FIFOF_DESTROY (1<<CAN_FIFOF_DESTROY_b)
107 #define CAN_FIFOF_ERROR (1<<CAN_FIFOF_ERROR_b)
108 #define CAN_FIFOF_ERR2BLOCK (1<<CAN_FIFOF_ERR2BLOCK_b)
109 #define CAN_FIFOF_BLOCK (1<<CAN_FIFOF_BLOCK_b)
110 #define CAN_FIFOF_OVERRUN (1<<CAN_FIFOF_OVERRUN_b)
111 #define CAN_FIFOF_FULL (1<<CAN_FIFOF_FULL_b)
112 #define CAN_FIFOF_EMPTY (1<<CAN_FIFOF_EMPTY_b)
113 #define CAN_FIFOF_DEAD (1<<CAN_FIFOF_DEAD_b)
114 #define CAN_FIFOF_INACTIVE (1<<CAN_FIFOF_INACTIVE_b)
115 #define CAN_FIFOF_FREEONEMPTY (1<<CAN_FIFOF_FREEONEMPTY_b)
116 #define CAN_FIFOF_READY (1<<CAN_FIFOF_READY_b)
117 #define CAN_FIFOF_NOTIFYPEND (1<<CAN_FIFOF_NOTIFYPEND_b)
118 #define CAN_FIFOF_RTL_MEM (1<<CAN_FIFOF_RTL_MEM_b)
120 #define canque_fifo_test_fl(fifo,fifo_fl) \
121 test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
122 #define canque_fifo_set_fl(fifo,fifo_fl) \
123 set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
124 #define canque_fifo_clear_fl(fifo,fifo_fl) \
125 clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
126 #define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
127 test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
128 #define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
129 test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
133 * canque_fifo_get_inslot - allocate slot for the input of one CAN message
134 * @fifo: pointer to the FIFO structure
135 * @slotp: pointer to location to store pointer to the allocated slot.
136 * @cmd: optional command associated with allocated slot.
138 * Return Value: The function returns negative value if there is no
139 * free slot in the FIFO queue.
142 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
144 can_spin_irqflags_t flags;
145 struct canque_slot_t *slot;
146 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
147 /* get the first free slot slot from flist */
148 if(!(slot=fifo->flist)) {
149 canque_fifo_set_fl(fifo,OVERRUN);
150 canque_fifo_set_fl(fifo,FULL);
151 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
155 /* adjust free slot list */
156 if(!(fifo->flist=slot->next))
157 canque_fifo_set_fl(fifo,FULL);
158 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
160 slot->slot_flags=cmd&CAN_SLOTF_CMD;
165 * canque_fifo_put_inslot - releases slot to further processing
166 * @fifo: pointer to the FIFO structure
167 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
169 * Return Value: The nonzero return value indicates, that the queue was empty
170 * before call to the function. The caller should wake-up output side of the queue.
173 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
176 can_spin_irqflags_t flags;
178 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
179 if(*fifo->tail) can_printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
181 fifo->tail=&slot->next;
183 if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
184 ret=CAN_FIFOF_EMPTY; /* Fifo has been empty before put */
185 if(canque_fifo_test_and_clear_fl(fifo,INACTIVE))
186 ret=CAN_FIFOF_INACTIVE; /* Fifo has been empty before put */
187 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
192 * canque_fifo_abort_inslot - release and abort slot
193 * @fifo: pointer to the FIFO structure
194 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
196 * Return Value: The nonzero value indicates, that fifo was full
199 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
202 can_spin_irqflags_t flags;
203 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
204 slot->next=fifo->flist;
206 if(canque_fifo_test_and_clear_fl(fifo,FULL))
208 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
213 * canque_fifo_test_outslot - test and get ready slot from the FIFO
214 * @fifo: pointer to the FIFO structure
215 * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
217 * Return Value: The negative value indicates, that queue is empty.
218 * The positive or zero value represents command stored into slot by
219 * the call to the function canque_fifo_get_inslot().
220 * The successfully acquired FIFO output slot has to be released by
221 * the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
224 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
226 can_spin_irqflags_t flags;
228 struct canque_slot_t *slot;
229 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
230 if(!(slot=fifo->head)){;
231 canque_fifo_set_fl(fifo,EMPTY);
232 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
236 if(!(fifo->head=slot->next))
237 fifo->tail=&fifo->head;
238 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
241 cmd=slot->slot_flags;
242 return cmd&CAN_SLOTF_CMD;
247 * canque_fifo_free_outslot - free processed FIFO slot
248 * @fifo: pointer to the FIFO structure
249 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
251 * Return Value: The returned value informs about FIFO state change.
252 * The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
253 * the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
254 * has been processed.
257 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
260 can_spin_irqflags_t flags;
261 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
262 slot->next=fifo->flist;
264 if(canque_fifo_test_and_clear_fl(fifo,FULL))
267 canque_fifo_set_fl(fifo,EMPTY);
268 ret|=CAN_FIFOF_EMPTY;
270 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
275 * canque_fifo_again_outslot - interrupt and postpone processing of the slot
276 * @fifo: pointer to the FIFO structure
277 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
279 * Return Value: The function cannot fail..
282 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
284 can_spin_irqflags_t flags;
285 can_spin_lock_irqsave(&fifo->fifo_lock, flags);
286 if(!(slot->next=fifo->head))
287 fifo->tail=&slot->next;
289 can_spin_unlock_irqrestore(&fifo->fifo_lock, flags);
293 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
295 int canque_fifo_init_slots(struct canque_fifo_t *fifo);
297 #define CANQUEUE_PRIO_NR 3
299 /* Forward declarations for external types */
304 * struct canque_edge_t - CAN message delivery subsystem graph edge
305 * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
306 * @filtid: the possible CAN message identifiers filter.
307 * @filtmask: the filter mask, the comparison considers only
308 * @filtid bits corresponding to set bits in the @filtmask field.
309 * @inpeers: the lists of all peers FIFOs connected by their
310 * input side (@inends) to the same terminal (@struct canque_ends_t).
311 * @outpeers: the lists of all peers FIFOs connected by their
312 * output side (@outends) to the same terminal (@struct canque_ends_t).
313 * @activepeers: the lists of peers FIFOs connected by their
314 * output side (@outends) to the same terminal (@struct canque_ends_t)
315 * with same priority and active state.
316 * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
317 * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
318 * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
319 * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
320 * @edge_num: edge sequential number intended for debugging purposes only
321 * @pending_peers: edges with pending delayed events (RTL->Linux calls)
322 * @pending_inops: bitmask of pending operations
323 * @pending_outops: bitmask of pending operations
325 * This structure represents one direction connection from messages source
326 * (@inends) to message consumer (@outends) fifo ends hub. The edge contains
327 * &struct canque_fifo_t for message fifo implementation.
329 struct canque_edge_t {
330 struct canque_fifo_t fifo;
331 unsigned long filtid;
332 unsigned long filtmask;
333 struct list_head inpeers;
334 struct list_head outpeers;
335 struct list_head activepeers;
336 struct canque_ends_t *inends;
337 struct canque_ends_t *outends;
342 struct list_head pending_peers;
343 unsigned long pending_inops;
344 unsigned long pending_outops;
345 #endif /*CAN_WITH_RTL*/
349 * struct canque_ends_t - CAN message delivery subsystem graph vertex (FIFO ends)
350 * @ends_flags: this field holds flags describing state of the ENDS structure.
351 * @active: the array of the lists of active edges directed to the ends structure
352 * with ready messages. The array is indexed by the edges priorities.
353 * @idle: the list of the edges directed to the ends structure with empty FIFOs.
354 * @inlist: the list of outgoing edges input sides.
355 * @outlist: the list of all incoming edges output sides. Each of there edges
356 * is listed on one of @active or @idle lists.
357 * @ends_lock: the lock synchronizing operations between threads accessing
358 * same ends structure.
359 * @notify: pointer to notify procedure. The next state changes are notified.
360 * %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side.
361 * %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
362 * %CANQUEUE_NOTIFY_PROC (in->out call) - empty state negated => out side is requested to process slots.
363 * %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
364 * called with some lock to prevent edge disappear.
365 * %CANQUEUE_NOTIFY_DEAD (both) - edge is in progress of deletion.
366 * %CANQUEUE_NOTIFY_ATACH (both) - new edge has been attached to end.
367 * %CANQUEUE_NOTIFY_FILTCH (out->in call) - edge filter rules changed
368 * %CANQUEUE_NOTIFY_ERROR (out->in call) - error in messages processing.
369 * @context: space to store ends user specific information
370 * @endinfo: space to store some other ends usage specific informations
371 * mainly for waking-up by the notify calls.
372 * @dead_peers: used to chain ends wanting for postponed destruction
374 * Structure represents place to connect edges to for CAN communication entity.
375 * The zero, one or more incoming and outgoing edges can be connected to
378 struct canque_ends_t {
379 unsigned long ends_flags;
380 struct list_head active[CANQUEUE_PRIO_NR];
381 struct list_head idle;
382 struct list_head inlist;
383 struct list_head outlist;
384 can_spinlock_t ends_lock; /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */
385 void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
389 wait_queue_head_t readq;
390 wait_queue_head_t writeq;
391 wait_queue_head_t emptyq;
392 #ifdef CAN_ENABLE_KERN_FASYNC
393 struct fasync_struct *fasync;
394 #endif /*CAN_ENABLE_KERN_FASYNC*/
398 rtl_spinlock_t rtl_lock;
399 rtl_wait_t rtl_readq;
400 atomic_t rtl_readq_age;
401 rtl_wait_t rtl_writeq;
402 atomic_t rtl_writeq_age;
403 rtl_wait_t rtl_emptyq;
404 atomic_t rtl_emptyq_age;
405 unsigned long pend_flags;
407 #endif /*CAN_WITH_RTL*/
409 struct msgobj_t *msgobj;
410 struct canchip_t *chip;
412 wait_queue_head_t daemonq;
413 #else /*CAN_WITH_RTL*/
414 pthread_t worker_thread;
415 #endif /*CAN_WITH_RTL*/
418 struct list_head dead_peers;
421 #define CANQUEUE_NOTIFY_EMPTY 1 /* out -> in - all slots are processed by FIFO out side */
422 #define CANQUEUE_NOTIFY_SPACE 2 /* out -> in - full state negated => there is space for new message */
423 #define CANQUEUE_NOTIFY_PROC 3 /* in -> out - empty state negated => out side is requested to process slots */
424 #define CANQUEUE_NOTIFY_NOUSR 4 /* called with some lock to prevent edge disappear */
425 #define CANQUEUE_NOTIFY_DEAD 5 /* */
426 #define CANQUEUE_NOTIFY_DEAD_WANTED 6 /* */
427 #define CANQUEUE_NOTIFY_ATTACH 7 /* */
428 #define CANQUEUE_NOTIFY_FILTCH 8 /* filter changed */
429 #define CANQUEUE_NOTIFY_ERROR 0x10000 /* error notifiers */
430 #define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
431 #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
432 #define CANQUEUE_NOTIFY_ERRTX_BUS 0x11003 /* tx bus error */
434 #define CAN_ENDSF_DEAD (1<<0)
435 #define CAN_ENDSF_MEM_RTL (1<<1)
438 * canque_notify_inends - request to send notification to the input ends
439 * @qedge: pointer to the edge structure
440 * @what: notification type
443 void canque_notify_inends(struct canque_edge_t *qedge, int what)
446 if(qedge->inends->notify)
447 qedge->inends->notify(qedge->inends,qedge,what);
451 * canque_notify_outends - request to send notification to the output ends
452 * @qedge: pointer to the edge structure
453 * @what: notification type
456 void canque_notify_outends(struct canque_edge_t *qedge, int what)
459 if(qedge->outends->notify)
460 qedge->outends->notify(qedge->outends,qedge,what);
464 * canque_notify_bothends - request to send notification to the both ends
465 * @qedge: pointer to the edge structure
466 * @what: notification type
469 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
471 canque_notify_inends(qedge, what);
472 canque_notify_outends(qedge, what);
476 * canque_activate_edge - mark output end of the edge as active
477 * @qedge: pointer to the edge structure
478 * @inends: input side of the edge
480 * Function call moves output side of the edge from idle onto active edges
481 * list. This function has to be called with edge reference count held.
482 * that is same as for most of other edge functions.
485 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
487 can_spin_irqflags_t flags;
488 struct canque_ends_t *outends;
489 if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
490 qedge->edge_prio=CANQUEUE_PRIO_NR-1;
491 if((outends=qedge->outends)){
492 can_spin_lock_irqsave(&outends->ends_lock, flags);
493 can_spin_lock(&qedge->fifo.fifo_lock);
494 if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
495 list_del(&qedge->activepeers);
496 list_add_tail(&qedge->activepeers,&outends->active[qedge->edge_prio]);
498 can_spin_unlock(&qedge->fifo.fifo_lock);
499 can_spin_unlock_irqrestore(&outends->ends_lock, flags);
504 * canque_filtid2internal - converts message ID and filter flags into internal format
505 * @id: CAN message 11 or 29 bit identifier
506 * @filtflags: CAN message flags
508 * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
511 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
513 filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
514 filtflags += filtflags&MSG_RTR;
515 return (id&MSG_ID_MASK) | (filtflags<<28);
518 int canque_get_inslot(struct canque_ends_t *qends,
519 struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
521 int canque_get_inslot4id(struct canque_ends_t *qends,
522 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
523 int cmd, unsigned long id, int prio);
525 int canque_put_inslot(struct canque_ends_t *qends,
526 struct canque_edge_t *qedge, struct canque_slot_t *slot);
528 int canque_abort_inslot(struct canque_ends_t *qends,
529 struct canque_edge_t *qedge, struct canque_slot_t *slot);
531 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
533 int canque_test_outslot(struct canque_ends_t *qends,
534 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
536 int canque_free_outslot(struct canque_ends_t *qends,
537 struct canque_edge_t *qedge, struct canque_slot_t *slot);
539 int canque_again_outslot(struct canque_ends_t *qends,
540 struct canque_edge_t *qedge, struct canque_slot_t *slot);
542 int canque_set_filt(struct canque_edge_t *qedge,
543 unsigned long filtid, unsigned long filtmask, int flags);
545 int canque_flush(struct canque_edge_t *qedge);
547 int canqueue_disconnect_edge(struct canque_edge_t *qedge);
549 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
551 int canqueue_ends_init_gen(struct canque_ends_t *qends);
553 void canqueue_block_inlist(struct canque_ends_t *qends);
555 void canqueue_block_outlist(struct canque_ends_t *qends);
557 int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest);
559 int canqueue_ends_kill_outlist(struct canque_ends_t *qends);
561 int canqueue_ends_filt_conjuction(struct canque_ends_t *qends, struct canfilt_t *filt);
563 int canqueue_ends_flush_inlist(struct canque_ends_t *qends);
565 int canqueue_ends_flush_outlist(struct canque_ends_t *qends);
567 /* edge reference and traversal functions */
569 void canque_edge_do_dead(struct canque_edge_t *edge);
572 * canque_edge_incref - increments edge reference count
573 * @edge: pointer to the edge structure
576 void canque_edge_incref(struct canque_edge_t *edge)
578 atomic_inc(&edge->edge_used);
582 can_spin_irqflags_t canque_edge_lock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends)
584 can_spin_irqflags_t flags;
586 can_spin_lock_irqsave(&inends->ends_lock, flags);
587 can_spin_lock(&outends->ends_lock);
589 can_spin_lock_irqsave(&outends->ends_lock, flags);
590 if(outends!=inends) can_spin_lock(&inends->ends_lock);
596 void canque_edge_unlock_both_ends(struct canque_ends_t *inends, struct canque_ends_t *outends, can_spin_irqflags_t flags)
598 if(outends!=inends) can_spin_unlock(&outends->ends_lock);
599 can_spin_unlock_irqrestore(&inends->ends_lock, flags);
602 /* Non-inlined version of edge reference decrement */
603 void __canque_edge_decref(struct canque_edge_t *edge);
606 void __canque_edge_decref_body(struct canque_edge_t *edge)
608 can_spin_irqflags_t flags;
610 struct canque_ends_t *inends=edge->inends;
611 struct canque_ends_t *outends=edge->outends;
613 flags=canque_edge_lock_both_ends(inends, outends);
614 if(atomic_dec_and_test(&edge->edge_used)) {
615 dead_fl=!canque_fifo_test_and_set_fl(&edge->fifo,DEAD);
616 /* Because of former evolution of edge references
617 management notify of CANQUEUE_NOTIFY_NOUSR could
618 be moved to canque_edge_do_dead :-) */
620 canque_edge_unlock_both_ends(inends, outends, flags);
621 if(dead_fl) canque_edge_do_dead(edge);
624 #ifndef CAN_HAVE_ARCH_CMPXCHG
626 * canque_edge_decref - decrements edge reference count
627 * @edge: pointer to the edge structure
629 * This function has to be called without lock held for both ends of edge.
630 * If reference count drops to 0, function canque_edge_do_dead()
634 void canque_edge_decref(struct canque_edge_t *edge)
636 __canque_edge_decref_body(edge);
640 void canque_edge_decref(struct canque_edge_t *edge)
644 x = atomic_read(&edge->edge_used);
647 return __canque_edge_decref(edge);
649 #ifdef CAN_HAVE_ATOMIC_CMPXCHG
650 atomic_cmpxchg(&edge->edge_used, x, x-1);
651 #else /* workaround for case that atomic_cmpxchg is not defined */
652 /* This code strongly depends on the definition of atomic_t !!!! */
653 x=__cmpxchg(&edge->edge_used, x, x-1, sizeof(atomic_t));
654 /* If even this does not help, comment out CAN_HAVE_ARCH_CMPXCHG in can_sysdep.h */
661 struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
663 can_spin_irqflags_t flags;
664 struct list_head *entry;
665 struct canque_edge_t *edge;
667 can_spin_lock_irqsave(&qends->ends_lock, flags);
668 entry=qends->inlist.next;
670 if(entry != &qends->inlist) {
671 edge=list_entry(entry,struct canque_edge_t,inpeers);
672 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
676 canque_edge_incref(edge);
680 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
686 struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
688 can_spin_irqflags_t flags;
689 struct list_head *entry;
690 struct canque_edge_t *next;
692 can_spin_lock_irqsave(&qends->ends_lock, flags);
693 entry=edge->inpeers.next;
695 if(entry != &qends->inlist) {
696 next=list_entry(entry,struct canque_edge_t,inpeers);
697 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
701 canque_edge_incref(next);
705 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
706 canque_edge_decref(edge);
710 #define canque_for_each_inedge(qends, edge) \
711 for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
714 struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends)
716 can_spin_irqflags_t flags;
717 struct list_head *entry;
718 struct canque_edge_t *edge;
720 can_spin_lock_irqsave(&qends->ends_lock, flags);
721 entry=qends->outlist.next;
723 if(entry != &qends->outlist) {
724 edge=list_entry(entry,struct canque_edge_t,outpeers);
725 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
729 canque_edge_incref(edge);
733 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
739 struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
741 can_spin_irqflags_t flags;
742 struct list_head *entry;
743 struct canque_edge_t *next;
745 can_spin_lock_irqsave(&qends->ends_lock, flags);
746 entry=edge->outpeers.next;
748 if(entry != &qends->outlist) {
749 next=list_entry(entry,struct canque_edge_t,outpeers);
750 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
754 canque_edge_incref(next);
758 can_spin_unlock_irqrestore(&qends->ends_lock, flags);
759 canque_edge_decref(edge);
763 #define canque_for_each_outedge(qends, edge) \
764 for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge))
766 /* Linux kernel specific functions */
768 int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr);
770 int canque_fifo_done_kern(struct canque_fifo_t *fifo);
772 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
774 int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
775 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
776 int cmd, unsigned long id, int prio);
778 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
779 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
781 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
783 int canqueue_ends_init_kern(struct canque_ends_t *qends);
785 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
787 void canqueue_ends_dispose_postpone(struct canque_ends_t *qends);
789 void canqueue_kern_initialize(void);
793 extern struct tasklet_struct canque_dead_tl; /*publication required only for RTL*/
795 /* RT-Linux specific functions and variables */
797 extern int canqueue_rtl_irq;
799 extern unsigned long canqueue_rtl2lin_pend;
801 #define CAN_RTL2LIN_PEND_DEAD_b 0
803 void canqueue_rtl_initialize(void);
804 void canqueue_rtl_done(void);
806 int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
807 struct canque_edge_t *qedge, int what);
809 struct canque_edge_t *canque_new_edge_rtl(int slotsnr);
811 void canque_dispose_edge_rtl(struct canque_edge_t *qedge);
813 int canque_get_inslot4id_wait_rtl(struct canque_ends_t *qends,
814 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
815 int cmd, unsigned long id, int prio);
817 int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
818 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
820 int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge);
822 void canque_ends_free_rtl(struct canque_ends_t *qends);
824 int canqueue_ends_init_rtl(struct canque_ends_t *qends);
826 int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync);
828 #else /*CAN_WITH_RTL*/
830 static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends,
831 struct canque_edge_t *qedge, int what) { return 0; }
833 #endif /*CAN_WITH_RTL*/
836 #endif /*_CAN_QUEUE_H*/