]> rtime.felk.cvut.cz Git - lincan.git/commitdiff
Changes, which should enable to handle more VME Unican cards under RT-Linux.
authorppisa <ppisa>
Thu, 3 Feb 2005 16:18:55 +0000 (16:18 +0000)
committerppisa <ppisa>
Thu, 3 Feb 2005 16:18:55 +0000 (16:18 +0000)
Solution is not fully clean and it is not consistent with RT-Linux
way to handle regular ISA and PCI interrupts. The deeper analysis is
required, how to use this approach with regular Linux. May it be, that Linux 2.6.x
with latest IRQ threads and mutexes instead of spin-lock  patches from Ingo
Molnar could profit from this in future too.

lincan/include/constants.h
lincan/src/can_devrtl.c
lincan/src/unican.c

index 327e5ef48427e21e17acfbf084fa8768646d6284..dc2bb40b15d8f838ab0ab814c19fd2c03e3d07bf 100644 (file)
 #define CHIP_MAX_IRQLOOP 1000
 
 /* System independent defines of IRQ handled state */
 #define CHIP_MAX_IRQLOOP 1000
 
 /* System independent defines of IRQ handled state */
-#define CANCHIP_IRQ_NONE    0
-#define CANCHIP_IRQ_HANDLED 1
-#define CANCHIP_IRQ_STUCK   2
+#define CANCHIP_IRQ_NONE     0
+#define CANCHIP_IRQ_HANDLED  1
+#define CANCHIP_IRQ_ACCEPTED 2
+#define CANCHIP_IRQ_STUCK    3
 
 /* These flags can be used for the candevices_t structure flags data entry */
 #define CANDEV_PROGRAMMABLE_IRQ (1<<0)
 
 /* These flags can be used for the candevices_t structure flags data entry */
 #define CANDEV_PROGRAMMABLE_IRQ (1<<0)
index 5bbc2c0ff2cf7230d32af9f71fce5bd2bb55a8f6..c7ff970e7d51babeff45354fa4a7c094ebce3028 100644 (file)
@@ -31,6 +31,7 @@ unsigned int can_rtl_isr( unsigned int irq_num, struct pt_regs *r )
        int board_nr;
        int chip_nr;
        int irq2linux=0;
        int board_nr;
        int chip_nr;
        int irq2linux=0;
+       int ret;
        pthread_t thread=NULL;
 
        DEBUGMSG("can_rtl_isr invoked for irq %d\n",irq_num);
        pthread_t thread=NULL;
 
        DEBUGMSG("can_rtl_isr invoked for irq %d\n",irq_num);
@@ -44,6 +45,9 @@ unsigned int can_rtl_isr( unsigned int irq_num, struct pt_regs *r )
                                continue;
                        if(chip->chip_irq!=irq_num) continue;
 
                                continue;
                        if(chip->chip_irq!=irq_num) continue;
 
+                       if(chip->chipspecops->irq_accept)
+                               ret=chip->chipspecops->irq_accept(chip->chip_irq,chip);
+
                        set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags);
                        set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags);
                        if(chip->flags & CHIP_IRQ_PCI)
                        set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags);
                        set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags);
                        if(chip->flags & CHIP_IRQ_PCI)
@@ -135,9 +139,17 @@ void * can_chip_worker_thread(void *arg)
                if(chip->chip_irq>=0) {
                        if ((chip->flags & CHIP_IRQ_VME) == 0) can_enable_irq(chip->chip_irq);
                    #ifdef CAN_ENABLE_VME_SUPPORT
                if(chip->chip_irq>=0) {
                        if ((chip->flags & CHIP_IRQ_VME) == 0) can_enable_irq(chip->chip_irq);
                    #ifdef CAN_ENABLE_VME_SUPPORT
-                       else tundra_rtl_enable_pci_irq(); 
+                     #if 0
+                       else tundra_rtl_enable_pci_irq();
+                     #endif
                        /* FIXME: Bad practice. Doesn't work with more
                        /* FIXME: Bad practice. Doesn't work with more
-                        * than one card. */
+                        * than one card.
+                        *
+                        * irq_accept added to the LinCAN driver now,
+                        * and above workaround should not be required.
+                        * Enable rtl_hard_enable_irq() at line 
+                        * ca91c042.c:1045
+                        */
                    #endif /*CAN_ENABLE_VME_SUPPORT*/
 
                }
                    #endif /*CAN_ENABLE_VME_SUPPORT*/
 
                }
