diff options
| author | Minkyu Kang <mk7.kang@samsung.com> | 2012-12-10 13:44:41 +0900 | 
|---|---|---|
| committer | Minkyu Kang <mk7.kang@samsung.com> | 2012-12-10 14:13:27 +0900 | 
| commit | 2c601c7208713ba9b2158c57adcf515f4bdbc212 (patch) | |
| tree | 9f6e70f33565beceb956b98c261bee19731d50d2 /common/bouncebuf.c | |
| parent | b8a7c467960ffb4d5a5e1eef5f7783fb6f594542 (diff) | |
| parent | fd4d564b3c80b111f18c93adb14233a6a7ddb0e9 (diff) | |
| download | olio-uboot-2014.01-2c601c7208713ba9b2158c57adcf515f4bdbc212.tar.xz olio-uboot-2014.01-2c601c7208713ba9b2158c57adcf515f4bdbc212.zip | |
Merge branch 'master' of git://git.denx.de/u-boot into resolve
Conflicts:
	README
	board/samsung/universal_c210/universal.c
	drivers/misc/Makefile
	drivers/power/power_fsl.c
	include/configs/mx35pdk.h
	include/configs/mx53loco.h
	include/configs/seaboard.h
Diffstat (limited to 'common/bouncebuf.c')
| -rw-r--r-- | common/bouncebuf.c | 73 | 
1 files changed, 40 insertions, 33 deletions
| diff --git a/common/bouncebuf.c b/common/bouncebuf.c index 4f827f893..1df12cdda 100644 --- a/common/bouncebuf.c +++ b/common/bouncebuf.c @@ -27,21 +27,19 @@  #include <errno.h>  #include <bouncebuf.h> -static int addr_aligned(void *data, size_t len) +static int addr_aligned(struct bounce_buffer *state)  {  	const ulong align_mask = ARCH_DMA_MINALIGN - 1;  	/* Check if start is aligned */ -	if ((ulong)data & align_mask) { -		debug("Unaligned start address %p\n", data); +	if ((ulong)state->user_buffer & align_mask) { +		debug("Unaligned buffer address %p\n", state->user_buffer);  		return 0;  	} -	data += len; - -	/* Check if end is aligned */ -	if ((ulong)data & align_mask) { -		debug("Unaligned end address %p\n", data); +	/* Check if length is aligned */ +	if (state->len != state->len_aligned) { +		debug("Unaligned buffer length %d\n", state->len);  		return 0;  	} @@ -49,44 +47,53 @@ static int addr_aligned(void *data, size_t len)  	return 1;  } -int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_start(struct bounce_buffer *state, void *data, +			size_t len, unsigned int flags)  { -	void *tmp; -	size_t alen; - -	if (addr_aligned(*data, len)) { -		*backup = NULL; -		return 0; -	} +	state->user_buffer = data; +	state->bounce_buffer = data; +	state->len = len; +	state->len_aligned = roundup(len, ARCH_DMA_MINALIGN); +	state->flags = flags; -	alen = roundup(len, ARCH_DMA_MINALIGN); -	tmp = memalign(ARCH_DMA_MINALIGN, alen); +	if (!addr_aligned(state)) { +		state->bounce_buffer = memalign(ARCH_DMA_MINALIGN, +						state->len_aligned); +		if (!state->bounce_buffer) +			return -ENOMEM; -	if (!tmp) -		return -ENOMEM; - -	if (flags & GEN_BB_READ) -		memcpy(tmp, *data, len); +		if (state->flags & GEN_BB_READ) +			memcpy(state->bounce_buffer, state->user_buffer, +				state->len); +	} -	*backup = *data; -	*data = tmp; +	/* +	 * Flush data to RAM so DMA reads can pick it up, +	 * and any CPU writebacks don't race with DMA writes +	 */ +	flush_dcache_range((unsigned long)state->bounce_buffer, +				(unsigned long)(state->bounce_buffer) + +					state->len_aligned);  	return 0;  } -int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_stop(struct bounce_buffer *state)  { -	void *tmp = *data; +	if (state->flags & GEN_BB_WRITE) { +		/* Invalidate cache so that CPU can see any newly DMA'd data */ +		invalidate_dcache_range((unsigned long)state->bounce_buffer, +					(unsigned long)(state->bounce_buffer) + +						state->len_aligned); +	} -	/* The buffer was already aligned, since "backup" is NULL. */ -	if (!*backup) +	if (state->bounce_buffer == state->user_buffer)  		return 0; -	if (flags & GEN_BB_WRITE) -		memcpy(*backup, *data, len); +	if (state->flags & GEN_BB_WRITE) +		memcpy(state->user_buffer, state->bounce_buffer, state->len); -	*data = *backup; -	free(tmp); +	free(state->bounce_buffer);  	return 0;  } |