Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 17181
b: refs/heads/master
c: 5110459
h: refs/heads/master
i:
  17179: 889b906
v: v3
  • Loading branch information
Arnd Bergmann authored and Paul Mackerras committed Jan 9, 2006
1 parent 3a95331 commit 9a8215b
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 124 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: 3b3d22cb84a0bb12f6bbb2b1158972894bec3f21
refs/heads/master: 5110459f181ef1f11200bb3dec61953f08cc49e7
93 changes: 15 additions & 78 deletions trunk/arch/powerpc/platforms/cell/spu_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
spu->dar = ea;
spu->dsisr = dsisr;
mb();
wake_up(&spu->stop_wq);
if (spu->stop_callback)
spu->stop_callback(spu);
return 0;
}

Expand All @@ -151,15 +152,17 @@ static int __spu_trap_stop(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
spu->stop_code = in_be32(&spu->problem->spu_status_R);
wake_up(&spu->stop_wq);
if (spu->stop_callback)
spu->stop_callback(spu);
return 0;
}

static int __spu_trap_halt(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
spu->stop_code = in_be32(&spu->problem->spu_status_R);
wake_up(&spu->stop_wq);
if (spu->stop_callback)
spu->stop_callback(spu);
return 0;
}

Expand Down Expand Up @@ -190,12 +193,13 @@ spu_irq_class_0(int irq, void *data, struct pt_regs *regs)

spu = data;
spu->class_0_pending = 1;
wake_up(&spu->stop_wq);
if (spu->stop_callback)
spu->stop_callback(spu);

return IRQ_HANDLED;
}

static int
int
spu_irq_class_0_bottom(struct spu *spu)
{
unsigned long stat;
Expand All @@ -214,8 +218,10 @@ spu_irq_class_0_bottom(struct spu *spu)
__spu_trap_error(spu);

out_be64(&spu->priv1->int_stat_class0_RW, stat);
return 0;

return (stat & 0x7) ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);

static irqreturn_t
spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
Expand Down Expand Up @@ -250,6 +256,7 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs)

return stat ? IRQ_HANDLED : IRQ_NONE;
}
EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom);

static irqreturn_t
spu_irq_class_2(int irq, void *data, struct pt_regs *regs)
Expand Down Expand Up @@ -478,7 +485,7 @@ static int spu_handle_mm_fault(struct spu *spu)
return -EFAULT;
}

static int spu_handle_pte_fault(struct spu *spu)
int spu_irq_class_1_bottom(struct spu *spu)
{
u64 ea, dsisr, access, error = 0UL;
int ret = 0;
Expand Down Expand Up @@ -508,76 +515,6 @@ static int spu_handle_pte_fault(struct spu *spu)
return ret;
}

static inline int spu_pending(struct spu *spu, u32 * stat)
{
struct spu_problem __iomem *prob = spu->problem;
u64 pte_fault;

*stat = in_be32(&prob->spu_status_R);
pte_fault = spu->dsisr &
(MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
}

int spu_run(struct spu *spu)
{
struct spu_problem __iomem *prob;
struct spu_priv1 __iomem *priv1;
struct spu_priv2 __iomem *priv2;
u32 status;
int ret;

prob = spu->problem;
priv1 = spu->priv1;
priv2 = spu->priv2;

/* Let SPU run. */
eieio();
out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_RUNNABLE);

do {
ret = wait_event_interruptible(spu->stop_wq,
spu_pending(spu, &status));

if (spu->dsisr &
(MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
ret = spu_handle_pte_fault(spu);

if (spu->class_0_pending)
spu_irq_class_0_bottom(spu);

if (!ret && signal_pending(current))
ret = -ERESTARTSYS;

} while (!ret && !(status &
(SPU_STATUS_STOPPED_BY_STOP |
SPU_STATUS_STOPPED_BY_HALT)));

/* Ensure SPU is stopped. */
out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
eieio();
while (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)
cpu_relax();

out_be64(&priv2->slb_invalidate_all_W, 0);
out_be64(&priv1->tlb_invalidate_entry_W, 0UL);
eieio();

/* Check for SPU breakpoint. */
if (unlikely(current->ptrace & PT_PTRACED)) {
status = in_be32(&prob->spu_status_R);

if ((status & SPU_STATUS_STOPPED_BY_STOP)
&& status >> SPU_STOP_STATUS_SHIFT == 0x3fff) {
force_sig(SIGTRAP, current);
ret = -ERESTARTSYS;
}
}

return ret;
}
EXPORT_SYMBOL_GPL(spu_run);

static void __iomem * __init map_spe_prop(struct device_node *n,
const char *name)
{
Expand Down Expand Up @@ -693,9 +630,9 @@ static int __init create_spu(struct device_node *spe)
out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1));
out_be64(&spu->priv1->mfc_sr1_RW, 0x33);

init_waitqueue_head(&spu->stop_wq);
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;

down(&spu_mutex);
spu->number = number++;
Expand Down
19 changes: 19 additions & 0 deletions trunk/arch/powerpc/platforms/cell/spufs/backing_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,23 @@ static char *spu_backing_get_ls(struct spu_context *ctx)
return ctx->csa.lscsa->ls;
}

