AnsweredAssumed Answered

MPC831e + DMA

Question asked by Juan Antonio Medina Guerrero on Sep 24, 2008
Latest reply on Oct 15, 2008 by Juan Antonio Medina Guerrero


            We are facing some issues when trying to use the MPC8313e  DMA peripheral. When we start a DMA transaction our system freezes so we must reset it. We are trying several buffer configurations (dynamical and static) and various transfer sizes but the same problem keeps on happening, the systems stops responding. There is also an important thing that may help you to find the cause. Sometimes the system freezes at the first transaction, but sometimes it happens later.


Below you can find the piece of code that fails. This code works without DMA (using a write loop). Could you please help us identifying the wrong part?


Thanks in advance.


DMA:  memory to PCI (4byte, direct mode, snooping).

            Memory buffer from kmalloc

            1000 bytes



// pointer to the kmalloc'd area, rounded up to a page boundary

static char *buffer_area;

// original pointer for kmalloc'd area as returned by kmalloc

static void *buffer_ptr;






// Allocate a memory area with kmalloc. Will be rounded up to a page boundary

       buffer_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL);

       if ( buffer_ptr == NULL)


             printk ( KERN_ALERT "\n\tERROR: kmalloc\n");

             return -ENOMEM;


// round it up to the page bondary

       buffer_area = (int *)((((unsigned long)buffer_ptr) + PAGE_SIZE - 1) & PAGE_MASK);

       printk ("\n\tkmalloc buffer (0x%.8x@%lu)...", buffer_area,(NPAGES + 2) * PAGE_SIZE);







       int *buffer=(int *)buffer_area;


       printk("pci_write:smileyvery-happy:MA buffer  %.8x v - %.8x p - %.8x b\n",

             buffer, virt_to_phys(buffer), virt_to_bus(buffer));


       copy_from_user((void *)buffer,(void *)buf,count_c);


       *dmadar1=swapbyte(PCI_ADDR);                   //Dest Address

       *dmasar1=swapbyte(virt_to_phys (buffer));      //Source Address



       *dmabcr1=swapbyte(wr);                         //Byte count



       *dmamr1=DMAMR_WR;                       //Config Mode

       printk("DMA_WR: Before START\n");


       *dmamr1=DMAMR_WR_S;                     //Start DMA

       printk("DMA_WR: After START\n");






Console output:



kmalloc buffer (0xc0998000@28672)...



pci_write:smileyvery-happy:MA buffer  c7fb0000 v - 07fb0000 p - 07fb0000 b


        Config DMA

     MODE       STATUS     DESC ACT   SOURCE     DEST       COUNT      NEXT DESC

(1) 04801200   00000000   00000000   00009c00   004000e3   e8030000   00000000


        Config DMA

     MODE       STATUS     DESC ACT   SOURCE     DEST       COUNT      NEXT DESC

(1)  Here is where the system stops. There should be written the same as in the previous example