]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/can_quekern.c
Added missing indication CAN_ENDSF_MEM_RTL for RTL pool malloc.
[lincan.git] / lincan / src / can_quekern.c
index 39c033070fa5b042f03d967af53c2db4d944554f..5089e5cbc2c8aec6cbc9ad95d51385c4afd65ff3 100644 (file)
 extern atomic_t edge_num_cnt;
 
 #ifdef CAN_DEBUG
-       #define DEBUGQUE(fmt,args...) can_printk(KERN_ERR "can_queue (debug): " fmt,\
+       #define DEBUGQUE(fmt,args...) can_printk(KERN_ERR "can_quekern (debug): " fmt,\
        ##args)
 
 #else
        #define DEBUGQUE(fmt,args...)
 #endif
 
-#define ERRMSGQUE(fmt,args...) can_printk(KERN_ERR "can_queue: " fmt,\
+#define ERRMSGQUE(fmt,args...) can_printk(KERN_ERR "can_quekern: " fmt,\
        ##args)
 
 
@@ -84,8 +84,10 @@ void canque_dead_func(unsigned long data)
        can_spin_lock_irqsave(&canque_dead_func_lock, flags);
        entry=canque_dead_ends.next;
        can_spin_unlock_irqrestore(&canque_dead_func_lock,flags);
+       /* lock can be released there, because only one instance of canque_dead_tl
+          can run at once and all other functions add ends only to head */
        while(entry!=&canque_dead_ends){
-               qends=list_entry(canque_dead_ends.next,struct canque_ends_t,dead_peers);
+               qends=list_entry(entry,struct canque_ends_t,dead_peers);
                entry=entry->next;
                if(!list_empty(&qends->inlist))
                        continue;
@@ -106,6 +108,19 @@ void canque_dead_func(unsigned long data)
 
 }
 
+static inline void canque_dead_tasklet_schedule(void)
+{
+    #ifdef CAN_WITH_RTL
+       if(!rtl_rt_system_is_idle()){
+               set_bit(CAN_RTL2LIN_PEND_DEAD_b,&canqueue_rtl2lin_pend);
+               rtl_global_pend_irq (canqueue_rtl_irq);
+               return;
+       }
+    #endif /*CAN_WITH_RTL*/
+
+       tasklet_schedule(&canque_dead_tl);
+}
+
 
 void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl)
 {
@@ -113,6 +128,27 @@ void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl)
        
        if(dead_fl) return;
        
+       canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
+    #ifdef CAN_WITH_RTL
+       /* The problem of the above call is, that in RT-Linux to Linux notify
+          case is edge scheduled for delayed notify delivery, this needs
+          to be reflected there */
+       if(atomic_read(&edge->edge_used)>0){
+               can_spin_lock_irqsave(&edge->inends->ends_lock, flags);
+               can_spin_lock(&edge->outends->ends_lock);
+               if(atomic_read(&edge->edge_used)>0){
+                       /* left edge to live for a while, banshee comes again in a while */
+                       canque_fifo_clear_fl(&edge->fifo,DEAD);
+                       can_spin_unlock(&edge->outends->ends_lock);
+                       can_spin_unlock_irqrestore(&edge->inends->ends_lock, flags);
+                       can_printk(KERN_ERR "can_quertl (debug): canque_edge_do_dead postponed\n");
+                       return;
+               }
+               can_spin_unlock(&edge->outends->ends_lock);
+               can_spin_unlock_irqrestore(&edge->inends->ends_lock, flags);
+       }
+    #endif /*CAN_WITH_RTL*/
+       
        if(canqueue_disconnect_edge(edge)<0){
                ERRMSGQUE("canque_edge_do_dead: canqueue_disconnect_edge failed !!!\n");
                return;
@@ -121,7 +157,7 @@ void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl)
        can_spin_lock_irqsave(&canque_dead_func_lock, flags);
        list_add(&edge->inpeers,&canque_dead_edges);
        can_spin_unlock_irqrestore(&canque_dead_func_lock, flags);
-       tasklet_schedule(&canque_dead_tl);
+       canque_dead_tasklet_schedule();
 }
 
 
@@ -427,7 +463,7 @@ void canqueue_ends_dispose_postpone(struct canque_ends_t *qends)
        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);
+       canque_dead_tasklet_schedule();
 }