Skip to content

Commit 241c32d

Browse files
committed
Merge tag 'riscv-for-linus-5.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V fixes from Palmer Dabbelt: "A set of three fixes, all aimed at fixing some fallout from the recent sparse hart ID support" * tag 'riscv-for-linus-5.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: RISC-V: Fix IPI/RFENCE hmask on non-monotonic hartid ordering RISC-V: Fix handling of empty cpu masks RISC-V: Fix hartid mask handling for hartid 31 and up
2 parents 7993e65 + 5feef64 commit 241c32d

1 file changed

Lines changed: 47 additions & 25 deletions

File tree

arch/riscv/kernel/sbi.c

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
66
*/
77

8+
#include <linux/bits.h>
89
#include <linux/init.h>
910
#include <linux/pm.h>
1011
#include <linux/reboot.h>
@@ -85,7 +86,7 @@ static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mas
8586
pr_warn("Unable to send any request to hartid > BITS_PER_LONG for SBI v0.1\n");
8687
break;
8788
}
88-
hmask |= 1 << hartid;
89+
hmask |= BIT(hartid);
8990
}
9091

9192
return hmask;
@@ -160,7 +161,7 @@ static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
160161
{
161162
unsigned long hart_mask;
162163

163-
if (!cpu_mask)
164+
if (!cpu_mask || cpumask_empty(cpu_mask))
164165
cpu_mask = cpu_online_mask;
165166
hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
166167

@@ -176,7 +177,7 @@ static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
176177
int result = 0;
177178
unsigned long hart_mask;
178179

179-
if (!cpu_mask)
180+
if (!cpu_mask || cpumask_empty(cpu_mask))
180181
cpu_mask = cpu_online_mask;
181182
hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
182183

@@ -249,26 +250,37 @@ static void __sbi_set_timer_v02(uint64_t stime_value)
249250

250251
static int __sbi_send_ipi_v02(const struct cpumask *cpu_mask)
251252
{
252-
unsigned long hartid, cpuid, hmask = 0, hbase = 0;
253+
unsigned long hartid, cpuid, hmask = 0, hbase = 0, htop = 0;
253254
struct sbiret ret = {0};
254255
int result;
255256

256-
if (!cpu_mask)
257+
if (!cpu_mask || cpumask_empty(cpu_mask))
257258
cpu_mask = cpu_online_mask;
258259

259260
for_each_cpu(cpuid, cpu_mask) {
260261
hartid = cpuid_to_hartid_map(cpuid);
261-
if (hmask && ((hbase + BITS_PER_LONG) <= hartid)) {
262-
ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
263-
hmask, hbase, 0, 0, 0, 0);
264-
if (ret.error)
265-
goto ecall_failed;
266-
hmask = 0;
267-
hbase = 0;
262+
if (hmask) {
263+
if (hartid + BITS_PER_LONG <= htop ||
264+
hbase + BITS_PER_LONG <= hartid) {
265+
ret = sbi_ecall(SBI_EXT_IPI,
266+
SBI_EXT_IPI_SEND_IPI, hmask,
267+
hbase, 0, 0, 0, 0);
268+
if (ret.error)
269+
goto ecall_failed;
270+
hmask = 0;
271+
} else if (hartid < hbase) {
272+
/* shift the mask to fit lower hartid */
273+
hmask <<= hbase - hartid;
274+
hbase = hartid;
275+
}
268276
}
269-
if (!hmask)
277+
if (!hmask) {
270278
hbase = hartid;
271-
hmask |= 1UL << (hartid - hbase);
279+
htop = hartid;
280+
} else if (hartid > htop) {
281+
htop = hartid;
282+
}
283+
hmask |= BIT(hartid - hbase);
272284
}
273285

274286
if (hmask) {
@@ -344,25 +356,35 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
344356
unsigned long start, unsigned long size,
345357
unsigned long arg4, unsigned long arg5)
346358
{
347-
unsigned long hartid, cpuid, hmask = 0, hbase = 0;
359+
unsigned long hartid, cpuid, hmask = 0, hbase = 0, htop = 0;
348360
int result;
349361

350-
if (!cpu_mask)
362+
if (!cpu_mask || cpumask_empty(cpu_mask))
351363
cpu_mask = cpu_online_mask;
352364

353365
for_each_cpu(cpuid, cpu_mask) {
354366
hartid = cpuid_to_hartid_map(cpuid);
355-
if (hmask && ((hbase + BITS_PER_LONG) <= hartid)) {
356-
result = __sbi_rfence_v02_call(fid, hmask, hbase,
357-
start, size, arg4, arg5);
358-
if (result)
359-
return result;
360-
hmask = 0;
361-
hbase = 0;
367+
if (hmask) {
368+
if (hartid + BITS_PER_LONG <= htop ||
369+
hbase + BITS_PER_LONG <= hartid) {
370+
result = __sbi_rfence_v02_call(fid, hmask,
371+
hbase, start, size, arg4, arg5);
372+
if (result)
373+
return result;
374+
hmask = 0;
375+
} else if (hartid < hbase) {
376+
/* shift the mask to fit lower hartid */
377+
hmask <<= hbase - hartid;
378+
hbase = hartid;
379+
}
362380
}
363-
if (!hmask)
381+
if (!hmask) {
364382
hbase = hartid;
365-
hmask |= 1UL << (hartid - hbase);
383+
htop = hartid;
384+
} else if (hartid > htop) {
385+
htop = hartid;
386+
}
387+
hmask |= BIT(hartid - hbase);
366388
}
367389

368390
if (hmask) {

0 commit comments

Comments
 (0)