From 640191975102437a074ca72f7638d13bceb72eed Mon Sep 17 00:00:00 2001 From: wusheng Date: Fri, 25 Oct 2024 18:58:21 +0800 Subject: [PATCH 1/4] pci/quirks: LS7A2000 enable msi LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ38J -------------------------------- 7A2000 pcie of port H need to enable MSI when host bridge Signed-off-by: wusheng --- drivers/pci/quirks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 86a4930ff54ee..d4e34d2c8e383 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -383,6 +383,20 @@ static void quirk_tigerpoint_bm_sts(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); #endif +static void loongson_pcie_msi_quirk(struct pci_dev *dev) +{ + u16 val; + u16 class; + + class = dev->class >> 8; + if (class == PCI_CLASS_BRIDGE_HOST) { + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &val); + val |= PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, val); + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, 0x7a59, loongson_pcie_msi_quirk); + /* Chipsets where PCI->PCI transfers vanish or hang */ static void quirk_nopcipci(struct pci_dev *dev) { -- Gitee From 375d7f74f7099abf22f2c7e7235ce45a33f78110 Mon Sep 17 00:00:00 2001 From: Haowei Zheng Date: Fri, 25 Oct 2024 18:58:22 +0800 Subject: [PATCH 2/4] acpi: mcfg quirk: Increased multi-chip support for the 3C6000 LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ38J -------------------------------- After this, capable of supporting up to eight chips. Signed-off-by: Haowei Zheng --- arch/loongarch/include/asm/irq.h | 4 ++-- drivers/acpi/pci_mcfg.c | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 79f4c834ffe8b..b65f8ffc6a0e8 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -43,8 +43,8 @@ void spurious_interrupt(void); extern bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu); -#define MAX_IO_PICS 2 -#define NR_IRQS (64 + (256 * MAX_IO_PICS)) +#define MAX_IO_PICS 16 +#define NR_IRQS (64 + NR_VECTORS * (NR_CPUS + MAX_IO_PICS)) struct acpi_vector_group { int node; diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index 8c04e71ac544a..70ceb6905c0a3 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -185,6 +185,19 @@ static struct mcfg_fixup mcfg_quirks[] = { LOONGSON_ECAM_MCFG("LOONGSON", 0), LOONGSON_ECAM_MCFG("\0", 1), LOONGSON_ECAM_MCFG("LOONGSON", 1), + LOONGSON_ECAM_MCFG("\0", 2), + LOONGSON_ECAM_MCFG("LOONGSON", 2), + LOONGSON_ECAM_MCFG("\0", 3), + LOONGSON_ECAM_MCFG("LOONGSON", 3), + LOONGSON_ECAM_MCFG("\0", 4), + LOONGSON_ECAM_MCFG("LOONGSON", 4), + LOONGSON_ECAM_MCFG("\0", 5), + LOONGSON_ECAM_MCFG("LOONGSON", 5), + LOONGSON_ECAM_MCFG("\0", 6), + LOONGSON_ECAM_MCFG("LOONGSON", 6), + LOONGSON_ECAM_MCFG("\0", 7), + LOONGSON_ECAM_MCFG("LOONGSON", 7), + #endif /* LOONGARCH */ #ifdef CONFIG_SW64 -- Gitee From 1c1c00037eb689f81d98f269fbdf76fa178bb15d Mon Sep 17 00:00:00 2001 From: zhangtianyang Date: Fri, 25 Oct 2024 18:58:23 +0800 Subject: [PATCH 3/4] Loongarch: Dynamic enable writecombine LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ38J -------------------------------- Signed-off-by: zhangtianyang --- arch/loongarch/kernel/setup.c | 28 ++++++++++++++++++++++++++-- include/drm/drm_cache.h | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 481c85a5f1b57..a210e2507368d 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -184,12 +184,14 @@ bool wc_enabled = false; EXPORT_SYMBOL(wc_enabled); +static int wc_arg = -1; + static int __init setup_writecombine(char *p) { if (!strcmp(p, "on")) - wc_enabled = true; + wc_arg = true; else if (!strcmp(p, "off")) - wc_enabled = false; + wc_arg = false; else pr_warn("Unknown writecombine setting \"%s\".\n", p); @@ -371,6 +373,26 @@ static void __init bootcmdline_init(char **cmdline_p) *cmdline_p = boot_command_line; } +static void __init writecombine_detect(void) +{ + u64 cpuname; + + if (wc_arg >= 0) { + wc_enabled = wc_arg; + return; + } + + cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME); + + switch (cpuname) { + case 0x0000303030364333: + wc_enabled = true; + break; + default: + break; + } +} + void __init platform_init(void) { arch_reserve_vmcore(); @@ -394,6 +416,8 @@ void __init platform_init(void) smbios_parse(); pr_info("The BIOS Version: %s\n", b_info.bios_version); + writecombine_detect(); + pr_info("WriteCombine: %s\n", wc_enabled ? "on":"off"); efi_runtime_init(); } diff --git a/include/drm/drm_cache.h b/include/drm/drm_cache.h index 08e0e3ffad131..667fb0368ef6d 100644 --- a/include/drm/drm_cache.h +++ b/include/drm/drm_cache.h @@ -74,7 +74,7 @@ static inline bool drm_arch_can_wc_memory(void) * cache coherency machanism. This means WUC can only used for write-only * memory regions. */ - return false; + return wc_enabled; #else return true; #endif -- Gitee From fcf5d35be96ef2ca2cc76bff6623ca58c3ecd1eb Mon Sep 17 00:00:00 2001 From: gaojuxin Date: Fri, 25 Oct 2024 18:58:24 +0800 Subject: [PATCH 4/4] LoongArch: Add workaround for 3C6000 about io wr/rd LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ38J -------------------------------- Signed-off-by: gaojuxin --- arch/loongarch/include/asm/io.h | 149 ++++++++++++++++++++++++++++++++ arch/loongarch/kernel/smp.c | 20 ++++- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h index 4a8adcca329b8..dccb1921dfd29 100644 --- a/arch/loongarch/include/asm/io.h +++ b/arch/loongarch/include/asm/io.h @@ -73,6 +73,155 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t #define __io_aw() mmiowb() +#include +extern spinlock_t lcl_node_lock[16]; +#define __raw_readb __raw_readb +static inline u8 __raw_readb(const volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + u8 val; + + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node + 8], irq_flag); + val = *(const volatile u8 __force *)addr; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node + 8], irq_flag); + /* read barrier */ + rmb(); + return val; +} + +#define __raw_readw __raw_readw +static inline u16 __raw_readw(const volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + u16 val; + + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node + 8], irq_flag); + val = *(const volatile u16 __force *)addr; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node + 8], irq_flag); + /* read barrier */ + rmb(); + return val; +} + +#define __raw_readl __raw_readl +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + u32 val; + + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node + 8], irq_flag); + val = *(const volatile u32 __force *)addr; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node + 8], irq_flag); + /* read barrier */ + rmb(); + return val; +} + +#ifdef CONFIG_64BIT +#define __raw_readq __raw_readq +static inline u64 __raw_readq(const volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + u64 val; + + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node + 8], irq_flag); + val = *(const volatile u64 __force *)addr; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node + 8], irq_flag); + /* read barrier */ + rmb(); + return val; +} +#endif /* CONFIG_64BIT */ + +#define __raw_writeb __raw_writeb +static inline void __raw_writeb(u8 value, volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + + /* write barrier */ + wmb(); + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node], irq_flag); + *(volatile u8 __force *)addr = value; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node], irq_flag); +} + +#define __raw_writew __raw_writew +static inline void __raw_writew(u16 value, volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + + /* write barrier */ + wmb(); + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node], irq_flag); + *(volatile u16 __force *)addr = value; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node], irq_flag); +} + +#define __raw_writel __raw_writel +static inline void __raw_writel(u32 value, volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + + /* write barrier */ + wmb(); + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node], irq_flag); + *(volatile u32 __force *)addr = value; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node], irq_flag); +} + +#ifdef CONFIG_64BIT +#define __raw_writeq __raw_writeq +static inline void __raw_writeq(u64 value, volatile void __iomem *addr) +{ + unsigned long dst_node, node; + unsigned long irq_flag; + + /* write barrier */ + wmb(); + dst_node = ((unsigned long)addr >> 44) & 0xf; + node = get_csr_cpuid() / 32; + if (node != dst_node) + spin_lock_irqsave(&lcl_node_lock[node], irq_flag); + *(volatile u64 __force *)addr = value; + if (node != dst_node) + spin_unlock_irqrestore(&lcl_node_lock[node], irq_flag); +} +#endif /* CONFIG_64BIT */ #include #define ARCH_HAS_VALID_PHYS_ADDR_RANGE diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index ea69606fd9f51..3e904356df3c3 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -35,6 +35,8 @@ #include #include "legacy_boot.h" +spinlock_t lcl_node_lock[16]; +EXPORT_SYMBOL(lcl_node_lock); int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ EXPORT_SYMBOL(__cpu_number_map); @@ -196,7 +198,19 @@ static void ipi_write_action(int cpu, u32 action) static void loongson_send_ipi_single(int cpu, unsigned int action) { + unsigned int curr_cpu = cpu_logical_map(smp_processor_id()); + unsigned int t_cpu = cpu_logical_map(cpu); + int flag = -1; + unsigned long irq_flag; + + if ((curr_cpu / 32) != (t_cpu / 32)) { + flag = curr_cpu / 32; + spin_lock_irqsave(&lcl_node_lock[flag], irq_flag); + asm ("dbar 0x0"); + } ipi_write_action(cpu_logical_map(cpu), (u32)action); + if (flag >= 0) + spin_unlock_irqrestore(&lcl_node_lock[flag], irq_flag); } static void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int action) @@ -204,7 +218,7 @@ static void loongson_send_ipi_mask(const struct cpumask *mask, unsigned int acti unsigned int i; for_each_cpu(i, mask) - ipi_write_action(cpu_logical_map(i), (u32)action); + loongson_send_ipi_single(i, (u32)action); } void arch_send_call_function_single_ipi(int cpu) @@ -305,6 +319,10 @@ static void __init fdt_smp_setup(void) void __init loongson_smp_setup(void) { + int i; + + for (i = 0; i < 16; i++) + spin_lock_init(&lcl_node_lock[i]); fdt_smp_setup(); cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package; -- Gitee