[Cbe-oss-dev] [RFC 4/5] spufs: add kernel support for spu task

Jeremy Kerr jk at ozlabs.org
Wed Jun 13 14:38:49 EST 2007


Hi Sebastian,

> Utilisation of SPUs by the kernel, main implementation.
> The idea behind this implemtation is that there are single jobs that
> are executed asynchronous on the SPU. The user queues jobs with
> enqueue_for_spu() and gets a callback once the job is completed. The
> function itself does not block, it returns -EINPROGRESS.

As Ben said, just return 0 instead.

Also, I'm a little confused about the queue API - the user queues a 
kspu_work_item with this function, and it later gets an 'enqueue' 
callback, where it may put an entry on the ringbuffer, right?

> +config SPU_KERNEL_SUPPORT
> +	tristate "Support for utilisation of SPU by the kernel"
> +	default m
> +	depends on SPU_FS

Maybe this should depend on CONFIG_EXPERIMENTAL?

> +choice
> +	prompt "Slots in the ringbuffer"
> +	depends on SPU_KERNEL_SUPPORT
> +	default SPU_RINB_SLOTS_16
> +	help
> +	  This option allows you to determine the number of slots in the
> +	  ringbuffer. More slots means that more work may be queued on
> +	  the SPU before waiting for completion. The number of slots must
> +	  be power of two. Every slot takes approx 128 bytes of memory.

Does this need to be a config option?

(if so, can we make this tied to the KSPU options, eg KSPU_RING_SLOTS ?)

>  SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include \
> -		   -I$(objtree)/include2 -D__KERNEL__
> +		   -I$(objtree)/include2 -D__KERNEL__ -ffreestanding

What happens without -ffreestanding?

> +
> +struct kspu_code single_spu_code = {
> +	.code = (unsigned char*) spu_kspu_code,

Would be good to keep the .code member the same type as the symbol here.

> --- /dev/null
> +++ b/arch/powerpc/platforms/cell/spufs/kspu_helper.c
> @@ -0,0 +1,574 @@
> +/*
> + * Helper function for dealing with kspus
> + */

I'd say that these aren't just 'helper' functions, they're the core API. 
Might be better to call this arch/powerpc/platforms/cell/spusf/kspu.c

> +	if (!ret)
> +		WARN_ON(1);
> +	else {
> +		kfree(kctx->notify_cb_info);
> +		kfree(kctx);
> +	}

Minor one, but keep the bracketing consistent within one if/else block.


> +static void set_reg32(struct spu_lscsa *lscsa, int reg, unsigned int 
p) +{
> +	lscsa->gprs[reg].slot[0] = p;
> +}

Would this be useful for other (non-KSPU) purposes? should we make this 
a generic SPU function?

> +	 * |      آ�      |

I get some whacky character here that puts my mailer in right-to-left 
text mode.

> +#define BACKCHAIN (kctx->spu_code->data_offset - 16)

This makes me think that the data_offset member is misnamed, as it has 
nothing to do with the 'data' section of the KSPU program.

> +#define STACK_GAP 176
> +#define INITIAL_STACK (BACKCHAIN - STACK_GAP)
> +
> +	/*
> +	 * if kspu_data_offset is too large it will overflow not allocated
> +	 * data will be modofied
> +	 */
> +	if (INITIAL_STACK > KSPU_LS_SIZE)
> +		BUG();

BUG_ON ?

> +	lscsa = ctx->csa.lscsa;
> +	set_reg32(lscsa, 1, (unsigned int) (INITIAL_STACK));

we probably don't need the 'lscsa' variable for only one usage.

> +	spu_release(ctx);
> +	printk("Stack ready 0x%x08\n", INITIAL_STACK);

0x%08x? Also, if you're going to keep these printk()s in a later patch, 
they'd probably be better as pr_debug()s.

> +	ret = -EFBIG;
> +	printk("SPU's queue: %d elemets, %d bytes each (%d bytes total)\n",
> +			spu_code->queue_mask+1, spu_code->queue_entr_size,
> +			(spu_code->queue_mask+1) * spu_code->queue_entr_size);
> +	ring_space = (spu_code->queue_mask+1) * spu_code->queue_entr_size;
> +	ring_space += sizeof(struct kspu_ring_data);
> +	if (spu_code->data_offset != KSPU_LS_SIZE - ring_space) {
> +		printk("data offset: %04x, ring space: %04x\n",
> spu_code->data_offset, ring_space);
> +		printk("data expect: %04x\n", KSPU_LS_SIZE - ring_space);
> +	} 
> +
> +	if (spu_code->code_len > KSPU_LS_SIZE)
> +		goto err;

Put the 'ret = -EFBIG' closer to the error check.


> +	kctx->notify_cb_info = kzalloc(sizeof(void*) *

              sizeof(*kctx->notify_cb_info) ----^   ?

> +
> +	do {
> +		ret = spufs_run_spu(ctx, npc, event);
> +		if (ret & SPU_STATUS_STOPPED_BY_STOP) {
> +			if (ret >> SPU_STOP_STATUS_SHIFT == 0x1234) {

We'll need to formalise this stopcode somehow, a #define should do the 
trick.


> +
> +	printk("Entering main loop\n");
> +
> +	do {
> +		fastpath = 0;

What conditions can we take the fast path? can we rename the variable to 
reflect this?

> +static struct kspu_context *kspu_ctx;

As ben mentioned, we could have one per physical SPE, or even make this 
configurable? or create contexts as required?


> Index: b/arch/powerpc/platforms/cell/spufs/spu_main.c
> ===================================================================
> --- /dev/null
> +++ b/arch/powerpc/platforms/cell/spufs/spu_main.c
> @@ -0,0 +1,35 @@
> +/*
> + * This code can be considered as crt0.S
> + * Compile with -O[123S] and make sure that here is only one
> function + * that starts at 0x0
> + */
> +#include <spu_mfcio.h>
> +
> +#include <asm/kspu/merged_code.h>
> +
> +spu_operation spu_ops[TOTAL_SPU_FUNCS] __attribute__((aligned(16)))

ops vs. funcs ?

> = { +
> +};
> +
> +#define DMA_TAG 1
> +void _start(void) __attribute__((noreturn));
> +void _start(void)
> +{
> +	struct kernel_spu_data *spu_data;
> +
> +	mfc_write_tag_mask(1<< DMA_TAG);

Why do you set the tag here ?

> +	spu_data = (struct kernel_spu_data*) KERNEL_SPU_DATA_OFFSET;
> +
> +	while (42) {
> +
> +		unsigned int consumed = spu_data->kspu_ring_data.consumed;
> +		unsigned int outstanding = spu_data->kspu_ring_data.outstanding;
> +
> +		if (consumed != outstanding) {
> +			int cons = consumed & (RB_SLOTS-1);
> +
> +			spu_ops[spu_data->work_item[cons].operation](cons);
> +		} else
> +			spu_stop(0x99);

We should probably #define this.


> Index: b/include/asm-powerpc/kspu/merged_code.h
> ===================================================================
> --- /dev/null
> +++ b/include/asm-powerpc/kspu/merged_code.h
> @@ -0,0 +1,46 @@
> +#ifndef KSPU_MERGED_CODE_H
> +#define KSPU_MERGED_CODE_H
> +#include <linux/autoconf.h>
> +
> +#define KSPU_LS_SIZE 0x40000

This is defined in spu.h:

include/asm-powerpc/spu.h:#define LS_SIZE (256 * 1024)

Can we somehow share this with the SPE-application header?

Cheers,


Jeremy




More information about the cbe-oss-dev mailing list