[Cbe-oss-dev] [patch 07/10] spufs: add kernel support for spu task

Arnd Bergmann arnd at arndb.de
Thu Aug 30 00:19:42 EST 2007


On Wednesday 29 August 2007, Sebastian Siewior wrote:
> I tried. What about:

better, but I think you can do more:

> static void setup_spu_sched(struct spu_context *ctx)
> {
>         if (ctx->state == SPU_STATE_SAVED) {
>                 __spu_update_sched_info(ctx);
>                 spu_set_timeslice(ctx);
>                 spu_activate(ctx, 0);
>         } else {
>                 /*
>                  * We have to update the scheduling priority under active_mutex
>                  * to protect against find_victim().
>                  */
>                 spu_update_sched_info(ctx);
>         }
> }
> 
> static void check_spu_state(struct kspu_context *kctx, unsigned int *npc,
>                 unsigned int *status)
> {
>         if (!(*status & SPU_STATUS_RUNNING)) {
>                 /* spu is currently not running */
>                 pr_debug("SPU not running, last stop code was: %08x\n",
>                                 *status >> SPU_STOP_STATUS_SHIFT);
>                 if (pending_spu_work(kctx)) {
>                         /* spu should run again */
>                         pr_debug("Activate SPU\n");
>                         kspu_fill_dummy_reqs(kctx);
> 
>                         spu_run_fini(kctx->spu_ctx, npc, status);
>                         spu_acquire_runnable(kctx->spu_ctx, 0);
>                         spu_run_init(kctx->spu_ctx, npc);
>                 } else {
>                         /* spu finished work */
>                         pr_debug("SPU will remain in stop state\n");
>                         spu_run_fini(kctx->spu_ctx, npc, status);
>                         spu_yield(kctx->spu_ctx);
>                         spu_acquire(kctx->spu_ctx);
>                 }
>         } else {
>                 pr_debug("SPU is running, switch state to util user\n");
>                 spuctx_switch_state(kctx->spu_ctx, SPU_UTIL_USER);
>         }
> }
> 
> /*
>  * based on run.c spufs_run_spu
>  */
> static int spufs_run_kernel_spu(void *priv)
> {
>         struct kspu_context *kctx = (struct kspu_context *) priv;
>         struct spu_context *ctx = kctx->spu_ctx;
>         int ret;
>         u32 status;
>         unsigned int npc = 0;
>         int fastpath;
>         DEFINE_WAIT(wait_for_stop);
>         DEFINE_WAIT(wait_for_ibox);
>         DEFINE_WAIT(wait_for_newitem);
> 
>         ctx->event_return = 0;
>         spu_acquire(ctx);
>         ctx->ops->master_start(ctx);
> 
>         setup_spu_sched(ctx);
> 
>         spu_run_init(ctx, &npc);
>         do {
>                 fastpath = 0;
>                 prepare_to_wait(&ctx->stop_wq, &wait_for_stop,
>                                 TASK_INTERRUPTIBLE);
>                 prepare_to_wait(&ctx->ibox_wq, &wait_for_ibox,
>                                 TASK_INTERRUPTIBLE);
>                 prepare_to_wait(&kctx->newitem_wq, &wait_for_newitem,
>                                 TASK_INTERRUPTIBLE);

Everything from here


>                 if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE,
>                                                 &ctx->sched_flags))) {
>                         if (!(status & SPU_STATUS_STOPPED_BY_STOP)) {
>                                 spu_switch_notify(ctx->spu, ctx);
>                         }
>                 }
> 
>                 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
> 
>                 pr_debug("going to handle class1\n");
>                 ret = spufs_handle_class1(ctx);
>                 if (unlikely(ret)) {
>                         /*
>                          * SPE_EVENT_SPE_DATA_STORAGE => refernce invalid memory
>                          */
>                         printk(KERN_ERR "Invalid memory dereferenced by the"
>                                         "spu: %d\n", ret);
>                         BUG();
>                 }
> 
>                 /* FIXME BUG: We need a physical SPU to discover
>                  * ctx->spu->class_0_pending. It is not saved on context
>                  * switch. We may lose this on context switch.
>                  */
>                 status = ctx->ops->status_read(ctx);
>                 if (unlikely((ctx->spu && ctx->spu->class_0_pending) ||
>                                         status & SPU_STATUS_INVALID_INSTR)) {
>                         printk(KERN_ERR "kspu error, status_register: 0x%08x\n",
>                                         status);
>                         printk(KERN_ERR "event return: 0x%08lx, spu's npc: "
>                                         "0x%08x\n", kctx->spu_ctx->event_return,
>                                         kctx->spu_ctx->ops->npc_read(
>                                                 kctx->spu_ctx));
>                         printk(KERN_ERR "class_0_pending: 0x%x\n", ctx->spu->class_0_pending);
>                         print_kctx_debug(kctx);
>                         BUG();
>                 }
> 
>                 if (notify_done_reqs(kctx))
>                         fastpath = 1;
> 
>                 if (queue_requests(kctx))
>                         fastpath = 1;
> 
>                 check_spu_state(kctx, &npc, &status);

to here can probably go into a separate function.

>                 if (fastpath)
>                         continue;

with fastpath being the return value of that function, so you end up with

		if (spufs_process_kspu_events(ctx))
			continue;

You might need more arguments there, but try to avoid them.

>                 spu_release(ctx);
>                 schedule();
>                 spu_acquire(ctx);
> 
>         } while (!kthread_should_stop() || !list_empty(&kctx->work_queue));
> 
>         finish_wait(&ctx->stop_wq, &wait_for_stop);
>         finish_wait(&ctx->ibox_wq, &wait_for_ibox);
>         finish_wait(&kctx->newitem_wq, &wait_for_newitem);
> 
>         ctx->ops->master_stop(ctx);
>         spu_release(ctx);
>         return 0;
> }

	Arnd <><


More information about the cbe-oss-dev mailing list