static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
{
spin_lock(&ctx->csa.register_lock);
ctx->csa.prob.spu_runcntl_RW = val;
if (val & SPU_RUNCNTL_RUNNABLE) {
ctx->csa.prob.spu_status_R |= SPU_STATUS_RUNNING;
} else {
ctx->csa.prob.spu_status_R &= ~SPU_STATUS_RUNNING;
}
spin_unlock(&ctx->csa.register_lock);
}

static void spu_backing_runcntl_stop(struct spu_context *ctx)
{
spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
}

struct spu_context_ops spu_backing_ops = {
.mbox_read = spu_backing_mbox_read,
.mbox_stat_read = spu_backing_mbox_stat_read,
Expand All @@ -249,4 +266,6 @@ struct spu_context_ops spu_backing_ops = {
.npc_write = spu_backing_npc_write,
.status_read = spu_backing_status_read,
.get_ls = spu_backing_get_ls,
.runcntl_write = spu_backing_runcntl_write,
.runcntl_stop = spu_backing_runcntl_stop,
};
5 changes: 2 additions & 3 deletions trunk/arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
init_rwsem(&ctx->state_sema);
init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq);
ctx->ibox_fasync = NULL;
ctx->wbox_fasync = NULL;
ctx->state = SPU_STATE_SAVED;
Expand Down Expand Up @@ -105,7 +106,7 @@ void spu_release(struct spu_context *ctx)
up_read(&ctx->state_sema);
}

static void spu_unmap_mappings(struct spu_context *ctx)
void spu_unmap_mappings(struct spu_context *ctx)
{
unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
}
Expand All @@ -126,7 +127,6 @@ int spu_acquire_runnable(struct spu_context *ctx)

down_write(&ctx->state_sema);
if (ctx->state == SPU_STATE_SAVED) {
spu_unmap_mappings(ctx);
ret = spu_activate(ctx, 0);
ctx->state = SPU_STATE_RUNNABLE;
}
Expand Down Expand Up @@ -154,7 +154,6 @@ void spu_acquire_saved(struct spu_context *ctx)
down_write(&ctx->state_sema);

if (ctx->state == SPU_STATE_RUNNABLE) {
spu_unmap_mappings(ctx);
spu_deactivate(ctx);
ctx->state = SPU_STATE_SAVED;
}
Expand Down
117 changes: 107 additions & 10 deletions trunk/arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/poll.h>
#include <linux/ptrace.h>

#include <asm/io.h>
#include <asm/semaphore.h>
Expand Down Expand Up @@ -540,26 +541,122 @@ static struct file_operations spufs_wbox_stat_fops = {
.read = spufs_wbox_stat_read,
};

long spufs_run_spu(struct file *file, struct spu_context *ctx,
u32 *npc, u32 *status)
/* interrupt-level stop callback function. */
void spufs_stop_callback(struct spu *spu)
{
struct spu_context *ctx = spu->ctx;

wake_up_all(&ctx->stop_wq);
}

static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
{
struct spu *spu;
u64 pte_fault;

*stat = ctx->ops->status_read(ctx);
if (ctx->state != SPU_STATE_RUNNABLE)
return 1;
spu = ctx->spu;
pte_fault = spu->dsisr &
(MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
}

static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
u32 * status)
{
int ret;

ret = spu_acquire_runnable(ctx);
if (ret)
if ((ret = spu_acquire_runnable(ctx)) != 0)
return ret;

ctx->ops->npc_write(ctx, *npc);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
return 0;
}

ret = spu_run(ctx->spu);

if (!ret)
ret = ctx->ops->status_read(ctx);
static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
u32 * status)
{
int ret = 0;

*status = ctx->ops->status_read(ctx);
*npc = ctx->ops->npc_read(ctx);

spu_release(ctx);

if (signal_pending(current))
ret = -ERESTARTSYS;
if (unlikely(current->ptrace & PT_PTRACED)) {
if ((*status & SPU_STATUS_STOPPED_BY_STOP)
&& (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
force_sig(SIGTRAP, current);
ret = -ERESTARTSYS;
}
}
return ret;
}

static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
u32 *status)
{
int ret;

if ((ret = spu_run_fini(ctx, npc, status)) != 0)
return ret;
if (*status & (SPU_STATUS_STOPPED_BY_STOP |
SPU_STATUS_STOPPED_BY_HALT)) {
return *status;
}
if ((ret = spu_run_init(ctx, npc, status)) != 0)
return ret;
return 0;
}

static inline int spu_process_events(struct spu_context *ctx)
{
struct spu *spu = ctx->spu;
u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
int ret = 0;

if (spu->dsisr & pte_fault)
ret = spu_irq_class_1_bottom(spu);
if (spu->class_0_pending)
ret = spu_irq_class_0_bottom(spu);
if (!ret && signal_pending(current))
ret = -ERESTARTSYS;
return ret;
}

long spufs_run_spu(struct file *file, struct spu_context *ctx,
u32 * npc, u32 * status)
{
int ret;

if ((ret = spu_run_init(ctx, npc, status)) != 0)
return ret;

do {
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
if (unlikely(ret))
break;
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, status);
if (ret) {
return ret;
}
continue;
}
ret = spu_process_events(ctx);

} while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
SPU_STATUS_STOPPED_BY_HALT)));

ctx->ops->runcntl_stop(ctx);
ret = spu_run_fini(ctx, npc, status);
if (!ret)
ret = *status;
spu_yield(ctx);

return ret;
}

Expand Down
Loading

0 comments on commit 9a8215b

Please sign in to comment.