static void mpc85xx_smp_machine_kexec(struct kimage *image) { int timeout = INT_MAX; int i, num_cpus = num_present_cpus(); mpc85xx_smp_flush_dcache_kexec(image); if (image->type == KEXEC_TYPE_DEFAULT) smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) && ( timeout > 0 ) ) { timeout--; } if ( !timeout ) printk(KERN_ERR "Unable to bring down secondary cpu(s)"); for_each_online_cpu(i) { if ( i == smp_processor_id() ) continue; mpic_reset_core(i); } default_machine_kexec(image); }
static void mpc85xx_smp_machine_kexec(struct kimage *image) { int timeout = 2000; int i; set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); while ( (kexec_down_cpus != (num_online_cpus() - 1)) && ( timeout > 0 ) ) { timeout--; } if ( !timeout ) printk(KERN_ERR "Unable to bring down secondary cpu(s)"); for (i = 0; i < num_present_cpus(); i++) { if ( i == smp_processor_id() ) continue; mpic_reset_core(i); } default_machine_kexec(image); }
static int __cpuinit smp_85xx_kick_cpu(int nr) { unsigned long flags; const u64 *cpu_rel_addr; __iomem struct epapr_spin_table *spin_table; struct device_node *np; int hw_cpu = get_hard_smp_processor_id(nr); int ioremappable; int ret = 0; WARN_ON(nr < 0 || nr >= NR_CPUS); WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS); pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); np = of_get_cpu_node(nr, NULL); cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); if (cpu_rel_addr == NULL) { printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); return -ENOENT; } /* * A secondary core could be in a spinloop in the bootpage * (0xfffff000), somewhere in highmem, or somewhere in lowmem. * The bootpage and highmem can be accessed via ioremap(), but * we need to directly access the spinloop if its in lowmem. */ ioremappable = *cpu_rel_addr > virt_to_phys(high_memory); /* Map the spin table */ if (ioremappable) spin_table = ioremap(*cpu_rel_addr, sizeof(struct epapr_spin_table)); else spin_table = phys_to_virt(*cpu_rel_addr); local_irq_save(flags); #ifdef CONFIG_PPC32 #ifdef CONFIG_HOTPLUG_CPU /* Corresponding to generic_set_cpu_dead() */ generic_set_cpu_up(nr); if (system_state == SYSTEM_RUNNING) { out_be32(&spin_table->addr_l, 0); /* * We don't set the BPTR register here since it already points * to the boot page properly. */ mpic_reset_core(hw_cpu); /* wait until core is ready... */ if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1, 10000, 100)) { pr_err("%s: timeout waiting for core %d to reset\n", __func__, hw_cpu); ret = -ENOENT; goto out; } /* clear the acknowledge status */ __secondary_hold_acknowledge = -1; } #endif out_be32(&spin_table->pir, hw_cpu); out_be32(&spin_table->addr_l, __pa(__early_start)); if (!ioremappable) flush_dcache_range((ulong)spin_table, (ulong)spin_table + sizeof(struct epapr_spin_table)); /* Wait a bit for the CPU to ack. */ if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu, 10000, 100)) { pr_err("%s: timeout waiting for core %d to ack\n", __func__, hw_cpu); ret = -ENOENT; goto out; } out: #else smp_generic_kick_cpu(nr); out_be32(&spin_table->pir, hw_cpu); out_be64((u64 *)(&spin_table->addr_h), __pa((u64)*((unsigned long long *)generic_secondary_smp_init))); if (!ioremappable) flush_dcache_range((ulong)spin_table, (ulong)spin_table + sizeof(struct epapr_spin_table)); #endif local_irq_restore(flags); if (ioremappable) iounmap(spin_table); return ret; }