Commit 3ab33d6d authored by Srikar Dronamraju's avatar Srikar Dronamraju Committed by Michael Ellerman

powerpc/smp: Optimize update_mask_by_l2

All threads of a SMT4 core can either be part of this CPU's l2-cache
mask or not related to this CPU l2-cache mask. Use this relation to
reduce the number of iterations needed to find all the CPUs that share
the same l2-cache.

Use a temporary mask to iterate through the CPUs that may share l2_cache
mask. Also instead of setting one CPU at a time into cpu_l2_cache_mask,
copy the SMT4/sub mask at one shot.
Signed-off-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200921095653.9701-10-srikar@linux.vnet.ibm.com
parent 375370a1
...@@ -670,6 +670,28 @@ static void set_cpus_unrelated(int i, int j, ...@@ -670,6 +670,28 @@ static void set_cpus_unrelated(int i, int j,
} }
#endif #endif
/*
* Extends set_cpus_related. Instead of setting one CPU at a time in
* dstmask, set srcmask at oneshot. dstmask should be super set of srcmask.
*/
static void or_cpumasks_related(int i, int j, struct cpumask *(*srcmask)(int),
struct cpumask *(*dstmask)(int))
{
struct cpumask *mask;
int k;
mask = srcmask(j);
for_each_cpu(k, srcmask(i))
cpumask_or(dstmask(k), dstmask(k), mask);
if (i == j)
return;
mask = srcmask(i);
for_each_cpu(k, srcmask(j))
cpumask_or(dstmask(k), dstmask(k), mask);
}
/* /*
* parse_thread_groups: Parses the "ibm,thread-groups" device tree * parse_thread_groups: Parses the "ibm,thread-groups" device tree
* property for the CPU device node @dn and stores * property for the CPU device node @dn and stores
...@@ -1220,7 +1242,9 @@ static struct device_node *cpu_to_l2cache(int cpu) ...@@ -1220,7 +1242,9 @@ static struct device_node *cpu_to_l2cache(int cpu)
static bool update_mask_by_l2(int cpu) static bool update_mask_by_l2(int cpu)
{ {
struct cpumask *(*submask_fn)(int) = cpu_sibling_mask;
struct device_node *l2_cache, *np; struct device_node *l2_cache, *np;
cpumask_var_t mask;
int i; int i;
l2_cache = cpu_to_l2cache(cpu); l2_cache = cpu_to_l2cache(cpu);
...@@ -1240,22 +1264,37 @@ static bool update_mask_by_l2(int cpu) ...@@ -1240,22 +1264,37 @@ static bool update_mask_by_l2(int cpu)
return false; return false;
} }
cpumask_set_cpu(cpu, cpu_l2_cache_mask(cpu)); alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu));
for_each_cpu_and(i, cpu_online_mask, cpu_cpu_mask(cpu)) { cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu));
if (has_big_cores)
submask_fn = cpu_smallcore_mask;
/* Update l2-cache mask with all the CPUs that are part of submask */
or_cpumasks_related(cpu, cpu, submask_fn, cpu_l2_cache_mask);
/* Skip all CPUs already part of current CPU l2-cache mask */
cpumask_andnot(mask, mask, cpu_l2_cache_mask(cpu));
for_each_cpu(i, mask) {
/* /*
* when updating the marks the current CPU has not been marked * when updating the marks the current CPU has not been marked
* online, but we need to update the cache masks * online, but we need to update the cache masks
*/ */
np = cpu_to_l2cache(i); np = cpu_to_l2cache(i);
if (!np)
continue;
if (np == l2_cache) /* Skip all CPUs already part of current CPU l2-cache */
set_cpus_related(cpu, i, cpu_l2_cache_mask); if (np == l2_cache) {
or_cpumasks_related(cpu, i, submask_fn, cpu_l2_cache_mask);
cpumask_andnot(mask, mask, submask_fn(i));
} else {
cpumask_andnot(mask, mask, cpu_l2_cache_mask(i));
}
of_node_put(np); of_node_put(np);
} }
of_node_put(l2_cache); of_node_put(l2_cache);
free_cpumask_var(mask);
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment