[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Problem with external dma and linked lists.



Hi,

I've got a problem with our driver that uses the external dma channel 0.
Here a description of the problem : 

I try to setup a linked list for output transfers. The driver works
perfectly when there is only one descriptor available to the dma
controller. When I try to setup a linked list, the output channel 0 stops
after the first descriptor.  Here the content of the dma registers in the
interrupt routine that will be called after the first packet has been
processed. 

Altera ACEX 1k Adding descriptor to EMPTY queue
Altera ACEX 1k Added descriptor = 0x40e8d200
Altera ACEX 1k Adding descriptor to queue
Altera ACEX 1k Added descriptor = 0x40e8d280

<interrupt>

Altera ACEX 1k Bytes send = 32760, Bytes left = 32696
Altera ACEX 1k Bytes in FIFO = 64
Altera ACEX 1k CH4 DESCR = 0x40e8d280
Altera ACEX 1k CH4 FIRST = 0x40e8d280
Altera ACEX 1k CH4 NEXT = 0x0
Altera ACEX 1k CH4 Status = 0x3
Altera ACEX 1k DMA0 Status = 0x0

I try to transfer 32760 bytes with the second descriptor. The descriptor
has been loaded by the dma controller, the address has been updated in CH4
DESCR register. The dma channel 4 is still running but the external dma
channel has been stopped.  The linked list seems to be okay, the
descriptor data has been successfully processed and the register data
seems to be okay.

Here the setup of the external dma channel  :

			IO_STATE (R_EXT_DMA_0_CMD, cnt, disable) |
			IO_STATE (R_EXT_DMA_0_CMD, rqpol, ahigh) |
			IO_STATE (R_EXT_DMA_0_CMD, apol, ahigh) |
			IO_STATE (R_EXT_DMA_0_CMD, rq_ack, handsh) |
			IO_STATE (R_EXT_DMA_0_CMD, wid, word) |
			IO_STATE (R_EXT_DMA_0_CMD, dir, output) |
			IO_STATE (R_EXT_DMA_0_CMD, run, start) |
			nCount >> 1;

The counter is disabled, the controller works in handshake mode.

Here the code that adds a new descriptor to the linked list : 

		g_pDmaDescr = 	(etrax_dma_descr*) kmalloc( sizeof( etrax_dma_descr ),
GFP_KERNEL );
	
		if( g_pDmaDescr == NULL )
			return -ENOMEM;

		/* Clear descriptor struct */

		memset( g_pDmaDescr, 0, sizeof( etrax_dma_descr ));

		/* Fill out DMA descriptor */

		g_pDmaDescr->sw_len 	= nCount;
		g_pDmaDescr->ctrl	= d_eol | d_eop | d_wait;
		g_pDmaDescr->next	= 0;
		g_pDmaDescr->hw_len 	= 0;
		g_pDmaDescr->status 	= 0;
		g_pDmaDescr->buf 	= virt_to_phys( pBuffer );


		g_pLastDmaDescr->next = virt_to_phys( g_pDmaDescr );

		/* Clear last decriptor flag */

		g_pLastDmaDescr->ctrl &= ~d_eol;

		printk(KERN_ERR "%s Added descriptor = 0x%x\n", FPGA_NAME,
g_pLastDmaDescr->next );

		/* Remember new last descriptor */

		g_pLastDmaDescr = g_pDmaDescr;

		/* Restart DMA channel */

		*R_DMA_CH4_CMD 		= IO_STATE( R_DMA_CH4_CMD, cmd, restart );


g_pLastDmaDescr is a static pointer to the last descriptor that has been
transfered to the dma controller.

Do I miss something ? After processing the link list, the dma controller
needs to be resetted for further operation. 

Thank you in advance,

	Arne Bockholdt

Dipl. Inform. Arne Bockholdt
REA Elektronik GmbH
Teichwiesenstr. 1
64367 Mühltal-Waschenbach
Tel. +49 (0) 6154 / 638-115, Fax -195
ABockholdt@xxxxxxx.de