mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
1139aeb1c5
As of commit966a967116
("smp: Avoid using two cache lines for struct call_single_data"), the smp code prefers 32-byte aligned call_single_data objects for performance reasons, but the block layer includes an instance of this structure in the main 'struct request' that is more senstive to size than to performance here, see4ccafe0320
("block: unalign call_single_data in struct request"). The result is a violation of the calling conventions that clang correctly points out: block/blk-mq.c:630:39: warning: passing 8-byte aligned argument to 32-byte aligned parameter 2 of 'smp_call_function_single_async' may result in an unaligned pointer access [-Walign-mismatch] smp_call_function_single_async(cpu, &rq->csd); It does seem that the usage of the call_single_data without cache line alignment should still be allowed by the smp code, so just change the function prototype so it accepts both, but leave the default alignment unchanged for the other users. This seems better to me than adding a local hack to shut up an otherwise correct warning in the caller. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Jens Axboe <axboe@kernel.dk> Link: https://lkml.kernel.org/r/20210505211300.3174456-1-arnd@kernel.org
74 lines
1.5 KiB
C
74 lines
1.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Uniprocessor-only support functions. The counterpart to kernel/smp.c
|
|
*/
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/export.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/hypervisor.h>
|
|
|
|
int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
|
|
int wait)
|
|
{
|
|
unsigned long flags;
|
|
|
|
if (cpu != 0)
|
|
return -ENXIO;
|
|
|
|
local_irq_save(flags);
|
|
func(info);
|
|
local_irq_restore(flags);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(smp_call_function_single);
|
|
|
|
int smp_call_function_single_async(int cpu, struct __call_single_data *csd)
|
|
{
|
|
unsigned long flags;
|
|
|
|
local_irq_save(flags);
|
|
csd->func(csd->info);
|
|
local_irq_restore(flags);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(smp_call_function_single_async);
|
|
|
|
/*
|
|
* Preemption is disabled here to make sure the cond_func is called under the
|
|
* same condtions in UP and SMP.
|
|
*/
|
|
void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func,
|
|
void *info, bool wait, const struct cpumask *mask)
|
|
{
|
|
unsigned long flags;
|
|
|
|
preempt_disable();
|
|
if ((!cond_func || cond_func(0, info)) && cpumask_test_cpu(0, mask)) {
|
|
local_irq_save(flags);
|
|
func(info);
|
|
local_irq_restore(flags);
|
|
}
|
|
preempt_enable();
|
|
}
|
|
EXPORT_SYMBOL(on_each_cpu_cond_mask);
|
|
|
|
int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, bool phys)
|
|
{
|
|
int ret;
|
|
|
|
if (cpu != 0)
|
|
return -ENXIO;
|
|
|
|
if (phys)
|
|
hypervisor_pin_vcpu(0);
|
|
ret = func(par);
|
|
if (phys)
|
|
hypervisor_pin_vcpu(-1);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(smp_call_on_cpu);
|