X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/cc1811f284f00d214e198cb20b466d261201385b..b34a548a5dfd2f0b068fd835a4cd51680d851068:/lincan/src/can_quekern.c diff --git a/lincan/src/can_quekern.c b/lincan/src/can_quekern.c index 8725f64..39c0330 100644 --- a/lincan/src/can_quekern.c +++ b/lincan/src/can_quekern.c @@ -15,14 +15,14 @@ extern atomic_t edge_num_cnt; #ifdef CAN_DEBUG - #define DEBUGQUE(fmt,args...) printk(KERN_ERR "can_queue (debug): " fmt,\ + #define DEBUGQUE(fmt,args...) can_printk(KERN_ERR "can_queue (debug): " fmt,\ ##args) #else #define DEBUGQUE(fmt,args...) #endif -#define ERRMSGQUE(fmt,args...) printk(KERN_ERR "can_queue: " fmt,\ +#define ERRMSGQUE(fmt,args...) can_printk(KERN_ERR "can_queue: " fmt,\ ##args) @@ -71,6 +71,13 @@ void canque_dead_func(unsigned long data) while((qedge=canque_dead_edges_cut_first())){ DEBUGQUE("edge %d disposed\n",qedge->edge_num); + #ifdef CAN_WITH_RTL + if(canque_fifo_test_fl(&qedge->fifo,RTL_MEM)){ + canque_dispose_edge_rtl(qedge); + continue; + } + #endif /*CAN_WITH_RTL*/ + canque_fifo_done_kern(&qedge->fifo); kfree(qedge); } @@ -88,6 +95,12 @@ void canque_dead_func(unsigned long data) list_del(&qends->dead_peers); can_spin_unlock_irqrestore(&canque_dead_func_lock,flags); DEBUGQUE("ends structure disposed\n"); + #ifdef CAN_WITH_RTL + if(qends->ends_flags&CAN_ENDSF_MEM_RTL){ + canque_ends_free_rtl(qends); + continue; + } + #endif /*CAN_WITH_RTL*/ kfree(qends); } @@ -132,6 +145,13 @@ void canqueue_notify_kern(struct canque_ends_t *qends, struct canque_edge_t *qed { DEBUGQUE("canqueue_notify_kern for edge %d, use %d and event %d\n", qedge->edge_num,(int)atomic_read(&qedge->edge_used),what); + + /* delay event delivery for RT-Linux -> kernel notifications */ + if(canqueue_rtl2lin_check_and_pend(qends,qedge,what)){ + DEBUGQUE("canqueue_notify_kern postponed\n"); + return; + } + switch(what){ case CANQUEUE_NOTIFY_EMPTY: wake_up(&qends->endinfo.fileinfo.emptyq); @@ -253,6 +273,38 @@ int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qed } +/** + * canque_fifo_init_kern - initialize one CAN FIFO + * @fifo: pointer to the FIFO structure + * @slotsnr: number of requested slots + * + * Return Value: The negative value indicates, that there is no memory + * to allocate space for the requested number of the slots. + */ +int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr) +{ + int size; + if(!slotsnr) slotsnr=MAX_BUF_LENGTH; + size=sizeof(struct canque_slot_t)*slotsnr; + fifo->entry=kmalloc(size,GFP_KERNEL); + if(!fifo->entry) return -1; + fifo->slotsnr=slotsnr; + return canque_fifo_init_slots(fifo); +} + +/** + * canque_fifo_done_kern - frees slots allocated for CAN FIFO + * @fifo: pointer to the FIFO structure + */ +int canque_fifo_done_kern(struct canque_fifo_t *fifo) +{ + if(fifo->entry) + kfree(fifo->entry); + fifo->entry=NULL; + return 1; +} + + /** * canque_new_edge_kern - allocate new edge structure in the Linux kernel context * @slotsnr: required number of slots in the newly allocated edge structure @@ -268,7 +320,7 @@ struct canque_edge_t *canque_new_edge_kern(int slotsnr) memset(qedge,0,sizeof(struct canque_edge_t)); can_spin_lock_init(&qedge->fifo.fifo_lock); - if(canque_fifo_init_slots(&qedge->fifo, slotsnr)<0){ + if(canque_fifo_init_kern(&qedge->fifo, slotsnr)<0){ kfree(qedge); DEBUGQUE("canque_new_edge_kern failed\n"); return NULL; @@ -340,7 +392,7 @@ int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head can_spin_unlock_irqrestore(&qends->ends_lock,flags); if(canqueue_disconnect_edge_kern(qends, edge)>=0) { /* Free edge memory */ - canque_fifo_done(&edge->fifo); + canque_fifo_done_kern(&edge->fifo); kfree(edge); }else{ canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED); @@ -366,6 +418,19 @@ int canqueue_ends_sync_all_kern(struct canque_ends_t *qends) return 0; } + +void canqueue_ends_dispose_postpone(struct canque_ends_t *qends) +{ + can_spin_irqflags_t flags; + + can_spin_lock_irqsave(&canque_dead_func_lock, flags); + qends->ends_flags |= CAN_ENDSF_DEAD; + list_add(&qends->dead_peers,&canque_dead_ends); + can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); + tasklet_schedule(&canque_dead_tl); +} + + /** * canqueue_ends_dispose_kern - finalizing of the ends structure for Linux kernel clients * @qends: pointer to ends structure @@ -376,7 +441,6 @@ int canqueue_ends_sync_all_kern(struct canque_ends_t *qends) */ int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync) { - can_spin_irqflags_t flags; int delayed; DEBUGQUE("canqueue_ends_dispose_kern\n"); @@ -397,11 +461,7 @@ int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync) wake_up(&qends->endinfo.fileinfo.emptyq); if(delayed){ - can_spin_lock_irqsave(&canque_dead_func_lock, flags); - qends->ends_flags |= CAN_ENDSF_DEAD; - list_add(&qends->dead_peers,&canque_dead_ends); - can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); - tasklet_schedule(&canque_dead_tl); + canqueue_ends_dispose_postpone(qends); DEBUGQUE("canqueue_ends_dispose_kern delayed\n"); return 1;