[Cbe-oss-dev] [PATCH 1/2]MARS: Fix 64 bit dma list usage
Yuji Mano
yuji.mano at am.sony.com
Wed Oct 8 09:50:29 EST 2008
This fixes the internal implementation usage of dma lists so that they can
be used properly in a 64-bit environment. The dma list command assumes the
upper 32-bits of EAs in the list are the same values. Since this is not
guaranteed on linux for 64-bit environments, the function that prepares the
dma lists now checks to see if the upper 32-bits of the address range to be
transferred are the same. If it crosses a 64-bit boundary, the dma list
operation is divided into 2 separate dma list calls.
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
src/mpu/lib/dma.h | 61 ++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 48 insertions(+), 13 deletions(-)
--- a/src/mpu/lib/dma.h
+++ b/src/mpu/lib/dma.h
@@ -47,11 +47,22 @@
#include <assert.h>
#include <spu_mfcio.h>
-#define MARS_DMA_TAG 31 /* dma tag reserved for MARS */
-#define MARS_DMA_TAG_MAX 31 /* dma tag 0~31 */
-#define MARS_DMA_ALIGN_MASK 0xf /* dma 16 byte alignment mask */
-#define MARS_DMA_SIZE_MASK 0xf /* dma 16 byte size mask */
-#define MARS_DMA_SIZE_MAX 16384 /* dma single tranfer size max 16KB */
+/* dma tag reserved for MARS */
+#define MARS_DMA_TAG 31
+/* dma tag 0~31 */
+#define MARS_DMA_TAG_MAX 31
+/* dma 16 byte alignment mask */
+#define MARS_DMA_ALIGN_MASK 0xf
+/* dma 16 byte size mask */
+#define MARS_DMA_SIZE_MASK 0xf
+/* dma single tranfer size max 16KB */
+#define MARS_DMA_SIZE_MAX 16384
+/* dma large transfer boundary max */
+#define MARS_DMA_LIST_BOUNDARY_MASK 0xffffffff00000000ULL
+/* dma list array size */
+#define MARS_DMA_LIST_SIZE 16
+/* dma large transfer size max */
+#define MARS_DMA_LARGE_SIZE_MAX (MARS_DMA_SIZE_MAX * MARS_DMA_LIST_SIZE)
#if defined(__cplusplus)
extern "C" {
@@ -82,21 +93,45 @@ static inline unsigned int _list_init(mf
static inline void _mars_dma_large_get(void *ls, uint64_t ea,
uint32_t size, uint32_t tag)
{
- mfc_list_element_t list[16] __attribute__((aligned(8)));
+ mfc_list_element_t list[MARS_DMA_LIST_SIZE] __attribute__((aligned(8)));
unsigned int list_size;
+ uint64_t ea2 = (ea + size - 1) & MARS_DMA_LIST_BOUNDARY_MASK;
- list_size = _list_init(list, size, mfc_ea2l(ea));
- mfc_getl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+ if (mfc_ea2h(ea) != mfc_ea2h(ea2)) {
+ uint32_t size1 = ea2 - ea;
+ uint32_t size2 = size - size1;
+
+ list_size = _list_init(list, size1, mfc_ea2l(ea));
+ mfc_getl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+
+ list_size = _list_init(list, size2, mfc_ea2l(ea2));
+ mfc_getl((volatile void *)ls, ea2, &list, list_size, tag, 0, 0);
+ } else {
+ list_size = _list_init(list, size, mfc_ea2l(ea));
+ mfc_getl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+ }
}
static inline void _mars_dma_large_put(const void *ls, uint64_t ea,
uint32_t size, uint32_t tag)
{
- mfc_list_element_t list[16] __attribute__((aligned(8)));
+ mfc_list_element_t list[MARS_DMA_LIST_SIZE] __attribute__((aligned(8)));
unsigned int list_size;
+ uint64_t ea2 = (ea + size - 1) & MARS_DMA_LIST_BOUNDARY_MASK;
- list_size = _list_init(list, size, mfc_ea2l(ea));
- mfc_putl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+ if (mfc_ea2h(ea) != mfc_ea2h(ea2)) {
+ uint32_t size1 = ea2 - ea;
+ uint32_t size2 = size - size1;
+
+ list_size = _list_init(list, size1, mfc_ea2l(ea));
+ mfc_putl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+
+ list_size = _list_init(list, size2, mfc_ea2l(ea2));
+ mfc_putl((volatile void *)ls, ea2, &list, list_size, tag, 0, 0);
+ } else {
+ list_size = _list_init(list, size, mfc_ea2l(ea));
+ mfc_putl((volatile void *)ls, ea, &list, list_size, tag, 0, 0);
+ }
}
/*
@@ -365,7 +400,7 @@ static inline void mars_dma_large_get(vo
{
assert(((uintptr_t)ls & MARS_DMA_ALIGN_MASK) == 0);
assert(((uintptr_t)ea & MARS_DMA_ALIGN_MASK) == 0);
- assert(size);
+ assert(size && size <= MARS_DMA_LARGE_SIZE_MAX);
assert(tag <= MARS_DMA_TAG_MAX);
_mars_dma_large_get(ls, ea, size, tag);
@@ -419,7 +454,7 @@ static inline void mars_dma_large_put(co
{
assert(((uintptr_t)ls & MARS_DMA_ALIGN_MASK) == 0);
assert(((uintptr_t)ea & MARS_DMA_ALIGN_MASK) == 0);
- assert(size);
+ assert(size && size <= MARS_DMA_LARGE_SIZE_MAX);
assert(tag <= MARS_DMA_TAG_MAX);
_mars_dma_large_put(ls, ea, size, tag);
More information about the cbe-oss-dev
mailing list