diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index aeb69a46d9154b4890ea57ca4baf1cd6c3238e4b..56b121c3577ca22c6fc7c0434b65e69fb8ded621 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -395,13 +395,12 @@ config SMP config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP - select GENERIC_IRQ_MIGRATION help - Say Y here to allow turning CPUs off and on. CPUs can be - controlled through /sys/devices/system/cpu. - (Note: power management support will enable this option - automatically on SMP systems. ) - Say N if you want to disable CPU hotplug. + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + (Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. config NR_CPUS int "Maximum number of CPUs (2-256)" diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index a4b13cc652c72386d07b4633821576308410bafa..e64d09fee82727c3ba33fdd09d1740c8d8e46344 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -983,6 +983,7 @@ CONFIG_OVERLAY_FS_INDEX=y CONFIG_OVERLAY_FS_XINO_AUTO=y CONFIG_OVERLAY_FS_METACOPY=y CONFIG_FSCACHE=y +CONFIG_CACHEFILES=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 31be19474288cea85f9938740f8d82467b658716..b434590c3160d806bf081b9f7b1de9fc420843a5 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -119,6 +119,7 @@ extern struct fwnode_handle *pch_lpc_handle; extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev); +extern void fixup_irqs(void); #include diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index eb33189276447630b04451ddfcf5202561195f0a..12adbb2bb67d92cbbee4dff5e41e9e3dd10050b8 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -361,13 +361,17 @@ static inline pte_t pte_mkclean(pte_t pte) static inline pte_t pte_mkdirty(pte_t pte) { - pte_val(pte) |= (_PAGE_DIRTY | _PAGE_MODIFIED); + pte_val(pte) |= _PAGE_MODIFIED; + if (pte_val(pte) & _PAGE_WRITE) + pte_val(pte) |= _PAGE_DIRTY; return pte; } static inline pte_t pte_mkwrite(pte_t pte) { - pte_val(pte) |= (_PAGE_WRITE | _PAGE_DIRTY); + pte_val(pte) |= _PAGE_WRITE; + if (pte_val(pte) & _PAGE_MODIFIED) + pte_val(pte) |= _PAGE_DIRTY; return pte; } @@ -464,7 +468,9 @@ static inline int pmd_write(pmd_t pmd) static inline pmd_t pmd_mkwrite(pmd_t pmd) { - pmd_val(pmd) |= (_PAGE_WRITE | _PAGE_DIRTY); + pmd_val(pmd) |= _PAGE_WRITE; + if (pmd_val(pmd) & _PAGE_MODIFIED) + pmd_val(pmd) |= _PAGE_DIRTY; return pmd; } @@ -487,7 +493,9 @@ static inline pmd_t pmd_mkclean(pmd_t pmd) static inline pmd_t pmd_mkdirty(pmd_t pmd) { - pmd_val(pmd) |= (_PAGE_DIRTY | _PAGE_MODIFIED); + pmd_val(pmd) |= _PAGE_MODIFIED; + if (pmd_val(pmd) & _PAGE_WRITE) + pmd_val(pmd) |= _PAGE_DIRTY; return pmd; } diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 126a9dcf79031084f558d7c678ea01bd224bdfca..edad18cd2789683c48dd9cf1f7c9fe59b8200b42 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -96,6 +96,42 @@ static int __init get_ipi_irq(void) return -EINVAL; } +#ifdef CONFIG_HOTPLUG_CPU +static void handle_irq_affinity(void) +{ + struct irq_desc *desc; + struct irq_chip *chip; + unsigned int irq; + unsigned long flags; + struct cpumask *affinity; + + for_each_active_irq(irq) { + desc = irq_to_desc(irq); + if (!desc) + continue; + + raw_spin_lock_irqsave(&desc->lock, flags); + + affinity = desc->irq_data.common->affinity; + if (!cpumask_intersects(affinity, cpu_online_mask)) + cpumask_copy(affinity, cpu_online_mask); + + chip = irq_data_get_irq_chip(&desc->irq_data); + if (chip && chip->irq_set_affinity) + chip->irq_set_affinity(&desc->irq_data, + desc->irq_data.common->affinity, true); + raw_spin_unlock_irqrestore(&desc->lock, flags); + } +} + +void fixup_irqs(void) +{ + handle_irq_affinity(); + irq_cpu_offline(); + clear_csr_ecfg(ECFG0_IM); +} +#endif + void __init init_IRQ(void) { int i, ret; diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c index 86600e39799e4e5e438fa56143b95c88f0a27d3f..f6c0bdb0238be74bc386f7fa6e58500da496a78a 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -156,7 +156,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->csr_crmd = p->thread.csr_crmd; childregs->csr_prmd = p->thread.csr_prmd; childregs->csr_ecfg = p->thread.csr_ecfg; - return 0; + goto out; } /* user thread */ @@ -175,14 +175,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, */ childregs->csr_euen = 0; + if (clone_flags & CLONE_SETTLS) + childregs->regs[2] = tls; + +out: clear_tsk_thread_flag(p, TIF_USEDFPU); clear_tsk_thread_flag(p, TIF_USEDSIMD); clear_tsk_thread_flag(p, TIF_LSX_CTX_LIVE); clear_tsk_thread_flag(p, TIF_LASX_CTX_LIVE); - if (clone_flags & CLONE_SETTLS) - childregs->regs[2] = tls; - return 0; } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 4b7b42cf19bdcf89c7ad8a8cf8d05b319cce774e..4d2cb1e2d6611373ede87672b20329fe8847d217 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -272,8 +272,7 @@ int loongson3_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); local_irq_save(flags); - irq_migrate_all_off_this_cpu(); - clear_csr_ecfg(ECFG0_IM); + fixup_irqs(); local_irq_restore(flags); local_flush_tlb_all(); diff --git a/drivers/i2c/busses/i2c-loongson.c b/drivers/i2c/busses/i2c-loongson.c index a2dc0dd1e4f8ef98b715dc09682478cdd3d1f9fd..be533c53e6da525cbda53a5c7b644acf973ee05b 100644 --- a/drivers/i2c/busses/i2c-loongson.c +++ b/drivers/i2c/busses/i2c-loongson.c @@ -508,6 +508,7 @@ static int loongson_i2c_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); i2c_del_adapter(&dev->adapter); + free_irq(dev->irq, dev); iounmap(dev->base); kfree(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index 1d9fa3398ceaf11fe98403e7c10649475a0207a9..2deb849246328e558ce5493c75e6be163cf881e0 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -392,14 +392,12 @@ static int __init acpi_cascade_irqdomain_init(void) int __init pch_pic_acpi_init(struct irq_domain *parent, struct acpi_madt_bio_pic *acpi_pchpic) { - int ret, vec_base; + int ret; struct fwnode_handle *domain_handle; if (find_pch_pic(acpi_pchpic->gsi_base) >= 0) return 0; - vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ; - domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address); if (!domain_handle) { pr_err("Unable to allocate domain handle\n"); @@ -407,7 +405,7 @@ int __init pch_pic_acpi_init(struct irq_domain *parent, } ret = pch_pic_init(acpi_pchpic->address, acpi_pchpic->size, - vec_base, parent, domain_handle, acpi_pchpic->gsi_base); + 0, parent, domain_handle, acpi_pchpic->gsi_base); if (ret < 0) { irq_domain_free_fwnode(domain_handle);