#include "../include/can.h"
#include "../include/can_queue.h"
+/*
+ * Modifies Tx message processing
+ * 0 .. local message processing disabled
+ * 1 .. local messages disabled by default but can be enabled by canque_set_filt
+ * 2 .. local messages enabled by default, can be disabled by canque_set_filt
+ */
+extern int processlocal;
+
+/*#define CAN_DEBUG*/
+
#ifdef CAN_DEBUG
#define DEBUGQUE(fmt,args...) printk(KERN_ERR "can_queue (debug): " fmt,\
##args)
struct canque_slot_t *slot;
spin_lock_irqsave(&fifo->fifo_lock, flags);
slot=fifo->head;
- *fifo->tail=fifo->flist;
- fifo->flist=slot;
- fifo->head=NULL;
- fifo->tail=&fifo->head;
- ret=canque_fifo_test_and_set_fl(fifo,EMPTY);
+ if(slot){
+ *fifo->tail=fifo->flist;
+ fifo->flist=slot;
+ fifo->head=NULL;
+ fifo->tail=&fifo->head;
+ }
+ canque_fifo_clear_fl(fifo,FULL);
+ ret=canque_fifo_test_and_set_fl(fifo,EMPTY)?0:1;
spin_unlock_irqrestore(&fifo->fifo_lock, flags);
return ret;
}
int destnr=0;
int ret;
unsigned long flags;
+ unsigned long msgid;
struct canque_edge_t *edge;
struct list_head *entry;
struct canque_slot_t *slot;
- DEBUGQUE("canque_filter_msg2edges for msg ID %ld\n",msg->id);
+ DEBUGQUE("canque_filter_msg2edges for msg ID 0x%08lx and flags 0x%02x\n",
+ msg->id, msg->flags);
+ msgid = canque_filtid2internal(msg->id, msg->flags);
+
spin_lock_irqsave(&qends->ends_lock, flags);
list_for_each(entry,&qends->inlist){
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)
+ if((msgid^edge->filtid)&edge->filtmask)
continue;
atomic_inc(&edge->edge_used);
spin_unlock_irqrestore(&qends->ends_lock, flags);
* @qedge: pointer to the edge
* @filtid: ID to set for the edge
* @filtmask: mask used for ID match check
+ * @filtflags: required filer flags
*
* Return Value: Negative value is returned if edge is in the process of delete.
*/
int canque_set_filt(struct canque_edge_t *qedge,
- unsigned long filtid, unsigned long filtmask)
+ unsigned long filtid, unsigned long filtmask, int filtflags)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
- atomic_inc(&qedge->edge_used);
- qedge->filtid=filtid;
- qedge->filtmask=filtmask;
+
+ if(!(filtflags&MSG_PROCESSLOCAL) && (processlocal<2))
+ filtflags |= MSG_LOCAL_MASK;
+
+ qedge->filtid=canque_filtid2internal(filtid, filtflags);
+ qedge->filtmask=canque_filtid2internal(filtmask, filtflags>>MSG_FILT_MASK_SHIFT);
+
if(canque_fifo_test_fl(&qedge->fifo,DEAD)) ret=-1;
else ret=canque_fifo_test_and_set_fl(&qedge->fifo,BLOCK)?1:0;
}
spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
if(!ret)canque_fifo_clear_fl(&qedge->fifo,BLOCK);
- if(atomic_dec_and_test(&qedge->edge_used))
- canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
spin_unlock_irqrestore(&qedge->fifo.fifo_lock,flags);
- DEBUGQUE("canque_set_filt for edge %d, ID %ld and mask %ld returned %d\n",qedge->edge_num,filtid,filtmask,ret);
+ DEBUGQUE("canque_set_filt for edge %d, ID %ld, mask %ld, flags %d returned %d\n",
+ qedge->edge_num,filtid,filtmask,filtflags,ret);
return ret;
}
int ret;
unsigned long flags;
- atomic_inc(&qedge->edge_used);
ret=canque_fifo_flush_slots(&qedge->fifo);
if(ret){
canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
list_del(&qedge->outpeers);
list_add(&qedge->outpeers,&qedge->outends->idle);
}
- if(atomic_dec_and_test(&qedge->edge_used))
- canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
spin_unlock(&qedge->fifo.fifo_lock);
spin_unlock_irqrestore(&qedge->outends->ends_lock, flags);
}
}
atomic_set(&qedge->edge_used,0);
qedge->filtid = 0;
- qedge->filtmask = 0;
+ qedge->filtmask = canque_filtid2internal(0l, (processlocal<2)? MSG_LOCAL:0);
qedge->edge_prio = 0;
#ifdef CAN_DEBUG
/* not exactly clean, but enough for debugging */