/* * Resume all paused cpus. */ void cpu_resume_others(void) { __cpuset_t cpuset; CPUSET_CLEAR(cpus_resumed); CPUSET_ASSIGN(cpuset, cpus_paused); CPUSET_CLEAR(cpus_paused); /* CPUs awake on cpus_paused clear */ if (cpu_ipi_wait(&cpus_resumed, cpuset)) cpu_ipi_error("resume", cpus_resumed, cpuset); }
/* * Resume a single cpu */ void cpu_resume(int index) { CPUSET_CLEAR(cpus_resumed); CPUSET_DEL(cpus_paused, index); if (cpu_ipi_wait(&cpus_resumed, CPUSET_SINGLE(index))) cpu_ipi_error("resume", cpus_resumed, CPUSET_SINGLE(index)); }
/* * Resume all paused cpus. */ void mp_resume_cpus(void) { int i = 3; sparc64_cpuset_t cpuset; CPUSET_CLEAR(cpuset); /* XXX: gcc -Wuninitialized */ while (i-- > 0) { CPUSET_CLEAR(cpus_resumed); CPUSET_ASSIGN(cpuset, cpus_paused); membar_Sync(); CPUSET_CLEAR(cpus_paused); /* CPUs awake on cpus_paused clear */ if (!sparc64_ipi_wait(&cpus_resumed, cpuset)) return; } sparc64_ipi_error("resume", cpus_resumed, cpuset); }
/* * Initialize IPI machinery. */ void sparc64_ipi_init(void) { /* Clear all cpu sets. */ CPUSET_CLEAR(cpus_halted); CPUSET_CLEAR(cpus_spinning); CPUSET_CLEAR(cpus_paused); CPUSET_CLEAR(cpus_resumed); /* * Prepare cpu type dependent function pointers */ if (CPU_ISSUN4V) { smp_tlb_flush_pte_func = sparc64_ipi_flush_pte_sun4v; sparc64_ipi_dcache_flush_page_func = sparc64_ipi_dcache_flush_page_sun4v; } else if (CPU_IS_USIII_UP()) { smp_tlb_flush_pte_func = sparc64_ipi_flush_pte_usiii; sparc64_ipi_dcache_flush_page_func = sparc64_ipi_dcache_flush_page_usiii; } else { smp_tlb_flush_pte_func = sparc64_ipi_flush_pte_us; sparc64_ipi_dcache_flush_page_func = sparc64_ipi_dcache_flush_page_us; } if (CPU_ISSUN4V) sparc64_send_ipi = sparc64_send_ipi_sun4v; else sparc64_send_ipi = sparc64_send_ipi_sun4u; }
/* * Halt all cpus but ourselves. */ void mp_halt_cpus(void) { sparc64_cpuset_t cpumask, cpuset; struct cpu_info *ci; CPUSET_ASSIGN(cpuset, cpus_active); CPUSET_DEL(cpuset, cpu_number()); CPUSET_ASSIGN(cpumask, cpuset); CPUSET_SUB(cpuset, cpus_halted); if (CPUSET_EMPTY(cpuset)) return; CPUSET_CLEAR(cpus_spinning); sparc64_multicast_ipi(cpuset, sparc64_ipi_halt, 0, 0); if (sparc64_ipi_wait(&cpus_halted, cpumask)) sparc64_ipi_error("halt", cpumask, cpus_halted); /* * Depending on available firmware methods, other cpus will * either shut down themselfs, or spin and wait for us to * stop them. */ if (CPUSET_EMPTY(cpus_spinning)) { /* give other cpus a few cycles to actually power down */ delay(10000); return; } /* there are cpus spinning - shut them down if we can */ if (prom_has_stop_other()) { for (ci = cpus; ci != NULL; ci = ci->ci_next) { if (!CPUSET_HAS(cpus_spinning, ci->ci_index)) continue; prom_stop_other(ci->ci_cpuid); } } }