Hello all,
I have a linux driver for a 4-input DVB card. I have two other ASI cards that transmit data and the 4 receivers of DVB card receive the data. When I make the driver, it installs fine. dmesg shows everything alright. The test applications run perfectly okay too. After that, I tried testing the driver. So, I stopped and started the transmitters and receivers several times. After certain attempts (no pattern really)
to stop and start, the machine completely freezes. I have to manually power the machine down. But, when I use only one ASI card (one transmitter and two receivers on the DVB card), it all works fine. I am running Fedora Core 4.
Can anyone help me debug the code? Or else, at least, shed some light on the debugging side of it. Any help is appreciated. I can post the driver code as well if anyone would like to see it. I am guessing its the interrupts that are not being released properly.
Thanks,
DB
Code for Interrupt handling----
static irqreturn_t dvbm_qlf_irq_handler (int irq, void *dev_id, struct pt_regs *regs) { int i; struct master_dev *card = dev_id; struct list_head *p = &card->iface_list; struct master_iface *iface; unsigned int dmaintsrc = readl (card->bridge_addr + LSDMA_INTSRC); unsigned int status, interrupting_iface = 0;
for (i = 0; i < 4; i++) { p = p->next;
iface = list_entry (p, struct master_iface, list);
/* Check and Clear ASI interrupts */ spin_lock (&card->irq_lock); status = readl (card->core_addr + DVBM_QLF_ICSR(i));
if ((status & DVBM_QLF_ICSR_ISMASK) != 0) { writel (status, card->core_addr + DVBM_QLF_ICSR(i));
if (status & DVBM_QLF_ICSR_RXCDIS) { set_bit (ASI_EVENT_RX_CARRIER_ORDER, &iface->events); interrupting_iface |= (0x1 events); interrupting_iface |= (0x1 events); interrupting_iface |= (0x1 events); interrupting_iface |= (0x1 events); interrupting_iface |= (0x1 irq_lock);
/* Check and Clear DMA interrupts */ if (dmaintsrc & LSDMA_INTSRC_CH(i)) {
/* Read the interrupt type and clear it */ spin_lock (&card->irq_lock); status = readl (card->bridge_addr + LSDMA_CSR(i)); writel (status, card->bridge_addr + LSDMA_CSR(i)); spin_unlock (&card->irq_lock);
/* Increment the buffer pointer */ if (status & LSDMA_CH_CSR_INTSRCBUFFER) { lsdma_advance (iface->dma); if (lsdma_rx_isempty (iface->dma)) { set_bit (ASI_EVENT_RX_BUFFER_ORDER, &iface->events); } }
/* Flag end-of-chain */ if (status & LSDMA_CH_CSR_INTSRCDONE) { set_bit (0, &iface->dma_done); }
/* Flag DMA abort */ if (status & LSDMA_CH_CSR_INTSRCSTOP) { set_bit (0, &iface->dma_done); }
interrupting_iface |= (0x1 bridge_addr + LSDMA_INTMSK); return IRQ_HANDLED; } return IRQ_NONE; }