浏览代码

[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>
Kazunori Asayama 18 年之前
父节点
当前提交
933b0e3524
共有 1 个文件被更改,包括 5 次插入4 次删除
  1. 5 4
      arch/powerpc/platforms/cell/spufs/file.c

+ 5 - 4
arch/powerpc/platforms/cell/spufs/file.c

@@ -1499,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
 		if (status)
 		if (status)
 			ret = status;
 			ret = status;
 	}
 	}
-	spu_release(ctx);
 
 
 	if (ret)
 	if (ret)
-		goto out;
+		goto out_unlock;
 
 
 	ctx->tagwait |= 1 << cmd.tag;
 	ctx->tagwait |= 1 << cmd.tag;
 	ret = size;
 	ret = size;
 
 
+out_unlock:
+	spu_release(ctx);
 out:
 out:
 	return ret;
 	return ret;
 }
 }
@@ -1517,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
 	u32 free_elements, tagstatus;
 	u32 free_elements, tagstatus;
 	unsigned int mask;
 	unsigned int mask;
 
 
+	poll_wait(file, &ctx->mfc_wq, wait);
+
 	spu_acquire(ctx);
 	spu_acquire(ctx);
 	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
 	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
 	free_elements = ctx->ops->get_mfc_free_elements(ctx);
 	free_elements = ctx->ops->get_mfc_free_elements(ctx);
 	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
 	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
 	spu_release(ctx);
 	spu_release(ctx);
 
 
-	poll_wait(file, &ctx->mfc_wq, wait);
-
 	mask = 0;
 	mask = 0;
 	if (free_elements & 0xffff)
 	if (free_elements & 0xffff)
 		mask |= POLLOUT | POLLWRNORM;
 		mask |= POLLOUT | POLLWRNORM;