Skip to content

Commit f3d8fa7

Browse files
bibo-maoMingcongBai
authored andcommitted
LoongArch/smp: Refine some ipi functions on LoongArch platform
LoongArch inclusion category: bugfix ------------------------------------------ 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: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Xianglai Li <lixianglai@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
1 parent f28ecf6 commit f3d8fa7

File tree

7 files changed

+72
-80
lines changed

7 files changed

+72
-80
lines changed

arch/loongarch/include/asm/hardirq.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
extern void ack_bad_irq(unsigned int irq);
1313
#define ack_bad_irq ack_bad_irq
1414

15+
enum ipi_msg_type {
16+
IPI_RESCHEDULE,
17+
IPI_CALL_FUNCTION,
18+
};
1519
#define NR_IPI 2
1620

1721
typedef struct {

arch/loongarch/include/asm/irq.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,18 @@ extern struct fwnode_handle *liointc_handle;
119119
extern struct fwnode_handle *pch_lpc_handle;
120120
extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
121121

122-
extern irqreturn_t loongson_ipi_interrupt(int irq, void *dev);
123122
extern void fixup_irqs(void);
124123

124+
static inline int get_percpu_irq(int vector)
125+
{
126+
struct irq_domain *d;
127+
128+
d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
129+
if (d)
130+
return irq_create_mapping(d, vector);
131+
132+
return -EINVAL;
133+
}
125134
#include <asm-generic/irq.h>
126135

127136
#endif /* _ASM_IRQ_H */

arch/loongarch/include/asm/smp.h

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
#include <linux/threads.h>
1313
#include <linux/cpumask.h>
1414

15+
struct smp_ops {
16+
void (*init_ipi)(void);
17+
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
18+
void (*send_ipi_single)(int cpu, unsigned int action);
19+
};
20+
21+
extern struct smp_ops smp_ops;
1522
extern int smp_num_siblings;
1623
extern int num_processors;
1724
extern int disabled_cpus;
@@ -24,8 +31,6 @@ void loongson_prepare_cpus(unsigned int max_cpus);
2431
void loongson_boot_secondary(int cpu, struct task_struct *idle);
2532
void loongson_init_secondary(void);
2633
void loongson_smp_finish(void);
27-
void loongson_send_ipi_single(int cpu, unsigned int action);
28-
void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action);
2934
#ifdef CONFIG_HOTPLUG_CPU
3035
int loongson_cpu_disable(void);
3136
void loongson_cpu_die(unsigned int cpu);
@@ -59,9 +64,12 @@ extern int __cpu_logical_map[NR_CPUS];
5964

6065
#define cpu_physical_id(cpu) cpu_logical_map(cpu)
6166

62-
#define SMP_BOOT_CPU 0x1
63-
#define SMP_RESCHEDULE 0x2
64-
#define SMP_CALL_FUNCTION 0x4
67+
#define ACTION_BOOT_CPU 0
68+
#define ACTION_RESCHEDULE 1
69+
#define ACTION_CALL_FUNCTION 2
70+
#define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU)
71+
#define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE)
72+
#define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION)
6573

6674
struct secondary_data {
6775
unsigned long stack;
@@ -71,24 +79,15 @@ extern struct secondary_data cpuboot_data;
7179

7280
extern asmlinkage void smpboot_entry(void);
7381
extern asmlinkage void start_secondary(void);
74-
82+
extern void arch_send_call_function_single_ipi(int cpu);
83+
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
7584
extern void calculate_cpu_foreign_map(void);
7685

7786
/*
7887
* Generate IPI list text
7988
*/
8089
extern void show_ipi_list(struct seq_file *p, int prec);
8190

82-
static inline void arch_send_call_function_single_ipi(int cpu)
83-
{
84-
loongson_send_ipi_single(cpu, SMP_CALL_FUNCTION);
85-
}
86-
87-
static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
88-
{
89-
loongson_send_ipi_mask(mask, SMP_CALL_FUNCTION);
90-
}
91-
9291
#ifdef CONFIG_HOTPLUG_CPU
9392
static inline int __cpu_disable(void)
9493
{

arch/loongarch/kernel/irq.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,6 @@ static void __init init_vec_parent_group(void)
8686
acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse);
8787
}
8888

