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

RE: Kernel oops using DMA on MCM



Hi, in the fixed version I changed that portion of the code so now it looks
like:

	char out_buffer[OUT_BUFFER_SIZE+OUT_BUFFER_PAD] __attribute__
((aligned(L1_CACHE_BYTES)));
	volatile char* outreadp;  /* Next byte to be read by dma (updated at
interrupt time) */
	volatile char* outwritep; /* Next byte to be written by tasklet */
	// Align DMA input buffer to avoid the DMA cache bug of Etrax 100LX
	char in_buffer[IN_BUFFER_SIZE+IN_BUFFER_PAD] __attribute__
((aligned(L1_CACHE_BYTES)));
	volatile char* inreadp;  /* Next byte to be read by tasklet */
	volatile char* inwritep; /* Next byte to be written by dma (updated
at interript handler) */

, where buffer sizes are 384 (multiple of the cacheline now) and pad sizes
are 64 bytes, similar to the ethernet driver.

Initially I had not aligned the output buffer, and I found that this was
causing the kernel oops somehow. When I also aligned the output buffer, the
driver started to work reliably. In my tests I found that whenever I remove
the alignment from the output buffer, transmit DMA causes kernel oops. I
experimented with different pad sizes too, and even if it is , the driver
seems to work reliably. I am planning to leave it at 2*cacheline, however.

Regards,

Mahmut


> -----Original Message-----
> From: Mikael Starvik [mailto:mikael.starvik@xxxxxxx.com]
> Sent: Thursday, 19 December 2002 21:06
> To: 'Fettahlioglu, Mahmut'
> Cc: dev-etrax
> Subject: RE: Kernel oops using DMA on MCM
> 
> 
> Great, good work!
> 
> >What has happened was probably not the cache-bug though, 
> because according
> >to its doco it was only supposed to happen for DMA receive 
> channels, not
> >transmit. Any thoughts?
> 
> No, not really. I have to check your code in detail. After a 
> quick peak
> it seams dangerous to have IN_BUFFER_SIZE = OUT_BUFFER_SIZE = 240
> because 240 = 7.5 cacheline. Does your sync_port look like this:
> 
> char out_buffer[OUT_BUFFER_SIZE];
> volatile char* outreadp;  /* Next byte to be read by dma 
> (updated at interrupt time) */
> volatile char* outwritep; /* Next byte to be written by tasklet */
> char in_buffer[IN_BUFFER_SIZE] __attribute__ ((aligned (32)));
> volatile char* inreadp;  /* Next byte to be read by tasklet */
> volatile char* inwritep; /* Next byte to be written by dma 
> (updated at interript handler) */
> 
> you have to make sure that inreadp etc does not share cache line 
> with in_buffer. This can be done by making sure that either:
> 
> 1. IN_BUFFER_SIZE is a multiple of 32
> 2. A pad is added after in_buffer that is never used
> 3. inreadp is also cache line aligned 
> 
> e.g.
> 
> char in_buffer[IN_BUFFER_SIZE] __attribute__ ((aligned (32)));
> char pad[32 - (IN_BUFFER_SIZE % 32)];
> 
> or 
> 
> char in_buffer[IN_BUFFER_SIZE] __attribute__ ((aligned (32)));
> int dummy __attribute__ ((aligned (32))); 
> 
> PS. The CRIS compiler never pads struct. DS
> 
> /Mikael
>