[PATCH] spufs: cooperative scheduler support
[deliverable/linux.git] / arch / powerpc / platforms / cell / spufs / file.c
index c1e643310494f558346b4cab819d1a2bac873407..786fdb1a1cc16cc2940704367193be6a6c937c1e 100644 (file)
 
 #include "spufs.h"
 
+
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
 {
        struct spufs_inode_info *i = SPUFS_I(inode);
        file->private_data = i->i_ctx;
+       file->f_mapping = i->i_ctx->local_store;
        return 0;
 }
 
@@ -44,23 +46,16 @@ static ssize_t
 spufs_mem_read(struct file *file, char __user *buffer,
                                size_t size, loff_t *pos)
 {
-       struct spu *spu;
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
+       char *local_store;
        int ret;
 
-       ctx = file->private_data;
-       spu = ctx->spu;
+       spu_acquire(ctx);
 
-       down_read(&ctx->backing_sema);
-       if (spu->number & 0/*1*/) {
-               ret = generic_file_read(file, buffer, size, pos);
-               goto out;
-       }
+       local_store = ctx->ops->get_ls(ctx);
+       ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
 
-       ret = simple_read_from_buffer(buffer, size, pos,
-                                       spu->local_store, LS_SIZE);
-out:
-       up_read(&ctx->backing_sema);
+       spu_release(ctx);
        return ret;
 }
 
@@ -69,50 +64,181 @@ spufs_mem_write(struct file *file, const char __user *buffer,
                                        size_t size, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
-       struct spu *spu = ctx->spu;
-
-       if (spu->number & 0) //1)
-               return generic_file_write(file, buffer, size, pos);
+       char *local_store;
+       int ret;
 
        size = min_t(ssize_t, LS_SIZE - *pos, size);
        if (size <= 0)
                return -EFBIG;
        *pos += size;
-       return copy_from_user(spu->local_store + *pos - size,
-                               buffer, size) ? -EFAULT : size;
+
+       spu_acquire(ctx);
+
+       local_store = ctx->ops->get_ls(ctx);
+       ret = copy_from_user(local_store + *pos - size,
+                            buffer, size) ? -EFAULT : size;
+
+       spu_release(ctx);
+       return ret;
 }
 
+#ifdef CONFIG_SPARSEMEM
+static struct page *
+spufs_mem_mmap_nopage(struct vm_area_struct *vma,
+                     unsigned long address, int *type)
+{
+       struct page *page = NOPAGE_SIGBUS;
+
+       struct spu_context *ctx = vma->vm_file->private_data;
+       unsigned long offset = address - vma->vm_start;
+       offset += vma->vm_pgoff << PAGE_SHIFT;
+
+       spu_acquire(ctx);
+
+       if (ctx->state == SPU_STATE_SAVED)
+               page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
+       else
+               page = pfn_to_page((ctx->spu->local_store_phys + offset)
+                                  >> PAGE_SHIFT);
+
+       spu_release(ctx);
+
+       if (type)
+               *type = VM_FAULT_MINOR;
+
+       return page;
+}
+
+static struct vm_operations_struct spufs_mem_mmap_vmops = {
+       .nopage = spufs_mem_mmap_nopage,
+};
+
 static int
 spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct spu_context *ctx = file->private_data;
