Commit c79c0a45 authored by Bibo Mao's avatar Bibo Mao Committed by Xianglai Li
Browse files

LoongArch/smp: Refine some ipi functions on LoongArch platform

LoongArch inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9BTWW



------------------------------------------

It is code refine about ipi handling on LoongArch platform, there are
three modifications.
1. Add generic function get_percpu_irq(), replacing some percpu irq
functions such as get_ipi_irq()/get_pmc_irq()/get_timer_irq() with
get_percpu_irq().

2. Change definition about parameter action called by function
loongson_send_ipi_single() and loongson_send_ipi_mask(), and it is
defined as decimal encoding format at ipi sender side. Normal decimal
encoding is used rather than binary bitmap encoding for ipi action, ipi
hw sender uses decimal encoding code, and ipi receiver will get binary
bitmap encoding, the ipi hw will convert it into bitmap in ipi message
buffer.

3. Add structure smp_ops on LoongArch platform so that pv ipi can be used
later.

Signed-off-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarXianglai Li <lixianglai@loongson.cn>
parent a3cf1794
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -12,6 +12,10 @@
extern void ack_bad_irq(unsigned int irq);
#define ack_bad_irq ack_bad_irq

enum ipi_msg_type {
	IPI_RESCHEDULE,
	IPI_CALL_FUNCTION,
};
#define NR_IPI	2

typedef struct {
+10 −1
Original line number Diff line number Diff line
@@ -119,9 +119,18 @@ extern struct fwnode_handle *liointc_handle;
extern struct fwnode_handle *pch_lpc_handle;
extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];

extern irqreturn_t loongson_ipi_interrupt(int irq, void *dev);
extern void fixup_irqs(void);

static inline int get_percpu_irq(int vector)
{
	struct irq_domain *d;

	d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
	if (d)
		return irq_create_mapping(d, vector);

	return -EINVAL;
}
#include <asm-generic/irq.h>

#endif /* _ASM_IRQ_H */
+15 −16
Original line number Diff line number Diff line
@@ -12,6 +12,13 @@
#include <linux/threads.h>
#include <linux/cpumask.h>

struct smp_ops {
	void (*init_ipi)(void);
	void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
	void (*send_ipi_single)(int cpu, unsigned int action);
};

extern struct smp_ops smp_ops;
extern int smp_num_siblings;
extern int num_processors;
extern int disabled_cpus;
@@ -24,8 +31,6 @@ void loongson_prepare_cpus(unsigned int max_cpus);
void loongson_boot_secondary(int cpu, struct task_struct *idle);
void loongson_init_secondary(void);
void loongson_smp_finish(void);
void loongson_send_ipi_single(int cpu, unsigned int action);
void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action);
#ifdef CONFIG_HOTPLUG_CPU
int loongson_cpu_disable(void);
void loongson_cpu_die(unsigned int cpu);
@@ -59,9 +64,12 @@ extern int __cpu_logical_map[NR_CPUS];

#define cpu_physical_id(cpu)	cpu_logical_map(cpu)

#define SMP_BOOT_CPU		0x1
#define SMP_RESCHEDULE		0x2
#define SMP_CALL_FUNCTION	0x4
#define ACTION_BOOT_CPU	0
#define ACTION_RESCHEDULE	1
#define ACTION_CALL_FUNCTION	2
#define SMP_BOOT_CPU		BIT(ACTION_BOOT_CPU)
#define SMP_RESCHEDULE		BIT(ACTION_RESCHEDULE)
#define SMP_CALL_FUNCTION	BIT(ACTION_CALL_FUNCTION)

struct secondary_data {
	unsigned long stack;
@@ -71,7 +79,8 @@ extern struct secondary_data cpuboot_data;

extern asmlinkage void smpboot_entry(void);
extern asmlinkage void start_secondary(void);

extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern void calculate_cpu_foreign_map(void);

/*
@@ -79,16 +88,6 @@ extern void calculate_cpu_foreign_map(void);
 */
extern void show_ipi_list(struct seq_file *p, int prec);

static inline void arch_send_call_function_single_ipi(int cpu)
{
	loongson_send_ipi_single(cpu, SMP_CALL_FUNCTION);
}

static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
	loongson_send_ipi_mask(mask, SMP_CALL_FUNCTION);
}

#ifdef CONFIG_HOTPLUG_CPU
static inline int __cpu_disable(void)
{
+1 −21
Original line number Diff line number Diff line
@@ -86,16 +86,6 @@ static void __init init_vec_parent_group(void)
	acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse);
}

static int __init get_ipi_irq(void)
{
	struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);

	if (d)
		return irq_create_mapping(d, INT_IPI);

	return -EINVAL;
}

#ifdef CONFIG_HOTPLUG_CPU
static void handle_irq_affinity(void)
{
@@ -135,10 +125,6 @@ void fixup_irqs(void)
void __init init_IRQ(void)
{
	int i, ret;
#ifdef CONFIG_SMP
	int r, ipi_irq;
	static int ipi_dummy_dev;
#endif
	unsigned int order = get_order(IRQ_STACK_SIZE);
	struct page *page;

@@ -154,13 +140,7 @@ void __init init_IRQ(void)
		irqchip_init();
	}
#ifdef CONFIG_SMP
	ipi_irq = get_ipi_irq();
	if (ipi_irq < 0)
		panic("IPI IRQ mapping failed\n");
	irq_set_percpu_devid(ipi_irq);
	r = request_percpu_irq(ipi_irq, loongson_ipi_interrupt, "IPI", &ipi_dummy_dev);
	if (r < 0)
		panic("IPI IRQ request failed\n");
	smp_ops.init_ipi();
#endif

	for (i = 0; i < NR_IRQS; i++)
+2 −12
Original line number Diff line number Diff line
@@ -456,16 +456,6 @@ static void loongarch_pmu_disable(struct pmu *pmu)
static DEFINE_MUTEX(pmu_reserve_mutex);
static atomic_t active_events = ATOMIC_INIT(0);

static int get_pmc_irq(void)
{
	struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);

	if (d)
		return irq_create_mapping(d, INT_PCOV);

	return -EINVAL;
}

static void reset_counters(void *arg);
static int __hw_perf_event_init(struct perf_event *event);

@@ -473,7 +463,7 @@ static void hw_perf_event_destroy(struct perf_event *event)
{
	if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
		on_each_cpu(reset_counters, NULL, 1);
		free_irq(get_pmc_irq(), &loongarch_pmu);
		free_irq(get_percpu_irq(INT_PCOV), &loongarch_pmu);
		mutex_unlock(&pmu_reserve_mutex);
	}
}
@@ -562,7 +552,7 @@ static int loongarch_pmu_event_init(struct perf_event *event)
	if (event->cpu >= 0 && !cpu_online(event->cpu))
		return -ENODEV;

	irq = get_pmc_irq();
	irq = get_percpu_irq(INT_PCOV);
	flags = IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_SHARED;
	if (!atomic_inc_not_zero(&active_events)) {
		mutex_lock(&pmu_reserve_mutex);
Loading