diff options
author | Arnd Bergmann <arnd@arndb.de> | 2005-11-15 15:53:52 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-09 14:49:30 +1100 |
commit | 8b3d6663c6217e4f50cc3720935a96da9b984117 (patch) | |
tree | 5295c29787ac66c26ddf715868fda7fcd3ad5f97 /arch/powerpc/platforms/cell/spufs/switch.c | |
parent | 05b841174c289ca62a6b42d883b8791d9ac3a4bd (diff) |
[PATCH] spufs: cooperative scheduler support
This adds a scheduler for SPUs to make it possible to use
more logical SPUs than physical ones are present in the
system.
Currently, there is no support for preempting a running
SPU thread, they have to leave the SPU by either triggering
an event on the SPU that causes it to return to the
owning thread or by sending a signal to it.
This patch also adds operations that enable accessing an SPU
in either runnable or saved state. We use an RW semaphore
to protect the state of the SPU from changing underneath
us, while we are holding it readable. In order to change
the state, it is acquired writeable and a context save
or restore is executed before downgrading the semaphore
to read-only.
From: Mark Nutter <mnutter@us.ibm.com>,
Uli Weigand <Ulrich.Weigand@de.ibm.com>
Signed-off-by: Arnd Bergmann <arndb@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/switch.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 70345b0524f..51266257b0a 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -646,7 +646,7 @@ static inline void save_spu_mb(struct spu_state *csa, struct spu *spu) eieio(); csa->spu_chnlcnt_RW[29] = in_be64(&priv2->spu_chnlcnt_RW); for (i = 0; i < 4; i++) { - csa->pu_mailbox_data[i] = in_be64(&priv2->spu_chnldata_RW); + csa->spu_mailbox_data[i] = in_be64(&priv2->spu_chnldata_RW); } out_be64(&priv2->spu_chnlcnt_RW, 0UL); eieio(); @@ -1667,7 +1667,7 @@ static inline void restore_spu_mb(struct spu_state *csa, struct spu *spu) eieio(); out_be64(&priv2->spu_chnlcnt_RW, csa->spu_chnlcnt_RW[29]); for (i = 0; i < 4; i++) { - out_be64(&priv2->spu_chnldata_RW, csa->pu_mailbox_data[i]); + out_be64(&priv2->spu_chnldata_RW, csa->spu_mailbox_data[i]); } eieio(); } @@ -2079,7 +2079,10 @@ int spu_save(struct spu_state *prev, struct spu *spu) acquire_spu_lock(spu); /* Step 1. */ rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); - + if (rc) { + panic("%s failed on SPU[%d], rc=%d.\n", + __func__, spu->number, rc); + } return rc; } @@ -2098,34 +2101,31 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); + spu->stop_code = 0; + spu->dar = 0; + spu->dsisr = 0; + spu->slb_replace = 0; + spu->class_0_pending = 0; rc = __do_spu_restore(new, spu); release_spu_lock(spu); - + if (rc) { + panic("%s failed on SPU[%d] rc=%d.\n", + __func__, spu->number, rc); + } return rc; } /** - * spu_switch - SPU context switch (save + restore). - * @prev: pointer to SPU context save area, to be saved. - * @new: pointer to SPU context save area, to be restored. + * spu_harvest - SPU harvest (reset) operation * @spu: pointer to SPU iomem structure. * - * Perform save, then restore. Only harvest if the - * save fails, as cleanup is otherwise not needed. + * Perform SPU harvest (reset) operation. */ -int spu_switch(struct spu_state *prev, struct spu_state *new, struct spu *spu) +void spu_harvest(struct spu *spu) { - int rc; - - acquire_spu_lock(spu); /* Save, Step 1. */ - rc = __do_spu_save(prev, spu); /* Save, Steps 2-53. */ - if (rc != 0) { - harvest(prev, spu); - } - rc = __do_spu_restore(new, spu); + acquire_spu_lock(spu); + harvest(NULL, spu); release_spu_lock(spu); - - return rc; } static void init_prob(struct spu_state *csa) @@ -2181,6 +2181,7 @@ static void init_priv2(struct spu_state *csa) void spu_init_csa(struct spu_state *csa) { struct spu_lscsa *lscsa; + unsigned char *p; if (!csa) return; @@ -2192,6 +2193,11 @@ void spu_init_csa(struct spu_state *csa) memset(lscsa, 0, sizeof(struct spu_lscsa)); csa->lscsa = lscsa; + csa->register_lock = SPIN_LOCK_UNLOCKED; + + /* Set LS pages reserved to allow for user-space mapping. */ + for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) + SetPageReserved(vmalloc_to_page(p)); init_prob(csa); init_priv1(csa); @@ -2200,5 +2206,10 @@ void spu_init_csa(struct spu_state *csa) void spu_fini_csa(struct spu_state *csa) { + /* Clear reserved bit before vfree. */ + unsigned char *p; + for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) + ClearPageReserved(vmalloc_to_page(p)); + vfree(csa->lscsa); } |