aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2006-01-04 14:31:29 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 23:44:45 -0500
commitce8ab8541203f6c7be5b2eeaa97f14f1d8d44e4f (patch)
treeabdb994ac4ded9a90684f0cdc71ea58e6247ab43 /arch/powerpc
parent8837d9216f99048636fbb2c11347358e99e06181 (diff)
[PATCH] spufs: move spu_run call to its own file
The logic for sys_spu_run keeps growing and it does not really belong into file.c any more since we moved away from using regular file operations to our own syscall. No functional change in here. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c152
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c131
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h28
4 files changed, 160 insertions, 153 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index 9bfaba8791e3..a7cddf40e3d9 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,6 +1,6 @@
1obj-$(CONFIG_SPU_FS) += spufs.o 1obj-$(CONFIG_SPU_FS) += spufs.o
2spufs-y += inode.o file.o context.o switch.o syscalls.o 2spufs-y += inode.o file.o context.o switch.o syscalls.o
3spufs-y += sched.o backing_ops.o hw_ops.o 3spufs-y += sched.o backing_ops.o hw_ops.o run.o
4 4
5# Rules to build switch.o with the help of SPU tool chain 5# Rules to build switch.o with the help of SPU tool chain
6SPU_CROSS := spu- 6SPU_CROSS := spu-
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index e63426822fd5..dfa649c9b956 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -304,34 +304,6 @@ static struct file_operations spufs_mbox_stat_fops = {
304 .read = spufs_mbox_stat_read, 304 .read = spufs_mbox_stat_read,
305}; 305};
306 306
307/*
308 * spufs_wait
309 * Same as wait_event_interruptible(), except that here
310 * we need to call spu_release(ctx) before sleeping, and
311 * then spu_acquire(ctx) when awoken.
312 */
313
314#define spufs_wait(wq, condition) \
315({ \
316 int __ret = 0; \
317 DEFINE_WAIT(__wait); \
318 for (;;) { \
319 prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
320 if (condition) \
321 break; \
322 if (!signal_pending(current)) { \
323 spu_release(ctx); \
324 schedule(); \
325 spu_acquire(ctx); \
326 continue; \
327 } \
328 __ret = -ERESTARTSYS; \
329 break; \
330 } \
331 finish_wait(&(wq), &__wait); \
332 __ret; \
333})
334
335/* low-level ibox access function */ 307/* low-level ibox access function */
336size_t spu_ibox_read(struct spu_context *ctx, u32 *data) 308size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
337{ 309{
@@ -529,130 +501,6 @@ static struct file_operations spufs_wbox_stat_fops = {
529 .read = spufs_wbox_stat_read, 501 .read = spufs_wbox_stat_read,
530}; 502};
531 503
532/* interrupt-level stop callback function. */
533void spufs_stop_callback(struct spu *spu)
534{
535 struct spu_context *ctx = spu->ctx;
536
537 wake_up_all(&ctx->stop_wq);
538}
539
540static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
541{
542 struct spu *spu;
543 u64 pte_fault;
544
545 *stat = ctx->ops->status_read(ctx);
546 if (ctx->state != SPU_STATE_RUNNABLE)
547 return 1;
548 spu = ctx->spu;
549 pte_fault = spu->dsisr &
550 (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
551 return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
552}
553
554static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
555 u32 * status)
556{
557 int ret;
558
559 if ((ret = spu_acquire_runnable(ctx)) != 0)
560 return ret;
561 ctx->ops->npc_write(ctx, *npc);
562 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
563 return 0;
564}
565
566static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
567 u32 * status)
568{
569 int ret = 0;
570
571 *status = ctx->ops->status_read(ctx);
572 *npc = ctx->ops->npc_read(ctx);
573 spu_release(ctx);
574
575 if (signal_pending(current))
576 ret = -ERESTARTSYS;
577 if (unlikely(current->ptrace & PT_PTRACED)) {
578 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
579 && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
580 force_sig(SIGTRAP, current);
581 ret = -ERESTARTSYS;
582 }
583 }
584 return ret;
585}
586
587static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
588 u32 *status)
589{
590 int ret;
591
592 if ((ret = spu_run_fini(ctx, npc, status)) != 0)
593 return ret;
594 if (*status & (SPU_STATUS_STOPPED_BY_STOP |
595 SPU_STATUS_STOPPED_BY_HALT)) {
596 return *status;
597 }
598 if ((ret = spu_run_init(ctx, npc, status)) != 0)
599 return ret;
600 return 0;
601}
602
603static inline int spu_process_events(struct spu_context *ctx)
604{
605 struct spu *spu = ctx->spu;
606 u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
607 int ret = 0;
608
609 if (spu->dsisr & pte_fault)
610 ret = spu_irq_class_1_bottom(spu);
611 if (spu->class_0_pending)
612 ret = spu_irq_class_0_bottom(spu);
613 if (!ret && signal_pending(current))
614 ret = -ERESTARTSYS;
615 return ret;
616}
617
618long spufs_run_spu(struct file *file, struct spu_context *ctx,
619 u32 * npc, u32 * status)
620{
621 int ret;
622
623 if (down_interruptible(&ctx->run_sema))
624 return -ERESTARTSYS;
625
626 ret = spu_run_init(ctx, npc, status);
627 if (ret)
628 goto out;
629
630 do {
631 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
632 if (unlikely(ret))
633 break;
634 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
635 ret = spu_reacquire_runnable(ctx, npc, status);
636 if (ret)
637 goto out;
638 continue;
639 }
640 ret = spu_process_events(ctx);
641
642 } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
643 SPU_STATUS_STOPPED_BY_HALT)));
644
645 ctx->ops->runcntl_stop(ctx);
646 ret = spu_run_fini(ctx, npc, status);
647 if (!ret)
648 ret = *status;
649 spu_yield(ctx);
650
651out:
652 up(&ctx->run_sema);
653 return ret;
654}
655
656static ssize_t spufs_signal1_read(struct file *file, char __user *buf, 504static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
657 size_t len, loff_t *pos) 505 size_t len, loff_t *pos)
658{ 506{
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
new file mode 100644
index 000000000000..18ea8866c61a
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -0,0 +1,131 @@
1#include <linux/wait.h>
2#include <linux/ptrace.h>
3
4#include <asm/spu.h>
5
6#include "spufs.h"
7
8/* interrupt-level stop callback function. */
9void spufs_stop_callback(struct spu *spu)
10{
11 struct spu_context *ctx = spu->ctx;
12
13 wake_up_all(&ctx->stop_wq);
14}
15
16static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
17{
18 struct spu *spu;
19 u64 pte_fault;
20
21 *stat = ctx->ops->status_read(ctx);
22 if (ctx->state != SPU_STATE_RUNNABLE)
23 return 1;
24 spu = ctx->spu;
25 pte_fault = spu->dsisr &
26 (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
27 return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
28}
29
30static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
31 u32 * status)
32{
33 int ret;
34
35 if ((ret = spu_acquire_runnable(ctx)) != 0)
36 return ret;
37 ctx->ops->npc_write(ctx, *npc);
38 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
39 return 0;
40}
41
42static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
43 u32 * status)
44{
45 int ret = 0;
46
47 *status = ctx->ops->status_read(ctx);
48 *npc = ctx->ops->npc_read(ctx);
49 spu_release(ctx);
50
51 if (signal_pending(current))
52 ret = -ERESTARTSYS;
53 if (unlikely(current->ptrace & PT_PTRACED)) {
54 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
55 && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
56 force_sig(SIGTRAP, current);
57 ret = -ERESTARTSYS;
58 }
59 }
60 return ret;
61}
62
63static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
64 u32 *status)
65{
66 int ret;
67
68 if ((ret = spu_run_fini(ctx, npc, status)) != 0)
69 return ret;
70 if (*status & (SPU_STATUS_STOPPED_BY_STOP |
71 SPU_STATUS_STOPPED_BY_HALT)) {
72 return *status;
73 }
74 if ((ret = spu_run_init(ctx, npc, status)) != 0)
75 return ret;
76 return 0;
77}
78
79static inline int spu_process_events(struct spu_context *ctx)
80{
81 struct spu *spu = ctx->spu;
82 u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
83 int ret = 0;
84
85 if (spu->dsisr & pte_fault)
86 ret = spu_irq_class_1_bottom(spu);
87 if (spu->class_0_pending)
88 ret = spu_irq_class_0_bottom(spu);
89 if (!ret && signal_pending(current))
90 ret = -ERESTARTSYS;
91 return ret;
92}
93
94long spufs_run_spu(struct file *file, struct spu_context *ctx,
95 u32 * npc, u32 * status)
96{
97 int ret;
98
99 if (down_interruptible(&ctx->run_sema))
100 return -ERESTARTSYS;
101
102 ret = spu_run_init(ctx, npc, status);
103 if (ret)
104 goto out;
105
106 do {
107 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
108 if (unlikely(ret))
109 break;
110 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
111 ret = spu_reacquire_runnable(ctx, npc, status);
112 if (ret)
113 goto out;
114 continue;
115 }
116 ret = spu_process_events(ctx);
117
118 } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
119 SPU_STATUS_STOPPED_BY_HALT)));
120
121 ctx->ops->runcntl_stop(ctx);
122 ret = spu_run_fini(ctx, npc, status);
123 if (!ret)
124 ret = *status;
125 spu_yield(ctx);
126
127out:
128 up(&ctx->run_sema);
129 return ret;
130}
131
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 48961ac584a1..c715ed0c4014 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -124,6 +124,34 @@ void spu_yield(struct spu_context *ctx);
124int __init spu_sched_init(void); 124int __init spu_sched_init(void);
125void __exit spu_sched_exit(void); 125void __exit spu_sched_exit(void);
126 126
127/*
128 * spufs_wait
129 * Same as wait_event_interruptible(), except that here
130 * we need to call spu_release(ctx) before sleeping, and
131 * then spu_acquire(ctx) when awoken.
132 */
133
134#define spufs_wait(wq, condition) \
135({ \
136 int __ret = 0; \
137 DEFINE_WAIT(__wait); \
138 for (;;) { \
139 prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
140 if (condition) \
141 break; \
142 if (!signal_pending(current)) { \
143 spu_release(ctx); \
144 schedule(); \
145 spu_acquire(ctx); \
146 continue; \
147 } \
148 __ret = -ERESTARTSYS; \
149 break; \
150 } \
151 finish_wait(&(wq), &__wait); \
152 __ret; \
153})
154
127size_t spu_wbox_write(struct spu_context *ctx, u32 data); 155size_t spu_wbox_write(struct spu_context *ctx, u32 data);
128size_t spu_ibox_read(struct spu_context *ctx, u32 *data); 156size_t spu_ibox_read(struct spu_context *ctx, u32 *data);
129 157