[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