Skip to content

Commit

Permalink
[PATCH] spufs: implement mfc access for PPE-side DMA
Browse files Browse the repository at this point in the history
This patch adds a new file called 'mfc' to each spufs directory.
The file accepts DMA commands that are a subset of what would
be legal DMA commands for problem state register access. Upon
reading the file, a bitmask is returned with the completed
tag groups set.

The file is meant to be used from an abstraction in libspe
that is added by a different patch.

From the kernel perspective, this means a process can now
offload a memory copy from or into an SPE local store
without having to run code on the SPE itself.

The transfer will only be performed while the SPE is owned
by one thread that is waiting in the spu_run system call
and the data will be transferred into that thread's
address space, independent of which thread started the
transfer.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Arnd Bergmann authored and Paul Mackerras committed Mar 27, 2006
1 parent 2dd1493 commit a33a7d7
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 5 deletions.
7 changes: 5 additions & 2 deletions arch/powerpc/platforms/cell/spu_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
{
pr_debug("%s\n", __FUNCTION__);
pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);

/* Handle kernel space hash faults immediately.
User hash faults need to be deferred to process context. */
Expand Down Expand Up @@ -168,7 +168,7 @@ static int __spu_trap_halt(struct spu *spu)
static int __spu_trap_tag_group(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
/* wake_up(&spu->dma_wq); */
spu->mfc_callback(spu);
return 0;
}

Expand Down Expand Up @@ -242,6 +242,8 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
spu_mfc_dsisr_set(spu, 0ul);
spu_int_stat_clear(spu, 1, stat);
spin_unlock(&spu->register_lock);
pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
dar, dsisr);

if (stat & 1) /* segment fault */
__spu_trap_data_seg(spu, dar);
Expand Down Expand Up @@ -632,6 +634,7 @@ static int __init create_spu(struct device_node *spe)
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;
spu->mfc_callback = NULL;

mutex_lock(&spu_mutex);
spu->number = number++;
Expand Down
47 changes: 47 additions & 0 deletions arch/powerpc/platforms/cell/spufs/backing_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,49 @@ static void spu_backing_runcntl_stop(struct spu_context *ctx)
spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
}

static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
u32 mode)
{
struct spu_problem_collapsed *prob = &ctx->csa.prob;
int ret;

spin_lock(&ctx->csa.register_lock);
ret = -EAGAIN;
if (prob->dma_querytype_RW)
goto out;
ret = 0;
/* FIXME: what are the side-effects of this? */
prob->dma_querymask_RW = mask;
prob->dma_querytype_RW = mode;
out:
spin_unlock(&ctx->csa.register_lock);

return ret;
}

static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx)
{
return ctx->csa.prob.dma_tagstatus_R;
}

static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx)
{
return ctx->csa.prob.dma_qstatus_R;
}

static int spu_backing_send_mfc_command(struct spu_context *ctx,
struct mfc_dma_command *cmd)
{
int ret;

spin_lock(&ctx->csa.register_lock);
ret = -EAGAIN;
/* FIXME: set up priv2->puq */
spin_unlock(&ctx->csa.register_lock);

return ret;
}

struct spu_context_ops spu_backing_ops = {
.mbox_read = spu_backing_mbox_read,
.mbox_stat_read = spu_backing_mbox_stat_read,
Expand All @@ -305,4 +348,8 @@ struct spu_context_ops spu_backing_ops = {
.get_ls = spu_backing_get_ls,
.runcntl_write = spu_backing_runcntl_write,
.runcntl_stop = spu_backing_runcntl_stop,
.set_mfc_query = spu_backing_set_mfc_query,
.read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
.get_mfc_free_elements = spu_backing_get_mfc_free_elements,
.send_mfc_command = spu_backing_send_mfc_command,
};
5 changes: 3 additions & 2 deletions arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq);
init_waitqueue_head(&ctx->mfc_wq);
ctx->ibox_fasync = NULL;
ctx->wbox_fasync = NULL;
ctx->mfc_fasync = NULL;
ctx->tagwait = 0;
ctx->state = SPU_STATE_SAVED;
ctx->local_store = local_store;
ctx->spu = NULL;
Expand All @@ -68,8 +71,6 @@ void destroy_spu_context(struct kref *kref)
ctx = container_of(kref, struct spu_context, kref);
down_write(&ctx->state_sema);
spu_deactivate(ctx);
ctx->ibox_fasync = NULL;
ctx->wbox_fasync = NULL;
up_write(&ctx->state_sema);
spu_fini_csa(&ctx->csa);
kfree(ctx);
Expand Down
Loading

0 comments on commit a33a7d7

Please sign in to comment.