-       struct spu *spu = ctx->spu;
-       unsigned long pfn;
-
-       if (spu->number & 0) //1)
-               return generic_file_mmap(file, vma);
+       if (!(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
 
+       /* FIXME: */
        vma->vm_flags |= VM_RESERVED;
-       vma->vm_page_prot = __pgprot(pgprot_val (vma->vm_page_prot)
-                                                       | _PAGE_NO_CACHE);
-       pfn = spu->local_store_phys >> PAGE_SHIFT;
-       /*
-        * This will work for actual SPUs, but not for vmalloc memory:
-        */
-       if (remap_pfn_range(vma, vma->vm_start, pfn,
-                               vma->vm_end-vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
+       vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+                                    | _PAGE_NO_CACHE);
+
+       vma->vm_ops = &spufs_mem_mmap_vmops;
        return 0;
 }
+#endif
 
 static struct file_operations spufs_mem_fops = {
        .open    = spufs_mem_open,
        .read    = spufs_mem_read,
        .write   = spufs_mem_write,
+       .llseek  = generic_file_llseek,
+#ifdef CONFIG_SPARSEMEM
        .mmap    = spufs_mem_mmap,
+#endif
+};
+
+static int
+spufs_regs_open(struct inode *inode, struct file *file)
+{
+       struct spufs_inode_info *i = SPUFS_I(inode);
+       file->private_data = i->i_ctx;
+       return 0;
+}
+
+static ssize_t
+spufs_regs_read(struct file *file, char __user *buffer,
+               size_t size, loff_t *pos)
+{
+       struct spu_context *ctx = file->private_data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       int ret;
+
+       spu_acquire_saved(ctx);
+
+       ret = simple_read_from_buffer(buffer, size, pos,
+                                     lscsa->gprs, sizeof lscsa->gprs);
+
+       spu_release(ctx);
+       return ret;
+}
+
+static ssize_t
+spufs_regs_write(struct file *file, const char __user *buffer,
+                size_t size, loff_t *pos)
+{
+       struct spu_context *ctx = file->private_data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       int ret;
+
+       size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
+       if (size <= 0)
+               return -EFBIG;
+       *pos += size;
+
+       spu_acquire_saved(ctx);
+
+       ret = copy_from_user(lscsa->gprs + *pos - size,
+                            buffer, size) ? -EFAULT : size;
+
+       spu_release(ctx);
+       return ret;
+}
+
+static struct file_operations spufs_regs_fops = {
+       .open    = spufs_regs_open,
+       .read    = spufs_regs_read,
+       .write   = spufs_regs_write,
        .llseek  = generic_file_llseek,
 };
 
+static ssize_t
+spufs_fpcr_read(struct file *file, char __user * buffer,
+               size_t size, loff_t * pos)
+{
+       struct spu_context *ctx = file->private_data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       int ret;
+
+       spu_acquire_saved(ctx);
+
+       ret = simple_read_from_buffer(buffer, size, pos,
+                                     &lscsa->fpcr, sizeof(lscsa->fpcr));
+
+       spu_release(ctx);
+       return ret;
+}
+
+static ssize_t
+spufs_fpcr_write(struct file *file, const char __user * buffer,
+                size_t size, loff_t * pos)
+{
+       struct spu_context *ctx = file->private_data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       int ret;
+
+       size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
+       if (size <= 0)
+               return -EFBIG;
+       *pos += size;
+
+       spu_acquire_saved(ctx);
+
+       ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
+                            buffer, size) ? -EFAULT : size;
+
+       spu_release(ctx);
+       return ret;
+}
+
+static struct file_operations spufs_fpcr_fops = {
+       .open = spufs_regs_open,
+       .read = spufs_fpcr_read,
+       .write = spufs_fpcr_write,
+       .llseek = generic_file_llseek,
+};
+
 /* generic open function for all pipe-like files */
 static int spufs_pipe_open(struct inode *inode, struct file *file)
 {
@@ -125,21 +251,19 @@ static int spufs_pipe_open(struct inode *inode, struct file *file)
 static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
-       struct spu_problem __iomem *prob;
-       u32 mbox_stat;
+       struct spu_context *ctx = file->private_data;
        u32 mbox_data;
+       int ret;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
-       prob = ctx->spu->problem;
-       mbox_stat = in_be32(&prob->mb_stat_R);
-       if (!(mbox_stat & 0x0000ff))
-               return -EAGAIN;
+       spu_acquire(ctx);
+       ret = ctx->ops->mbox_read(ctx, &mbox_data);
+       spu_release(ctx);
 
-       mbox_data = in_be32(&prob->pu_mb_R);
+       if (!ret)
+               return -EAGAIN;
 
        if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
                return -EFAULT;
@@ -155,14 +279,17 @@ static struct file_operations spufs_mbox_fops = {
 static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
        u32 mbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
-       mbox_stat = in_be32(&ctx->spu->problem->mb_stat_R) & 0xff;
+       spu_acquire(ctx);
+
+       mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
+
+       spu_release(ctx);
 
        if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat))
                return -EFAULT;
@@ -175,57 +302,78 @@ static struct file_operations spufs_mbox_stat_fops = {
        .read   = spufs_mbox_stat_read,
 };
 
+/*
+ * spufs_wait
+ *     Same as wait_event_interruptible(), except that here
+ *     we need to call spu_release(ctx) before sleeping, and
+ *     then spu_acquire(ctx) when awoken.
+ */
+
+#define spufs_wait(wq, condition)                                      \
+({                                                                     \
+       int __ret = 0;                                                  \
+       DEFINE_WAIT(__wait);                                            \
+       for (;;) {                                                      \
+               prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE);    \
+               if (condition)                                          \
+                       break;                                          \
+               if (!signal_pending(current)) {                         \
+                       spu_release(ctx);                               \
+                       schedule();                                     \
+                       spu_acquire(ctx);                               \
+                       continue;                                       \
+               }                                                       \
+               __ret = -ERESTARTSYS;                                   \
+               break;                                                  \
+       }                                                               \
+       finish_wait(&(wq), &__wait);                                    \
+       __ret;                                                          \
+})
+
 /* low-level ibox access function */
