* 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
+ * Version lincan-0.3 17 Jun 2004
*/
#ifdef CAN_WITH_RTL
struct list_head canque_pending_edges_list;
can_spinlock_t canque_pending_edges_lock;
+unsigned long canqueue_rtl2lin_pend;
-static int canqueue_rtl_irq = 0;
+int canqueue_rtl_irq = 0;
void
canqueue_rtl2lin_handler(int irq, void *ignore, struct pt_regs *ignoreregs)
can_spin_unlock_irqrestore (&canque_pending_edges_lock, flags);
+ if(test_and_clear_bit(CAN_RTL2LIN_PEND_DEAD_b,&canqueue_rtl2lin_pend))
+ tasklet_schedule(&canque_dead_tl);
+
return;
}
}
+/**
+ * canque_get_inslot4id_wait_rtl - find or wait for best outgoing edge and slot for given ID
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to allocated slot
+ * @cmd: command type for slot
+ * @id: communication ID of message to send into edge
+ * @prio: optional priority of message
+ *
+ * Same as canque_get_inslot4id(), except, that it waits for free slot
+ * in case, that queue is full. Function is specific for Linux userspace clients.
+ * Return Value: If there is no usable edge negative value is returned.
+ */
+int canque_get_inslot4id_wait_rtl(struct canque_ends_t *qends,
+ struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+ int cmd, unsigned long id, int prio)
+{
+ rtl_irqstate_t flags;
+ int ret;
+ unsigned old_age;
+ rtl_sigset_t sigset;
+
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age);
+ while((ret=canque_get_inslot4id(qends,qedgep,slotp,cmd,id,prio))==-1){
+ rtl_sigemptyset(&sigset);
+ rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age))
+ sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_writeq, &qends->endinfo.rtlinfo.rtl_lock);
+ rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(RTL_SIGINTR(&sigset))
+ return -1;
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age);
+ }
+
+ return ret;
+}
+
+
+/**
+ * canque_get_outslot_wait_rtl - receive or wait for ready slot for given ends
+ * @qends: ends structure belonging to calling communication object
+ * @qedgep: place to store pointer to found edge
+ * @slotp: place to store pointer to received slot
+ *
+ * The same as canque_test_outslot(), except it waits in the case, that there is
+ * no ready slot for given ends. Function is specific for Linux userspace clients.
+ * Return Value: Negative value informs, that there is no ready output
+ * slot for given ends. Positive value is equal to the command
+ * slot has been allocated by the input side.
+ */
+int canque_get_outslot_wait_rtl(struct canque_ends_t *qends,
+ struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
+{
+ rtl_irqstate_t flags;
+ int ret;
+ unsigned old_age;
+ rtl_sigset_t sigset;
+
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age);
+ while((ret=canque_test_outslot(qends,qedgep,slotp))==-1){
+ rtl_sigemptyset(&sigset);
+ rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age))
+ sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_readq, &qends->endinfo.rtlinfo.rtl_lock);
+ rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(RTL_SIGINTR(&sigset))
+ return -1;
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age);
+ }
+ return ret;
+}
+
+
+/**
+ * canque_sync_wait_rtl - wait for all slots processing
+ * @qends: ends structure belonging to calling communication object
+ * @qedge: pointer to edge
+ *
+ * Functions waits for ends transition into empty state.
+ * Return Value: Positive value indicates, that edge empty state has been reached.
+ * Negative or zero value informs about interrupted wait or other problem.
+ */
+int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge)
+{
+ rtl_irqstate_t flags;
+ int ret;
+ unsigned old_age;
+ rtl_sigset_t sigset;
+
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age);
+ while(!(ret=canque_fifo_test_fl(&qedge->fifo,EMPTY)?1:0)){
+ rtl_sigemptyset(&sigset);
+ rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age))
+ sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_emptyq, &qends->endinfo.rtlinfo.rtl_lock);
+ rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ if(RTL_SIGINTR(&sigset))
+ return -1;
+ old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age);
+ }
+
+ return ret;
+}
+
+
/**
* canque_fifo_init_rtl - initialize one CAN FIFO
* @fifo: pointer to the FIFO structure
return canque_fifo_init_slots(fifo);
}
+
/**
* canque_fifo_done_rtl - frees slots allocated for CAN FIFO
* @fifo: pointer to the FIFO structure
switch(what){
case CANQUEUE_NOTIFY_EMPTY:
rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_emptyq_age);
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))
break;
case CANQUEUE_NOTIFY_SPACE:
rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags);
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_writeq_age);
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);
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_readq_age);
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);
+
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_readq_age);
rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq);
+
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_writeq_age);
rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq);
+
+ atomic_inc(&qends->endinfo.rtlinfo.rtl_emptyq_age);
rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq);
+
rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags);
break;
case CANQUEUE_NOTIFY_DEAD_WANTED:
rtl_wait_init(&(qends->endinfo.rtlinfo.rtl_emptyq));
qends->notify=canqueue_notify_rtl;
+ qends->endinfo.rtlinfo.pend_flags=0;
return 0;
}
+/**
+ * canqueue_rtl_initialize - initialization of global RT-Linux specific features
+ */
void canqueue_rtl_initialize(void)
{
INIT_LIST_HEAD(&canque_pending_edges_list);
}
+/**
+ * canqueue_rtl_done - finalization of glopal RT-Linux specific features
+ */
void canqueue_rtl_done(void)
{
rtl_free_soft_irq (canqueue_rtl_irq);