89-
static int __init get_ipi_irq(void)
90-
{
91-
struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
92-
93-
if (d)
94-
return irq_create_mapping(d, INT_IPI);
95-
96-
return -EINVAL;
97-
}
98-
9989
#ifdef CONFIG_HOTPLUG_CPU
10090
static void handle_irq_affinity(void)
10191
{
@@ -135,10 +125,6 @@ void fixup_irqs(void)
135125
void __init init_IRQ(void)
136126
{
137127
int i, ret;
138-
#ifdef CONFIG_SMP
139-
int r, ipi_irq;
140-
static int ipi_dummy_dev;
141-
#endif
142128
unsigned int order = get_order(IRQ_STACK_SIZE);
143129
struct page *page;
144130

@@ -154,13 +140,7 @@ void __init init_IRQ(void)
154140
irqchip_init();
155141
}
156142
#ifdef CONFIG_SMP
157-
ipi_irq = get_ipi_irq();
158-
if (ipi_irq < 0)
159-
panic("IPI IRQ mapping failed\n");
160-
irq_set_percpu_devid(ipi_irq);
161-
r = request_percpu_irq(ipi_irq, loongson_ipi_interrupt, "IPI", &ipi_dummy_dev);
162-
if (r < 0)
163-
panic("IPI IRQ request failed\n");
143+
smp_ops.init_ipi();
164144
#endif
165145

166146
for (i = 0; i < NR_IRQS; i++)

arch/loongarch/kernel/perf_event.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -456,24 +456,14 @@ static void loongarch_pmu_disable(struct pmu *pmu)
456456
static DEFINE_MUTEX(pmu_reserve_mutex);
457457
static atomic_t active_events = ATOMIC_INIT(0);
458458

459-
static int get_pmc_irq(void)
460-
{
461-
struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
462-
463-
if (d)
464-
return irq_create_mapping(d, INT_PCOV);
465-
466-
return -EINVAL;
467-
}
468-
469459
static void reset_counters(void *arg);
470460
static int __hw_perf_event_init(struct perf_event *event);
471461

472462
static void hw_perf_event_destroy(struct perf_event *event)
473463
{
474464
if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
475465
on_each_cpu(reset_counters, NULL, 1);
476-
free_irq(get_pmc_irq(), &loongarch_pmu);
466+
free_irq(get_percpu_irq(INT_PCOV), &loongarch_pmu);
477467
mutex_unlock(&pmu_reserve_mutex);
478468
}
479469
}
@@ -562,7 +552,7 @@ static int loongarch_pmu_event_init(struct perf_event *event)
562552
if (event->cpu >= 0 && !cpu_online(event->cpu))
563553
return -ENODEV;
564554

565-
irq = get_pmc_irq();
555+
irq = get_percpu_irq(INT_PCOV);
566556
flags = IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_SHARED;
567557
if (!atomic_inc_not_zero(&active_events)) {
568558
mutex_lock(&pmu_reserve_mutex);

arch/loongarch/kernel/smp.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ static cpumask_t cpu_core_setup_map;
6767
struct secondary_data cpuboot_data;
6868
static DEFINE_PER_CPU(int, cpu_state);
6969

70-
enum ipi_msg_type {
71-
IPI_RESCHEDULE,
72-
IPI_CALL_FUNCTION,
73-
};
74-
7570
static const char *ipi_types[NR_IPI] __tracepoint_string = {
7671
[IPI_RESCHEDULE] = "Rescheduling interrupts",
7772
[IPI_CALL_FUNCTION] = "Function call interrupts",
@@ -191,43 +186,48 @@ static u32 ipi_read_clear(int cpu)
191186

192187
static void ipi_write_action(int cpu, u32 action)
193188
{
194-
unsigned int irq = 0;
195-
196-
while ((irq = ffs(action))) {
197-
uint32_t val = IOCSR_IPI_SEND_BLOCKING;
189+
uint32_t val;
198190

199-
val |= (irq - 1);
200-
val |= (cpu << IOCSR_IPI_SEND_CPU_SHIFT);
201-
iocsr_write32(val, LOONGARCH_IOCSR_IPI_SEND);
202-
action &= ~BIT(irq - 1);
203-
}
191+
val = IOCSR_IPI_SEND_BLOCKING | action;
192+
val |= (cpu << IOCSR_IPI_SEND_CPU_SHIFT);
193+
iocsr_write32(val, LOONGARCH_IOCSR_IPI_SEND);
204194
}
205195

206-
void loongson_send_ipi_single(int cpu, unsigned int action)
196+
static void loongson_send_ipi_single(int cpu, unsigned int action)
207197
{
208198
ipi_write_action(cpu_logical_map(cpu), (u32)action);
209199
}
210200

211-
void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action)
201+
static void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action)
212202
{
213203
unsigned int i;
214204

215205
for_each_cpu(i, mask)
216206
ipi_write_action(cpu_logical_map(i), (u32)action);
217207
}
218208