index 4efabc874e98ef4be97510e1effc2f184fd08b93..f72bacc169eca68433c8f865ae82fa69df807abc 100644 (file)
@@ -558,10 +558,7 @@ void unican_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
 /**
  * unican_irq_handler: - interrupt service routine
  * @irq: interrupt vector number, this value is system specific
 /**
  * unican_irq_handler: - interrupt service routine
  * @irq: interrupt vector number, this value is system specific
- * @dev_id: driver private pointer registered at time of request_irq() call.
- *     The CAN driver uses this pointer to store relationship of interrupt
- *     to chip state structure - @struct canchip_t
- * @regs: system dependent value pointing to registers stored in exception frame
+ * @chip: pointer to chip state structure
  * 
  * Interrupt handler is activated when state of CAN controller chip changes,
  * there is message to be read or there is more space for new messages or
  * 
  * Interrupt handler is activated when state of CAN controller chip changes,
  * there is message to be read or there is more space for new messages or
@@ -582,8 +579,13 @@ int unican_irq_handler(int irq, struct canchip_t *chip)
                return CANCHIP_IRQ_NONE;
        }
 
                return CANCHIP_IRQ_NONE;
        }
 
-       if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST)
+       if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST) {
+               /* Reenable interrupts generation, this has to be even there, 
+                * because irq_accept disables interrupts
+                */
+               cl2_gen_interrupt(chipext);
                return CANCHIP_IRQ_NONE;
                return CANCHIP_IRQ_NONE;
+       }
 
        cl2_clear_interrupt(chipext);
 
 
        cl2_clear_interrupt(chipext);
 
@@ -606,12 +608,31 @@ int unican_irq_handler(int irq, struct canchip_t *chip)
                unican_read(chip, obj);
        }
 
                unican_read(chip, obj);
        }
 
+       /* Reenable interrupts generation */
        cl2_gen_interrupt(chipext);
 
        return CANCHIP_IRQ_HANDLED;
 }
 
 
        cl2_gen_interrupt(chipext);
 
        return CANCHIP_IRQ_HANDLED;
 }
 
 
+/**
+ * unican_irq_accept: - fast irq accept routine, blocks further interrupts
+ * @irq: interrupt vector number, this value is system specific
+ * @chip: pointer to chip state structure
+ * 
+ * This routine only accepts interrupt reception and stops further
+ * incoming interrupts, but does not handle situation causing interrupt.
+ * File: src/unican.c
+ */
+int unican_irq_accept(int irq, struct canchip_t *chip)
+{
+       sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
+
+       cl2_clear_interrupt(chipext);
+
+       return CANCHIP_IRQ_ACCEPTED;
+}
+
 /*void unican_do_tx_timeout(unsigned long data)
 {
        struct msgobj_t *obj=(struct msgobj_t *)data;
 /*void unican_do_tx_timeout(unsigned long data)
 {
        struct msgobj_t *obj=(struct msgobj_t *)data;
@@ -797,7 +818,7 @@ int unican_init_chip_data(struct candevice_t *candev, int chipnr)
        chip->chipspecops->start_chip=unican_start_chip;
        chip->chipspecops->stop_chip=unican_stop_chip;
        chip->chipspecops->irq_handler=unican_irq_handler;
        chip->chipspecops->start_chip=unican_start_chip;
        chip->chipspecops->stop_chip=unican_stop_chip;
        chip->chipspecops->irq_handler=unican_irq_handler;
-       chip->chipspecops->irq_accept=NULL;
+       chip->chipspecops->irq_accept=unican_irq_accept;
 
        return 0;
 }
 
        return 0;
 }