-size_t spu_ibox_read(struct spu *spu, u32 *data)
+size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
 {
-       int ret;
-
-       spin_lock_irq(&spu->register_lock);
+       return ctx->ops->ibox_read(ctx, data);
+}
 
-       if (in_be32(&spu->problem->mb_stat_R) & 0xff0000) {
-               /* read the first available word */
-               *data = in_be64(&spu->priv2->puint_mb_R);
-               ret = 4;
-       } else {
-               /* make sure we get woken up by the interrupt */
-               out_be64(&spu->priv1->int_mask_class2_RW,
-                       in_be64(&spu->priv1->int_mask_class2_RW) | 0x1);
-               ret = 0;
-       }
+static int spufs_ibox_fasync(int fd, struct file *file, int on)
+{
+       struct spu_context *ctx = file->private_data;
 
-       spin_unlock_irq(&spu->register_lock);
-       return ret;
+       return fasync_helper(fd, file, on, &ctx->ibox_fasync);
 }
-EXPORT_SYMBOL(spu_ibox_read);
 
-static int spufs_ibox_fasync(int fd, struct file *file, int on)
+/* interrupt-level ibox callback function. */
+void spufs_ibox_callback(struct spu *spu)
 {
-       struct spu_context *ctx;
-       ctx = file->private_data;
-       return fasync_helper(fd, file, on, &ctx->spu->ibox_fasync);
+       struct spu_context *ctx = spu->ctx;
+
+       wake_up_all(&ctx->ibox_wq);
+       kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
 }
 
 static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
        u32 ibox_data;
        ssize_t ret;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
+       spu_acquire(ctx);
 
        ret = 0;
        if (file->f_flags & O_NONBLOCK) {
-               if (!spu_ibox_read(ctx->spu, &ibox_data))
+               if (!spu_ibox_read(ctx, &ibox_data))
                        ret = -EAGAIN;
        } else {
-               ret = wait_event_interruptible(ctx->spu->ibox_wq,
-                                spu_ibox_read(ctx->spu, &ibox_data));
+               ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
        }
 
+       spu_release(ctx);
+
        if (ret)
                return ret;
 
