void mips_cm_lock_other(unsigned int core, unsigned int vp) { unsigned curr_core; u32 val; preempt_disable(); curr_core = current_cpu_data.core; spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), per_cpu(cm_core_lock_flags, curr_core)); if (mips_cm_revision() >= CM_REV_CM3) { val = core << CM3_GCR_Cx_OTHER_CORE_SHF; val |= vp << CM3_GCR_Cx_OTHER_VP_SHF; } else { BUG_ON(vp != 0); val = core << CM_GCR_Cx_OTHER_CORENUM_SHF; } write_gcr_cl_other(val); /* * Ensure the core-other region reflects the appropriate core & * VP before any accesses to it occur. */ mb(); }
void mips_cm_lock_other(unsigned int cluster, unsigned int core, unsigned int vp, unsigned int block) { unsigned int curr_core, cm_rev; u32 val; cm_rev = mips_cm_revision(); preempt_disable(); if (cm_rev >= CM_REV_CM3) { val = core << __ffs(CM3_GCR_Cx_OTHER_CORE); val |= vp << __ffs(CM3_GCR_Cx_OTHER_VP); if (cm_rev >= CM_REV_CM3_5) { val |= CM_GCR_Cx_OTHER_CLUSTER_EN; val |= cluster << __ffs(CM_GCR_Cx_OTHER_CLUSTER); val |= block << __ffs(CM_GCR_Cx_OTHER_BLOCK); } else { WARN_ON(cluster != 0); WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); } /* * We need to disable interrupts in SMP systems in order to * ensure that we don't interrupt the caller with code which * may modify the redirect register. We do so here in a * slightly obscure way by using a spin lock, since this has * the neat property of also catching any nested uses of * mips_cm_lock_other() leading to a deadlock or a nice warning * with lockdep enabled. */ spin_lock_irqsave(this_cpu_ptr(&cm_core_lock), *this_cpu_ptr(&cm_core_lock_flags)); } else { WARN_ON(cluster != 0); WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); /* * We only have a GCR_CL_OTHER per core in systems with * CM 2.5 & older, so have to ensure other VP(E)s don't * race with us. */ curr_core = cpu_core(¤t_cpu_data); spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), per_cpu(cm_core_lock_flags, curr_core)); val = core << __ffs(CM_GCR_Cx_OTHER_CORENUM); } write_gcr_cl_other(val); /* * Ensure the core-other region reflects the appropriate core & * VP before any accesses to it occur. */ mb(); }
static unsigned core_vpe_count(unsigned core) { unsigned cfg; if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) return 1; write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK; return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1; }