drm/rockchip: vop2: Fix the windows switch between different layers
[drm/drm-misc.git] / arch / riscv / kernel / vdso / hwprobe.c
bloba158c029344f60c022e7565757ff44df7e3d89e5
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright 2023 Rivos, Inc
4 */
6 #include <linux/string.h>
7 #include <linux/types.h>
8 #include <vdso/datapage.h>
9 #include <vdso/helpers.h>
11 extern int riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
12 size_t cpusetsize, unsigned long *cpus,
13 unsigned int flags);
15 static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count,
16 size_t cpusetsize, unsigned long *cpus,
17 unsigned int flags)
19 const struct vdso_data *vd = __arch_get_vdso_data();
20 const struct arch_vdso_time_data *avd = &vd->arch_data;
21 bool all_cpus = !cpusetsize && !cpus;
22 struct riscv_hwprobe *p = pairs;
23 struct riscv_hwprobe *end = pairs + pair_count;
26 * Defer to the syscall for exotic requests. The vdso has answers
27 * stashed away only for the "all cpus" case. If all CPUs are
28 * homogeneous, then this function can handle requests for arbitrary
29 * masks.
31 if ((flags != 0) || (!all_cpus && !avd->homogeneous_cpus))
32 return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags);
34 /* This is something we can handle, fill out the pairs. */
35 while (p < end) {
36 if (riscv_hwprobe_key_is_valid(p->key)) {
37 p->value = avd->all_cpu_hwprobe_values[p->key];
39 } else {
40 p->key = -1;
41 p->value = 0;
44 p++;
47 return 0;
50 static int riscv_vdso_get_cpus(struct riscv_hwprobe *pairs, size_t pair_count,
51 size_t cpusetsize, unsigned long *cpus,
52 unsigned int flags)
54 const struct vdso_data *vd = __arch_get_vdso_data();
55 const struct arch_vdso_time_data *avd = &vd->arch_data;
56 struct riscv_hwprobe *p = pairs;
57 struct riscv_hwprobe *end = pairs + pair_count;
58 unsigned char *c = (unsigned char *)cpus;
59 bool empty_cpus = true;
60 bool clear_all = false;
61 int i;
63 if (!cpusetsize || !cpus)
64 return -EINVAL;
66 for (i = 0; i < cpusetsize; i++) {
67 if (c[i]) {
68 empty_cpus = false;
69 break;
73 if (empty_cpus || flags != RISCV_HWPROBE_WHICH_CPUS || !avd->homogeneous_cpus)
74 return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags);
76 while (p < end) {
77 if (riscv_hwprobe_key_is_valid(p->key)) {
78 struct riscv_hwprobe t = {
79 .key = p->key,
80 .value = avd->all_cpu_hwprobe_values[p->key],
83 if (!riscv_hwprobe_pair_cmp(&t, p))
84 clear_all = true;
85 } else {
86 clear_all = true;
87 p->key = -1;
88 p->value = 0;
90 p++;
93 if (clear_all) {
94 for (i = 0; i < cpusetsize; i++)
95 c[i] = 0;
98 return 0;
101 /* Add a prototype to avoid -Wmissing-prototypes warning. */
102 int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
103 size_t cpusetsize, unsigned long *cpus,
104 unsigned int flags);
106 int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
107 size_t cpusetsize, unsigned long *cpus,
108 unsigned int flags)
110 if (flags & RISCV_HWPROBE_WHICH_CPUS)
111 return riscv_vdso_get_cpus(pairs, pair_count, cpusetsize,
112 cpus, flags);
114 return riscv_vdso_get_values(pairs, pair_count, cpusetsize,
115 cpus, flags);