static long unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
static long unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
-static cpumask_t fast_misaligned_access;
-
static u64 __maybe_unused
measure_cycles(void (*func)(void *dst, const void *src, size_t len),
void *dst, void *src, size_t len)
* Set the value of fast_misaligned_access of a CPU. These operations
* are atomic to avoid race conditions.
*/
- if (ret) {
+ if (ret)
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST;
- cpumask_set_cpu(cpu, &fast_misaligned_access);
- } else {
+ else
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW;
- cpumask_clear_cpu(cpu, &fast_misaligned_access);
- }
return 0;
}
DEFINE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);
-static void modify_unaligned_access_branches(cpumask_t *mask, int weight)
+static void modify_unaligned_access_branches(const cpumask_t *mask)
{
- if (cpumask_weight(mask) == weight)
+ bool fast = true;
+ int cpu;
+
+ for_each_cpu(cpu, mask) {
+ if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) {
+ fast = false;
+ break;
+ }
+ }
+
+ if (fast)
static_branch_enable_cpuslocked(&fast_unaligned_access_speed_key);
else
static_branch_disable_cpuslocked(&fast_unaligned_access_speed_key);
}
-static void set_unaligned_access_static_branches_except_cpu(int cpu)
-{
- /*
- * Same as set_unaligned_access_static_branches, except excludes the
- * given CPU from the result. When a CPU is hotplugged into an offline
- * state, this function is called before the CPU is set to offline in
- * the cpumask, and thus the CPU needs to be explicitly excluded.
- */
-
- cpumask_t fast_except_me;
-
- cpumask_and(&fast_except_me, &fast_misaligned_access, cpu_online_mask);
- cpumask_clear_cpu(cpu, &fast_except_me);
-
- modify_unaligned_access_branches(&fast_except_me, num_online_cpus() - 1);
-}
-
-static void set_unaligned_access_static_branches(void)
-{
- /*
- * This will be called after check_unaligned_access_all_cpus so the
- * result of unaligned access speed for all CPUs will be available.
- *
- * To avoid the number of online cpus changing between reading
- * cpu_online_mask and calling num_online_cpus, cpus_read_lock must be
- * held before calling this function.
- */
-
- cpumask_t fast_and_online;
-
- cpumask_and(&fast_and_online, &fast_misaligned_access, cpu_online_mask);
-
- modify_unaligned_access_branches(&fast_and_online, num_online_cpus());
-}
-
static int riscv_online_cpu(unsigned int cpu)
{
int ret = cpu_online_unaligned_access_init(cpu);
#endif
exit:
- set_unaligned_access_static_branches();
+ modify_unaligned_access_branches(cpu_online_mask);
return 0;
}
static int riscv_offline_cpu(unsigned int cpu)
{
- set_unaligned_access_static_branches_except_cpu(cpu);
+ cpumask_t mask;
+
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(cpu, &mask);
+
+ modify_unaligned_access_branches(&mask);
return 0;
}
riscv_online_cpu_vec, NULL);
cpus_read_lock();
- set_unaligned_access_static_branches();
+ modify_unaligned_access_branches(cpu_online_mask);
cpus_read_unlock();
return 0;