Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c25620d7 authored by Masato Noguchi's avatar Masato Noguchi Committed by Paul Mackerras
Browse files

[POWERPC] cell: wrap master run control bit



Add platform specific SPU run control routines to the spufs.  The current
spufs implementation uses the SPU master run control bit (MFC_SR1[S]) to
control SPE execution, but the PS3 hypervisor does not support the use of
this feature.

This change adds the run control wrapper routies spu_enable_spu() and
spu_disable_spu().  The bare metal routines use the master run control
bit, and the PS3 specific routines use the priv2 run control register.

An outstanding enhancement for the PS3 would be to add a guard to check
for incorrect access to the spu problem state when the spu context is
disabled.  This check could be implemented with a flag added to the spu
context that would inhibit mapping problem state pages, and a routine
to unmap spu problem state pages.  When the spu is enabled with
ps3_enable_spu() the flag would be set allowing pages to be mapped,
and when the spu is disabled with ps3_disable_spu() the flag would be
cleared and mapped problem state pages would be unmapped.

Signed-off-by: default avatarMasato Noguchi <Masato.Noguchi@jp.sony.com>
Signed-off-by: default avatarGeoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: default avatarJeremy Kerr <jk@ozlabs.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent eda09fbd
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <asm/firmware.h>
#include <asm/prom.h>

#include "spufs/spufs.h"
#include "interrupt.h"

struct device_node *spu_devnode(struct spu *spu)
@@ -369,6 +370,16 @@ static int of_destroy_spu(struct spu *spu)
	return 0;
}

static void enable_spu_by_master_run(struct spu_context *ctx)
{
	ctx->ops->master_start(ctx);
}

static void disable_spu_by_master_run(struct spu_context *ctx)
{
	ctx->ops->master_stop(ctx);
}

/* Hardcoded affinity idxs for qs20 */
#define QS20_SPES_PER_BE 8
static int qs20_reg_idxs[QS20_SPES_PER_BE] =   { 0, 2, 4, 6, 7, 5, 3, 1 };
@@ -540,5 +551,7 @@ const struct spu_management_ops spu_management_of_ops = {
	.enumerate_spus = of_enumerate_spus,
	.create_spu = of_create_spu,
	.destroy_spu = of_destroy_spu,
	.enable_spu = enable_spu_by_master_run,
	.disable_spu = disable_spu_by_master_run,
	.init_affinity = init_affinity,
};
+6 −0
Original line number Diff line number Diff line
@@ -285,6 +285,11 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
	spin_unlock(&ctx->csa.register_lock);
}

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

static void spu_backing_master_start(struct spu_context *ctx)
{
	struct spu_state *csa = &ctx->csa;
@@ -381,6 +386,7 @@ struct spu_context_ops spu_backing_ops = {
	.get_ls = spu_backing_get_ls,
	.runcntl_read = spu_backing_runcntl_read,
	.runcntl_write = spu_backing_runcntl_write,
	.runcntl_stop = spu_backing_runcntl_stop,
	.master_start = spu_backing_master_start,
	.master_stop = spu_backing_master_stop,
	.set_mfc_query = spu_backing_set_mfc_query,
+10 −0
Original line number Diff line number Diff line
@@ -220,6 +220,15 @@ static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
	spin_unlock_irq(&ctx->spu->register_lock);
}

static void spu_hw_runcntl_stop(struct spu_context *ctx)
{
	spin_lock_irq(&ctx->spu->register_lock);
	out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
	while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
		cpu_relax();
	spin_unlock_irq(&ctx->spu->register_lock);
}

static void spu_hw_master_start(struct spu_context *ctx)
{
	struct spu *spu = ctx->spu;
@@ -321,6 +330,7 @@ struct spu_context_ops spu_hw_ops = {
	.get_ls = spu_hw_get_ls,
	.runcntl_read = spu_hw_runcntl_read,
	.runcntl_write = spu_hw_runcntl_write,
	.runcntl_stop = spu_hw_runcntl_stop,
	.master_start = spu_hw_master_start,
	.master_stop = spu_hw_master_stop,
	.set_mfc_query = spu_hw_set_mfc_query,
+2 −2
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
	if (mutex_lock_interruptible(&ctx->run_mutex))
		return -ERESTARTSYS;

	ctx->ops->master_start(ctx);
	spu_enable_spu(ctx);
	ctx->event_return = 0;

	spu_acquire(ctx);
@@ -376,7 +376,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
		ctx->stats.libassist++;


	ctx->ops->master_stop(ctx);
	spu_disable_spu(ctx);
	ret = spu_run_fini(ctx, npc, &status);
	spu_yield(ctx);

+1 −0
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ struct spu_context_ops {
	char*(*get_ls) (struct spu_context * ctx);
	 u32 (*runcntl_read) (struct spu_context * ctx);
	void (*runcntl_write) (struct spu_context * ctx, u32 data);
	void (*runcntl_stop) (struct spu_context * ctx);
	void (*master_start) (struct spu_context * ctx);
	void (*master_stop) (struct spu_context * ctx);
	int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
Loading