diff options
author | Kazunori Asayama <asayama@sm.sony.co.jp> | 2007-06-28 20:58:08 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-07-03 01:24:46 -0400 |
commit | 933b0e35247ef0dbd1a078a0ba3705ddbbda129f (patch) | |
tree | 9f96bc933290724a26b0feeed18f7a07a141cc00 /arch | |
parent | fe2f896d67b89a409c366c9a69e30291ab124467 (diff) |
[POWERPC] spufs: Fix lost events in poll/epoll on mfc
When waiting for I/O events on mfc in an SPU context by using
poll/epoll syscalls, some of the events can be lost because of wrong
order of poll_wait and MFC status checks in the spufs_mfc_poll
function and non-atomic update of tagwait. This fixes the
problem.
Signed-off-by: Kazunori Asayama <asayama@sm.sony.co.jp>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 30f7b077f347..c2814ea96af2 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -1499,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | |||
1499 | if (status) | 1499 | if (status) |
1500 | ret = status; | 1500 | ret = status; |
1501 | } | 1501 | } |
1502 | spu_release(ctx); | ||
1503 | 1502 | ||
1504 | if (ret) | 1503 | if (ret) |
1505 | goto out; | 1504 | goto out_unlock; |
1506 | 1505 | ||
1507 | ctx->tagwait |= 1 << cmd.tag; | 1506 | ctx->tagwait |= 1 << cmd.tag; |
1508 | ret = size; | 1507 | ret = size; |
1509 | 1508 | ||
1509 | out_unlock: | ||
1510 | spu_release(ctx); | ||
1510 | out: | 1511 | out: |
1511 | return ret; | 1512 | return ret; |
1512 | } | 1513 | } |
@@ -1517,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) | |||
1517 | u32 free_elements, tagstatus; | 1518 | u32 free_elements, tagstatus; |
1518 | unsigned int mask; | 1519 | unsigned int mask; |
1519 | 1520 | ||
1521 | poll_wait(file, &ctx->mfc_wq, wait); | ||
1522 | |||
1520 | spu_acquire(ctx); | 1523 | spu_acquire(ctx); |
1521 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); | 1524 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); |
1522 | free_elements = ctx->ops->get_mfc_free_elements(ctx); | 1525 | free_elements = ctx->ops->get_mfc_free_elements(ctx); |
1523 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); | 1526 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); |
1524 | spu_release(ctx); | 1527 | spu_release(ctx); |
1525 | 1528 | ||
1526 | poll_wait(file, &ctx->mfc_wq, wait); | ||
1527 | |||
1528 | mask = 0; | 1529 | mask = 0; |
1529 | if (free_elements & 0xffff) | 1530 | if (free_elements & 0xffff) |
1530 | mask |= POLLOUT | POLLWRNORM; | 1531 | mask |= POLLOUT | POLLWRNORM; |