Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 38993
b: refs/heads/master
c: cdcc89b
h: refs/heads/master
i:
  38991: e03e508
v: v3
  • Loading branch information
Arnd Bergmann authored and Paul Mackerras committed Oct 4, 2006
1 parent 15d8996 commit eabb449
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ac91cb8dae061ced64e475d0d70fac4a95298819
refs/heads/master: cdcc89bb1c6e886a55fe00e2de3b9c65d41674c2
154 changes: 125 additions & 29 deletions trunk/arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,27 +354,54 @@ static int spufs_pipe_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file);
}

/*
* Read as many bytes from the mailbox as possible, until
* one of the conditions becomes true:
*
* - no more data available in the mailbox
* - end of the user provided buffer
* - end of the mapped area
*/
static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
struct spu_context *ctx = file->private_data;
u32 mbox_data;
int ret;
u32 mbox_data, __user *udata;
ssize_t count;

if (len < 4)
return -EINVAL;

if (!access_ok(VERIFY_WRITE, buf, len))
return -EFAULT;

udata = (void __user *)buf;

spu_acquire(ctx);
ret = ctx->ops->mbox_read(ctx, &mbox_data);
for (count = 0; count <= len; count += 4, udata++) {
int ret;
ret = ctx->ops->mbox_read(ctx, &mbox_data);
if (ret == 0)
break;

/*
* at the end of the mapped area, we can fault
* but still need to return the data we have
* read successfully so far.
*/
ret = __put_user(mbox_data, udata);
if (ret) {
if (!count)
count = -EFAULT;
break;
}
}
spu_release(ctx);

if (!ret)
return -EAGAIN;

if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
return -EFAULT;
if (!count)
count = -EAGAIN;

return 4;
return count;
}

static struct file_operations spufs_mbox_fops = {
Expand Down Expand Up @@ -430,36 +457,70 @@ void spufs_ibox_callback(struct spu *spu)
kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
}

/*
* Read as many bytes from the interrupt mailbox as possible, until
* one of the conditions becomes true:
*
* - no more data available in the mailbox
* - end of the user provided buffer
* - end of the mapped area
*
* If the file is opened without O_NONBLOCK, we wait here until
* any data is available, but return when we have been able to
* read something.
*/
static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
struct spu_context *ctx = file->private_data;
u32 ibox_data;
ssize_t ret;
u32 ibox_data, __user *udata;
ssize_t count;

if (len < 4)
return -EINVAL;

if (!access_ok(VERIFY_WRITE, buf, len))
return -EFAULT;

udata = (void __user *)buf;

spu_acquire(ctx);

ret = 0;
/* wait only for the first element */
count = 0;
if (file->f_flags & O_NONBLOCK) {
if (!spu_ibox_read(ctx, &ibox_data))
ret = -EAGAIN;
count = -EAGAIN;
} else {
ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
}
if (count)
goto out;

spu_release(ctx);
/* if we can't write at all, return -EFAULT */
count = __put_user(ibox_data, udata);
if (count)
goto out;

if (ret)
return ret;
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
ret = ctx->ops->ibox_read(ctx, &ibox_data);
if (ret == 0)
break;
/*
* at the end of the mapped area, we can fault
* but still need to return the data we have
* read successfully so far.
*/
ret = __put_user(ibox_data, udata);
if (ret)
break;
}

ret = 4;
if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
ret = -EFAULT;
out:
spu_release(ctx);

return ret;
return count;
}

static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
Expand Down Expand Up @@ -532,32 +593,67 @@ void spufs_wbox_callback(struct spu *spu)
kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
}

/*
* Write as many bytes to the interrupt mailbox as possible, until
* one of the conditions becomes true:
*
* - the mailbox is full
* - end of the user provided buffer
* - end of the mapped area
*
* If the file is opened without O_NONBLOCK, we wait here until
* space is availabyl, but return when we have been able to
* write something.
*/
static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
size_t len, loff_t *pos)
{
struct spu_context *ctx = file->private_data;
u32 wbox_data;
int ret;
u32 wbox_data, __user *udata;
ssize_t count;

if (len < 4)
return -EINVAL;

if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
udata = (void __user *)buf;
if (!access_ok(VERIFY_READ, buf, len))
return -EFAULT;

if (__get_user(wbox_data, udata))
return -EFAULT;

spu_acquire(ctx);

ret = 0;
/*
* make sure we can at least write one element, by waiting
* in case of !O_NONBLOCK
*/
count = 0;
if (file->f_flags & O_NONBLOCK) {
if (!spu_wbox_write(ctx, wbox_data))
ret = -EAGAIN;
count = -EAGAIN;
} else {
ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
}

spu_release(ctx);
if (count)
goto out;

return ret ? ret : sizeof wbox_data;
/* write aѕ much as possible */
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
ret = __get_user(wbox_data, udata);
if (ret)
break;

ret = spu_wbox_write(ctx, wbox_data);
if (ret == 0)
break;
}

out:
spu_release(ctx);
return count;
}

static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
Expand Down

0 comments on commit eabb449

Please sign in to comment.