@@ -238,16 +386,17 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
 
 static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
 {
-       struct spu_context *ctx;
-       struct spu_problem __iomem *prob;
+       struct spu_context *ctx = file->private_data;
        u32 mbox_stat;
        unsigned int mask;
 
-       ctx = file->private_data;
-       prob = ctx->spu->problem;
-       mbox_stat = in_be32(&prob->mb_stat_R);
+       spu_acquire(ctx);
+
+       mbox_stat = ctx->ops->mbox_stat_read(ctx);
+
+       spu_release(ctx);
 
-       poll_wait(file, &ctx->spu->ibox_wq, wait);
+       poll_wait(file, &ctx->ibox_wq, wait);
 
        mask = 0;
        if (mbox_stat & 0xff0000)
@@ -266,14 +415,15 @@ static struct file_operations spufs_ibox_fops = {
 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
        u32 ibox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
-       ibox_stat = (in_be32(&ctx->spu->problem->mb_stat_R) >> 16) & 0xff;
+       spu_acquire(ctx);
+       ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
+       spu_release(ctx);
 
        if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
                return -EFAULT;
@@ -287,75 +437,69 @@ static struct file_operations spufs_ibox_stat_fops = {
 };
 
 /* low-level mailbox write */
-size_t spu_wbox_write(struct spu *spu, u32 data)
+size_t spu_wbox_write(struct spu_context *ctx, u32 data)
 {
-       int ret;
+       return ctx->ops->wbox_write(ctx, data);
+}
 
-       spin_lock_irq(&spu->register_lock);
+static int spufs_wbox_fasync(int fd, struct file *file, int on)
+{
+       struct spu_context *ctx = file->private_data;
+       int ret;
 
-       if (in_be32(&spu->problem->mb_stat_R) & 0x00ff00) {
-               /* we have space to write wbox_data to */
-               out_be32(&spu->problem->spu_mb_W, data);
-               ret = 4;
-       } else {
-               /* make sure we get woken up by the interrupt when space
-                  becomes available */
-               out_be64(&spu->priv1->int_mask_class2_RW,
-                       in_be64(&spu->priv1->int_mask_class2_RW) | 0x10);
-               ret = 0;
-       }
+       ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
 
-       spin_unlock_irq(&spu->register_lock);
        return ret;
 }
-EXPORT_SYMBOL(spu_wbox_write);
 
-static int spufs_wbox_fasync(int fd, struct file *file, int on)
+/* interrupt-level wbox callback function. */
+void spufs_wbox_callback(struct spu *spu)
 {
-       struct spu_context *ctx;
-       ctx = file->private_data;
-       return fasync_helper(fd, file, on, &ctx->spu->wbox_fasync);
+       struct spu_context *ctx = spu->ctx;
+
+       wake_up_all(&ctx->wbox_wq);
+       kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
 }
 
 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
        u32 wbox_data;
        int ret;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
-
        if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
                return -EFAULT;
 
+       spu_acquire(ctx);
+
        ret = 0;
        if (file->f_flags & O_NONBLOCK) {
-               if (!spu_wbox_write(ctx->spu, wbox_data))
+               if (!spu_wbox_write(ctx, wbox_data))
                        ret = -EAGAIN;
        } else {
-               ret = wait_event_interruptible(ctx->spu->wbox_wq,
-                       spu_wbox_write(ctx->spu, wbox_data));
+               ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
        }
 
+       spu_release(ctx);
+
        return ret ? ret : sizeof wbox_data;
 }
 
 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
 {
-       struct spu_context *ctx;
-       struct spu_problem __iomem *prob;
+       struct spu_context *ctx = file->private_data;
        u32 mbox_stat;
        unsigned int mask;
 
-       ctx = file->private_data;
-       prob = ctx->spu->problem;
-       mbox_stat = in_be32(&prob->mb_stat_R);
+       spu_acquire(ctx);
+       mbox_stat = ctx->ops->mbox_stat_read(ctx);
+       spu_release(ctx);
 
-       poll_wait(file, &ctx->spu->wbox_wq, wait);
+       poll_wait(file, &ctx->wbox_wq, wait);
 
        mask = 0;
        if (mbox_stat & 0x00ff00)
@@ -374,14 +518,15 @@ static struct file_operations spufs_wbox_fops = {
 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
+       struct spu_context *ctx = file->private_data;
        u32 wbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       ctx = file->private_data;
-       wbox_stat = (in_be32(&ctx->spu->problem->mb_stat_R) >> 8) & 0xff;
+       spu_acquire(ctx);
+       wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
+       spu_release(ctx);
 
        if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
                return -EFAULT;
@@ -395,47 +540,41 @@ static struct file_operations spufs_wbox_stat_fops = {
 };
 
 long spufs_run_spu(struct file *file, struct spu_context *ctx,
-               u32 *npc, u32 *status)
+                               u32 *npc, u32 *status)
 {
-       struct spu_problem __iomem *prob;
        int ret;
 
-       if (file->f_flags & O_NONBLOCK) {
-               ret = -EAGAIN;
-               if (!down_write_trylock(&ctx->backing_sema))
-                       goto out;
-       } else {
-               down_write(&ctx->backing_sema);
-       }
+       ret = spu_acquire_runnable(ctx);
+       if (ret)
+               return ret;
 
-       prob = ctx->spu->problem;
-       out_be32(&prob->spu_npc_RW, *npc);
+       ctx->ops->npc_write(ctx, *npc);
 
        ret = spu_run(ctx->spu);
 
-       *status = in_be32(&prob->spu_status_R);
-       *npc = in_be32(&prob->spu_npc_RW);
+       if (!ret)
+               ret = ctx->ops->status_read(ctx);
 
-       up_write(&ctx->backing_sema);
+       *npc = ctx->ops->npc_read(ctx);
 
-out:
+       spu_release(ctx);
+       spu_yield(ctx);
        return ret;
 }
 
 static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
-       struct spu_context *ctx;
-       struct spu_problem *prob;
+       struct spu_context *ctx = file->private_data;
        u32 data;
 
-       ctx = file->private_data;
-       prob = ctx->spu->problem;
-
        if (len < 4)
                return -EINVAL;
 
-       data = in_be32(&prob->signal_notify1);
+       spu_acquire(ctx);
+       data = ctx->ops->signal1_read(ctx);
+       spu_release(ctx);
+
        if (copy_to_user(buf, &data, 4))
                return -EFAULT;
 
@@ -446,11 +585,9 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
-       struct spu_problem *prob;
        u32 data;
 
        ctx = file->private_data;
-       prob = ctx->spu->problem;
 
        if (len < 4)
                return -EINVAL;
@@ -458,7 +595,9 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       out_be32(&prob->signal_notify1, data);
+       spu_acquire(ctx);
+       ctx->ops->signal1_write(ctx, data);
+       spu_release(ctx);
 
        return 4;
 }
@@ -473,16 +612,17 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
-       struct spu_problem *prob;
        u32 data;
 
        ctx = file->private_data;
-       prob = ctx->spu->problem;
 
        if (len < 4)
                return -EINVAL;
 
-       data = in_be32(&prob->signal_notify2);
+       spu_acquire(ctx);
+       data = ctx->ops->signal2_read(ctx);
+       spu_release(ctx);
+
        if (copy_to_user(buf, &data, 4))
                return -EFAULT;
 
@@ -493,11 +633,9 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
-       struct spu_problem *prob;
        u32 data;
 
        ctx = file->private_data;
-       prob = ctx->spu->problem;
 
        if (len < 4)
                return -EINVAL;
@@ -505,7 +643,9 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       out_be32(&prob->signal_notify2, data);
+       spu_acquire(ctx);
+       ctx->ops->signal2_write(ctx, data);
+       spu_release(ctx);
 
        return 4;
 }
