[#7222] BF-537: MAC DMA TX interrupt called in infinite loop
Submitted By: Rainer Hoischen
Open Date
2012-07-31 06:37:51 Close Date
2012-08-24 04:05:57
Priority:
Medium Assignee:
Nobody
Status:
Closed Fixed In Release:
N/A
Found In Release:
2010R1-RC5 Release:
Category:
N/A Board:
Custom
Processor:
BF537 Silicon Revision:
0.3
Is this bug repeatable?:
Yes Resolution:
Assigned (Not Start)
Uboot version or rev.:
Toolchain version or rev.:
2010R1-RC4
App binary format:
FDPIC
Summary: BF-537: MAC DMA TX interrupt called in infinite loop
Details:
I recently started working on a simple, very limited real-time driver for the Blackfin ethernet MAC device (outgoing UDP packets only, reception of frames is still handled by the non real-time driver in bfin_mac.c). The custom board which I'm using is quite similar to the BF-537 STAMP.
The real-time driver also uses a chained list of descriptor pairs (packet descriptor "desc_a" and status descriptor "desc_b") for DMA TX. While experimenting with the DMA TX interrupt assigned to DMA channel 2, I experienced some strange behaviour.
I started by using the xenomai real-time driver development API (rtdm_irq_xxxx) to register and manage the interrupt, but this didn't work at all. The system hangs on transmission of the first packet via DMA.
I had more success by leaving the interrupt management to the Linux Kernel. First I tried to enable the interrupt globally by calling enable_irq(IRQ_MAC_TX), but in this case the kernel issued a warning:
WARNING: at kernel/irq/manage.c:274 ___enable_irq+0x3c/0x60()
Unbalanced enable for IRQ 25
Then I tried a descriptor-based interrupt setup by enabling the DI_EN flag in the config word of the second status descriptor desc_b (along with DMAEN for both descriptors and other settings for direction, fetching etc.). The minimalist ISR looks like this:
static irqreturn_t bfin_mac_interrupt_tx(int irq, void *irq_handle)
{
u16 irq_status;
irq_status = bfin_read_DMA2_IRQ_STATUS();
while (irq_status & (DMA_RUN | DFETCH)) {
DBG_ISR_PRINTK(1, "tx relax DMA status: 0x%04x\n", irq_status);
irq_status = bfin_read_DMA2_IRQ_STATUS();
}
bfin_write_DMA2_IRQ_STATUS(bfin_read_DMA2_IRQ_STATUS() | DMA_DONE | DMA_ERR);
SSYNC();
DBG_ISR_PRINTK(1, "** ISR TX: opmode = 0x%x, sysctl = 0x%x, irq status=0x%x (was: 0x%x), dma_config=0x%x\n",
bfin_read_EMAC_OPMODE(), bfin_read_EMAC_SYSCTL(), bfin_read_DMA2_IRQ_STATUS(), irq_status, bfin_read_DMA2_CONFIG());
return IRQ_HANDLED;
}
Now this ISR was called on the transmission of a packet, but in an infinite loop. I could see from the debug output that the irq status flag was cleared in the status register after the first call but nevertheless it was called infinitely regardless of any packet transmission.
Does anybody has an idea what's going wrong here?
Thanks,
Rainer
Follow-ups
--- Sonic Zhang 2012-07-31 23:49:42
You should post this question on EZ Linux community first.
--- Sonic Zhang 2012-08-24 05:04:21
Discussed on Forum
Files
Changes
Commits
Dependencies
Duplicates
Associations
Tags
File Name File Type File Size Posted By
No Files Were Found