aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-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