--- zzzz-none-000/linux-3.18.24/arch/mips/kernel/smp.c 2015-10-31 20:39:51.000000000 +0000 +++ rtl96-5690pro-762/linux-3.18.24/arch/mips/kernel/smp.c 2024-08-14 08:36:36.000000000 +0000 @@ -42,7 +42,9 @@ #include #include #include - +#ifdef PLAT_QEMU +extern int plat_qemu; +#endif volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ @@ -63,6 +65,13 @@ cpumask_t cpu_core_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_core_map); +/* + * A logcal cpu mask containing only one VPE per core to + * reduce the number of IPIs on large MT systems. + */ +cpumask_t cpu_foreign_map __read_mostly; +EXPORT_SYMBOL(cpu_foreign_map); + /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -103,6 +112,29 @@ } } +/* + * Calculate a new cpu_foreign_map mask whenever a + * new cpu appears or disappears. + */ +static inline void calculate_cpu_foreign_map(void) +{ + int i, k, core_present; + cpumask_t temp_foreign_map; + + /* Re-calculate the mask */ + for_each_online_cpu(i) { + core_present = 0; + for_each_cpu(k, &temp_foreign_map) + if (cpu_data[i].package == cpu_data[k].package && + cpu_data[i].core == cpu_data[k].core) + core_present = 1; + if (!core_present) + cpumask_set_cpu(i, &temp_foreign_map); + } + + cpumask_copy(&cpu_foreign_map, &temp_foreign_map); +} + struct plat_smp_ops *mp_ops; EXPORT_SYMBOL(mp_ops); @@ -146,8 +178,12 @@ set_cpu_sibling_map(cpu); set_cpu_core_map(cpu); - cpu_set(cpu, cpu_callin_map); + calculate_cpu_foreign_map(); + cpu_set(cpu, cpu_callin_map); +#ifdef PLAT_QEMU + if (!plat_qemu) +#endif synchronise_count_slave(cpu); /* @@ -173,13 +209,20 @@ static void stop_this_cpu(void *dummy) { /* - * Remove this CPU: + * Remove this CPU. Be a bit slow here and + * set the bits for every online CPU so we don't miss + * any IPI whilst taking this VPE down. */ + + cpumask_copy(&cpu_foreign_map, cpu_online_mask); + + /* Make it visible to every other CPU */ + smp_mb(); + set_cpu_online(smp_processor_id(), false); - for (;;) { - if (cpu_wait) - (*cpu_wait)(); /* Wait if available. */ - } + calculate_cpu_foreign_map(); + local_irq_disable(); + while (1); } void smp_send_stop(void) @@ -199,6 +242,7 @@ mp_ops->prepare_cpus(max_cpus); set_cpu_sibling_map(0); set_cpu_core_map(0); + calculate_cpu_foreign_map(); #ifndef CONFIG_HOTPLUG_CPU init_cpu_present(cpu_possible_mask); #endif @@ -222,7 +266,9 @@ */ while (!cpu_isset(cpu, cpu_callin_map)) udelay(100); - +#ifdef PLAT_QEMU + if (!plat_qemu) +#endif synchronise_count_master(cpu); return 0; }