* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/spu.h>
-#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
#include <asm/mmu_context.h>
* Poll MFC_CNTL[Ps] until value '11' is read
* (purge complete).
*/
- POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
- MFC_CNTL_PURGE_DMA_STATUS_MASK) ==
+ POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
MFC_CNTL_PURGE_DMA_COMPLETE);
}
static inline void save_ch_part1(struct spu_state *csa, struct spu *spu)
{
struct spu_priv2 __iomem *priv2 = spu->priv2;
- u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
int i;
/* Save, Step 42:
+ * Save the following CH: [0,1,3,4,24,25,27]
*/
-
- /* Save CH 1, without channel count */
- out_be64(&priv2->spu_chnlcntptr_RW, 1);
- csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW);
-
- /* Save the following CH: [0,3,4,24,25,27] */
for (i = 0; i < 7; i++) {
idx = ch_indices[i];
out_be64(&priv2->spu_chnlcntptr_RW, idx);
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) << SLB_VSID_SHIFT) |
- SLB_VSID_KERNEL | llp;
+ slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
+
+ /* Large pages are used for kernel text/data, but not vmalloc. */
+ if (cpu_has_feature(CPU_FTR_16M_PAGE)
+ && REGION_ID(ea) == KERNEL_REGION_ID)
+ slb[0] |= SLB_VSID_L;
}
static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
* Restore, Step 47.
* Poll MFC_CNTL[Ss] until 11 is returned.
*/
- POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
- MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
+ POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
MFC_CNTL_SUSPEND_COMPLETE);
}
static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu)
{
struct spu_priv2 __iomem *priv2 = spu->priv2;
- u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
u64 idx;
int i;
/* Restore, Step 20:
+ * Reset the following CH: [0,1,3,4,24,25,27]
*/
-
- /* Reset CH 1 */
- out_be64(&priv2->spu_chnlcntptr_RW, 1);
- out_be64(&priv2->spu_chnldata_RW, 0UL);
-
- /* Reset the following CH: [0,3,4,24,25,27] */
for (i = 0; i < 7; i++) {
idx = ch_indices[i];
out_be64(&priv2->spu_chnlcntptr_RW, idx);
cycles_t resume_time = get_cycles();
cycles_t delta_time = resume_time - csa->suspend_time;
- csa->lscsa->decr.slot[0] -= delta_time;
+ csa->lscsa->decr.slot[0] = delta_time;
}
}
static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu)
{
struct spu_priv2 __iomem *priv2 = spu->priv2;
- u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
int i;
/* Restore, Step 59:
+ * Restore the following CH: [0,1,3,4,24,25,27]
*/
-
- /* Restore CH 1 without count */
- out_be64(&priv2->spu_chnlcntptr_RW, 1);
- out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]);
-
- /* Restore the following CH: [0,3,4,24,25,27] */
for (i = 0; i < 7; i++) {
idx = ch_indices[i];
out_be64(&priv2->spu_chnlcntptr_RW, idx);
}
return rc;
}
-EXPORT_SYMBOL_GPL(spu_save);
/**
* spu_restore - SPU context restore, with harvest and locking.
* @spu: pointer to SPU iomem structure.
*
* Perform harvest + restore, as we may not be coming
- * from a previous successful save operation, and the
+ * from a previous succesful save operation, and the
* hardware state is unknown.
*/
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;
}
return rc;
}
-EXPORT_SYMBOL_GPL(spu_restore);
/**
* spu_harvest - SPU harvest (reset) operation
csa->spu_chnlcnt_RW[28] = 1;
csa->spu_chnlcnt_RW[30] = 1;
csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP;
- csa->prob.mb_stat_R = 0x000400;
}
static void init_priv1(struct spu_state *csa)
csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
CLASS1_ENABLE_STORAGE_FAULT_INTR;
csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |
- CLASS2_ENABLE_SPU_HALT_INTR |
- CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR;
+ CLASS2_ENABLE_SPU_HALT_INTR;
}
static void init_priv2(struct spu_state *csa)
memset(lscsa, 0, sizeof(struct spu_lscsa));
csa->lscsa = lscsa;
- spin_lock_init(&csa->register_lock);
+ 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)
init_priv1(csa);
init_priv2(csa);
}
-EXPORT_SYMBOL_GPL(spu_init_csa);
void spu_fini_csa(struct spu_state *csa)
{
vfree(csa->lscsa);
}
-EXPORT_SYMBOL_GPL(spu_fini_csa);