[#7222] BF-537: MAC DMA TX interrupt called in infinite loop

Document created by Aaronwu Employee on Sep 12, 2013
Version 1Show Document
  • View in full screen mode

[#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

Attachments

    Outcomes