]> err.no Git - linux-2.6/blobdiff - arch/powerpc/platforms/cell/spufs/switch.c
Merge git://git.infradead.org/~dedekind/ubi-2.6
[linux-2.6] / arch / powerpc / platforms / cell / spufs / switch.c
index 8cbc6574820fb9b5db023e36eeefad9525609063..d2a1249d36dd2a7bc018727e09c3b7c57b88cf1c 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -48,6 +49,8 @@
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 
+#include "spufs.h"
+
 #include "spu_save_dump.h"
 #include "spu_restore_dump.h"
 
@@ -115,6 +118,8 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
         *     Write INT_MASK_class1 with value of 0.
         *     Save INT_Mask_class2 in CSA.
         *     Write INT_MASK_class2 with value of 0.
+        *     Synchronize all three interrupts to be sure
+        *     we no longer execute a handler on another CPU.
         */
        spin_lock_irq(&spu->register_lock);
        if (csa) {
@@ -127,6 +132,9 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
        spu_int_mask_set(spu, 2, 0ul);
        eieio();
        spin_unlock_irq(&spu->register_lock);
+       synchronize_irq(spu->irqs[0]);
+       synchronize_irq(spu->irqs[1]);
+       synchronize_irq(spu->irqs[2]);
 }
 
 static inline void set_watchdog_timer(struct spu_state *csa, struct spu *spu)
@@ -718,8 +726,9 @@ static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
         * Restore, Step 23.
         *     Change the software context switch pending flag
         *     to context switch active.
+        *
+        *     This implementation does not uses a switch active flag.
         */
-       set_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags);
        clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);
        mb();
 }
@@ -738,9 +747,9 @@ static inline void enable_interrupts(struct spu_state *csa, struct spu *spu)
         *     (translation) interrupts.
         */
        spin_lock_irq(&spu->register_lock);
-       spu_int_stat_clear(spu, 0, ~0ul);
-       spu_int_stat_clear(spu, 1, ~0ul);
-       spu_int_stat_clear(spu, 2, ~0ul);
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        spu_int_mask_set(spu, 0, 0ul);
        spu_int_mask_set(spu, 1, class1_mask);
        spu_int_mask_set(spu, 2, 0ul);
@@ -897,8 +906,8 @@ static inline void wait_tag_complete(struct spu_state *csa, struct spu *spu)
        POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask);
 
        local_irq_save(flags);
-       spu_int_stat_clear(spu, 0, ~(0ul));
-       spu_int_stat_clear(spu, 2, ~(0ul));
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        local_irq_restore(flags);
 }
 
@@ -916,8 +925,8 @@ static inline void wait_spu_stopped(struct spu_state *csa, struct spu *spu)
        POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
 
        local_irq_save(flags);
-       spu_int_stat_clear(spu, 0, ~(0ul));
-       spu_int_stat_clear(spu, 2, ~(0ul));
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        local_irq_restore(flags);
 }
 
@@ -1393,9 +1402,9 @@ static inline void clear_interrupts(struct spu_state *csa, struct spu *spu)
        spu_int_mask_set(spu, 0, 0ul);
        spu_int_mask_set(spu, 1, 0ul);
        spu_int_mask_set(spu, 2, 0ul);
-       spu_int_stat_clear(spu, 0, ~0ul);
-       spu_int_stat_clear(spu, 1, ~0ul);
-       spu_int_stat_clear(spu, 2, ~0ul);
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        spin_unlock_irq(&spu->register_lock);
 }
 
@@ -1737,9 +1746,8 @@ static inline void reset_switch_active(struct spu_state *csa, struct spu *spu)
 {
        /* Restore, Step 74:
         *     Reset the "context switch active" flag.
+        *     Not performed by this implementation.
         */
-       clear_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags);
-       mb();
 }
 
 static inline void reenable_interrupts(struct spu_state *csa, struct spu *spu)
@@ -1807,6 +1815,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
        save_mfc_csr_ato(prev, spu);    /* Step 24. */
        save_mfc_tclass_id(prev, spu);  /* Step 25. */
        set_mfc_tclass_id(prev, spu);   /* Step 26. */
+       save_mfc_cmd(prev, spu);        /* Step 26a - moved from 44. */
        purge_mfc_queue(prev, spu);     /* Step 27. */
        wait_purge_complete(prev, spu); /* Step 28. */
        setup_mfc_sr1(prev, spu);       /* Step 30. */
@@ -1823,7 +1832,6 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
        save_ppuint_mb(prev, spu);      /* Step 41. */
        save_ch_part1(prev, spu);       /* Step 42. */
        save_spu_mb(prev, spu);         /* Step 43. */
-       save_mfc_cmd(prev, spu);        /* Step 44. */
        reset_ch(prev, spu);            /* Step 45. */
 }
 
@@ -2075,10 +2083,6 @@ int spu_save(struct spu_state *prev, struct spu *spu)
        int rc;
 
        acquire_spu_lock(spu);          /* Step 1.     */
-       prev->dar = spu->dar;
-       prev->dsisr = spu->dsisr;
-       spu->dar = 0;
-       spu->dsisr = 0;
        rc = __do_spu_save(prev, spu);  /* Steps 2-53. */
        release_spu_lock(spu);
        if (rc != 0 && rc != 2 && rc != 6) {
@@ -2105,9 +2109,6 @@ int spu_restore(struct spu_state *new, struct spu *spu)
        acquire_spu_lock(spu);
        harvest(NULL, spu);
        spu->slb_replace = 0;
-       new->dar = 0;
-       new->dsisr = 0;
-       spu->class_0_pending = 0;
        rc = __do_spu_restore(new, spu);
        release_spu_lock(spu);
        if (rc) {
@@ -2187,10 +2188,8 @@ int spu_init_csa(struct spu_state *csa)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
        spu_free_lscsa(csa);
 }
-EXPORT_SYMBOL_GPL(spu_fini_csa);