Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=58bd403c3c79dd41acf5af2d170bd4e0872bb326
Commit:     58bd403c3c79dd41acf5af2d170bd4e0872bb326
Parent:     a0a7ae8939e3fdecf5478ddba54562e23de7ca1d
Author:     Jeremy Kerr <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 5 13:49:31 2007 +1100
Committer:  Arnd Bergmann <[EMAIL PROTECTED]>
CommitDate: Wed Dec 19 01:00:04 2007 +0100

    [POWERPC] cell: handle kernel SLB setup in spu_base.c
    
    Currently, the SPU context switch code (spufs/switch.c) sets up the
    SPU's SLBs directly, which requires some low-level mm stuff.
    
    This change moves the kernel SLB setup to spu_base.c, by exposing
    a function spu_setup_kernel_slbs() to do this setup. This allows us
    to remove the low-level mm code from switch.c, making it possible
    to later move switch.c to the spufs module.
    
    Also, add a struct spu_slb for the cases where we need to deal with
    SLB entries.
    
    Signed-off-by: Jeremy Kerr <[EMAIL PROTECTED]>
    Signed-off-by: Arnd Bergmann <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/cell/spu_base.c     |   49 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/cell/spufs/switch.c |   33 +------------------
 include/asm-powerpc/spu.h                  |    4 ++
 3 files changed, 54 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spu_base.c 
b/arch/powerpc/platforms/cell/spu_base.c
index 5257120..2ec1d38 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -34,6 +34,7 @@
 #include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
+#include <asm/spu_csa.h>
 #include <asm/xmon.h>
 #include <asm/prom.h>
 
@@ -73,6 +74,10 @@ static LIST_HEAD(spu_full_list);
 static DEFINE_SPINLOCK(spu_full_list_lock);
 static DEFINE_MUTEX(spu_full_list_mutex);
 
+struct spu_slb {
+       u64 esid, vsid;
+};
+
 void spu_invalidate_slbs(struct spu *spu)
 {
        struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -150,6 +155,18 @@ static void spu_restart_dma(struct spu *spu)
                out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
 }
 
+static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
+{
+       struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+       pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
+                       __func__, slbe, slb->vsid, slb->esid);
+
+       out_be64(&priv2->slb_index_W, slbe);
+       out_be64(&priv2->slb_vsid_RW, slb->vsid);
+       out_be64(&priv2->slb_esid_RW, slb->esid);
+}
+
 static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 {
        struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -239,6 +256,38 @@ static int __spu_trap_data_map(struct spu *spu, unsigned 
long ea, u64 dsisr)
        return 0;
 }
 
+static void __spu_kernel_slb(void *addr, struct spu_slb *slb)
+{
+       unsigned long ea = (unsigned long)addr;
+       u64 llp;
+
+       if (REGION_ID(ea) == KERNEL_REGION_ID)
+               llp = mmu_psize_defs[mmu_linear_psize].sllp;
+       else
+               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+
+       slb->vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
+               SLB_VSID_KERNEL | llp;
+       slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
+}
+
+/**
+ * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
+ * need to map both the context save area, and the save/restore code.
+ */
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, void 
*code)
+{
+       struct spu_slb code_slb, lscsa_slb;
+
+       __spu_kernel_slb(lscsa, &lscsa_slb);
+       __spu_kernel_slb(code, &code_slb);
+
+       spu_load_slb(spu, 0, &lscsa_slb);
+       if (lscsa_slb.esid != code_slb.esid)
+               spu_load_slb(spu, 1, &code_slb);
+}
+EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
+
 static irqreturn_t
 spu_irq_class_0(int irq, void *data)
 {
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c 
b/arch/powerpc/platforms/cell/spufs/switch.c
index 3d64c81..96f5514 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -691,35 +691,8 @@ static inline void resume_mfc_queue(struct spu_state *csa, 
struct spu *spu)
        out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void get_kernel_slb(u64 ea, u64 slb[2])
-{
-       u64 llp;
-
-       if (REGION_ID(ea) == KERNEL_REGION_ID)
-               llp = mmu_psize_defs[mmu_linear_psize].sllp;
-       else
-               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
-       slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-               SLB_VSID_KERNEL | llp;
-       slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
-}
-
-static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
-{
-       struct spu_priv2 __iomem *priv2 = spu->priv2;
-
-       out_be64(&priv2->slb_index_W, slbe);
-       eieio();
-       out_be64(&priv2->slb_vsid_RW, slb[0]);
-       out_be64(&priv2->slb_esid_RW, slb[1]);
-       eieio();
-}
-
 static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
 {
-       u64 code_slb[2];
-       u64 lscsa_slb[2];
-
        /* Save, Step 47:
         * Restore, Step 30.
         *     If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
@@ -735,11 +708,7 @@ static inline void setup_mfc_slbs(struct spu_state *csa, 
struct spu *spu)
         *     translation is desired by OS environment).
         */
        spu_invalidate_slbs(spu);
-       get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
-       get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
-       load_mfc_slb(spu, code_slb, 0);
-       if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
-               load_mfc_slb(spu, lscsa_slb, 1);
+       spu_setup_kernel_slbs(spu, csa->lscsa, &spu_save_code);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index b1accce..844c7cd 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -104,6 +104,7 @@
 
 struct spu_context;
 struct spu_runqueue;
+struct spu_lscsa;
 struct device_node;
 
 enum spu_utilization_state {
@@ -200,6 +201,9 @@ int spu_irq_class_0_bottom(struct spu *spu);
 int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
+void spu_setup_kernel_slbs(struct spu *spu,
+               struct spu_lscsa *lscsa, void *code);
+
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);
 #else
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to