[Cbe-oss-dev] [PATCH 3/3] libspe2: Clean up proxy DMA and add error checks
Kazunori Asayama
asayama at sm.sony.co.jp
Mon Jun 25 23:48:02 EST 2007
This patch modifies proxy DMA implementation in libspe2 as following:
- share the same code between 'get' and 'put'
- make scope of variables smaller
- add missing error checks
Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
---
spebase/dma.c | 201 +++++++++++++++++++++++++++-------------------------------
1 file changed, 97 insertions(+), 104 deletions(-)
Index: b/spebase/dma.c
===================================================================
--- a/spebase/dma.c 2007-06-22 21:48:00.000000000 +0900
+++ b/spebase/dma.c 2007-06-25 10:32:40.000000000 +0900
@@ -32,107 +32,93 @@
static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status);
static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status);
-static int spe_do_mfc_put(spe_context_ptr_t spectx, unsigned src, void *dst,
- unsigned size, unsigned tag, unsigned class,
- enum mfc_cmd cmd)
+static int issue_mfc_command(spe_context_ptr_t spectx, unsigned lsa, void *ea,
+ unsigned size, unsigned tag, unsigned tid, unsigned rid,
+ enum mfc_cmd cmd)
{
- struct mfc_command_parameter_area parm = {
- .lsa = src,
- .ea = (unsigned long) dst,
- .size = size,
- .tag = tag,
- .class = class,
- .cmd = cmd,
- };
- int ret, fd;
- unsigned int eah, eal;
- volatile struct spe_mfc_command_area *cmd_area =
- spectx->base_private->mfc_mmap_base;
+ int ret;
- DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x\n", parm.lsa,
- parm.ea, parm.size, parm.tag, parm.class, parm.cmd);
+ DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x %x\n", lsa,
+ (unsigned long)ea, size, tag, tid, rid, (unsigned)cmd);
+
+ /* tag 16-31 are reserved by kernel */
+ if (tag > 0x0f || tid > 0xff || rid > 0xff) {
+ errno = EINVAL;
+ return -1;
+ }
if (spectx->base_private->flags & SPE_MAP_PS) {
+ volatile struct spe_mfc_command_area *cmd_area =
+ spectx->base_private->mfc_mmap_base;
+ unsigned int eal = (uintptr_t) ea & 0xFFFFFFFF;
+ unsigned int eah = (unsigned long long)(uintptr_t) ea >> 32;
_base_spe_context_lock(spectx, FD_MFC);
- eal = (uintptr_t) dst & 0xFFFFFFFF;
- eah = (unsigned long long)(uintptr_t) dst >> 32;
while ((cmd_area->MFC_QStatus & 0x0000FFFF) == 0) ;
do {
- cmd_area->MFC_LSA = src;
+ cmd_area->MFC_LSA = lsa;
cmd_area->MFC_EAH = eah;
cmd_area->MFC_EAL = eal;
cmd_area->MFC_Size_Tag = (size << 16) | tag;
- cmd_area->MFC_ClassID_CMD = (class << 16) | cmd;
+ cmd_area->MFC_ClassID_CMD = (tid << 24) | (rid << 16) | cmd;
ret = cmd_area->MFC_CMDStatus & 0x00000003;
} while (ret); // at least one of the two bits is set
_base_spe_context_unlock(spectx, FD_MFC);
- return ret;
+ return 0;
}
-
- fd = open_if_closed(spectx, FD_MFC, 0);
- if (fd != -1) {
- ret = write(fd, &parm, sizeof (parm));
- if ((ret < 0) && (errno != EIO)) {
- perror("spe_do_mfc_put: internal error");
+ else {
+ int fd;
+ fd = open_if_closed(spectx, FD_MFC, 0);
+ if (fd != -1) {
+ struct mfc_command_parameter_area parm = {
+ .lsa = lsa,
+ .ea = (unsigned long) ea,
+ .size = size,
+ .tag = tag,
+ .class = (tid << 8) | rid,
+ .cmd = cmd,
+ };
+ ret = write(fd, &parm, sizeof (parm));
+ if ((ret < 0) && (errno != EIO)) {
+ perror("spe_do_mfc_put: internal error");
+ }
+ return ret < 0 ? -1 : 0;
}
- return ret < 0 ? -1 : 0;
}
- /* the kernel does not support DMA, so just copy directly */
- memcpy(dst, spectx->base_private->mem_mmap_base + src, size);
- return 0;
+ /* the kernel does not support DMA */
+ return 1;
}
-static int spe_do_mfc_get(spe_context_ptr_t spectx, unsigned int dst, void *src,
- unsigned int size, unsigned int tag, unsigned int class,
+static int spe_do_mfc_put(spe_context_ptr_t spectx, unsigned src, void *dst,
+ unsigned size, unsigned tag, unsigned tid, unsigned rid,
enum mfc_cmd cmd)
{
- struct mfc_command_parameter_area parm = {
- .lsa = dst,
- .ea = (unsigned long) src,
- .size = size,
- .tag = tag,
- .class = class,
- .cmd = cmd,
- };
- int ret, fd;
- unsigned int eah, eal;
- volatile struct spe_mfc_command_area *cmd_area =
- spectx->base_private->mfc_mmap_base;
-
- DEBUG_PRINTF("queuing DMA %x %x %x %x %x %x\n", parm.lsa,
- parm.ea, parm.size, parm.tag, parm.class, parm.cmd);
-
-
- if (spectx->base_private->flags & SPE_MAP_PS) {
- _base_spe_context_lock(spectx, FD_MFC);
- eal = (uintptr_t) src & 0xFFFFFFFF;
- eah = (unsigned long long)(uintptr_t) src >> 32;
- while ((cmd_area->MFC_QStatus & 0x0000FFFF) == 0) ;
- do {
- cmd_area->MFC_LSA = dst;
- cmd_area->MFC_EAH = eah;
- cmd_area->MFC_EAL = eal;
- cmd_area->MFC_Size_Tag = (size << 16) | tag;
- cmd_area->MFC_ClassID_CMD = (class << 16) | cmd;
- ret = cmd_area->MFC_CMDStatus & 0x00000003;
- } while (ret); // at least one of the two bits is set
- _base_spe_context_unlock(spectx, FD_MFC);
- return ret;
- }
-
- fd = open_if_closed(spectx, FD_MFC, 0);
- if (fd != -1) {
- ret = write(fd, &parm, sizeof (parm));
- if ((ret < 0) && (errno != EIO)) {
- perror("spe_do_mfc_get: internal error");
- }
- return ret < 0 ? -1 : 0;
+ int ret;
+ ret = issue_mfc_command(spectx, src, dst, size, tag, tid, rid, cmd);
+ if (ret <= 0) {
+ return ret;
}
+ else {
+ /* the kernel does not support DMA, so just copy directly */
+ memcpy(dst, spectx->base_private->mem_mmap_base + src, size);
+ return 0;
+ }
+}
- /* the kernel does not support DMA, so just copy directly */
- memcpy(spectx->base_private->mem_mmap_base + dst, src, size);
- return 0;
+static int spe_do_mfc_get(spe_context_ptr_t spectx, unsigned int dst, void *src,
+ unsigned int size, unsigned int tag, unsigned tid, unsigned rid,
+ enum mfc_cmd cmd)
+{
+ int ret;
+ ret = issue_mfc_command(spectx, dst, src, size, tag, tid, rid, cmd);
+ if (ret <= 0) {
+ return ret;
+ }
+ else {
+ /* the kernel does not support DMA, so just copy directly */
+ memcpy(spectx->base_private->mem_mmap_base + dst, src, size);
+ return 0;
+ }
}
int _base_spe_mfcio_put(spe_context_ptr_t spectx,
@@ -143,7 +129,7 @@ int _base_spe_mfcio_put(spe_context_ptr_
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_put(spectx, ls, ea, size, tag & 0xf, tid << 8 | rid, MFC_CMD_PUT);
+ return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUT);
}
int _base_spe_mfcio_putb(spe_context_ptr_t spectx,
@@ -154,9 +140,7 @@ int _base_spe_mfcio_putb(spe_context_ptr
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_put(spectx, ls, ea, size, tag & 0xf,
- tid << 8 | rid, MFC_CMD_PUTB);
-
+ return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTB);
}
int _base_spe_mfcio_putf(spe_context_ptr_t spectx,
@@ -167,9 +151,7 @@ int _base_spe_mfcio_putf(spe_context_ptr
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_put(spectx, ls, ea, size, tag & 0xf,
- tid << 8 | rid, MFC_CMD_PUTF);
-
+ return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTF);
}
@@ -181,8 +163,7 @@ int _base_spe_mfcio_get(spe_context_ptr_
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_get(spectx, ls, ea, size, tag & 0xf,
- tid << 8 | rid, MFC_CMD_GET);
+ return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GET);
}
int _base_spe_mfcio_getb(spe_context_ptr_t spectx,
@@ -193,8 +174,7 @@ int _base_spe_mfcio_getb(spe_context_ptr
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_get(spectx, ls, ea, size, tag & 0xf,
- tid << 8 | rid, MFC_CMD_GETB);
+ return spe_do_mfc_get(spectx, ls, ea, size, tag, rid, rid, MFC_CMD_GETB);
}
int _base_spe_mfcio_getf(spe_context_ptr_t spectx,
@@ -205,8 +185,7 @@ int _base_spe_mfcio_getf(spe_context_ptr
unsigned int tid,
unsigned int rid)
{
- return spe_do_mfc_get(spectx, ls, ea, size, tag & 0xf,
- tid << 8 | rid, MFC_CMD_GETF);
+ return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GETF);
}
static int spe_mfcio_tag_status_read_all(spe_context_ptr_t spectx,
@@ -218,6 +197,9 @@ static int spe_mfcio_tag_status_read_all
return spe_read_tag_status_block(spectx, mask, tag_status);
} else {
fd = open_if_closed(spectx, FD_MFC, 0);
+ if (fd == -1) {
+ return -1;
+ }
if (fsync(fd) != 0) {
return -1;
@@ -225,7 +207,6 @@ static int spe_mfcio_tag_status_read_all
return spe_read_tag_status_block(spectx, mask, tag_status);
}
- return -1;
}
static int spe_mfcio_tag_status_read_any(spe_context_ptr_t spectx,
@@ -247,21 +228,24 @@ static int spe_mfcio_tag_status_read_imm
*/
static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status)
{
- int fd;
- volatile struct spe_mfc_command_area *cmd_area =
- spectx->base_private->mfc_mmap_base;
-
if (spectx->base_private->flags & SPE_MAP_PS) {
+ volatile struct spe_mfc_command_area *cmd_area =
+ spectx->base_private->mfc_mmap_base;
+
_base_spe_context_lock(spectx, FD_MFC);
cmd_area->Prxy_QueryMask = mask;
__asm__ ("eieio");
- *tag_status = 0;
- while (*tag_status ^ mask)
- *tag_status = cmd_area->Prxy_TagStatus;
+ do {
+ *tag_status = cmd_area->Prxy_TagStatus;
+ } while (*tag_status ^ mask);
_base_spe_context_unlock(spectx, FD_MFC);
return 0;
} else {
+ int fd;
fd = open_if_closed(spectx, FD_MFC, 0);
+ if (fd == -1) {
+ return -1;
+ }
if (read(fd,tag_status,4) == 4) {
return 0;
@@ -272,14 +256,12 @@ static int spe_read_tag_status_block(spe
static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status)
{
- struct pollfd poll_fd;
-
- int fd;
unsigned int ret;
- volatile struct spe_mfc_command_area *cmd_area =
- spectx->base_private->mfc_mmap_base;
if (spectx->base_private->flags & SPE_MAP_PS) {
+ volatile struct spe_mfc_command_area *cmd_area =
+ spectx->base_private->mfc_mmap_base;
+
_base_spe_context_lock(spectx, FD_MFC);
cmd_area->Prxy_QueryMask = mask;
__asm__ ("eieio");
@@ -287,7 +269,13 @@ static int spe_read_tag_status_noblock(s
_base_spe_context_unlock(spectx, FD_MFC);
return 0;
} else {
+ struct pollfd poll_fd;
+ int fd;
+
fd = open_if_closed(spectx, FD_MFC, 0);
+ if (fd == -1) {
+ return -1;
+ }
poll_fd.fd = fd;
poll_fd.events = POLLIN;
@@ -316,6 +304,11 @@ int _base_spe_mfcio_tag_status_read(spe_
mask = 0;
}
+ if (!tag_status) {
+ errno = EINVAL;
+ return -1;
+ }
+
switch (behavior) {
case SPE_TAG_ALL:
return spe_mfcio_tag_status_read_all(spectx, mask, tag_status);
More information about the cbe-oss-dev
mailing list