#include <asm/hazards.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
-#include <asm/smp.h>
#include <asm/mipsregs.h>
#include <asm/cacheflush.h>
#include <asm/time.h>
static atomic_t ipi_timer_latch[NR_CPUS];
/*
- * Number of InterProcessor Interupt (IPI) message buffers to allocate
+ * Number of InterProcessor Interrupt (IPI) message buffers to allocate
*/
#define IPIBUF_PER_CPU 4
/* Boot command line configuration overrides */
+static int vpe0limit;
static int ipibuffers = 0;
static int nostlb = 0;
static int asidmask = 0;
unsigned long smtc_asid_mask = 0xff;
+static int __init vpe0tcs(char *str)
+{
+ get_option(&str, &vpe0limit);
+
+ return 1;
+}
+
static int __init ipibufs(char *str)
{
get_option(&str, &ipibuffers);
return 1;
}
+__setup("vpe0tcs=", vpe0tcs);
__setup("ipibufs=", ipibufs);
__setup("nostlb", stlb_disable);
__setup("asidmask=", asidmask_set);
#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
-/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
-
-void __init sanitize_tlb_entries(void)
-{
- printk("Deprecated sanitize_tlb_entries() invoked\n");
-}
-
-
/*
* Configure shared TLB - VPC configuration bit must be set by caller
*/
static void smtc_configure_tlb(void)
{
- int i,tlbsiz,vpes;
+ int i, tlbsiz, vpes;
unsigned long mvpconf0;
unsigned long config1val;
/* In general, all TCs should have the same cpu_data indications */
memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
- if (cpu_data[0].cputype == CPU_34K)
+ if (cpu_data[0].cputype == CPU_34K ||
+ cpu_data[0].cputype == CPU_1004K)
cpu_data[cpu].options &= ~MIPS_CPU_FPU;
cpu_data[cpu].vpe_id = vpe;
cpu_data[cpu].tc_id = tc;
void mipsmt_prepare_cpus(void)
{
- int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+ int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
unsigned long flags;
unsigned long val;
int nipi;
cpu++;
/* Report on boot-time options */
- mips_mt_set_cpuoptions ();
+ mips_mt_set_cpuoptions();
if (vpelimit > 0)
printk("Limit of %d VPEs set\n", vpelimit);
if (tclimit > 0)
ntc = NR_CPUS;
if (tclimit > 0 && ntc > tclimit)
ntc = tclimit;
- tcpervpe = ntc / nvpe;
- slop = ntc % nvpe; /* Residual TCs, < NVPE */
+ slop = ntc % nvpe;
+ for (i = 0; i < nvpe; i++) {
+ tcpervpe[i] = ntc / nvpe;
+ if (slop) {
+ if((slop - i) > 0) tcpervpe[i]++;
+ }
+ }
+ /* Handle command line override for VPE0 */
+ if (vpe0limit > ntc) vpe0limit = ntc;
+ if (vpe0limit > 0) {
+ int slopslop;
+ if (vpe0limit < tcpervpe[0]) {
+ /* Reducing TC count - distribute to others */
+ slop = tcpervpe[0] - vpe0limit;
+ slopslop = slop % (nvpe - 1);
+ tcpervpe[0] = vpe0limit;
+ for (i = 1; i < nvpe; i++) {
+ tcpervpe[i] += slop / (nvpe - 1);
+ if(slopslop && ((slopslop - (i - 1) > 0)))
+ tcpervpe[i]++;
+ }
+ } else if (vpe0limit > tcpervpe[0]) {
+ /* Increasing TC count - steal from others */
+ slop = vpe0limit - tcpervpe[0];
+ slopslop = slop % (nvpe - 1);
+ tcpervpe[0] = vpe0limit;
+ for (i = 1; i < nvpe; i++) {
+ tcpervpe[i] -= slop / (nvpe - 1);
+ if(slopslop && ((slopslop - (i - 1) > 0)))
+ tcpervpe[i]--;
+ }
+ }
+ }
/* Set up shared TLB */
smtc_configure_tlb();
if (vpe != 0)
printk(", ");
printk("VPE %d: TC", vpe);
- for (i = 0; i < tcpervpe; i++) {
+ for (i = 0; i < tcpervpe[vpe]; i++) {
/*
* TC 0 is bound to VPE 0 at reset,
* and is presumably executing this
* code. Leave it alone!
*/
if (tc != 0) {
- smtc_tc_setup(vpe,tc, cpu);
- cpu++;
- }
- printk(" %d", tc);
- tc++;
- }
- if (slop) {
- if (tc != 0) {
- smtc_tc_setup(vpe,tc, cpu);
+ smtc_tc_setup(vpe, tc, cpu);
cpu++;
}
printk(" %d", tc);
tc++;
- slop--;
}
if (vpe != 0) {
/*
if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
((read_c0_tcbind() & TCBIND_CURVPE)
!= cpu_data[smp_processor_id() - 1].vpe_id)){
- write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+ write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
}
local_irq_enable();
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
if (type == SMTC_CLOCK_TICK)
atomic_inc(&ipi_timer_latch[cpu]);
- /* If not on same VPE, enqueue and send cross-VPE interupt */
+ /* If not on same VPE, enqueue and send cross-VPE interrupt */
smtc_ipi_nq(&IPIQ[cpu], pipi);
LOCK_CORE_PRA();
settc(cpu_data[cpu].tc_id);
/* Return from interrupt should be enough to cause scheduler check */
}
-
static void ipi_call_interrupt(void)
{
/* Invoke generic function invocation code in smp.c */
return;
if (!cpu_has_vint)
- panic("SMTC Kernel requires Vectored Interupt support");
+ panic("SMTC Kernel requires Vectored Interrupt support");
set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
if (cpu_has_vtag_icache)
flush_icache_all();
/* Traverse all online CPUs (hack requires contigous range) */
- for (i = 0; i < num_online_cpus(); i++) {
+ for_each_online_cpu(i) {
/*
* We don't need to worry about our own CPU, nor those of
* CPUs who don't share our TLB.
/*
* SMTC shares the TLB within VPEs and possibly across all VPEs.
*/
- for (i = 0; i < num_online_cpus(); i++) {
+ for_each_online_cpu(i) {
if ((smtc_status & SMTC_TLB_SHARED) ||
(cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
cpu_context(i, mm) = asid_cache(i) = asid;