]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/can_queue.c
Fixes for SMP kernels and build for 2.2.xx and 2.6.xx kernels
[lincan.git] / lincan / src / can_queue.c
index ad6160c54ef2150fd4428d79d1724f79c5f2d702..83b083933ddf6be9652acaeefd5ffa20155fa524 100644 (file)
@@ -239,6 +239,7 @@ int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg)
                edge=list_entry(entry,struct canque_edge_t,inpeers);
                if(canque_fifo_test_fl(&edge->fifo,BLOCK)||canque_fifo_test_fl(&edge->fifo,DEAD))
                        continue;
+               /* FIXME: the next comparison should be outside of ends lock */
                if((msg->id^edge->filtid)&edge->filtmask)
                        continue;
                atomic_inc(&edge->edge_used);
@@ -483,6 +484,7 @@ struct canque_edge_t *canque_new_edge_kern(int slotsnr)
        if(qedge == NULL) return NULL;
 
        memset(qedge,0,sizeof(struct canque_edge_t));
+       spin_lock_init(&qedge->fifo.fifo_lock);
        if(canque_fifo_init_slots(&qedge->fifo, slotsnr)<0){
                kfree(qedge);
                DEBUGQUE("canque_new_edge_kern failed\n");
@@ -530,8 +532,12 @@ int canqueue_disconnect_edge(struct canque_edge_t *qedge)
 {
        int ret;
        unsigned long flags;
-       spin_lock_irqsave(&qedge->inends->ends_lock,flags);
-       spin_lock(&qedge->outends->ends_lock);
+       struct canque_ends_t *inends, *outends;
+
+       inends=qedge->inends;
+       if(inends) spin_lock_irqsave(&inends->ends_lock,flags);
+       outends=qedge->outends;
+       if(outends) spin_lock(&outends->ends_lock);
        spin_lock(&qedge->fifo.fifo_lock);
        if(atomic_read(&qedge->edge_used)==0) {
                if(qedge->outends){
@@ -545,8 +551,8 @@ int canqueue_disconnect_edge(struct canque_edge_t *qedge)
                ret=1;
        } else ret=-1;
        spin_unlock(&qedge->fifo.fifo_lock);
-       spin_unlock(&qedge->outends->ends_lock);
-       spin_unlock_irqrestore(&qedge->inends->ends_lock,flags);
+       if(outends) spin_unlock(&outends->ends_lock);
+       if(inends) spin_unlock_irqrestore(&inends->ends_lock,flags);
        DEBUGQUE("canqueue_disconnect_edge %d returned %d\n",qedge->edge_num,ret);
        return ret;
 }
@@ -602,20 +608,15 @@ void canqueue_block_list(struct canque_ends_t *qends, struct list_head *list)
 {
        struct canque_edge_t *edge;
        struct list_head *entry;
-       unsigned long flags;
        
-       spin_lock_irqsave(&qends->ends_lock, flags);
+       /* has to be called with qends->ends_lock already locked */
        list_for_each(entry,&qends->inlist){
                if(list == &qends->inlist)
                        edge=list_entry(list->next,struct canque_edge_t,inpeers);
                else
                        edge=list_entry(list->next,struct canque_edge_t,outpeers);
                canque_fifo_set_fl(&edge->fifo,BLOCK);
-               /*spin_unlock_irqrestore(&qends->ends_lock, flags);*/
-               /* Loop can be break by interrupts and preempts there */
-               /*spin_lock_irqsave(&qends->ends_lock, flags);*/
        }
-       spin_unlock_irqrestore(&qends->ends_lock, flags);
 }