]> www.infradead.org Git - users/hch/block.git/commitdiff
LoongArch/smp: Refine some ipi functions on LoongArch platform
authorBibo Mao <maobibo@loongson.cn>
Mon, 6 May 2024 14:00:46 +0000 (22:00 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Mon, 6 May 2024 14:00:46 +0000 (22:00 +0800)
Refine the 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 a 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: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/hardirq.h
arch/loongarch/include/asm/irq.h
arch/loongarch/include/asm/smp.h
arch/loongarch/kernel/irq.c
arch/loongarch/kernel/perf_event.c
arch/loongarch/kernel/smp.c
arch/loongarch/kernel/time.c

index 0ef3b18f89803708d6e8a96b37c9ff037cc2e264..08eb72e01b1a7298ed3b5d5b19e9de17f457e15b 100644 (file)
@@ -14,6 +14,11 @@ extern void ack_bad_irq(unsigned int irq);
 
 #define NR_IPI 2
 
+enum ipi_msg_type {
+       IPI_RESCHEDULE,
+       IPI_CALL_FUNCTION,
+};
+
 typedef struct {
        unsigned int ipi_irqs[NR_IPI];
        unsigned int __softirq_pending;
index 218b4da0ea90d012199fe65f47eceae810a0a300..480418bc5071a5ebba50192744fe0be64b719d32 100644 (file)
@@ -117,7 +117,16 @@ 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);
+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>
 
index f81e5f01d61905f5b8d7da4786ba512258381acd..1c51bdf3516af5133e56f4d8da7b3510afdb91aa 100644 (file)
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 
+struct smp_ops {
+       void (*init_ipi)(void);
+       void (*send_ipi_single)(int cpu, unsigned int action);
+       void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
+};
+extern struct smp_ops mp_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;
@@ -81,12 +89,12 @@ 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);
+       mp_ops.send_ipi_single(cpu, ACTION_CALL_FUNCTION);
 }
 
 static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-       loongson_send_ipi_mask(mask, SMP_CALL_FUNCTION);
+       mp_ops.send_ipi_mask(mask, ACTION_CALL_FUNCTION);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index 883e5066ae445fa157c74fc9eb65939a5770f159..dcb1faf2c2b7e9d0195cdce32e54afc74b66893e 100644 (file)
@@ -87,23 +87,9 @@ 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;
-}
-
 void __init init_IRQ(void)
 {
        int i;
-#ifdef CONFIG_SMP
-       int r, ipi_irq;
-       static int ipi_dummy_dev;
-#endif
        unsigned int order = get_order(IRQ_STACK_SIZE);
        struct page *page;
 
@@ -113,13 +99,7 @@ void __init init_IRQ(void)
        init_vec_parent_group();
        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");
+       mp_ops.init_ipi();
 #endif
 
        for (i = 0; i < NR_IRQS; i++)
index cac7cba81b65f791cf5d3379dfda2daca01814ec..f86a4b838dd78ef1e1368e9665ec0082328ce6b5 100644 (file)
@@ -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);
index aabee0b280fe5f43a70d8a1091e6268a37d701e9..15b75e671bcd1deda85fe21b7bdce7a6f07ffce4 100644 (file)
@@ -66,11 +66,6 @@ static cpumask_t cpu_core_setup_map;
 struct secondary_data cpuboot_data;
 static DEFINE_PER_CPU(int, cpu_state);
 
-enum ipi_msg_type {
-       IPI_RESCHEDULE,
-       IPI_CALL_FUNCTION,
-};
-
 static const char *ipi_types[NR_IPI] __tracepoint_string = {
        [IPI_RESCHEDULE] = "Rescheduling interrupts",
        [IPI_CALL_FUNCTION] = "Function call interrupts",
@@ -190,24 +185,19 @@ static u32 ipi_read_clear(int cpu)
 
 static void ipi_write_action(int cpu, u32 action)
 {
-       unsigned int irq = 0;
-
-       while ((irq = ffs(action))) {
-               uint32_t val = IOCSR_IPI_SEND_BLOCKING;
+       uint32_t val;
 
-               val |= (irq - 1);
-               val |= (cpu << IOCSR_IPI_SEND_CPU_SHIFT);
-               iocsr_write32(val, LOONGARCH_IOCSR_IPI_SEND);
-               action &= ~BIT(irq - 1);
-       }
+       val = IOCSR_IPI_SEND_BLOCKING | action;
+       val |= (cpu << IOCSR_IPI_SEND_CPU_SHIFT);
+       iocsr_write32(val, LOONGARCH_IOCSR_IPI_SEND);
 }
 
-void loongson_send_ipi_single(int cpu, unsigned int action)
+static void loongson_send_ipi_single(int cpu, unsigned int action)
 {
        ipi_write_action(cpu_logical_map(cpu), (u32)action);
 }
 
-void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+static void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 {
        unsigned int i;
 
@@ -222,11 +212,11 @@ void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action)
  */
 void arch_smp_send_reschedule(int cpu)
 {
-       loongson_send_ipi_single(cpu, SMP_RESCHEDULE);
+       mp_ops.send_ipi_single(cpu, ACTION_RESCHEDULE);
 }
 EXPORT_SYMBOL_GPL(arch_smp_send_reschedule);
 
-irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
+static irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
 {
        unsigned int action;
        unsigned int cpu = smp_processor_id();
@@ -246,6 +236,26 @@ irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static void loongson_init_ipi(void)
+{
+       int r, ipi_irq;
+
+       ipi_irq = get_percpu_irq(INT_IPI);
+       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", &irq_stat);
+       if (r < 0)
+               panic("IPI IRQ request failed\n");
+}
+
+struct smp_ops mp_ops = {
+       .init_ipi               = loongson_init_ipi,
+       .send_ipi_single        = loongson_send_ipi_single,
+       .send_ipi_mask          = loongson_send_ipi_mask,
+};
+
 static void __init fdt_smp_setup(void)
 {
 #ifdef CONFIG_OF
@@ -323,7 +333,7 @@ void loongson_boot_secondary(int cpu, struct task_struct *idle)
 
        csr_mail_send(entry, cpu_logical_map(cpu), 0);
 
-       loongson_send_ipi_single(cpu, SMP_BOOT_CPU);
+       loongson_send_ipi_single(cpu, ACTION_BOOT_CPU);
 }
 
 /*
index e7015f7b70e37c4cabf736512c50a998455bbdf9..fd5354f9be7c32b128e242a774677d6a09415034 100644 (file)
@@ -123,16 +123,6 @@ void sync_counter(void)
        csr_write64(init_offset, LOONGARCH_CSR_CNTC);
 }
 
-static int get_timer_irq(void)
-{
-       struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY);
-
-       if (d)
-               return irq_create_mapping(d, INT_TI);
-
-       return -EINVAL;
-}
-
 int constant_clockevent_init(void)
 {
        unsigned int cpu = smp_processor_id();
@@ -142,7 +132,7 @@ int constant_clockevent_init(void)
        static int irq = 0, timer_irq_installed = 0;
 
        if (!timer_irq_installed) {
-               irq = get_timer_irq();
+               irq = get_percpu_irq(INT_TI);
                if (irq < 0)
                        pr_err("Failed to map irq %d (timer)\n", irq);
        }