@@ -519,23 +659,22 @@ static struct file_operations spufs_signal2_fops = {
 static void spufs_signal1_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       struct spu_priv2 *priv2 = ctx->spu->priv2;
-       u64 tmp;
 
-       spin_lock_irq(&ctx->spu->register_lock);
-       tmp = in_be64(&priv2->spu_cfg_RW);
-       if (val)
-               tmp |= 1;
-       else
-               tmp &= ~1;
-       out_be64(&priv2->spu_cfg_RW, tmp);
-       spin_unlock_irq(&ctx->spu->register_lock);
+       spu_acquire(ctx);
+       ctx->ops->signal1_type_set(ctx, val);
+       spu_release(ctx);
 }
 
 static u64 spufs_signal1_type_get(void *data)
 {
        struct spu_context *ctx = data;
-       return (in_be64(&ctx->spu->priv2->spu_cfg_RW) & 1) != 0;
+       u64 ret;
+
+       spu_acquire(ctx);
+       ret = ctx->ops->signal1_type_get(ctx);
+       spu_release(ctx);
+
+       return ret;
 }
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
                                        spufs_signal1_type_set, "%llu");
@@ -543,23 +682,22 @@ DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
 static void spufs_signal2_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       struct spu_priv2 *priv2 = ctx->spu->priv2;
-       u64 tmp;
 
-       spin_lock_irq(&ctx->spu->register_lock);
-       tmp = in_be64(&priv2->spu_cfg_RW);
-       if (val)
-               tmp |= 2;
-       else
-               tmp &= ~2;
-       out_be64(&priv2->spu_cfg_RW, tmp);
-       spin_unlock_irq(&ctx->spu->register_lock);
+       spu_acquire(ctx);
+       ctx->ops->signal2_type_set(ctx, val);
+       spu_release(ctx);
 }
 
 static u64 spufs_signal2_type_get(void *data)
 {
        struct spu_context *ctx = data;
-       return (in_be64(&ctx->spu->priv2->spu_cfg_RW) & 2) != 0;
+       u64 ret;
+
+       spu_acquire(ctx);
+       ret = ctx->ops->signal2_type_get(ctx);
+       spu_release(ctx);
+
+       return ret;
 }
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
                                        spufs_signal2_type_set, "%llu");
