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.
#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)
int board_nr;
int chip_nr;
int irq2linux=0;
int board_nr;
int chip_nr;
int irq2linux=0;
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);
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)
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.
+ *
+ * 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*/
}
/**
* 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
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);
cl2_clear_interrupt(chipext);
cl2_clear_interrupt(chipext);
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;
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;