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.
43 * This structure represents CAN FIFO queue. It is implemented as
44 * a single linked list of slots prepared for processing. The empty slots
45 * are stored in single linked list (@flist).
47 struct canque_fifo_t {
48 unsigned long fifo_flags;
49 unsigned long error_code;
50 struct canque_slot_t *head; /* points to the oldest entry */
51 struct canque_slot_t **tail; /* points to NULL pointer for chaining */
52 struct canque_slot_t *flist; /* points the first entry in the free list */
53 struct canque_slot_t *entry; /* points to first allocated entry */
54 spinlock_t fifo_lock; /* spin_lock_irqsave / spin_lock_irqrestore */
57 #define CAN_FIFOF_DESTROY_b 15
58 #define CAN_FIFOF_ERROR_b 14
59 #define CAN_FIFOF_ERR2BLOCK_b 13
60 #define CAN_FIFOF_BLOCK_b 12
61 #define CAN_FIFOF_OVERRUN_b 11
62 #define CAN_FIFOF_FULL_b 10
63 #define CAN_FIFOF_EMPTY_b 9
64 #define CAN_FIFOF_DEAD_b 8
65 #define CAN_FIFOF_INACTIVE_b 7
66 #define CAN_FIFOF_FREEONEMPTY_b 6
67 #define CAN_FIFOF_READY_b 5
69 #define CAN_FIFOF_DESTROY (1<<CAN_FIFOF_DESTROY_b)
70 #define CAN_FIFOF_ERROR (1<<CAN_FIFOF_ERROR_b)
71 #define CAN_FIFOF_ERR2BLOCK (1<<CAN_FIFOF_ERR2BLOCK_b)
72 #define CAN_FIFOF_BLOCK (1<<CAN_FIFOF_BLOCK_b)
73 #define CAN_FIFOF_OVERRUN (1<<CAN_FIFOF_OVERRUN_b)
74 #define CAN_FIFOF_FULL (1<<CAN_FIFOF_FULL_b)
75 #define CAN_FIFOF_EMPTY (1<<CAN_FIFOF_EMPTY_b)
76 #define CAN_FIFOF_DEAD (1<<CAN_FIFOF_DEAD_b)
77 #define CAN_FIFOF_INACTIVE (1<<CAN_FIFOF_INACTIVE_b)
78 #define CAN_FIFOF_FREEONEMPTY (1<<CAN_FIFOF_FREEONEMPTY_b)
79 #define CAN_FIFOF_READY (1<<CAN_FIFOF_READY_b)
81 #define canque_fifo_test_fl(fifo,fifo_fl) \
82 test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
83 #define canque_fifo_set_fl(fifo,fifo_fl) \
84 set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
85 #define canque_fifo_clear_fl(fifo,fifo_fl) \
86 clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
87 #define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
88 test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
89 #define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
90 test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
94 * canque_fifo_get_inslot - allocate slot for the input of one CAN message
95 * @fifo: pointer to the FIFO structure
96 * @slotp: pointer to location to store pointer to the allocated slot.
97 * @cmd: optional command associated with allocated slot.
99 * Return Value: The function returns negative value if there is no
100 * free slot in the FIFO queue.
103 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
106 struct canque_slot_t *slot;
107 spin_lock_irqsave(&fifo->fifo_lock, flags);
108 /* get the first free slot slot from flist */
109 if(!(slot=fifo->flist)) {
110 canque_fifo_set_fl(fifo,OVERRUN);
111 canque_fifo_set_fl(fifo,FULL);
112 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
116 /* adjust free slot list */
117 if(!(fifo->flist=slot->next))
118 canque_fifo_set_fl(fifo,FULL);
119 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
121 slot->slot_flags=cmd&CAN_SLOTF_CMD;
126 * canque_fifo_put_inslot - releases slot to further processing
127 * @fifo: pointer to the FIFO structure
128 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
130 * Return Value: The nonzero return value indicates, that the queue was empty
131 * before call to the function. The caller should wake-up output side of the queue.
134 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
139 spin_lock_irqsave(&fifo->fifo_lock, flags);
140 if(*fifo->tail) printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
142 fifo->tail=&slot->next;
144 if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
145 ret=CAN_FIFOF_EMPTY; /* Fifo has been empty before put */
146 if(canque_fifo_test_and_clear_fl(fifo,INACTIVE))
147 ret=CAN_FIFOF_INACTIVE; /* Fifo has been empty before put */
148 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
153 * canque_fifo_abort_inslot - release and abort slot
154 * @fifo: pointer to the FIFO structure
155 * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
157 * Return Value: The nonzero value indicates, that fifo was full
160 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
164 spin_lock_irqsave(&fifo->fifo_lock, flags);
165 slot->next=fifo->flist;
167 if(canque_fifo_test_and_clear_fl(fifo,FULL))
169 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
174 * canque_fifo_test_outslot - test and get ready slot from the FIFO
175 * @fifo: pointer to the FIFO structure
176 * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
178 * Return Value: The negative value indicates, that queue is empty.
179 * The positive or zero value represents command stored into slot by
180 * the call to the function canque_fifo_get_inslot().
181 * The successfully acquired FIFO output slot has to be released by
182 * the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
185 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
189 struct canque_slot_t *slot;
190 spin_lock_irqsave(&fifo->fifo_lock, flags);
191 if(!(slot=fifo->head)){;
192 canque_fifo_set_fl(fifo,EMPTY);
193 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
197 if(!(fifo->head=slot->next))
198 fifo->tail=&fifo->head;
199 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
202 cmd=slot->slot_flags;
203 return cmd&CAN_SLOTF_CMD;
208 * canque_fifo_free_outslot - free processed FIFO slot
209 * @fifo: pointer to the FIFO structure
210 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
212 * Return Value: The returned value informs about FIFO state change.
213 * The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
214 * the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
215 * has been processed.
218 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
222 spin_lock_irqsave(&fifo->fifo_lock, flags);
223 slot->next=fifo->flist;
225 if(canque_fifo_test_and_clear_fl(fifo,FULL))
228 canque_fifo_set_fl(fifo,EMPTY);
229 ret|=CAN_FIFOF_EMPTY;
231 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
236 * canque_fifo_again_outslot - interrupt and postpone processing of the slot
237 * @fifo: pointer to the FIFO structure
238 * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
240 * Return Value: The function cannot fail..
243 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
246 spin_lock_irqsave(&fifo->fifo_lock, flags);
247 if(!(slot->next=fifo->head))
248 fifo->tail=&slot->next;
250 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
254 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
256 int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr);
258 int canque_fifo_done(struct canque_fifo_t *fifo);
260 #define CANQUEUE_PRIO_NR 3
262 /* Forward declarations for external types */
267 * struct canque_edge_t - CAN message delivery subsystem graph edge
268 * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
269 * @filtid: the possible CAN message identifiers filter.
270 * @filtmask: the filter mask, the comparison considers only
271 * @filtid bits corresponding to set bits in the @filtmask field.
272 * @inpeers: the lists of all peer FIFOs connected by their
273 * input side (@inends) to the same terminal (@struct canque_ends_t).
274 * @outpeers: the lists of all peer FIFOs connected by their
275 * output side (@outends) to the same terminal (@struct canque_ends_t).
276 * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
277 * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
278 * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
279 * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
280 * @edge_num: edge sequential number intended for debugging purposes only
282 * This structure represents one direction connection from messages source
283 * (@inends) to message consumer (@outends) fifo ends hub. The edge contains
284 * &struct canque_fifo_t for message fifo implementation.
286 struct canque_edge_t {
287 struct canque_fifo_t fifo;
288 unsigned long filtid;
289 unsigned long filtmask;
290 struct list_head inpeers;
291 struct list_head outpeers;
292 struct canque_ends_t *inends;
293 struct canque_ends_t *outends;
300 * struct canque_ends_t - CAN message delivery subsystem graph vertex (FIFO ends)
301 * @ends_flags: this field holds flags describing state of the ENDS structure.
302 * @active: the array of the lists of active edges directed to the ends structure
303 * with ready messages. The array is indexed by the edges priorities.
304 * @idle: the list of the edges directed to the ends structure with empty FIFOs.
305 * @inlist: the list of outgoing edges input sides.
306 * @ends_lock: the lock synchronizing operations between threads accessing
307 * same ends structure.
308 * @notify: pointer to notify procedure. The next state changes are notified.
309 * %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side.
310 * %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
311 * %CANQUEUE_NOTIFY_PROC (in->out call) - empty state negated => out side is requested to process slots.
312 * %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
313 * called with some lock to prevent edge disappear.
314 * %CANQUEUE_NOTIFY_DEAD (both) - edge is in progress of deletion.
315 * %CANQUEUE_NOTIFY_ATACH (both) - new edge has been attached to end.
316 * %CANQUEUE_NOTIFY_FILTCH (out->in call) - edge filter rules changed
317 * %CANQUEUE_NOTIFY_ERROR (out->in call) - error in messages processing.
318 * @context: space to store ends user specific information
319 * @endinfo: space to store some other ends usage specific informations
320 * mainly for waking-up by the notify calls.
322 * Structure represents place to connect edges to for CAN communication entity.
323 * The zero, one or more incoming and outgoing edges can be connected to
326 struct canque_ends_t {
327 unsigned long ends_flags;
328 struct list_head active[CANQUEUE_PRIO_NR];
329 struct list_head idle;
330 struct list_head inlist;
331 spinlock_t ends_lock; /* spin_lock_irqsave / spin_lock_irqrestore */
332 void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
336 wait_queue_head_t readq;
337 wait_queue_head_t writeq;
338 wait_queue_head_t emptyq;
341 wait_queue_head_t daemonq;
342 struct msgobj_t *msgobj;
346 struct list_head dead_peers;
349 #define CANQUEUE_NOTIFY_EMPTY 1 /* out -> in - all slots are processed by FIFO out side */
350 #define CANQUEUE_NOTIFY_SPACE 2 /* out -> in - full state negated => there is space for new message */
351 #define CANQUEUE_NOTIFY_PROC 3 /* in -> out - empty state negated => out side is requested to process slots */
352 #define CANQUEUE_NOTIFY_NOUSR 4 /* called with some lock to prevent edge disappear */
353 #define CANQUEUE_NOTIFY_DEAD 5 /* */
354 #define CANQUEUE_NOTIFY_DEAD_WANTED 6 /* */
355 #define CANQUEUE_NOTIFY_ATTACH 7 /* */
356 #define CANQUEUE_NOTIFY_FILTCH 8 /* filter changed */
357 #define CANQUEUE_NOTIFY_ERROR 0x10000 /* error notifiers */
358 #define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
359 #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
360 #define CANQUEUE_NOTIFY_ERRTX_BUS 0x11003 /* tx bus error */
362 #define CAN_ENDSF_DEAD (1<<0)
365 * canque_notify_inends - request to send notification to the input ends
366 * @qedge: pointer to the edge structure
367 * @what: notification type
370 void canque_notify_inends(struct canque_edge_t *qedge, int what)
373 if(qedge->inends->notify)
374 qedge->inends->notify(qedge->inends,qedge,what);
378 * canque_notify_outends - request to send notification to the output ends
379 * @qedge: pointer to the edge structure
380 * @what: notification type
383 void canque_notify_outends(struct canque_edge_t *qedge, int what)
386 if(qedge->outends->notify)
387 qedge->outends->notify(qedge->outends,qedge,what);
391 * canque_notify_bothends - request to send notification to the both ends
392 * @qedge: pointer to the edge structure
393 * @what: notification type
396 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
398 canque_notify_inends(qedge, what);
399 canque_notify_outends(qedge, what);
403 * canque_activate_edge - mark output end of the edge as active
404 * @qedge: pointer to the edge structure
405 * @inends: input side of the edge
407 * Function call moves output side of the edge from idle onto active edges
411 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
414 struct canque_ends_t *outends;
415 if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
416 qedge->edge_prio=CANQUEUE_PRIO_NR-1;
417 spin_lock_irqsave(&inends->ends_lock, flags);
418 if((outends=qedge->outends)){
419 spin_lock(&outends->ends_lock);
420 spin_lock(&qedge->fifo.fifo_lock);
421 if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
422 list_del(&qedge->outpeers);
423 list_add_tail(&qedge->outpeers,&outends->active[qedge->edge_prio]);
425 spin_unlock(&qedge->fifo.fifo_lock);
426 spin_unlock(&outends->ends_lock);
429 spin_unlock_irqrestore(&inends->ends_lock, flags);
433 * canque_filtid2internal - converts message ID and filter flags into internal format
434 * @id: CAN message 11 or 29 bit identifier
435 * @filtflags: CAN message flags
437 * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
440 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
442 filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
443 filtflags += filtflags&MSG_RTR;
444 return (id&MSG_ID_MASK) | (filtflags<<28);
447 int canque_get_inslot(struct canque_ends_t *qends,
448 struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
450 int canque_get_inslot4id(struct canque_ends_t *qends,
451 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
452 int cmd, unsigned long id, int prio);
454 int canque_put_inslot(struct canque_ends_t *qends,
455 struct canque_edge_t *qedge, struct canque_slot_t *slot);
457 int canque_abort_inslot(struct canque_ends_t *qends,
458 struct canque_edge_t *qedge, struct canque_slot_t *slot);
460 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
462 int canque_test_outslot(struct canque_ends_t *qends,
463 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
465 int canque_free_outslot(struct canque_ends_t *qends,
466 struct canque_edge_t *qedge, struct canque_slot_t *slot);
468 int canque_again_outslot(struct canque_ends_t *qends,
469 struct canque_edge_t *qedge, struct canque_slot_t *slot);
471 int canque_set_filt(struct canque_edge_t *qedge,
472 unsigned long filtid, unsigned long filtmask, int flags);
474 int canque_flush(struct canque_edge_t *qedge);
476 int canqueue_disconnect_edge(struct canque_edge_t *qedge);
478 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
480 int canqueue_ends_init_gen(struct canque_ends_t *qends);
483 /* edge reference and traversal functions */
485 void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl);
488 void canque_edge_incref(struct canque_edge_t *edge)
490 atomic_inc(&edge->edge_used);
494 void canque_edge_decref(struct canque_edge_t *edge)
497 struct canque_ends_t *inends=edge->inends;
498 struct canque_ends_t *outends=edge->outends;
501 spin_lock_irqsave(&inends->ends_lock, flags);
502 spin_lock(&outends->ends_lock);
503 if(atomic_dec_and_test(&edge->edge_used)) {
504 dead_fl=canque_fifo_test_and_set_fl(&edge->fifo,DEAD);
505 /*This should not be there, but it cannot be outside of the lock :-(*/
506 canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
507 spin_unlock(&outends->ends_lock);
508 spin_unlock_irqrestore(&inends->ends_lock, flags);
509 canque_edge_do_dead(edge, dead_fl);
511 spin_unlock(&outends->ends_lock);
512 spin_unlock_irqrestore(&inends->ends_lock, flags);
517 struct canque_edge_t *canque_first_inedge(struct canque_ends_t *qends)
520 struct list_head *entry;
521 struct canque_edge_t *edge;
523 spin_lock_irqsave(&qends->ends_lock, flags);
524 entry=qends->inlist.next;
526 if(entry != &qends->inlist) {
527 edge=list_entry(entry,struct canque_edge_t,inpeers);
528 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
532 canque_edge_incref(edge);
536 spin_unlock_irqrestore(&qends->ends_lock, flags);
542 struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct canque_edge_t *edge)
545 struct list_head *entry;
546 struct canque_edge_t *next;
548 spin_lock_irqsave(&qends->ends_lock, flags);
549 entry=edge->inpeers.next;
551 if(entry != &qends->inlist) {
552 next=list_entry(entry,struct canque_edge_t,inpeers);
553 if(canque_fifo_test_fl(&edge->fifo,DEAD)) {
557 canque_edge_incref(next);
561 spin_unlock_irqrestore(&qends->ends_lock, flags);
562 canque_edge_decref(edge);
566 #define canque_for_each_inedge(qends, edge) \
567 for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge))
569 /* Linux kernel specific functions */
571 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
573 int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
574 struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
575 int cmd, unsigned long id, int prio);
577 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
578 struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
580 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
582 int canqueue_ends_init_kern(struct canque_ends_t *qends);
584 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync);
586 void canqueue_kern_initialize(void);
589 #endif /*_CAN_QUEUE_H*/