diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2024-07-03 09:44:19 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2024-07-03 09:44:19 +1000 |
commit | b235fb14a7cc1e6057114edfddcca1cc720815a3 (patch) | |
tree | 73173a744e99321bd2fe4d0e6876dd680aa9f6b3 | |
parent | 9b50bb207eff8a971a237f868c5e1f17287e970e (diff) | |
parent | 8051b80fbeef27981e31ce69aec3508a914eda85 (diff) |
Merge branch 'loongarch-next' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
-rw-r--r-- | arch/loongarch/include/asm/addrspace.h | 4 | ||||
-rw-r--r-- | arch/loongarch/include/asm/hardirq.h | 3 | ||||
-rw-r--r-- | arch/loongarch/include/asm/io.h | 10 | ||||
-rw-r--r-- | arch/loongarch/include/asm/irq_work.h | 10 | ||||
-rw-r--r-- | arch/loongarch/include/asm/loongarch.h | 10 | ||||
-rw-r--r-- | arch/loongarch/include/asm/smp.h | 2 | ||||
-rw-r--r-- | arch/loongarch/include/asm/stackframe.h | 11 | ||||
-rw-r--r-- | arch/loongarch/include/uapi/asm/unistd.h | 1 | ||||
-rw-r--r-- | arch/loongarch/kernel/acpi.c | 22 | ||||
-rw-r--r-- | arch/loongarch/kernel/head.S | 12 | ||||
-rw-r--r-- | arch/loongarch/kernel/paravirt.c | 6 | ||||
-rw-r--r-- | arch/loongarch/kernel/relocate.c | 26 | ||||
-rw-r--r-- | arch/loongarch/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/loongarch/kernel/smp.c | 21 | ||||
-rw-r--r-- | arch/loongarch/power/platform.c | 22 | ||||
-rw-r--r-- | arch/loongarch/power/suspend_asm.S | 8 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/loongarch.c | 2 |
17 files changed, 138 insertions, 36 deletions
diff --git a/arch/loongarch/include/asm/addrspace.h b/arch/loongarch/include/asm/addrspace.h index 7bd47d65bf7a..fe198b473f84 100644 --- a/arch/loongarch/include/asm/addrspace.h +++ b/arch/loongarch/include/asm/addrspace.h @@ -37,6 +37,10 @@ extern unsigned long vm_map_base; #define UNCACHE_BASE CSR_DMW0_BASE #endif +#ifndef WRITECOMBINE_BASE +#define WRITECOMBINE_BASE CSR_DMW2_BASE +#endif + #define DMW_PABITS 48 #define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1) diff --git a/arch/loongarch/include/asm/hardirq.h b/arch/loongarch/include/asm/hardirq.h index d41138abcf26..1d7feb719515 100644 --- a/arch/loongarch/include/asm/hardirq.h +++ b/arch/loongarch/include/asm/hardirq.h @@ -12,11 +12,12 @@ extern void ack_bad_irq(unsigned int irq); #define ack_bad_irq ack_bad_irq -#define NR_IPI 2 +#define NR_IPI 3 enum ipi_msg_type { IPI_RESCHEDULE, IPI_CALL_FUNCTION, + IPI_IRQ_WORK, }; typedef struct { diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h index c2f9979b2979..5e95a60df180 100644 --- a/arch/loongarch/include/asm/io.h +++ b/arch/loongarch/include/asm/io.h @@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size); static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size, unsigned long prot_val) { - if (prot_val & _CACHE_CC) + switch (prot_val & _CACHE_MASK) { + case _CACHE_CC: return (void __iomem *)(unsigned long)(CACHE_BASE + offset); - else + case _CACHE_SUC: return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset); + case _CACHE_WUC: + return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset); + default: + return NULL; + } } #define ioremap(offset, size) \ diff --git a/arch/loongarch/include/asm/irq_work.h b/arch/loongarch/include/asm/irq_work.h new file mode 100644 index 000000000000..d63076e9160d --- /dev/null +++ b/arch/loongarch/include/asm/irq_work.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LOONGARCH_IRQ_WORK_H +#define _ASM_LOONGARCH_IRQ_WORK_H + +static inline bool arch_irq_work_has_interrupt(void) +{ + return IS_ENABLED(CONFIG_SMP); +} + +#endif /* _ASM_LOONGARCH_IRQ_WORK_H */ diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index eb09adda54b7..c430df595376 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -877,7 +877,7 @@ #define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ #define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ -/* Direct Map window 0/1 */ +/* Direct Map window 0/1/2/3 */ #define CSR_DMW0_PLV0 _CONST64_(1 << 0) #define CSR_DMW0_VSEG _CONST64_(0x8000) #define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS) @@ -889,6 +889,14 @@ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0) +#define CSR_DMW2_PLV0 _CONST64_(1 << 0) +#define CSR_DMW2_MAT _CONST64_(2 << 4) +#define CSR_DMW2_VSEG _CONST64_(0xa000) +#define CSR_DMW2_BASE (CSR_DMW2_VSEG << DMW_PABITS) +#define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0) + +#define CSR_DMW3_INIT 0x0 + /* Performance Counter registers */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ diff --git a/arch/loongarch/include/asm/smp.h b/arch/loongarch/include/asm/smp.h index 278700cfee88..50db503f44e3 100644 --- a/arch/loongarch/include/asm/smp.h +++ b/arch/loongarch/include/asm/smp.h @@ -69,9 +69,11 @@ extern int __cpu_logical_map[NR_CPUS]; #define ACTION_BOOT_CPU 0 #define ACTION_RESCHEDULE 1 #define ACTION_CALL_FUNCTION 2 +#define ACTION_IRQ_WORK 3 #define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU) #define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE) #define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION) +#define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) struct secondary_data { unsigned long stack; diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index d9eafd3ee3d1..66736837085b 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -38,6 +38,17 @@ cfi_restore \reg \offset \docfi .endm + .macro SETUP_DMWINS temp + li.d \temp, CSR_DMW0_INIT # WUC, PLV0, 0x8000 xxxx xxxx xxxx + csrwr \temp, LOONGARCH_CSR_DMWIN0 + li.d \temp, CSR_DMW1_INIT # CAC, PLV0, 0x9000 xxxx xxxx xxxx + csrwr \temp, LOONGARCH_CSR_DMWIN1 + li.d \temp, CSR_DMW2_INIT # WUC, PLV0, 0xa000 xxxx xxxx xxxx + csrwr \temp, LOONGARCH_CSR_DMWIN2 + li.d \temp, CSR_DMW3_INIT # 0x0, unused + csrwr \temp, LOONGARCH_CSR_DMWIN3 + .endm + /* Jump to the runtime virtual address. */ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE diff --git a/arch/loongarch/include/uapi/asm/unistd.h b/arch/loongarch/include/uapi/asm/unistd.h index fcb668984f03..b344b1f91715 100644 --- a/arch/loongarch/include/uapi/asm/unistd.h +++ b/arch/loongarch/include/uapi/asm/unistd.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_CLONE3 diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 5cf59c617126..929a497c987e 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -57,15 +57,22 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) return ioremap_cache(phys, size); } +static int cpu_enumerated = 0; + #ifdef CONFIG_SMP static int set_processor_mask(u32 id, u32 flags) { - + int nr_cpus; int cpu, cpuid = id; - if (num_processors >= nr_cpu_ids) { - pr_warn(PREFIX "nr_cpus/possible_cpus limit of %i reached." - " processor 0x%x ignored.\n", nr_cpu_ids, cpuid); + if (!cpu_enumerated) + nr_cpus = NR_CPUS; + else + nr_cpus = nr_cpu_ids; + + if (num_processors >= nr_cpus) { + pr_warn(PREFIX "nr_cpus limit of %i reached." + " processor 0x%x ignored.\n", nr_cpus, cpuid); return -ENODEV; @@ -73,11 +80,13 @@ static int set_processor_mask(u32 id, u32 flags) if (cpuid == loongson_sysconf.boot_cpu_id) cpu = 0; else - cpu = cpumask_next_zero(-1, cpu_present_mask); + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); + + if (!cpu_enumerated) + set_cpu_possible(cpu, true); if (flags & ACPI_MADT_ENABLED) { num_processors++; - set_cpu_possible(cpu, true); set_cpu_present(cpu, true); __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; @@ -138,6 +147,7 @@ static void __init acpi_process_madt(void) acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, acpi_parse_eio_master, MAX_IO_PICS); + cpu_enumerated = 1; loongson_sysconf.nr_cpus = num_processors; } diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index 4677ea8fa8e9..fdb831dc64df 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); SYM_CODE_START(kernel_entry) # kernel entry point /* Config direct window and set PG */ - li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWINS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */ @@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry) * function after setting up the stack and tp registers. */ SYM_CODE_START(smpboot_entry) - li.d t0, CSR_DMW0_INIT # UC, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWINS t0 JUMP_VIRT_ADDR t0, t1 #ifdef CONFIG_PAGE_SIZE_4KB diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 1633ed4f692f..4272d2447445 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -2,6 +2,7 @@ #include <linux/export.h> #include <linux/types.h> #include <linux/interrupt.h> +#include <linux/irq_work.h> #include <linux/jump_label.h> #include <linux/kvm_para.h> #include <linux/static_call.h> @@ -97,6 +98,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev) info->ipi_irqs[IPI_CALL_FUNCTION]++; } + if (action & SMP_IRQ_WORK) { + irq_work_run(); + info->ipi_irqs[IPI_IRQ_WORK]++; + } + return IRQ_HANDLED; } diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c index 1acfa704c8d0..6834d627ff20 100644 --- a/arch/loongarch/kernel/relocate.c +++ b/arch/loongarch/kernel/relocate.c @@ -123,6 +123,32 @@ static inline __init bool kaslr_disabled(void) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) return true; +#ifdef CONFIG_HIBERNATION + str = strstr(builtin_cmdline, "nohibernate"); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return false; + + str = strstr(boot_command_line, "nohibernate"); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return false; + + str = strstr(builtin_cmdline, "noresume"); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return false; + + str = strstr(boot_command_line, "noresume"); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return false; + + str = strstr(builtin_cmdline, "resume="); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return true; + + str = strstr(boot_command_line, "resume="); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return true; +#endif + return false; } diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 3d048f1be143..0f0740f0be27 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -576,8 +576,10 @@ static void __init prefill_possible_map(void) for (i = 0; i < possible; i++) set_cpu_possible(i, true); - for (; i < NR_CPUS; i++) + for (; i < NR_CPUS; i++) { + set_cpu_present(i, false); set_cpu_possible(i, false); + } set_nr_cpu_ids(possible); } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 1436d2465939..ca405ab86aae 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -13,6 +13,7 @@ #include <linux/cpumask.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq_work.h> #include <linux/profile.h> #include <linux/seq_file.h> #include <linux/smp.h> @@ -70,6 +71,7 @@ static DEFINE_PER_CPU(int, cpu_state); static const char *ipi_types[NR_IPI] __tracepoint_string = { [IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_CALL_FUNCTION] = "Function call interrupts", + [IPI_IRQ_WORK] = "IRQ work interrupts", }; void show_ipi_list(struct seq_file *p, int prec) @@ -217,6 +219,13 @@ void arch_smp_send_reschedule(int cpu) } EXPORT_SYMBOL_GPL(arch_smp_send_reschedule); +#ifdef CONFIG_IRQ_WORK +void arch_irq_work_raise(void) +{ + mp_ops.send_ipi_single(smp_processor_id(), ACTION_IRQ_WORK); +} +#endif + static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) { unsigned int action; @@ -234,6 +243,11 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) per_cpu(irq_stat, cpu).ipi_irqs[IPI_CALL_FUNCTION]++; } + if (action & SMP_IRQ_WORK) { + irq_work_run(); + per_cpu(irq_stat, cpu).ipi_irqs[IPI_IRQ_WORK]++; + } + return IRQ_HANDLED; } @@ -271,11 +285,10 @@ static void __init fdt_smp_setup(void) if (cpuid >= nr_cpu_ids) continue; - if (cpuid == loongson_sysconf.boot_cpu_id) { + if (cpuid == loongson_sysconf.boot_cpu_id) cpu = 0; - } else { - cpu = cpumask_next_zero(-1, cpu_present_mask); - } + else + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); num_processors++; set_cpu_possible(cpu, true); diff --git a/arch/loongarch/power/platform.c b/arch/loongarch/power/platform.c index 3ea8e07aa225..4b5d82643c23 100644 --- a/arch/loongarch/power/platform.c +++ b/arch/loongarch/power/platform.c @@ -34,22 +34,34 @@ void enable_pci_wakeup(void) acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); } +static void default_suspend_addr(void) +{ + acpi_enter_sleep_state(ACPI_STATE_S3); +} + static int __init loongson3_acpi_suspend_init(void) { #ifdef CONFIG_ACPI acpi_status status; uint64_t suspend_addr = 0; - if (acpi_disabled || acpi_gbl_reduced_hardware) + if (acpi_disabled) + return 0; + + if (!acpi_gbl_reduced_hardware) + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); + + if (!acpi_sleep_state_supported(ACPI_STATE_S3)) return 0; - acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr); if (ACPI_FAILURE(status) || !suspend_addr) { - pr_err("ACPI S3 is not support!\n"); - return -1; + pr_info("ACPI S3 supported with hardware register default\n"); + loongson_sysconf.suspend_addr = (u64)default_suspend_addr; + } else { + pr_info("ACPI S3 supported with Loongson ACPI SADR extension\n"); + loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); } - loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); #endif return 0; } diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index e2fc3b4e31f0..9fe28d5a0270 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -66,18 +66,14 @@ SYM_FUNC_START(loongarch_suspend_enter) la.pcrel a0, loongarch_wakeup_start la.pcrel t0, loongarch_suspend_addr ld.d t0, t0, 0 - jirl a0, t0, 0 /* Call BIOS's STR sleep routine */ + jirl ra, t0, 0 /* Call BIOS's STR sleep routine */ /* * This is where we return upon wakeup. * Reload all of the registers and return. */ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL) - li.d t0, CSR_DMW0_INIT # UC, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWINS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */ diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index d0ef93551c44..3782d0a187d1 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, /* Config Direct Mapping */ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); + csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2); + csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image); |