209+
void arch_send_call_function_single_ipi(int cpu)
210+
{
211+
smp_ops.send_ipi_single(cpu, ACTION_CALL_FUNCTION);
212+
}
213+
214+
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
215+
{
216+
smp_ops.send_ipi_mask(mask, ACTION_CALL_FUNCTION);
217+
}
218+
219219
/*
220220
* This function sends a 'reschedule' IPI to another CPU.
221221
* it goes straight through and wastes no time serializing
222222
* anything. Worst case is that we lose a reschedule ...
223223
*/
224224
void arch_smp_send_reschedule(int cpu)
225225
{
226-
loongson_send_ipi_single(cpu, SMP_RESCHEDULE);
226+
smp_ops.send_ipi_single(cpu, ACTION_RESCHEDULE);
227227
}
228228
EXPORT_SYMBOL_GPL(arch_smp_send_reschedule);
229229

230-
irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
230+
static irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
231231
{
232232
unsigned int action;
233233
unsigned int cpu = smp_processor_id();
@@ -247,6 +247,26 @@ irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
247247
return IRQ_HANDLED;
248248
}
249249

250+
static void loongson_init_ipi(void)
251+
{
252+
int r, ipi_irq;
253+
254+
ipi_irq = get_percpu_irq(INT_IPI);
255+
if (ipi_irq < 0)
256+
panic("IPI IRQ mapping failed\n");
257+
258+
irq_set_percpu_devid(ipi_irq);
259+
r = request_percpu_irq(ipi_irq, loongson_ipi_interrupt, "IPI", &irq_stat);
260+
if (r < 0)
261+
panic("IPI IRQ request failed\n");
262+
}
263+
264+
struct smp_ops smp_ops = {
265+
.init_ipi = loongson_init_ipi,
266+
.send_ipi_single = loongson_send_ipi_single,
267+
.send_ipi_mask = loongson_send_ipi_mask,
268+
};
269+
250270
static void __init fdt_smp_setup(void)
251271
{
252272
#ifdef CONFIG_OF
@@ -325,7 +345,7 @@ void loongson_boot_secondary(int cpu, struct task_struct *idle)
325345

326346
csr_mail_send(entry, cpu_logical_map(cpu), 0);
327347

328-
loongson_send_ipi_single(cpu, SMP_BOOT_CPU);
348+
loongson_send_ipi_single(cpu, ACTION_BOOT_CPU);
329349
}
330350

331351
/*

arch/loongarch/kernel/time.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,6 @@ void sync_counter(void)
123123
csr_write64(init_offset, LOONGARCH_CSR_CNTC);
124124
}
125125

126-
static int get_timer_irq(void)
127-
{
128-
struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
129-
130-
if (d)
131-
return irq_create_mapping(d, INT_TI);
132-
133-
return -EINVAL;
134-
}
135-
136126
int constant_clockevent_init(void)
137127
{
138128
unsigned int cpu = smp_processor_id();
@@ -142,7 +132,7 @@ int constant_clockevent_init(void)
142132
static int irq = 0, timer_irq_installed = 0;
143133

144134
if (!timer_irq_installed) {
145-
irq = get_timer_irq();
135+
irq = get_percpu_irq(INT_TI);
146136
if (irq < 0)
147137
pr_err("Failed to map irq %d (timer)\n", irq);
148138
}

0 commit comments

Comments
 (0)