From b34a548a5dfd2f0b068fd835a4cd51680d851068 Mon Sep 17 00:00:00 2001 From: ppisa Date: Thu, 1 Jan 2004 22:54:26 +0000 Subject: [PATCH] LinCAN can be compiled in mode with RT-Linux chip worker threads now. Setup tested to work with Virtual and PCM3680 boards now. --- lincan/include/can_queue.h | 69 +++++++- lincan/include/can_sysdep.h | 52 +++++- lincan/include/constants.h | 30 +++- lincan/include/i82527.h | 2 +- lincan/include/irq.h | 6 +- lincan/include/main.h | 14 +- lincan/include/setup.h | 2 + lincan/include/sja1000.h | 2 +- lincan/src/Makefile.omk | 9 +- lincan/src/aim104.c | 2 +- lincan/src/bfadcan.c | 1 - lincan/src/can_devrtl.c | 166 +++++++++++++++++++ lincan/src/can_quekern.c | 80 +++++++-- lincan/src/can_quertl.c | 319 ++++++++++++++++++++++++++++++++++++ lincan/src/can_queue.c | 27 +-- lincan/src/cc_can104.c | 1 - lincan/src/close.c | 2 +- lincan/src/devcommon.c | 19 +++ lincan/src/finish.c | 5 +- lincan/src/i82527.c | 36 ++-- lincan/src/irq.c | 4 +- lincan/src/m437.c | 1 - lincan/src/main.c | 21 ++- lincan/src/nsi.c | 5 +- lincan/src/open.c | 4 +- lincan/src/pc_i03.c | 1 - lincan/src/pccan.c | 10 +- lincan/src/pcccan.c | 9 +- lincan/src/pcm3680.c | 1 - lincan/src/pikronisa.c | 1 - lincan/src/pip.c | 1 - lincan/src/setup.c | 73 ++++++--- lincan/src/sja1000.c | 42 ++--- lincan/src/sja1000p.c | 47 +++--- lincan/src/smartcan.c | 9 +- lincan/src/ssv.c | 9 +- lincan/src/template.c | 1 - lincan/src/virtual.c | 34 ++-- 38 files changed, 895 insertions(+), 222 deletions(-) create mode 100644 lincan/src/can_devrtl.c create mode 100644 lincan/src/can_quertl.c diff --git a/lincan/include/can_queue.h b/lincan/include/can_queue.h index 2fc422f..aacfd84 100644 --- a/lincan/include/can_queue.h +++ b/lincan/include/can_queue.h @@ -39,6 +39,7 @@ * @flist: pointer to list of the free slots associated with queue * @entry: pointer to the memory allocated for the list slots. * @fifo_lock: the lock to ensure atomicity of slot manipulation operations. + * @slotnr: number of allocated slots * * This structure represents CAN FIFO queue. It is implemented as * a single linked list of slots prepared for processing. The empty slots @@ -52,6 +53,7 @@ struct canque_fifo_t { struct canque_slot_t *flist; /* points the first entry in the free list */ struct canque_slot_t *entry; /* points to first allocated entry */ can_spinlock_t fifo_lock; /* can_spin_lock_irqsave / can_spin_unlock_irqrestore */ + int slotsnr; }; #define CAN_FIFOF_DESTROY_b 15 @@ -65,6 +67,8 @@ struct canque_fifo_t { #define CAN_FIFOF_INACTIVE_b 7 #define CAN_FIFOF_FREEONEMPTY_b 6 #define CAN_FIFOF_READY_b 5 +#define CAN_FIFOF_NOTIFYPEND_b 4 +#define CAN_FIFOF_RTL_MEM_b 3 #define CAN_FIFOF_DESTROY (1<fifo_flags) @@ -137,7 +143,7 @@ int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slo can_spin_irqflags_t flags; slot->next=NULL; can_spin_lock_irqsave(&fifo->fifo_lock, flags); - if(*fifo->tail) printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n"); + if(*fifo->tail) can_printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n"); *fifo->tail=slot; fifo->tail=&slot->next; ret=0; @@ -253,9 +259,7 @@ int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t * int canque_fifo_flush_slots(struct canque_fifo_t *fifo); -int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr); - -int canque_fifo_done(struct canque_fifo_t *fifo); +int canque_fifo_init_slots(struct canque_fifo_t *fifo); #define CANQUEUE_PRIO_NR 3 @@ -281,6 +285,9 @@ struct chip_t; * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge. * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1 * @edge_num: edge sequential number intended for debugging purposes only + * @pending_peers: edges with pending delayed events (RTL->Linux calls) + * @pending_inops: bitmask of pending operations + * @pending_outops: bitmask of pending operations * * This structure represents one direction connection from messages source * (@inends) to message consumer (@outends) fifo ends hub. The edge contains @@ -298,6 +305,11 @@ struct canque_edge_t { atomic_t edge_used; int edge_prio; int edge_num; + #ifdef CAN_WITH_RTL + struct list_head pending_peers; + unsigned long pending_inops; + unsigned long pending_outops; + #endif /*CAN_WITH_RTL*/ }; /** @@ -322,6 +334,7 @@ struct canque_edge_t { * @context: space to store ends user specific information * @endinfo: space to store some other ends usage specific informations * mainly for waking-up by the notify calls. + * @dead_peers: used to chain ends wanting for postponed destruction * * Structure represents place to connect edges to for CAN communication entity. * The zero, one or more incoming and outgoing edges can be connected to @@ -345,10 +358,23 @@ struct canque_ends_t { struct fasync_struct *fasync; #endif /*CAN_ENABLE_KERN_FASYNC*/ } fileinfo; + #ifdef CAN_WITH_RTL + struct { + rtl_spinlock_t rtl_lock; + rtl_wait_t rtl_readq; + rtl_wait_t rtl_writeq; + rtl_wait_t rtl_emptyq; + unsigned long pend_flags; + } rtlinfo; + #endif /*CAN_WITH_RTL*/ struct { - wait_queue_head_t daemonq; struct msgobj_t *msgobj; struct chip_t *chip; + #ifndef CAN_WITH_RTL + wait_queue_head_t daemonq; + #else /*CAN_WITH_RTL*/ + pthread_t worker_thread; + #endif /*CAN_WITH_RTL*/ } chipinfo; } endinfo; struct list_head dead_peers; @@ -367,7 +393,8 @@ struct canque_ends_t { #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */ #define CANQUEUE_NOTIFY_ERRTX_BUS 0x11003 /* tx bus error */ -#define CAN_ENDSF_DEAD (1<<0) +#define CAN_ENDSF_DEAD (1<<0) +#define CAN_ENDSF_MEM_RTL (1<<1) /** * canque_notify_inends - request to send notification to the input ends @@ -636,6 +663,10 @@ struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct ca /* Linux kernel specific functions */ +int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr); + +int canque_fifo_done_kern(struct canque_fifo_t *fifo); + struct canque_edge_t *canque_new_edge_kern(int slotsnr); int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends, @@ -651,7 +682,33 @@ int canqueue_ends_init_kern(struct canque_ends_t *qends); int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync); +void canqueue_ends_dispose_postpone(struct canque_ends_t *qends); + void canqueue_kern_initialize(void); +#ifdef CAN_WITH_RTL +/* RT-Linux specific functions */ + +void canqueue_rtl_initialize(void); +void canqueue_rtl_done(void); + +int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends, + struct canque_edge_t *qedge, int what); + +struct canque_edge_t *canque_new_edge_rtl(int slotsnr); + +void canque_dispose_edge_rtl(struct canque_edge_t *qedge); + +void canque_ends_free_rtl(struct canque_ends_t *qends); + +int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync); + +#else /*CAN_WITH_RTL*/ + +static inline int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends, + struct canque_edge_t *qedge, int what) { return 0; } + +#endif /*CAN_WITH_RTL*/ + #endif /*_CAN_QUEUE_H*/ diff --git a/lincan/include/can_sysdep.h b/lincan/include/can_sysdep.h index 0297e21..1de1454 100644 --- a/lincan/include/can_sysdep.h +++ b/lincan/include/can_sysdep.h @@ -1,6 +1,14 @@ #ifndef _CAN_SYSDEP_H #define _CAN_SYSDEP_H +#ifdef CAN_WITH_RTL +#include +#include +#include +#include +#include +#endif /*CAN_WITH_RTL*/ + /*#define __NO_VERSION__*/ /*#include */ @@ -13,6 +21,7 @@ #include #include #include + #include #include #include @@ -54,13 +63,24 @@ #endif /* Linux kernel < 2.5.7 or >= 2.6.0 */ - +#ifndef CAN_WITH_RTL #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && !defined(IRQ_RETVAL)) - typedef void irqreturn_t; - #define IRQ_NONE - #define IRQ_HANDLED - #define IRQ_RETVAL(x) + typedef void can_irqreturn_t; + #define CAN_IRQ_NONE + #define CAN_IRQ_HANDLED + #define CAN_IRQ_RETVAL(x) +#else /* <=2.5.67 */ + typedef irqreturn_t can_irqreturn_t; + #define CAN_IRQ_NONE IRQ_NONE + #define CAN_IRQ_HANDLED IRQ_HANDLED + #define CAN_IRQ_RETVAL IRQ_RETVAL #endif /* <=2.5.67 */ +#else /*CAN_WITH_RTL*/ + typedef int can_irqreturn_t; + #define CAN_IRQ_NONE 0 + #define CAN_IRQ_HANDLED 1 + #define CAN_IRQ_RETVAL(x) ((x) != 0) +#endif /*CAN_WITH_RTL*/ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,33)) #define can_synchronize_irq(irqnum) synchronize_irq() @@ -75,6 +95,7 @@ #define CAN_ENABLE_KERN_FASYNC #ifndef CAN_WITH_RTL +/* Standard LINUX kernel */ #define can_spinlock_t spinlock_t #define can_spin_irqflags_t unsigned long @@ -84,6 +105,19 @@ #define can_spin_unlock_irqrestore spin_unlock_irqrestore #define can_spin_lock_init spin_lock_init +#if defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +#define can_preempt_disable preempt_disable +#define can_preempt_enable preempt_enable +#else /*CONFIG_PREEMPT*/ +#define can_preempt_disable() do { } while (0) +#define can_preempt_enable() do { } while (0) +#endif /*CONFIG_PREEMPT*/ + +#define can_enable_irq enable_irq +#define can_disable_irq disable_irq + +#define can_printk printk + #else /*CAN_WITH_RTL*/ #define can_spinlock_t rtl_spinlock_t @@ -94,6 +128,14 @@ #define can_spin_unlock_irqrestore rtl_spin_unlock_irqrestore #define can_spin_lock_init rtl_spin_lock_init +#define can_preempt_disable() do { } while (0) +#define can_preempt_enable() do { } while (0) + +#define can_enable_irq rtl_hard_enable_irq +#define can_disable_irq rtl_hard_disable_irq + +#define can_printk rtl_printf + #endif /*CAN_WITH_RTL*/ #endif /*_CAN_SYSDEP_H*/ diff --git a/lincan/include/constants.h b/lincan/include/constants.h index 6e71643..ce0cbbd 100644 --- a/lincan/include/constants.h +++ b/lincan/include/constants.h @@ -35,15 +35,31 @@ #define MAX_BUF_LENGTH 64 //#define MAX_BUF_LENGTH 4 -#define IE (1<<1) -#define SIE (1<<2) -#define EIE (1<<3) /* These flags can be used for the msgobj_t structure flags data entry */ -#define OBJ_OPENED (1<<0) -#define OBJ_BUFFERS_ALLOCATED (1<<1) -#define OBJ_TX_REQUEST (1<<2) -#define OBJ_TX_LOCK (1<<3) +#define MSGOBJ_OPENED_b 0 +#define MSGOBJ_TX_REQUEST_b 1 +#define MSGOBJ_TX_LOCK_b 2 +#define MSGOBJ_IRQ_REQUEST_b 3 +#define MSGOBJ_WORKER_WAKE_b 4 + +#define MSGOBJ_OPENED (1<obj_flags) +#define can_msgobj_set_fl(obj,obj_fl) \ + set_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags) +#define can_msgobj_clear_fl(obj,obj_fl) \ + clear_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags) +#define can_msgobj_test_and_set_fl(obj,obj_fl) \ + test_and_set_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags) +#define can_msgobj_test_and_clear_fl(obj,obj_fl) \ + test_and_clear_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags) + /* These flags can be used for the chip_t structure flags data entry */ #define CHIP_CONFIGURED (1<<0) diff --git a/lincan/include/i82527.h b/lincan/include/i82527.h index c80ed00..c857b99 100644 --- a/lincan/include/i82527.h +++ b/lincan/include/i82527.h @@ -31,7 +31,7 @@ int i82527_set_btregs(struct chip_t *chip, unsigned short btr0, int i82527_start_chip(struct chip_t *chip); int i82527_stop_chip(struct chip_t *chip); int i82527_check_tx_stat(struct chip_t *chip); -irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs); #define MSG_OFFSET(object) ((object)*0x10) diff --git a/lincan/include/irq.h b/lincan/include/irq.h index 959a94b..6d262e2 100644 --- a/lincan/include/irq.h +++ b/lincan/include/irq.h @@ -7,6 +7,6 @@ * Version lincan-0.2 9 Jul 2003 */ -irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs); -irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs); -irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +can_irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +can_irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs); diff --git a/lincan/include/main.h b/lincan/include/main.h index 4bb0e0e..4d42d4d 100644 --- a/lincan/include/main.h +++ b/lincan/include/main.h @@ -13,13 +13,13 @@ #include "./can_queue.h" #ifdef CAN_DEBUG - #define DEBUGMSG(fmt,args...) printk(KERN_ERR "can.o (debug): " fmt,\ + #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "can.o (debug): " fmt,\ ##args) #else #define DEBUGMSG(fmt,args...) #endif -#define CANMSG(fmt,args...) printk(KERN_ERR "can.o: " fmt,##args) +#define CANMSG(fmt,args...) can_printk(KERN_ERR "can.o: " fmt,##args) /** @@ -152,6 +152,12 @@ struct chip_t { struct candevice_t *hostdevice; int max_objects; /* 1 for sja1000, 15 for i82527 */ + + #ifdef CAN_WITH_RTL + pthread_t worker_thread; + rtl_spinlock_t rtl_lock; + unsigned long pend_flags; + #endif /*CAN_WITH_RTL*/ }; /** @@ -179,7 +185,7 @@ struct msgobj_t { unsigned long obj_base_addr; unsigned int minor; /* associated device minor number */ unsigned int object; /* object number in chip_t +1 for debug printk */ - unsigned long flags; + unsigned long obj_flags; int ret; struct canque_ends_t *qends; @@ -297,7 +303,7 @@ struct chipspecops_t { unsigned short btr1); int (*start_chip)(struct chip_t *chip); int (*stop_chip)(struct chip_t *chip); - irqreturn_t (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs); + can_irqreturn_t (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs); }; struct mem_addr { diff --git a/lincan/include/setup.h b/lincan/include/setup.h index 686b83a..ae031f8 100644 --- a/lincan/include/setup.h +++ b/lincan/include/setup.h @@ -12,3 +12,5 @@ int list_hw(void); void *can_checked_malloc(size_t size); int can_checked_free(void *address_p); int can_del_mem_list(void); +int can_chip_setup_irq(struct chip_t *chip); +void can_chip_free_irq(struct chip_t *chip); diff --git a/lincan/include/sja1000.h b/lincan/include/sja1000.h index 35865b8..9046539 100644 --- a/lincan/include/sja1000.h +++ b/lincan/include/sja1000.h @@ -23,7 +23,7 @@ int sja1000_set_btregs(struct chip_t *chip, unsigned short btr0, unsigned short btr1); int sja1000_start_chip(struct chip_t *chip); int sja1000_stop_chip(struct chip_t *chip); -irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +can_irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs); /* BasicCAN mode address map */ #define SJACR 0x00 /* Control register */ diff --git a/lincan/src/Makefile.omk b/lincan/src/Makefile.omk index 20ab731..bbdcba7 100644 --- a/lincan/src/Makefile.omk +++ b/lincan/src/Makefile.omk @@ -1,6 +1,6 @@ -rtlinux_INCLUDES = -I $(srcdir)/../include +rtlinux_INCLUDES = -I $(srcdir)/../include -DCAN_WITH_RTL kernel_INCLUDES = -I $(srcdir)/../include -#kernel_INCLUDES += -DCAN_DEBUG +kernel_INCLUDES += -DCAN_DEBUG kernel_INCLUDES += -DWITH_DEVFS_FS kernel_MODULES = lincan @@ -11,8 +11,9 @@ lincan_cards_SOURCES = pip.c pccan.c smartcan.c nsi.c cc_can104.c \ pc_i03.c pcm3680.c aim104.c m437.c pcccan.c ssv.c \ bfadcan.c pikronisa.c virtual.c template.c -lincan_SOURCES = can_queue.c can_quekern.c devcommon.c main.c modparms.c \ - setup.c finish.c irq.c boardlist.c \ +lincan_SOURCES = can_queue.c can_quekern.c can_quertl.c main.c modparms.c \ + devcommon.c can_devrtl.c setup.c finish.c irq.c boardlist.c \ sja1000p.c sja1000.c i82527.c \ open.c proc.c close.c write.c read.c \ ioctl.c select.c fasync.c proc.c $(lincan_cards_SOURCES) + diff --git a/lincan/src/aim104.c b/lincan/src/aim104.c index 63ef735..cc24806 100644 --- a/lincan/src/aim104.c +++ b/lincan/src/aim104.c @@ -191,7 +191,7 @@ int aim104_init_chip_data(struct candevice_t *candev, int chipnr) int aim104_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; + chip->msgobj[objnr]->obj_flags=0; return 0; } diff --git a/lincan/src/bfadcan.c b/lincan/src/bfadcan.c index 21de5c7..2853ed1 100644 --- a/lincan/src/bfadcan.c +++ b/lincan/src/bfadcan.c @@ -238,7 +238,6 @@ int bfadcan_init_chip_data(struct candevice_t *candev, int chipnr) int bfadcan_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/can_devrtl.c b/lincan/src/can_devrtl.c new file mode 100644 index 0000000..182eb42 --- /dev/null +++ b/lincan/src/can_devrtl.c @@ -0,0 +1,166 @@ +/* can_devrtl.c - CAN message queues functions for the RT-Linux + * Linux CAN-bus device driver. + * New CAN queues by Pavel Pisa - OCERA team member + * email:pisa@cmp.felk.cvut.cz + * This software is released under the GPL-License. + * Version lincan-0.2 9 Jul 2003 + */ + +#ifdef CAN_WITH_RTL + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/can_queue.h" +#include "../include/main.h" +#include "../include/setup.h" + +#include + +unsigned int can_rtl_isr( unsigned int irq_num, struct pt_regs *r ) +{ + struct chip_t *chip; + struct candevice_t *candev; + int board_nr; + int chip_nr; + pthread_t thread=NULL; + + DEBUGMSG("can_rtl_isr invoked for irq %d\n",irq_num); + + /* I hate next loop, but RT-Linux does not provide context to ISR */ + for (board_nr=hardware_p->nr_boards; board_nr--; ) { + if((candev=hardware_p->candevice[board_nr])==NULL) + continue; + for(chip_nr=candev->nr_all_chips; chip_nr--; ) { + if((chip=candev->chip[chip_nr])==NULL) + continue; + if(chip->chip_irq!=irq_num) continue; + + set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags); + set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags); + + if(!chip->worker_thread) continue; + thread=chip->worker_thread; + pthread_kill(thread,RTL_SIGNAL_WAKEUP); + } + } + + /*rtl_global_pend_irq(irq_num);*/ + + /*if(thread) rtl_reschedule_thread(thread);*/ + + rtl_schedule(); + + return 0; +} + + + +/* +RTL_MARK_READY(pthread_self()) +RTL_MARK_SUSPENDED(pthread_self()); +return rtl_schedule(); +can_enable_irq +can_disable_irq +rtl_critical( state ) +rtl_end_critical( state ) +rtl_request_global_irq( irq, isr ); +rtl_free_global_irq( irq ) +*/ + +void * can_chip_worker_thread(void *arg) +{ + struct chip_t *chip = (struct chip_t *) arg; + struct msgobj_t *obj; + int ret, i; + int loop_cnt; + + if(!chip) return 0; + + + if (!(chip->flags & CHIP_CONFIGURED)){ + if (chip->chipspecops->chip_config(chip)) + CANMSG("Error configuring chip.\n"); + else + chip->flags |= CHIP_CONFIGURED; + + if((chip->msgobj[0])!=NULL) + if (chip->chipspecops->pre_read_config(chip,chip->msgobj[0])<0) + CANMSG("Error initializing chip for receiving\n"); + + } /* End of chip configuration */ + set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags); + + + while (1) { + DEBUGMSG("Worker thread for chip %d active\n",chip->chip_idx); + if(test_and_clear_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags)){ + DEBUGMSG("IRQ_REQUEST processing ...\n"); + loop_cnt = 100; + if(chip->chipspecops->irq_handler) do{ + ret=chip->chipspecops->irq_handler(chip->chip_irq,chip,NULL); + }while(ret && --loop_cnt); + continue; + } + if(test_and_clear_bit(MSGOBJ_TX_REQUEST_b,&chip->pend_flags)){ + DEBUGMSG("TX_REQUEST processing ...\n"); + for(i=0;imax_objects;i++){ + if((obj=chip->msgobj[i])==NULL) + continue; + if(!can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) + continue; + DEBUGMSG("Calling wakeup_tx\n"); + chip->chipspecops->wakeup_tx(chip, obj); + } + continue; + } + + /*re-enable chip IRQ, I am not sure, if this is required, + but it seems to not work without that */ + if(chip->chip_irq>=0) + can_enable_irq(chip->chip_irq); + + RTL_MARK_SUSPENDED(pthread_self()); + if(test_and_clear_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags)){ + RTL_MARK_READY(pthread_self()); + continue; + } + rtl_schedule(); + + } + return 0; +} + + +int can_chip_setup_irq(struct chip_t *chip) +{ + int ret; + + if(chip==NULL) + return -1; + if(chip->chipspecops->irq_handler){ + if (rtl_request_irq(chip->chip_irq,can_rtl_isr)) + return -1; + else { + DEBUGMSG("Registered interrupt %d\n",chip->chip_irq); + chip->flags |= CHIP_IRQ_SETUP; + } + } + ret=pthread_create(&chip->worker_thread, NULL, can_chip_worker_thread, chip); + if(ret<0) chip->worker_thread=NULL; + + return ret; +} + + +void can_chip_free_irq(struct chip_t *chip) +{ + if(chip->worker_thread) + pthread_delete_np(chip->worker_thread); + if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) { + rtl_free_irq(chip->chip_irq); + chip->flags &= ~CHIP_IRQ_SETUP; + } +} + + +#endif /*CAN_WITH_RTL*/ 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; diff --git a/lincan/src/can_quertl.c b/lincan/src/can_quertl.c new file mode 100644 index 0000000..45129b4 --- /dev/null +++ b/lincan/src/can_quertl.c @@ -0,0 +1,319 @@ +/* can_quertl.c - CAN message queues functions for the RT-Linux + * Linux CAN-bus device driver. + * New CAN queues by Pavel Pisa - OCERA team member + * email:pisa@cmp.felk.cvut.cz + * This software is released under the GPL-License. + * Version lincan-0.2 9 Jul 2003 + */ + +#ifdef CAN_WITH_RTL + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/can_queue.h" + +#include + +/* + * 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 CANQUE_PENDOPS_LIMIT 15 +#define CANQUE_PENDOPS_MASK ((1<pending_peers); + canque_fifo_clear_fl(&qedge->fifo, NOTIFYPEND); + pending_inops=qedge->pending_inops; + qedge->pending_inops=0; + pending_outops=qedge->pending_outops; + qedge->pending_outops=0; + can_spin_unlock_irqrestore (&canque_pending_edges_lock, flags); + + if(pending_outops & ~CANQUE_PENDOPS_MASK){ + pending_outops &= CANQUE_PENDOPS_MASK; + canque_notify_outends(qedge,CANQUEUE_NOTIFY_ERROR | qedge->fifo.error_code); + } + for(i=0;pending_outops;i++,pending_outops>>=1){ + if(pending_outops&1) + canque_notify_outends(qedge,i); + } + if(pending_inops & ~CANQUE_PENDOPS_MASK){ + pending_inops &= CANQUE_PENDOPS_MASK; + canque_notify_inends(qedge,CANQUEUE_NOTIFY_ERROR | qedge->fifo.error_code); + } + for(i=0;pending_inops;i++,pending_inops>>=1){ + if(pending_inops&1) + canque_notify_inends(qedge,i); + } + + canque_edge_decref(qedge); + can_spin_lock_irqsave (&canque_pending_edges_lock, flags); + } + + can_spin_unlock_irqrestore (&canque_pending_edges_lock, flags); + + return; +} + + +/** + * canqueue_rtl2lin_check_and_pend - postpones edge notification if called from RT-Linux + * @qends: notification target ends + * @qedge: edge delivering notification + * @what: notification type + * + * Return Value: if called from Linux context, returns 0 and lefts notification processing + * on caller responsibility. If called from RT-Linux contexts, schedules postponed + * event delivery and returns 1 + */ +int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends, + struct canque_edge_t *qedge, int what) +{ + can_spin_irqflags_t flags; + + if(rtl_rt_system_is_idle()) return 0; + + can_spin_lock_irqsave (&canque_pending_edges_lock, flags); + + if(what>CANQUE_PENDOPS_LIMIT) what=CANQUE_PENDOPS_LIMIT; + + if(qends == qedge->inends) { + set_bit(what,&qedge->pending_inops); + } else if(qends == qedge->outends) { + set_bit(what,&qedge->pending_outops); + } + + if(!canque_fifo_test_and_set_fl(&qedge->fifo, NOTIFYPEND)){ + canque_edge_incref(qedge); + list_add_tail(&qedge->pending_peers,&canque_pending_edges_list); + rtl_global_pend_irq (canqueue_rtl_irq); + } + + can_spin_unlock_irqrestore (&canque_pending_edges_lock, flags); + + return 1; + +} + + +/** + * canque_fifo_init_rtl - 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_rtl(struct canque_fifo_t *fifo, int slotsnr) +{ + int size; + if(!slotsnr) slotsnr=MAX_BUF_LENGTH; + size=sizeof(struct canque_slot_t)*slotsnr; + fifo->entry=rt_malloc(size); + if(!fifo->entry) return -1; + fifo->slotsnr=slotsnr; + return canque_fifo_init_slots(fifo); +} + +/** + * canque_fifo_done_rtl - frees slots allocated for CAN FIFO + * @fifo: pointer to the FIFO structure + */ +int canque_fifo_done_rtl(struct canque_fifo_t *fifo) +{ + if(fifo->entry) + rt_free(fifo->entry); + fifo->entry=NULL; + return 1; +} + +void canque_dispose_edge_rtl(struct canque_edge_t *qedge) +{ + canque_fifo_done_rtl(&qedge->fifo); + rt_free(qedge); +} + +/** + * canque_new_edge_rtl - allocate new edge structure in the RT-Linux context + * @slotsnr: required number of slots in the newly allocated edge structure + * + * Return Value: Returns pointer to allocated slot structure or %NULL if + * there is not enough memory to process operation. + */ +struct canque_edge_t *canque_new_edge_rtl(int slotsnr) +{ + struct canque_edge_t *qedge; + qedge = (struct canque_edge_t *)rt_malloc(sizeof(struct canque_edge_t)); + if(qedge == NULL) return NULL; + + memset(qedge,0,sizeof(struct canque_edge_t)); + can_spin_lock_init(&qedge->fifo.fifo_lock); + canque_fifo_set_fl(&qedge->fifo,RTL_MEM); + if(canque_fifo_init_rtl(&qedge->fifo, slotsnr)<0){ + rt_free(qedge); + return NULL; + } + atomic_set(&qedge->edge_used,1); + qedge->filtid = 0; + qedge->filtmask = canque_filtid2internal(0l, (processlocal<2)? MSG_LOCAL:0); + qedge->edge_prio = 0; + #if defined(CAN_DEBUG) && 0 + /* not exactly clean, but enough for debugging */ + atomic_inc(&edge_num_cnt); + qedge->edge_num=atomic_read(&edge_num_cnt); + #endif /* CAN_DEBUG */ + return qedge; +} + +void canque_ends_free_rtl(struct canque_ends_t *qends) +{ + rt_free(qends); +} + + +/** + * canqueue_notify_rtl - notification callback handler for Linux userspace clients + * @qends: pointer to the callback side ends structure + * @qedge: edge which invoked notification + * @what: notification type + */ +void canqueue_notify_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what) +{ + rtl_irqstate_t flags; + + switch(what){ + case CANQUEUE_NOTIFY_EMPTY: + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(canque_fifo_test_and_clear_fl(&qedge->fifo, FREEONEMPTY)) + canque_edge_decref(qedge); + break; + case CANQUEUE_NOTIFY_SPACE: + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + break; + case CANQUEUE_NOTIFY_PROC: + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + break; + case CANQUEUE_NOTIFY_NOUSR: + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + break; + case CANQUEUE_NOTIFY_DEAD_WANTED: + case CANQUEUE_NOTIFY_DEAD: + if(canque_fifo_test_and_clear_fl(&qedge->fifo, READY)) + canque_edge_decref(qedge); + break; + case CANQUEUE_NOTIFY_ATTACH: + break; + } +} + + +/** + * canqueue_ends_init_rtl - RT-Linux clients specific ends initialization + * @qends: pointer to the callback side ends structure + */ +int canqueue_ends_init_rtl(struct canque_ends_t *qends) +{ + canqueue_ends_init_gen(qends); + qends->context=NULL; + rtl_spin_lock_init(&(qends->endinfo.rtlinfo.rtl_lock)); + rtl_wait_init(&(qends->endinfo.rtlinfo.rtl_readq)); + rtl_wait_init(&(qends->endinfo.rtlinfo.rtl_writeq)); + rtl_wait_init(&(qends->endinfo.rtlinfo.rtl_emptyq)); + + qends->notify=canqueue_notify_rtl; + return 0; +} + +/** + * canqueue_ends_dispose_rtl - finalizing of the ends structure for Linux kernel clients + * @qends: pointer to ends structure + * @sync: flag indicating, that user wants to wait for processing of all remaining + * messages + * + * Return Value: Function should be designed such way to not fail. + */ +int canqueue_ends_dispose_rtl(struct canque_ends_t *qends, int sync) +{ + rtl_irqstate_t flags; + int delayed; + + canqueue_block_inlist(qends); + canqueue_block_outlist(qends); + + /*Wait for sending of all pending messages in the output FIFOs*/ + /*if(sync) + canqueue_ends_sync_all_rtl(qends);*/ + + /* Finish or kill all outgoing edges listed in inends */ + delayed=canqueue_ends_kill_inlist(qends, 1); + /* Kill all incoming edges listed in outends */ + delayed|=canqueue_ends_kill_outlist(qends); + + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq); + rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + + if(delayed || !(qends->ends_flags&CAN_ENDSF_MEM_RTL)){ + canqueue_ends_dispose_postpone(qends); + + return 1; + } + + canque_ends_free_rtl(qends); + return 0; +} + + + +void canqueue_rtl_initialize(void) +{ + INIT_LIST_HEAD(&canque_pending_edges_list); + can_spin_lock_init(&canque_pending_edges_lock); + + canqueue_rtl_irq = rtl_get_soft_irq (canqueue_rtl2lin_handler, "rtl_canqueue_irq"); +} + + +void canqueue_rtl_done(void) +{ + rtl_free_soft_irq (canqueue_rtl_irq); + +} + + +#endif /*CAN_WITH_RTL*/ diff --git a/lincan/src/can_queue.c b/lincan/src/can_queue.c index c0f1a6d..96c37a4 100644 --- a/lincan/src/can_queue.c +++ b/lincan/src/can_queue.c @@ -21,9 +21,10 @@ extern int processlocal; atomic_t edge_num_cnt; //#define CAN_DEBUG +#undef CAN_DEBUG #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 @@ -65,21 +66,17 @@ int canque_fifo_flush_slots(struct canque_fifo_t *fifo) /** - * canque_fifo_init_slots - initialize one CAN FIFO + * canque_fifo_init_slots - initializes slot chain of 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_slots(struct canque_fifo_t *fifo, int slotsnr) +int canque_fifo_init_slots(struct canque_fifo_t *fifo) { - int size; struct canque_slot_t *slot; - if(!slotsnr) slotsnr=MAX_BUF_LENGTH; - size=sizeof(struct canque_slot_t)*slotsnr; - fifo->entry=kmalloc(size,GFP_KERNEL); - if(!fifo->entry) return -1; + int slotsnr=fifo->slotsnr; + if(!fifo->entry || !slotsnr) return -1; slot=fifo->entry; fifo->flist=slot; while(--slotsnr){ @@ -93,18 +90,6 @@ int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr) return 1; } -/** - * canque_fifo_done - frees slots allocated for CAN FIFO - * @fifo: pointer to the FIFO structure - */ -int canque_fifo_done(struct canque_fifo_t *fifo) -{ - if(fifo->entry) - kfree(fifo->entry); - fifo->entry=NULL; - return 1; -} - /* atomic_dec_and_test(&qedge->edge_used); void atomic_inc(&qedge->edge_used); list_add_tail(struct list_head *new, struct list_head *head) diff --git a/lincan/src/cc_can104.c b/lincan/src/cc_can104.c index 9b8dd26..1197bcf 100644 --- a/lincan/src/cc_can104.c +++ b/lincan/src/cc_can104.c @@ -172,7 +172,6 @@ int cc104_init_chip_data(struct candevice_t *candev, int chipnr) int cc104_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/close.c b/lincan/src/close.c index 4df1533..73d4764 100644 --- a/lincan/src/close.c +++ b/lincan/src/close.c @@ -45,7 +45,7 @@ int can_close(struct inode *inode, struct file *file) kfree(canuser); if(atomic_dec_and_test(&obj->obj_used)){ - obj->flags &= ~OBJ_OPENED; + can_msgobj_clear_fl(obj,OPENED); /* FIXME: what about clearing chip HW status, stopping sending messages etc? */ }; diff --git a/lincan/src/devcommon.c b/lincan/src/devcommon.c index c26a36f..c0b6028 100644 --- a/lincan/src/devcommon.c +++ b/lincan/src/devcommon.c @@ -25,8 +25,25 @@ void canqueue_notify_chip(struct canque_ends_t *qends, struct canque_edge_t *qed wake_up(&qends->endinfo.chipinfo.daemonq); break;*/ case CANQUEUE_NOTIFY_PROC: + #ifndef CAN_WITH_RTL /*wake_up(&qends->endinfo.chipinfo.daemonq);*/ chip->chipspecops->wakeup_tx(chip, obj); + #else /*CAN_WITH_RTL*/ + can_msgobj_set_fl(obj,TX_REQUEST); + if(qends->endinfo.chipinfo.worker_thread){ + can_msgobj_set_fl(obj,WORKER_WAKE); + pthread_kill(qends->endinfo.chipinfo.worker_thread,RTL_SIGNAL_WAKEUP); + rtl_schedule(); + } else { + set_bit(MSGOBJ_TX_REQUEST_b,&chip->pend_flags); + + if(chip->worker_thread) { + set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags); + pthread_kill(chip->worker_thread,RTL_SIGNAL_WAKEUP); + rtl_schedule(); + } + } + #endif /*CAN_WITH_RTL*/ break; case CANQUEUE_NOTIFY_DEAD_WANTED: case CANQUEUE_NOTIFY_DEAD: @@ -46,7 +63,9 @@ int canqueue_ends_init_chip(struct canque_ends_t *qends, struct chip_t *chip, st if(ret<0) return ret; qends->context=NULL; + #ifndef CAN_WITH_RTL init_waitqueue_head(&qends->endinfo.chipinfo.daemonq); + #endif /*CAN_WITH_RTL*/ qends->endinfo.chipinfo.chip=chip; qends->endinfo.chipinfo.msgobj=obj; qends->notify=canqueue_notify_chip; diff --git a/lincan/src/finish.c b/lincan/src/finish.c index fdca959..922b4d3 100644 --- a/lincan/src/finish.c +++ b/lincan/src/finish.c @@ -57,10 +57,7 @@ void canchip_done(struct chip_t *chip) CANMSG("canchip_done: not registered in hostdevice\n"); } - if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) { - free_irq(chip->chip_irq, chip); - chip->flags &= ~CHIP_IRQ_SETUP; - } + can_chip_free_irq(chip); can_synchronize_irq(chip->chip_irq); diff --git a/lincan/src/i82527.c b/lincan/src/i82527.c index 7a57f45..7b9602f 100644 --- a/lincan/src/i82527.c +++ b/lincan/src/i82527.c @@ -463,7 +463,7 @@ inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, } } -irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { int id0=0, id1=0, id2=0, id3=0; @@ -483,7 +483,7 @@ irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) if (irq_register == 0x01) { DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT)); - return IRQ_NONE; + return CAN_IRQ_NONE; } if (irq_register == 0x02) @@ -494,15 +494,15 @@ irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) obj=chip->msgobj[object]; if (canobj_read_reg(chip,obj,iMSGCFG) & MCFG_DIR) { - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) i82527_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; } } else { @@ -536,7 +536,7 @@ irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) irq_register=i82527_seg_read_reg(chip, iIRQ); } - return IRQ_HANDLED; + return CAN_IRQ_HANDLED; } void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj, @@ -562,26 +562,20 @@ void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj, int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { - /* dummy lock to prevent preemption fully portable way */ - can_spinlock_t dummy_lock; + can_preempt_disable(); - /* preempt_disable() */ - can_spin_lock_init(&dummy_lock); - can_spin_lock(&dummy_lock); - - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) i82527_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; } - /* preempt_enable(); */ - can_spin_unlock(&dummy_lock); + can_preempt_enable(); return 0; } diff --git a/lincan/src/irq.c b/lincan/src/irq.c index e48db31..26d0cf7 100644 --- a/lincan/src/irq.c +++ b/lincan/src/irq.c @@ -13,7 +13,7 @@ #include "../include/irq.h" -irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { +can_irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { CANMSG("dummy_irq_handler called irq %d \n", irq); - return IRQ_NONE; + return CAN_IRQ_NONE; } diff --git a/lincan/src/m437.c b/lincan/src/m437.c index 6fa87e7..37308b2 100644 --- a/lincan/src/m437.c +++ b/lincan/src/m437.c @@ -229,7 +229,6 @@ int m437_init_chip_data(struct candevice_t *candev, int chipnr) int m437_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/main.c b/lincan/src/main.c index 918c2f7..c40310d 100644 --- a/lincan/src/main.c +++ b/lincan/src/main.c @@ -154,6 +154,10 @@ int init_module(void) return -ENODEV; } + #ifdef CAN_WITH_RTL + canqueue_rtl_initialize(); + #endif /*CAN_WITH_RTL*/ + for (i=0; inr_boards; i++) { candev=hardware_p->candevice[i]; if (candev->hwspecops->request_io(candev)) @@ -175,14 +179,9 @@ int init_module(void) for(j=0; jnr_all_chips; j++) { if((chip=candev->chip[j])==NULL) continue; - if(!chip->chipspecops->irq_handler) - continue; - - if (request_irq(chip->chip_irq,chip->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chip)) + if(can_chip_setup_irq(chip)<0) { + CANMSG("IRQ setup failed\n"); goto interrupt_error; - else { - DEBUGMSG("Registered interrupt %d\n",chip->chip_irq); - chip->flags |= CHIP_IRQ_SETUP; } } @@ -233,6 +232,10 @@ int init_module(void) memory_error: ; canhardware_done(hardware_p); + #ifdef CAN_WITH_RTL + canqueue_rtl_done(); + #endif /*CAN_WITH_RTL*/ + res=unregister_chrdev(major,DEVICE_NAME); if (res<0) CANMSG("Error unloading CAN driver, error: %d\n",res); @@ -268,6 +271,10 @@ void cleanup_module(void) canhardware_done(hardware_p); + #ifdef CAN_WITH_RTL + canqueue_rtl_done(); + #endif /*CAN_WITH_RTL*/ + if ( can_del_mem_list() ) CANMSG("Error deallocating memory\n"); diff --git a/lincan/src/nsi.c b/lincan/src/nsi.c index aeef392..9f6bdef 100644 --- a/lincan/src/nsi.c +++ b/lincan/src/nsi.c @@ -149,7 +149,6 @@ int nsi_init_obj_data(struct chip_t *chip, int objnr) chip->msgobj[objnr]->obj_base_addr= chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } @@ -193,10 +192,10 @@ unsigned nsi_read_register(unsigned long address) data */ unsigned char ret; - disable_irq(nsican_irq); + can_disable_irq(nsican_irq); outb(address-nsican_base, nsican_base); ret=inb(nsican_base+1); - enable_irq(nsican_irq); + can_enable_irq(nsican_irq); return ret; } diff --git a/lincan/src/open.c b/lincan/src/open.c index 38ee4d4..015b521 100644 --- a/lincan/src/open.c +++ b/lincan/src/open.c @@ -33,7 +33,7 @@ int can_open(struct inode *inode, struct file *file) atomic_inc(&obj->obj_used); DEBUGMSG("Device %d opened %d times.\n", MINOR_NR, atomic_read(&obj->obj_used)); - obj->flags |= OBJ_OPENED; + can_msgobj_set_fl(obj,OPENED); if (chip->flags & CHIP_CONFIGURED) DEBUGMSG("Device is already configured.\n"); @@ -46,8 +46,6 @@ int can_open(struct inode *inode, struct file *file) if (chip->chipspecops->pre_read_config(chip,obj)<0) CANMSG("Error initializing chip for receiving\n"); - /* chip->flags |= OBJ_BUFFERS_ALLOCATED; */ - } /* End of chip configuration */ canuser = (struct canuser_t *)kmalloc(sizeof(struct canuser_t), GFP_KERNEL); diff --git a/lincan/src/pc_i03.c b/lincan/src/pc_i03.c index 1e2c933..d926e33 100644 --- a/lincan/src/pc_i03.c +++ b/lincan/src/pc_i03.c @@ -199,7 +199,6 @@ int pci03_init_chip_data(struct candevice_t *candev, int chipnr) int pci03_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/pccan.c b/lincan/src/pccan.c index 8745404..6e32610 100644 --- a/lincan/src/pccan.c +++ b/lincan/src/pccan.c @@ -169,7 +169,7 @@ int pccanq_reset(struct candevice_t *candev) int i=0,chip_nr=0; for (i=0; i<4; i++) - disable_irq(candev->chip[i]->chip_irq); + can_disable_irq(candev->chip[i]->chip_irq); DEBUGMSG("Resetting pccan-q hardware ...\n"); while (i < 100000) { @@ -214,7 +214,7 @@ int pccanq_reset(struct candevice_t *candev) } for (i=0; i<4; i++) - enable_irq(candev->chip[i]->chip_irq); + can_enable_irq(candev->chip[i]->chip_irq); return 0; } @@ -290,12 +290,10 @@ int pccan_init_obj_data(struct chip_t *chip, int objnr) { if (!strcmp(chip->chip_type,"sja1000")) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; - } + } else { /* The spacing for this card is 0x3c0 */ chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10+(int)((objnr+1)/4)*0x3c0; - chip->msgobj[objnr]->flags=0; - } + } return 0; } diff --git a/lincan/src/pcccan.c b/lincan/src/pcccan.c index 6f7b576..64e6b70 100644 --- a/lincan/src/pcccan.c +++ b/lincan/src/pcccan.c @@ -219,7 +219,6 @@ int pcccan_init_chip_data(struct candevice_t *candev, int chipnr) int pcccan_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } @@ -254,10 +253,10 @@ int pcccan_program_irq(struct candevice_t *candev) */ void pcccan_write_register(unsigned char data, unsigned long address) { - disable_irq(pcccan_irq); + can_disable_irq(pcccan_irq); outb(address - pcccan_base, pcccan_base+1); outb(data, pcccan_base+6); - enable_irq(pcccan_irq); + can_enable_irq(pcccan_irq); } /** @@ -273,10 +272,10 @@ void pcccan_write_register(unsigned char data, unsigned long address) unsigned pcccan_read_register(unsigned long address) { unsigned ret; - disable_irq(pcccan_irq); + can_disable_irq(pcccan_irq); outb(address - pcccan_base, pcccan_base+1); ret=inb(pcccan_base+2); - enable_irq(pcccan_irq); + can_enable_irq(pcccan_irq); return ret; } diff --git a/lincan/src/pcm3680.c b/lincan/src/pcm3680.c index 4be3dd2..cfe5856 100644 --- a/lincan/src/pcm3680.c +++ b/lincan/src/pcm3680.c @@ -205,7 +205,6 @@ int pcm3680_init_chip_data(struct candevice_t *candev, int chipnr) int pcm3680_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/pikronisa.c b/lincan/src/pikronisa.c index 117560c..5778875 100644 --- a/lincan/src/pikronisa.c +++ b/lincan/src/pikronisa.c @@ -212,7 +212,6 @@ int pikronisa_init_chip_data(struct candevice_t *candev, int chipnr) int pikronisa_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/pip.c b/lincan/src/pip.c index 3e1984c..16c0098 100644 --- a/lincan/src/pip.c +++ b/lincan/src/pip.c @@ -144,7 +144,6 @@ int pip_init_chip_data(struct candevice_t *candev, int chipnr) int pip_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/setup.c b/lincan/src/setup.c index 57883ce..acc7cac 100644 --- a/lincan/src/setup.c +++ b/lincan/src/setup.c @@ -207,14 +207,15 @@ int init_device_struct(int card) if (candev->hwspecops->init_hw_data(candev)) goto error_nodev; - if (init_chip_struct(candev)) - goto error_nodev; + if ((ret=init_chip_struct(candev))) + goto error_chip; return 0; error_nodev: - candevice_done(candev); ret=-ENODEV; + error_chip: + candevice_done(candev); goto error_both; error_nomem: @@ -232,39 +233,40 @@ int init_device_struct(int card) */ int init_chip_struct(struct candevice_t *candev) { + struct chip_t *chip; static int irq_count=0; int i=0; /* Alocate and initialize the chip structures */ for (i=0; i < candev->nr_all_chips; i++) { candev->chip[i]=(struct chip_t *)can_checked_malloc(sizeof(struct chip_t)); - if (candev->chip[i]==NULL) + if ((chip=candev->chip[i])==NULL) return -ENOMEM; - memset(candev->chip[i], 0, sizeof(struct chip_t)); + memset(chip, 0, sizeof(struct chip_t)); - candev->chip[i]->write_register=candev->hwspecops->write_register; - candev->chip[i]->read_register=candev->hwspecops->read_register; + chip->write_register=candev->hwspecops->write_register; + chip->read_register=candev->hwspecops->read_register; - candev->chip[i]->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t)); - if (candev->chip[i]->chipspecops==NULL) + chip->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t)); + if (chip->chipspecops==NULL) return -ENOMEM; - - chips_p[irq_count]=candev->chip[i]; - candev->chip[i]->chip_idx=i; - candev->chip[i]->hostdevice=candev; - candev->chip[i]->chip_irq=irq[irq_count]; - candev->chip[i]->baudrate=baudrate[irq_count]*1000; - if(!candev->chip[i]->baudrate) - candev->chip[i]->baudrate=baudrate[0]*1000; - candev->chip[i]->flags=0x0; + + chips_p[irq_count]=chip; + chip->chip_idx=i; + chip->hostdevice=candev; + chip->chip_irq=irq[irq_count]; + chip->baudrate=baudrate[irq_count]*1000; + if(!chip->baudrate) + chip->baudrate=baudrate[0]*1000; + chip->flags=0x0; candev->hwspecops->init_chip_data(candev,i); if (init_chipspecops(candev,i)) return -ENODEV; - - init_obj_struct(candev, candev->chip[i], minor[irq_count]); + + init_obj_struct(candev, chip, minor[irq_count]); irq_count++; } @@ -300,7 +302,7 @@ int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int min obj->qends=qends; obj->tx_qedge=NULL; obj->tx_slot=NULL; - obj->flags = 0x0; + obj->obj_flags = 0x0; canqueue_ends_init_chip(qends, hostchip, obj); @@ -351,3 +353,32 @@ int init_chipspecops(struct candevice_t *candev, int chipnr) return 0; } + +#ifndef CAN_WITH_RTL + +int can_chip_setup_irq(struct chip_t *chip) +{ + if(chip==NULL) + return -1; + if(!chip->chipspecops->irq_handler) + return 0; + + if (request_irq(chip->chip_irq,chip->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chip)) + return -1; + else { + DEBUGMSG("Registered interrupt %d\n",chip->chip_irq); + chip->flags |= CHIP_IRQ_SETUP; + } + return 1; +} + + +void can_chip_free_irq(struct chip_t *chip) +{ + if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) { + free_irq(chip->chip_irq, chip); + chip->flags &= ~CHIP_IRQ_SETUP; + } +} + +#endif /*CAN_WITH_RTL*/ diff --git a/lincan/src/sja1000.c b/lincan/src/sja1000.c index 7b1f88d..8e41ae0 100644 --- a/lincan/src/sja1000.c +++ b/lincan/src/sja1000.c @@ -20,7 +20,7 @@ int sja1000_enable_configuration(struct chip_t *chip) int i=0; unsigned flags; - disable_irq(chip->chip_irq); + can_disable_irq(chip->chip_irq); flags=can_read_reg(chip,SJACR); @@ -32,7 +32,7 @@ int sja1000_enable_configuration(struct chip_t *chip) } if (i>=10) { CANMSG("Reset error\n"); - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return -ENODEV; } @@ -57,7 +57,7 @@ int sja1000_disable_configuration(struct chip_t *chip) return -ENODEV; } - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return 0; } @@ -331,7 +331,7 @@ int sja1000_config_irqs(struct chip_t *chip, short irqs) } -irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +can_irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { unsigned irq_register; struct chip_t *chip=(struct chip_t *)dev_id; @@ -343,21 +343,21 @@ irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs) // can_read_reg(chip, SJASR)); if ((irq_register & (IR_WUI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0) - return IRQ_NONE; + return CAN_IRQ_NONE; if ((irq_register & IR_RI) != 0) sja1000_irq_read_handler(chip, obj); if ((irq_register & IR_TI) != 0) { - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if (can_read_reg(chip, SJASR) & SR_TBS) sja1000_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; } } @@ -376,7 +376,7 @@ irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs) } } - return IRQ_HANDLED; + return CAN_IRQ_HANDLED; } void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj) @@ -446,26 +446,20 @@ void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) */ int sja1000_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { - /* dummy lock to prevent preemption fully portable way */ - can_spinlock_t dummy_lock; + can_preempt_disable(); - /* preempt_disable() */ - can_spin_lock_init(&dummy_lock); - can_spin_lock(&dummy_lock); - - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if (can_read_reg(chip, SJASR) & SR_TBS) sja1000_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; } - /* preempt_enable(); */ - can_spin_unlock(&dummy_lock); + can_preempt_enable(); return 0; } diff --git a/lincan/src/sja1000p.c b/lincan/src/sja1000p.c index b34e984..eafed8a 100644 --- a/lincan/src/sja1000p.c +++ b/lincan/src/sja1000p.c @@ -23,7 +23,7 @@ int sja1000p_enable_configuration(struct chip_t *chip) int i=0; enum sja1000_PeliCAN_MOD flags; - disable_irq(chip->chip_irq); + can_disable_irq(chip->chip_irq); flags=can_read_reg(chip,SJAMOD); @@ -37,7 +37,7 @@ int sja1000p_enable_configuration(struct chip_t *chip) } if (i>=10) { CANMSG("Reset error\n"); - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return -ENODEV; } @@ -69,7 +69,7 @@ int sja1000p_disable_configuration(struct chip_t *chip) return -ENODEV; } - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return 0; } @@ -605,7 +605,7 @@ void sja1000p_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) * message queues. * File: src/sja1000p.c */ -irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +can_irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { int irq_register, status, error_code; struct chip_t *chip=(struct chip_t *)dev_id; @@ -617,11 +617,11 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) // can_read_reg(chip,SJASR)); if ((irq_register & (IR_BEI|IR_EPI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0) - return IRQ_NONE; + return CAN_IRQ_NONE; - if(!obj->flags & OBJ_BUFFERS_ALLOCATED) { - CANMSG("sja1000p_irq_handler: called with device closed, irq_register 0x%02x\n", irq_register); - return IRQ_NONE; + if(!(chip->flags&CHIP_CONFIGURED)) { + CANMSG("sja1000p_irq_handler: called for non-configured device, irq_register 0x%02x\n", irq_register); + return CAN_IRQ_NONE; } if ((irq_register & IR_RI) != 0) { @@ -632,15 +632,15 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) if ((irq_register & IR_TI) != 0) { DEBUGMSG("sja1000_irq_handler: TI\n"); obj->ret = 0; - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if (can_read_reg(chip, SJASR) & SR_TBS) sja1000p_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; DEBUGMSG("TX looping in sja1000_irq_handler\n"); } } @@ -677,7 +677,7 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) obj->tx_retry_cnt=0; } - return IRQ_HANDLED; + return CAN_IRQ_HANDLED; } /** @@ -690,29 +690,24 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) */ int sja1000p_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { - /* dummy lock to prevent preemption fully portable way */ - can_spinlock_t dummy_lock; - /* preempt_disable() */ - can_spin_lock_init(&dummy_lock); - can_spin_lock(&dummy_lock); + can_preempt_disable(); - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if (can_read_reg(chip, SJASR) & SR_TBS){ obj->tx_retry_cnt=0; sja1000p_irq_write_handler(chip, obj); } - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; DEBUGMSG("TX looping in sja1000p_wakeup_tx\n"); } - /* preempt_enable(); */ - can_spin_unlock(&dummy_lock); + can_preempt_enable(); return 0; } diff --git a/lincan/src/smartcan.c b/lincan/src/smartcan.c index 7f11d5c..abbbe1a 100644 --- a/lincan/src/smartcan.c +++ b/lincan/src/smartcan.c @@ -93,7 +93,6 @@ int smartcan_init_chip_data(struct candevice_t *candev, int chipnr) int smartcan_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } @@ -101,19 +100,19 @@ int smartcan_init_obj_data(struct chip_t *chip, int objnr) void smartcan_write_register(unsigned char data, unsigned long address) { - disable_irq(smartcan_irq); + can_disable_irq(smartcan_irq); outb(address-smartcan_base,smartcan_base); outb(data,smartcan_base+1); - enable_irq(smartcan_irq); + can_enable_irq(smartcan_irq); } unsigned smartcan_read_register(unsigned long address) { unsigned ret; - disable_irq(smartcan_irq); + can_disable_irq(smartcan_irq); outb(address-smartcan_base,smartcan_base); ret=inb(smartcan_base+1); - enable_irq(smartcan_irq); + can_enable_irq(smartcan_irq); return ret; } diff --git a/lincan/src/ssv.c b/lincan/src/ssv.c index 793c67c..83fbba3 100644 --- a/lincan/src/ssv.c +++ b/lincan/src/ssv.c @@ -164,7 +164,6 @@ int ssv_init_obj_data(struct chip_t *chip, int objnr) chip->msgobj[objnr]->obj_base_addr= chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } @@ -214,17 +213,17 @@ unsigned ssv_read_register(unsigned long address) if((address-ssvcan_base)<0x100) { - disable_irq(ssvcan_irq[0]); + can_disable_irq(ssvcan_irq[0]); outb(address-ssvcan_base, ssvcan_base); ret=inb(ssvcan_base+1); - enable_irq(ssvcan_irq[0]); + can_enable_irq(ssvcan_irq[0]); } else { - disable_irq(ssvcan_irq[1]); + can_disable_irq(ssvcan_irq[1]); outb(address-ssvcan_base-0x100, ssvcan_base+0x02); ret=inb(ssvcan_base+1+0x02); - enable_irq(ssvcan_irq[1]); + can_enable_irq(ssvcan_irq[1]); } return ret; diff --git a/lincan/src/template.c b/lincan/src/template.c index 9b72902..f530228 100644 --- a/lincan/src/template.c +++ b/lincan/src/template.c @@ -182,7 +182,6 @@ int template_init_chip_data(struct candevice_t *candev, int chipnr) int template_init_obj_data(struct chip_t *chip, int objnr) { chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10; - chip->msgobj[objnr]->flags=0; return 0; } diff --git a/lincan/src/virtual.c b/lincan/src/virtual.c index e4b9c17..80ce0fb 100644 --- a/lincan/src/virtual.c +++ b/lincan/src/virtual.c @@ -280,27 +280,23 @@ void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) * message queues. * File: src/virtual.c */ -irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +can_irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { - return IRQ_HANDLED; + return CAN_IRQ_HANDLED; } void virtual_schedule_next(struct msgobj_t *obj) { int cmd; - /* dummy lock to prevent preemption fully portable way */ - can_spinlock_t dummy_lock; - /* preempt_disable() */ - can_spin_lock_init(&dummy_lock); - can_spin_lock(&dummy_lock); + can_preempt_disable(); - set_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_clear_fl(obj,TX_REQUEST); cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); if(cmd>=0) { @@ -309,14 +305,13 @@ void virtual_schedule_next(struct msgobj_t *obj) CANMSG("virtual: scheduled delivery\n"); } else - clear_bit(OBJ_TX_LOCK,&obj->flags); + can_msgobj_clear_fl(obj,TX_LOCK); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; DEBUGMSG("TX looping in virtual_schedule_next\n"); } - /* preempt_enable(); */ - can_spin_unlock(&dummy_lock); + can_preempt_enable(); } @@ -332,7 +327,7 @@ void virtual_do_tx_timeout(unsigned long data) obj->tx_slot=NULL; CANMSG("virtual: delayed delivery\n"); } - clear_bit(OBJ_TX_LOCK,&obj->flags); + can_msgobj_clear_fl(obj,TX_LOCK); virtual_schedule_next(obj); } @@ -347,13 +342,15 @@ void virtual_do_tx_timeout(unsigned long data) */ int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { - /* set_bit(OBJ_TX_REQUEST,&obj->flags); */ + /* can_msgobj_set_fl(obj,TX_REQUEST); */ struct canque_edge_t *qedge; struct canque_slot_t *slot; int cmd; - + + #ifndef CAN_WITH_RTL if(!virtual_bus_latency(obj)) { + #endif /*CAN_WITH_RTL*/ /* Ensure delivery of all ready slots */ while((cmd=canque_test_outslot(obj->qends, &qedge, &slot)) >= 0){ if(cmd==0) { @@ -362,9 +359,11 @@ int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) } canque_free_outslot(obj->qends, qedge, slot); } + #ifndef CAN_WITH_RTL } else { virtual_schedule_next(obj); } + #endif /*CAN_WITH_RTL*/ return 0; } @@ -483,7 +482,6 @@ int virtual_init_obj_data(struct chip_t *chip, int objnr) { struct msgobj_t *obj=chip->msgobj[objnr]; obj->obj_base_addr=chip->chip_base_addr; - obj->flags=0; obj->tx_timeout.function=virtual_do_tx_timeout; obj->tx_timeout.data=(unsigned long)obj; return 0; -- 2.39.2