@@ -567,20 +705,135 @@ DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
 static void spufs_npc_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       out_be32(&ctx->spu->problem->spu_npc_RW, val);
+       spu_acquire(ctx);
+       ctx->ops->npc_write(ctx, val);
+       spu_release(ctx);
 }
 
 static u64 spufs_npc_get(void *data)
 {
        struct spu_context *ctx = data;
        u64 ret;
-       ret = in_be32(&ctx->spu->problem->spu_npc_RW);
+       spu_acquire(ctx);
+       ret = ctx->ops->npc_read(ctx);
+       spu_release(ctx);
        return ret;
 }
 DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
 
+static void spufs_decr_set(void *data, u64 val)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       spu_acquire_saved(ctx);
+       lscsa->decr.slot[0] = (u32) val;
+       spu_release(ctx);
+}
+
+static u64 spufs_decr_get(void *data)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       u64 ret;
+       spu_acquire_saved(ctx);
+       ret = lscsa->decr.slot[0];
+       spu_release(ctx);
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
+                       "%llx\n")
+
+static void spufs_decr_status_set(void *data, u64 val)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       spu_acquire_saved(ctx);
+       lscsa->decr_status.slot[0] = (u32) val;
+       spu_release(ctx);
+}
+
+static u64 spufs_decr_status_get(void *data)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       u64 ret;
+       spu_acquire_saved(ctx);
+       ret = lscsa->decr_status.slot[0];
+       spu_release(ctx);
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
+                       spufs_decr_status_set, "%llx\n")
+
+static void spufs_spu_tag_mask_set(void *data, u64 val)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       spu_acquire_saved(ctx);
+       lscsa->tag_mask.slot[0] = (u32) val;
+       spu_release(ctx);
+}
+
+static u64 spufs_spu_tag_mask_get(void *data)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       u64 ret;
+       spu_acquire_saved(ctx);
+       ret = lscsa->tag_mask.slot[0];
+       spu_release(ctx);
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
+                       spufs_spu_tag_mask_set, "%llx\n")
+
+static void spufs_event_mask_set(void *data, u64 val)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       spu_acquire_saved(ctx);
+       lscsa->event_mask.slot[0] = (u32) val;
+       spu_release(ctx);
+}
+
+static u64 spufs_event_mask_get(void *data)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       u64 ret;
+       spu_acquire_saved(ctx);
+       ret = lscsa->event_mask.slot[0];
+       spu_release(ctx);
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
+                       spufs_event_mask_set, "%llx\n")
+
+static void spufs_srr0_set(void *data, u64 val)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       spu_acquire_saved(ctx);
+       lscsa->srr0.slot[0] = (u32) val;
+       spu_release(ctx);
+}
+
+static u64 spufs_srr0_get(void *data)
+{
+       struct spu_context *ctx = data;
+       struct spu_lscsa *lscsa = ctx->csa.lscsa;
+       u64 ret;
+       spu_acquire_saved(ctx);
+       ret = lscsa->srr0.slot[0];
+       spu_release(ctx);
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
+                       "%llx\n")
+
 struct tree_descr spufs_dir_contents[] = {
        { "mem",  &spufs_mem_fops,  0666, },
+       { "regs", &spufs_regs_fops,  0666, },
        { "mbox", &spufs_mbox_fops, 0444, },
        { "ibox", &spufs_ibox_fops, 0444, },
        { "wbox", &spufs_wbox_fops, 0222, },
@@ -592,5 +845,11 @@ struct tree_descr spufs_dir_contents[] = {
        { "signal1_type", &spufs_signal1_type, 0666, },
        { "signal2_type", &spufs_signal2_type, 0666, },
        { "npc", &spufs_npc_ops, 0666, },
+       { "fpcr", &spufs_fpcr_fops, 0666, },
+       { "decr", &spufs_decr_ops, 0666, },
+       { "decr_status", &spufs_decr_status_ops, 0666, },
+       { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
+       { "event_mask", &spufs_event_mask_ops, 0666, },
+       { "srr0", &spufs_srr0_ops, 0666, },
        {},
 };
This page took 0.035923 seconds and 5 git commands to generate.