Linux clock framework development
 help / color / mirror / Atom feed
* [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs
@ 2026-11-12  4:14 Florian Fainelli
  2026-11-12  4:14 ` [PATCH v3 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically Florian Fainelli
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Florian Fainelli @ 2026-11-12  4:14 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, Thomas Bogendoerfer, Paul Burton, Paul Cercueil,
	Stephen Boyd, Brian Masney, Jerome Brunet,
	周琰杰 (Zhou Yanjie), Jiaxun Yang, open list,
	open list:COMMON CLK FRAMEWORK, hns, paul

This patch series resurrects SMP support for the CI20 board. This was
submitted back in 2020 by Zhou Yanjie.

Changes in v3:

• Align the second line of the readl_poll_timeout_atomic() per Brian's
  feedback
• Collected Paul's R-b and T-b tags

Changes in v2:

• Moved SMP sources to arch/mips/ingenic/ and the header to arch/mips/include/asm/
• Removed CONFIG_MIPS_INGENIC_SMP, using CONFIG_MACH_JZ4780 and CONFIG_SMP directly
• Renamed JZ4780-specific SMP symbols to XBurst names
• Changed CPU enumeration to assign consecutive logical IDs and removed the explicit two-core limit
• Changed mailbox IRQ allocation failure from panic to logging and returning
• Shortened commit descriptions, removed Codex attribution, and adjusted source credits and sign-offs
• Kept the clock polling patch and CI20 defconfig changes unchanged,
  added Paul's R-b for patch #1
• Updated the kernel baseline to include additional upstream fixes

Florian Fainelli (1):
  clk: ingenic: Poll JZ4780 CPU1 power status atomically

周琰杰 (Zhou Yanjie) (2):
  MIPS: Ingenic: Add XBurst SMP support
  MIPS: CI20: Enable SMP with two CPUs

 MAINTAINERS                           |   3 +-
 arch/mips/Kbuild                      |   1 +
 arch/mips/configs/ci20_defconfig      |   2 +
 arch/mips/generic/init.c              |   3 +
 arch/mips/include/asm/ingenic-smp.h   |  20 +++
 arch/mips/ingenic/Kconfig             |   2 +
 arch/mips/ingenic/Makefile            |   5 +
 arch/mips/ingenic/ingenic-smp-entry.S |  54 ++++++
 arch/mips/ingenic/ingenic-smp.c       | 247 ++++++++++++++++++++++++++
 arch/mips/kernel/idle.c               |  26 ++-
 drivers/clk/ingenic/jz4780-cgu.c      |   4 +-
 11 files changed, 363 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/include/asm/ingenic-smp.h
 create mode 100644 arch/mips/ingenic/Makefile
 create mode 100644 arch/mips/ingenic/ingenic-smp-entry.S
 create mode 100644 arch/mips/ingenic/ingenic-smp.c

-- 
2.53.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically
  2026-11-12  4:14 [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
@ 2026-11-12  4:14 ` Florian Fainelli
  2026-11-12  4:14 ` [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support Florian Fainelli
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2026-11-12  4:14 UTC (permalink / raw)
  To: linux-mips
  Cc: Florian Fainelli, stable, Paul Cercueil, Thomas Bogendoerfer,
	Paul Burton, Stephen Boyd, Brian Masney, Jerome Brunet,
	周琰杰 (Zhou Yanjie), Jiaxun Yang, open list,
	open list:COMMON CLK FRAMEWORK, hns, paul

The CPU1 clock enable callback runs under the clock framework's spinlock
with interrupts disabled. Its readl_poll_timeout() can sleep between
reads, which is invalid in this context when SMP powers up CPU1.

Use readl_poll_timeout_atomic() with the existing interval and timeout.
This is a prerequisite for the JZ4780 SMP bring-up path. The original
CPU1 clock implementation by Zhou Yanjie is already upstream.

Cross-built for CI20; the subsequent SMP-enabled image brought up both
CPU cores. Development and validation used Codex assistance.

CC: stable@vger.kernel.org
Fixes: 6673db4f3f26 ("clk: JZ4780: Add function for enable the second core.")
Link: https://lkml.kernel.org/r/1582215889-113034-3-git-send-email-zhouyanjie@wanyeetech.com
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Tested-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/clk/ingenic/jz4780-cgu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index 1e88aef7ac0f..1809f8859c7e 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -242,8 +242,8 @@ static int jz4780_core1_enable(struct clk_hw *hw)
 	spin_unlock_irqrestore(&cgu->lock, flags);
 
 	/* wait for the CPU to be powered up */
-	retval = readl_poll_timeout(cgu->base + CGU_REG_LCR, lcr,
-				 !(lcr & LCR_SCPUS), 10, timeout);
+	retval = readl_poll_timeout_atomic(cgu->base + CGU_REG_LCR, lcr,
+					   !(lcr & LCR_SCPUS), 10, timeout);
 	if (retval == -ETIMEDOUT) {
 		pr_err("%s: Wait for power up core1 timeout\n", __func__);
 		return retval;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support
  2026-11-12  4:14 [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
  2026-11-12  4:14 ` [PATCH v3 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically Florian Fainelli
@ 2026-11-12  4:14 ` Florian Fainelli
  2026-11-12  4:49   ` sashiko-bot
  2026-11-12  4:14 ` [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
  2026-11-12  5:00 ` [PATCH v3 0/3] " Florian Fainelli
  3 siblings, 1 reply; 7+ messages in thread
From: Florian Fainelli @ 2026-11-12  4:14 UTC (permalink / raw)
  To: linux-mips
  Cc: 周琰杰 (Zhou Yanjie), Paul Cercueil,
	Florian Fainelli, Thomas Bogendoerfer, Paul Burton, Stephen Boyd,
	Brian Masney, Jerome Brunet, Jiaxun Yang, open list,
	open list:COMMON CLK FRAMEWORK, hns, paul

From: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>

Add support for the second XBurst core on the JZ4780, based on Zhou
Yanjie's 2020 series and Paul Burton's original CI20 SMP implementation.
Use the CP0 mailboxes for inter-processor interrupts.

XBurst stops its private cache clock when executing WAIT. Write back
the data cache before entering idle so that the other core can access
data belonging to the sleeping core.

Link: https://lkml.iu.edu/hypermail/linux/kernel/2005.2/03488.html
Link: https://lists.openwall.net/linux-kernel/2020/05/13/1482
Link: https://lists.openwall.net/linux-kernel/2020/05/19/1099
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Tested-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
[florian: forward ported to latest version]
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 MAINTAINERS                           |   3 +-
 arch/mips/Kbuild                      |   1 +
 arch/mips/generic/init.c              |   3 +
 arch/mips/include/asm/ingenic-smp.h   |  20 +++
 arch/mips/ingenic/Kconfig             |   2 +
 arch/mips/ingenic/Makefile            |   5 +
 arch/mips/ingenic/ingenic-smp-entry.S |  54 ++++++
 arch/mips/ingenic/ingenic-smp.c       | 247 ++++++++++++++++++++++++++
 arch/mips/kernel/idle.c               |  26 ++-
 9 files changed, 359 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/include/asm/ingenic-smp.h
 create mode 100644 arch/mips/ingenic/Makefile
 create mode 100644 arch/mips/ingenic/ingenic-smp-entry.S
 create mode 100644 arch/mips/ingenic/ingenic-smp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 222b7fc2c3aa..7128df320bab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13150,8 +13150,9 @@ L:	linux-mips@vger.kernel.org
 S:	Maintained
 F:	arch/mips/boot/dts/ingenic/
 F:	arch/mips/generic/board-ingenic.c
+F:	arch/mips/include/asm/ingenic-smp.h
 F:	arch/mips/include/asm/mach-ingenic/
-F:	arch/mips/ingenic/Kconfig
+F:	arch/mips/ingenic/
 F:	drivers/clk/ingenic/
 F:	drivers/dma/dma-jz4780.c
 F:	drivers/gpu/drm/ingenic/
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild
index e901bf554483..4912ab80d143 100644
--- a/arch/mips/Kbuild
+++ b/arch/mips/Kbuild
@@ -12,6 +12,7 @@ obj- := $(platform-y)
 # The object files are linked as core-y files would be linked
 
 obj-y += generic/
+obj-$(CONFIG_MACH_INGENIC) += ingenic/
 obj-y += kernel/
 obj-y += mm/
 obj-y += net/
diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c
index 1d712eac1617..38f294887c17 100644
--- a/arch/mips/generic/init.c
+++ b/arch/mips/generic/init.c
@@ -13,6 +13,7 @@
 
 #include <asm/bootinfo.h>
 #include <asm/fw/fw.h>
+#include <asm/ingenic-smp.h>
 #include <asm/irq_cpu.h>
 #include <asm/machine.h>
 #include <asm/mips-cps.h>
@@ -113,6 +114,8 @@ void __init device_tree_init(void)
 	unflatten_and_copy_device_tree();
 	mips_cpc_probe();
 
+	if (!register_ingenic_smp_ops())
+		return;
 	if (!register_cps_smp_ops())
 		return;
 	if (!register_vsmp_smp_ops())
diff --git a/arch/mips/include/asm/ingenic-smp.h b/arch/mips/include/asm/ingenic-smp.h
new file mode 100644
index 000000000000..ea81c333820d
--- /dev/null
+++ b/arch/mips/include/asm/ingenic-smp.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2013 Paul Burton <paulburton@kernel.org> */
+#ifndef __ASM_INGENIC_SMP_H__
+#define __ASM_INGENIC_SMP_H__
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kconfig.h>
+
+#if defined(CONFIG_MACH_JZ4780) && defined(CONFIG_SMP)
+int __init register_ingenic_smp_ops(void);
+void xburst_secondary_cpu_entry(void);
+#else
+static inline int register_ingenic_smp_ops(void)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ASM_INGENIC_SMP_H__ */
diff --git a/arch/mips/ingenic/Kconfig b/arch/mips/ingenic/Kconfig
index f595b339a4b8..583f8d3651df 100644
--- a/arch/mips/ingenic/Kconfig
+++ b/arch/mips/ingenic/Kconfig
@@ -64,6 +64,8 @@ config MACH_JZ4780
 	select MIPS_CPU_SCACHE
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_SMP
+	select SMP_UP if SMP
 
 config MACH_X1000
 	bool
diff --git a/arch/mips/ingenic/Makefile b/arch/mips/ingenic/Makefile
new file mode 100644
index 000000000000..fc3b1bf1f25a
--- /dev/null
+++ b/arch/mips/ingenic/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+ifdef CONFIG_SMP
+obj-$(CONFIG_MACH_JZ4780) += ingenic-smp.o ingenic-smp-entry.o
+endif
diff --git a/arch/mips/ingenic/ingenic-smp-entry.S b/arch/mips/ingenic/ingenic-smp-entry.S
new file mode 100644
index 000000000000..250a0c89c955
--- /dev/null
+++ b/arch/mips/ingenic/ingenic-smp-entry.S
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2013 Paul Burton <paulburton@kernel.org>
+ * XBurst secondary CPU reset entry
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+
+#define CACHE_SIZE	(32 * 1024)
+#define CACHE_LINESIZE	32
+
+	/* The CP0 REIM register only stores the upper 16 address bits. */
+	.section .text.smp-entry, "ax"
+	.balign 0x10000
+	.set noreorder
+LEAF(xburst_secondary_cpu_entry)
+	mtc0	zero, CP0_CAUSE
+	li	t0, ST0_CU0
+	mtc0	t0, CP0_STATUS
+	ehb
+
+	/* Invalidate both private caches before entering cached code. */
+	li	t0, KSEG0
+	ori	t1, t0, CACHE_SIZE
+	mtc0	zero, CP0_TAGLO
+	ehb
+1:	cache	Index_Store_Tag_I, 0(t0)
+	cache	Index_Store_Tag_D, 0(t0)
+	addiu	t0, t0, CACHE_LINESIZE
+	bne	t0, t1, 1b
+	 nop
+
+	mfc0	t0, CP0_CONFIG
+	li	t1, ~CONF_CM_CMASK
+	and	t0, t0, t1
+	ori	t0, t0, CONF_CM_CACHABLE_NONCOHERENT
+	mtc0	t0, CP0_CONFIG
+	mtc0	zero, CP0_PAGEMASK
+	ehb
+
+	/* CPU0 publishes these in RAM before releasing CPU1 from reset. */
+	la	t0, xburst_cpu_entry_sp
+	lw	sp, 0(t0)
+	la	t0, xburst_cpu_entry_gp
+	lw	gp, 0(t0)
+
+	la	t0, smp_bootstrap
+	jr	t0
+	 nop
+END(xburst_secondary_cpu_entry)
diff --git a/arch/mips/ingenic/ingenic-smp.c b/arch/mips/ingenic/ingenic-smp.c
new file mode 100644
index 000000000000..3cdb953c7a87
--- /dev/null
+++ b/arch/mips/ingenic/ingenic-smp.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * XBurst SMP support, based on Paul Burton's CI20 implementation and
+ * Zhou Yanjie's 2020 JZ4780 SMP series.
+ * Copyright (C) 2013 Paul Burton <paulburton@kernel.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/sched/task_stack.h>
+#include <linux/smp.h>
+
+#include <asm/addrspace.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/r4kcache.h>
+#include <asm/smp-ops.h>
+
+#include <asm/ingenic-smp.h>
+
+#define read_c0_corectrl()	__read_32bit_c0_register($12, 2)
+#define write_c0_corectrl(val)	__write_32bit_c0_register($12, 2, val)
+#define read_c0_corestatus()	__read_32bit_c0_register($12, 3)
+#define write_c0_corestatus(val)	__write_32bit_c0_register($12, 3, val)
+#define read_c0_reim()		__read_32bit_c0_register($12, 4)
+#define write_c0_reim(val)	__write_32bit_c0_register($12, 4, val)
+#define read_c0_mailbox0()	__read_32bit_c0_register($20, 0)
+#define write_c0_mailbox0(val)	__write_32bit_c0_register($20, 0, val)
+#define read_c0_mailbox1()	__read_32bit_c0_register($20, 1)
+#define write_c0_mailbox1(val)	__write_32bit_c0_register($20, 1, val)
+
+#define XBURST_MBOX_IRQ		(MIPS_CPU_IRQ_BASE + 3)
+#define CORECTRL_SWRST(cpu)	BIT(cpu)
+#define CORECTRL_RPC(cpu)	BIT(8 + (cpu))
+#define CORESTATUS_MIRQ(cpu)	BIT(cpu)
+#define REIM_ENTRY		GENMASK(31, 16)
+#define REIM_MBOXIRQ(cpu)	BIT(cpu)
+
+static struct clk *cpu1_clock;
+static DEFINE_RAW_SPINLOCK(smp_lock);
+
+/* Referenced by the uncached secondary CPU reset entry. */
+unsigned long xburst_cpu_entry_sp;
+unsigned long xburst_cpu_entry_gp;
+
+static irqreturn_t xburst_mbox_interrupt(int irq, void *dev_id)
+{
+	unsigned int cpu = cpu_logical_map(smp_processor_id());
+	u32 action, status;
+
+	raw_spin_lock(&smp_lock);
+	if (cpu == 0) {
+		action = read_c0_mailbox0();
+		write_c0_mailbox0(0);
+	} else {
+		action = read_c0_mailbox1();
+		write_c0_mailbox1(0);
+	}
+
+	status = read_c0_corestatus();
+	write_c0_corestatus(status & ~CORESTATUS_MIRQ(cpu));
+	irq_disable_hazard();
+	raw_spin_unlock(&smp_lock);
+
+	if (action & SMP_RESCHEDULE_YOURSELF)
+		scheduler_ipi();
+	if (action & SMP_CALL_FUNCTION)
+		generic_smp_call_function_interrupt();
+
+	return IRQ_HANDLED;
+}
+
+static void __init xburst_smp_setup(void)
+{
+	struct device_node *np;
+	u32 entry, reim;
+	unsigned int cpu = 0;
+	u64 hwid;
+
+	for_each_of_cpu_node(np) {
+		hwid = of_get_cpu_hwid(np, 0);
+		if (!of_device_is_available(np) ||
+		    hwid >= ARRAY_SIZE(__cpu_number_map))
+			continue;
+		if (cpu >= nr_cpu_ids) {
+			of_node_put(np);
+			break;
+		}
+		__cpu_number_map[hwid] = cpu;
+		__cpu_logical_map[cpu] = hwid;
+		set_cpu_possible(cpu, true);
+		cpu++;
+	}
+
+	/* Program the shared reset vector with mailbox delivery masked. */
+	reim = read_c0_reim();
+	reim &= ~(REIM_MBOXIRQ(0) | REIM_MBOXIRQ(1));
+	write_c0_reim(reim);
+	write_c0_mailbox0(0);
+	write_c0_mailbox1(0);
+	write_c0_corestatus(0);
+
+	entry = KSEG1ADDR((unsigned long)xburst_secondary_cpu_entry);
+	write_c0_reim((reim & ~REIM_ENTRY) | (entry & REIM_ENTRY));
+}
+
+static void __init xburst_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *np;
+	u32 reim;
+	int ret;
+
+	ret = request_irq(XBURST_MBOX_IRQ, xburst_mbox_interrupt,
+			  IRQF_PERCPU | IRQF_NO_THREAD, "core mailbox", NULL);
+	if (ret) {
+		pr_err("XBurst: cannot request mailbox IRQ: %d\n", ret);
+		return;
+	}
+
+	reim = read_c0_reim();
+	write_c0_reim(reim | REIM_MBOXIRQ(0));
+	set_c0_status(STATUSF_IP3);
+	irq_enable_hazard();
+
+	if (!cpu_possible(1))
+		return;
+
+	np = of_get_cpu_node(1, NULL);
+	cpu1_clock = of_clk_get(np, 0);
+	of_node_put(np);
+	if (IS_ERR(cpu1_clock)) {
+		pr_err("XBurst: cannot get CPU1 clock: %ld\n",
+		       PTR_ERR(cpu1_clock));
+		return;
+	}
+
+	ret = clk_prepare(cpu1_clock);
+	if (ret) {
+		clk_put(cpu1_clock);
+		cpu1_clock = ERR_PTR(ret);
+		pr_err("XBurst: cannot prepare CPU1 clock: %d\n", ret);
+	}
+}
+
+static int xburst_boot_secondary(int cpu, struct task_struct *idle)
+{
+	unsigned long flags;
+	u32 ctrl;
+	int ret;
+
+	if (cpu_logical_map(cpu) != 1 || IS_ERR_OR_NULL(cpu1_clock))
+		return -ENODEV;
+
+	raw_spin_lock_irqsave(&smp_lock, flags);
+	ctrl = read_c0_corectrl() | CORECTRL_SWRST(1) | CORECTRL_RPC(1);
+	write_c0_corectrl(ctrl);
+	back_to_back_c0_hazard();
+
+	ret = clk_enable(cpu1_clock);
+	if (ret)
+		goto unlock;
+
+	xburst_cpu_entry_sp = __KSTK_TOS(idle);
+	xburst_cpu_entry_gp = (unsigned long)task_thread_info(idle);
+	/* Publish bootstrap state before CPU1 starts using its private cache. */
+	r4k_blast_dcache();
+	/* Complete cache writeback before releasing reset. */
+	mb();
+	write_c0_corectrl(ctrl & ~CORECTRL_SWRST(1));
+	back_to_back_c0_hazard();
+unlock:
+	raw_spin_unlock_irqrestore(&smp_lock, flags);
+	return ret;
+}
+
+static void xburst_init_secondary(void)
+{
+	clear_c0_status(ST0_IM);
+	irq_disable_hazard();
+}
+
+static void xburst_smp_finish(void)
+{
+	unsigned int cpu = cpu_logical_map(smp_processor_id());
+	u32 reim;
+
+	raw_spin_lock(&smp_lock);
+	reim = read_c0_reim();
+	write_c0_reim(reim | REIM_MBOXIRQ(cpu));
+	raw_spin_unlock(&smp_lock);
+
+	change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP2 |
+			 STATUSF_IP1 | STATUSF_IP0);
+	irq_enable_hazard();
+	local_irq_enable();
+}
+
+static void xburst_send_ipi_locked(int cpu, unsigned int action)
+{
+	if (cpu_logical_map(cpu) == 0)
+		write_c0_mailbox0(read_c0_mailbox0() | action);
+	else
+		write_c0_mailbox1(read_c0_mailbox1() | action);
+	back_to_back_c0_hazard();
+}
+
+static void xburst_send_ipi_single(int cpu, unsigned int action)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&smp_lock, flags);
+	xburst_send_ipi_locked(cpu, action);
+	raw_spin_unlock_irqrestore(&smp_lock, flags);
+}
+
+static void xburst_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+	unsigned long flags;
+	int cpu;
+
+	raw_spin_lock_irqsave(&smp_lock, flags);
+	for_each_cpu(cpu, mask)
+		xburst_send_ipi_locked(cpu, action);
+	raw_spin_unlock_irqrestore(&smp_lock, flags);
+}
+
+static const struct plat_smp_ops xburst_smp_ops = {
+	.send_ipi_single = xburst_send_ipi_single,
+	.send_ipi_mask = xburst_send_ipi_mask,
+	.init_secondary = xburst_init_secondary,
+	.smp_finish = xburst_smp_finish,
+	.boot_secondary = xburst_boot_secondary,
+	.smp_setup = xburst_smp_setup,
+	.prepare_cpus = xburst_prepare_cpus,
+};
+
+int __init register_ingenic_smp_ops(void)
+{
+	if (!of_machine_is_compatible("ingenic,jz4780"))
+		return -ENODEV;
+
+	register_smp_ops(&xburst_smp_ops);
+	return 0;
+}
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 80e8a04a642e..46526997a4c6 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -18,6 +18,7 @@
 #include <asm/cpu-type.h>
 #include <asm/idle.h>
 #include <asm/mipsregs.h>
+#include <asm/r4kcache.h>
 
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
@@ -71,6 +72,23 @@ static void __cpuidle rm7k_wait_irqoff(void)
 		"	.set	pop					\n");
 }
 
+/* XBurst gates its private cache clock in WAIT; write back dirty data first. */
+static void __cpuidle xburst_wait_irqoff(void)
+{
+	unsigned long pending = read_c0_cause() & read_c0_status() & CAUSEF_IP;
+
+	if (!need_resched() && !pending) {
+		r4k_blast_dcache();
+		__asm__ __volatile__(
+			".set push\n"
+			".set mips3\n"
+			"sync\n"
+			"wait\n"
+			".set pop\n"
+			: : : "memory");
+	}
+}
+
 /*
  * Au1 'wait' is only useful when the 32kHz counter is used as timer,
  * since coreclock (and the cp0 counter) stops upon executing it. Only an
@@ -156,10 +174,16 @@ void __init check_wait(void)
 	case CPU_CAVIUM_OCTEON_PLUS:
 	case CPU_CAVIUM_OCTEON2:
 	case CPU_CAVIUM_OCTEON3:
-	case CPU_XBURST:
 	case CPU_LOONGSON32:
 		cpu_wait = r4k_wait;
 		break;
+	case CPU_XBURST:
+		if (IS_ENABLED(CONFIG_MACH_JZ4780) &&
+		    IS_ENABLED(CONFIG_SMP))
+			cpu_wait = xburst_wait_irqoff;
+		else
+			cpu_wait = r4k_wait;
+		break;
 	case CPU_LOONGSON64:
 		if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
 				(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) ||
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs
  2026-11-12  4:14 [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
  2026-11-12  4:14 ` [PATCH v3 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically Florian Fainelli
  2026-11-12  4:14 ` [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support Florian Fainelli
@ 2026-11-12  4:14 ` Florian Fainelli
  2026-11-12  4:31   ` sashiko-bot
  2026-11-12  5:00 ` [PATCH v3 0/3] " Florian Fainelli
  3 siblings, 1 reply; 7+ messages in thread
From: Florian Fainelli @ 2026-11-12  4:14 UTC (permalink / raw)
  To: linux-mips
  Cc: 周琰杰 (Zhou Yanjie), Paul Cercueil,
	Florian Fainelli, Thomas Bogendoerfer, Paul Burton, Stephen Boyd,
	Brian Masney, Jerome Brunet, Jiaxun Yang, open list,
	open list:COMMON CLK FRAMEWORK, hns, paul

From: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>

Enable both JZ4780 cores now that the generic Ingenic platform provides
secondary CPU reset and mailbox support. The existing device tree
already reserves TCU channels for both per-CPU clock events.

Link: https://lists.openwall.net/linux-kernel/2020/05/19/739
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Tested-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/mips/configs/ci20_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
index 90536cab417e..09d65094b1bd 100644
--- a/arch/mips/configs/ci20_defconfig
+++ b/arch/mips/configs/ci20_defconfig
@@ -22,6 +22,8 @@ CONFIG_EXPERT=y
 CONFIG_MACH_INGENIC_SOC=y
 CONFIG_JZ4780_CI20=y
 CONFIG_HIGHMEM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
 CONFIG_HZ_100=y
 # CONFIG_SUSPEND is not set
 # CONFIG_SECCOMP is not set
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs
  2026-11-12  4:14 ` [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
@ 2026-11-12  4:31   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-12  4:31 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: open list:COMMON CLK FRAMEWORK

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] mips: ingenic: invalid lock nesting in xburst_boot_secondary()
- [High] mips: ingenic: boot BUG_ON in mips_smp_ipi_allocate() and
  missing present mask
- [High] mips: ingenic: missing cpu_set_core() skips cache IPIs under
  CONFIG_MIPS_CPS
- [Low] mips: ingenic: 64-bit build failure in xburst_smp_setup() and
  entry asm
--

commit 2540a85d35c671f5a1df0622376784adb3fe4123
Author: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>

MIPS: CI20: Enable SMP with two CPUs

This commit enables SMP support with two CPUs in ci20_defconfig so both
JZ4780 cores are used on the CI20 board.

Link: https://lists.openwall.net/linux-kernel/2020/05/19/739

> diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
> index 90536cab417ee..09d65094b1bd2 100644
> --- a/arch/mips/configs/ci20_defconfig
> +++ b/arch/mips/configs/ci20_defconfig
> @@ -22,6 +22,8 @@ CONFIG_EXPERT=y
>  CONFIG_MACH_INGENIC_SOC=y
>  CONFIG_JZ4780_CI20=y
>  CONFIG_HIGHMEM=y
> +CONFIG_SMP=y
> +CONFIG_NR_CPUS=2
>  CONFIG_HZ_100=y
>  # CONFIG_SUSPEND is not set
>  # CONFIG_SECCOMP is not set

[Severity: High]
Does xburst_boot_secondary() in commit "MIPS: Ingenic: Add XBurst SMP
support" violate lock nesting rules by calling clk_enable(cpu1_clock)
while holding smp_lock?

arch/mips/ingenic/ingenic-smp.c:xburst_boot_secondary() {
    ...
	raw_spin_lock_irqsave(&smp_lock, flags);
	ctrl = read_c0_corectrl() | CORECTRL_SWRST(1) | CORECTRL_RPC(1);
	write_c0_corectrl(ctrl);
	back_to_back_c0_hazard();

	ret = clk_enable(cpu1_clock);
    ...
}

smp_lock is a raw_spinlock_t, whereas clk_enable() -> clk_enable_lock()
acquires the non-raw spinlock_t enable_lock and jz4780_core1_enable()
acquires the non-raw spinlock_t cgu->lock.  Booting CPU1 triggers a
lockdep invalid wait context splat and sleeps while atomic on preempt-rt
kernels, while also holding smp_lock with interrupts disabled across the
5000 us power-status poll in jz4780_core1_enable().

[Severity: Low]
Can arch/mips/ingenic/ingenic-smp.c and
arch/mips/ingenic/ingenic-smp-entry.S in commit "MIPS: Ingenic: Add XBurst
SMP support" fail to build on 64-bit generic kernels?

arch/mips/ingenic/ingenic-smp.c:xburst_smp_setup() {
    ...
	entry = KSEG1ADDR((unsigned long)xburst_secondary_cpu_entry);
	write_c0_reim((reim & ~REIM_ENTRY) | (entry & REIM_ENTRY));
}

arch/mips/ingenic/ingenic-smp-entry.S:xburst_secondary_cpu_entry() {
    ...
	li	t0, KSEG0
    ...
	la	t0, xburst_cpu_entry_sp
	lw	sp, 0(t0)
	la	t0, xburst_cpu_entry_gp
	lw	gp, 0(t0)

	la	t0, smp_bootstrap
}

BOARD_INGENIC can be enabled in a 64-bit generic kernel build, where
asm/addrspace.h only defines CKSEG1ADDR and CKSEG0 (not KSEG1ADDR or
KSEG0), and the 32-bit la and lw instructions in
xburst_secondary_cpu_entry fail to assemble against 64-bit unsigned long
and pointer symbols instead of using PTR_LA and LONG_L.

[Severity: High]
Does xburst_smp_setup() in commit "MIPS: Ingenic: Add XBurst SMP support"
leave CPU1 out of cpu_present_mask and trigger a boot crash in
mips_smp_ipi_allocate() on generic kernels?

arch/mips/ingenic/ingenic-smp.c:xburst_smp_setup() {
	for_each_of_cpu_node(np) {
    ...
		__cpu_number_map[hwid] = cpu;
		__cpu_logical_map[cpu] = hwid;
		set_cpu_possible(cpu, true);
		cpu++;
	}
}

Neither xburst_smp_setup() nor xburst_prepare_cpus() calls
set_cpu_present(cpu, true), and smp_prepare_cpus() only copies
cpu_possible_mask to cpu_present_mask when CPU hotplug is disabled, so
CPU1 is never brought up when hotplug is enabled.  In addition, generic
MIPS kernels select GENERIC_IRQ_IPI, which causes mips_smp_ipi_init() ->
mips_smp_ipi_allocate() to hit BUG_ON(num_present_cpus() > 1) at boot
because JZ4780 uses custom mailbox callbacks in xburst_smp_ops without
registering an IPI irq domain.

[Severity: High]
Does xburst_smp_setup() in commit "MIPS: Ingenic: Add XBurst SMP support"
miss calling cpu_set_core(&cpu_data[cpu], hwid)?

When MIPS_CPS is enabled (such as in generic_defconfig), decode_configs()
skips cpu_set_core(), leaving both JZ4780 cores with core ID 0.
cpus_are_siblings(0, 1) then returns true and leaves cpu_foreign_map
empty, causing r4k_on_each_cpu() to skip cross-CPU L1 I-cache and D-cache
flush IPIs between the two cores' non-coherent private caches.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261112041422.2997275-1-f.fainelli@gmail.com?part=3

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support
  2026-11-12  4:14 ` [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support Florian Fainelli
@ 2026-11-12  4:49   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-12  4:49 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: open list:COMMON CLK FRAMEWORK

Thank you for your contribution! Sashiko AI review found 6 potential
issues to consider:
- [High] MIPS: Ingenic: missing set_cpu_present() and hotplug ops in
  xburst_smp_ops
- [High] MIPS: Ingenic: boot BUG_ON in mips_smp_ipi_allocate() on
  generic kernel
- [High] MIPS: Ingenic: missing cpu_set_core() suppresses cache IPIs
  under MIPS_CPS
- [High] MIPS: idle: check_wait() selects xburst_wait_irqoff() on UP
  XBurst SoCs
- [Medium] MIPS: Ingenic: invalid wait context in
  xburst_boot_secondary()
- [Low] MIPS: Ingenic: 64-bit generic kernel build failure in
  ingenic-smp
--

commit 6b8dd5ed8b645649357726e158dd3bee858c1f08
Author: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>

MIPS: Ingenic: Add XBurst SMP support

This commit adds SMP support for the second XBurst core on the Ingenic
JZ4780 using CP0 mailboxes for IPIs and flushes the data cache before
entering WAIT on SMP JZ4780 kernels.

Link: https://lkml.iu.edu/hypermail/linux/kernel/2005.2/03488.html
Link: https://lists.openwall.net/linux-kernel/2020/05/13/1482
Link: https://lists.openwall.net/linux-kernel/2020/05/19/1099

[ ... ]

> diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c
> index 1d712eac16171..38f294887c17a 100644
> --- a/arch/mips/generic/init.c
> +++ b/arch/mips/generic/init.c
> @@ -13,6 +13,7 @@
>  
>  #include <asm/bootinfo.h>
>  #include <asm/fw/fw.h>
> +#include <asm/ingenic-smp.h>
>  #include <asm/irq_cpu.h>
>  #include <asm/machine.h>
>  #include <asm/mips-cps.h>
> @@ -113,6 +114,8 @@ void __init device_tree_init(void)
>  	unflatten_and_copy_device_tree();
>  	mips_cpc_probe();
>  
> +	if (!register_ingenic_smp_ops())
> +		return;
>  	if (!register_cps_smp_ops())
>  		return;
>  	if (!register_vsmp_smp_ops())

[Severity: High]
Does booting a generic MIPS kernel (CONFIG_MIPS_GENERIC_KERNEL=y) with
CONFIG_BOARD_INGENIC=y and CONFIG_SMP=y on JZ4780 hit BUG_ON() in
mips_smp_ipi_allocate()?

CONFIG_MIPS_GENERIC_KERNEL selects CONFIG_MIPS_GIC and
CONFIG_SYS_SUPPORTS_MULTITHREADING, which enable CONFIG_GENERIC_IRQ_IPI=y
under CONFIG_SMP=y.  Because xburst_smp_ops uses direct CP0 mailbox
interrupts instead of registering a DOMAIN_BUS_IPI irq_domain, the
early_initcall mips_smp_ipi_init() -> mips_smp_ipi_allocate() finds
ipidomain == NULL and panics whenever more than one CPU is present:

arch/mips/kernel/smp.c:mips_smp_ipi_allocate() {
    ...
	if (!ipidomain) {
		BUG_ON(num_present_cpus() > 1);
		return 0;
	}
    ...
}

[ ... ]

> diff --git a/arch/mips/ingenic/ingenic-smp-entry.S b/arch/mips/ingenic/ingenic-smp-entry.S
> new file mode 100644
> index 0000000000000..250a0c89c9556
> --- /dev/null
> +++ b/arch/mips/ingenic/ingenic-smp-entry.S
> @@ -0,0 +1,54 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2013 Paul Burton <paulburton@kernel.org>
> + * XBurst secondary CPU reset entry
> + */
> +
> +#include <asm/addrspace.h>
> +#include <asm/asm.h>
> +#include <asm/asmmacro.h>
> +#include <asm/cacheops.h>
> +#include <asm/mipsregs.h>
> +
> +#define CACHE_SIZE	(32 * 1024)
> +#define CACHE_LINESIZE	32
> +
> +	/* The CP0 REIM register only stores the upper 16 address bits. */
> +	.section .text.smp-entry, "ax"
> +	.balign 0x10000
> +	.set noreorder
> +LEAF(xburst_secondary_cpu_entry)
> +	mtc0	zero, CP0_CAUSE
> +	li	t0, ST0_CU0
> +	mtc0	t0, CP0_STATUS
> +	ehb
> +
> +	/* Invalidate both private caches before entering cached code. */
> +	li	t0, KSEG0
> +	ori	t1, t0, CACHE_SIZE

[ ... ]

> +	/* CPU0 publishes these in RAM before releasing CPU1 from reset. */
> +	la	t0, xburst_cpu_entry_sp
> +	lw	sp, 0(t0)
> +	la	t0, xburst_cpu_entry_gp
> +	lw	gp, 0(t0)
> +
> +	la	t0, smp_bootstrap
> +	jr	t0
> +	 nop
> +END(xburst_secondary_cpu_entry)

[Severity: Low]
Does this break 64-bit generic MIPS builds (CONFIG_MIPS_GENERIC_KERNEL=y,
CONFIG_64BIT=y) when CONFIG_BOARD_INGENIC=y and CONFIG_SMP=y are enabled?

CONFIG_BOARD_INGENIC has no dependency on CONFIG_32BIT and selects
CONFIG_MACH_JZ4780, so both ingenic-smp-entry.S and ingenic-smp.c are built
on 64-bit generic kernels.  In arch/mips/include/asm/addrspace.h, KSEG0 and
KSEG1ADDR() are only defined when CONFIG_64BIT is disabled (whereas CKSEG0
and CKSEG1ADDR() are always defined), causing xburst_secondary_cpu_entry and
xburst_smp_setup() to fail to build, alongside the 32-bit la and lw
instructions used here on unsigned long globals.

> diff --git a/arch/mips/ingenic/ingenic-smp.c b/arch/mips/ingenic/ingenic-smp.c
> new file mode 100644
> index 0000000000000..3cdb953c7a871
> --- /dev/null
> +++ b/arch/mips/ingenic/ingenic-smp.c

[ ... ]

> +static void __init xburst_smp_setup(void)
> +{
> +	struct device_node *np;
> +	u32 entry, reim;
> +	unsigned int cpu = 0;
> +	u64 hwid;
> +
> +	for_each_of_cpu_node(np) {
> +		hwid = of_get_cpu_hwid(np, 0);
> +		if (!of_device_is_available(np) ||
> +		    hwid >= ARRAY_SIZE(__cpu_number_map))
> +			continue;
> +		if (cpu >= nr_cpu_ids) {
> +			of_node_put(np);
> +			break;
> +		}
> +		__cpu_number_map[hwid] = cpu;
> +		__cpu_logical_map[cpu] = hwid;
> +		set_cpu_possible(cpu, true);
> +		cpu++;
> +	}

[Severity: High]
Does omitting cpu_set_core() in xburst_smp_setup() and
xburst_init_secondary() suppress cross-CPU cache flush IPIs when
CONFIG_MIPS_CPS=y is enabled?

In arch/mips/kernel/cpu-probe.c, decode_configs() skips calling
cpu_set_core() when CONFIG_MIPS_CPS=y (which is enabled in generic kernels):

arch/mips/kernel/cpu-probe.c:decode_configs() {
    ...
#ifndef CONFIG_MIPS_CPS
	if (cpu_has_mips_r2_r6) {
		unsigned int core;

		core = get_ebase_cpunum();
		if (cpu_has_mipsmt)
			core >>= fls(core_nvpes()) - 1;
		cpu_set_core(c, core);
	}
#endif
}

Because neither xburst_smp_setup() nor xburst_init_secondary() calls
cpu_set_core(&cpu_data[cpu], hwid), both CPUs keep core ID 0, so
cpus_are_siblings(0, 1) returns true and calculate_cpu_foreign_map() leaves
cpu_foreign_map empty.  r4k_on_each_cpu() then skips sending IPIs to flush
the other core's private 32 KiB L1 I-cache and D-cache, leaving stale cache
lines across cores.

[ ... ]

> +static int xburst_boot_secondary(int cpu, struct task_struct *idle)
> +{
> +	unsigned long flags;
> +	u32 ctrl;
> +	int ret;
> +
> +	if (cpu_logical_map(cpu) != 1 || IS_ERR_OR_NULL(cpu1_clock))
> +		return -ENODEV;
> +
> +	raw_spin_lock_irqsave(&smp_lock, flags);
> +	ctrl = read_c0_corectrl() | CORECTRL_SWRST(1) | CORECTRL_RPC(1);
> +	write_c0_corectrl(ctrl);
> +	back_to_back_c0_hazard();
> +
> +	ret = clk_enable(cpu1_clock);

[Severity: Medium]
Does calling clk_enable(cpu1_clock) while holding the raw spinlock smp_lock
trigger an invalid wait context splat under CONFIG_PROVE_RAW_LOCK_NESTING?

clk_enable() acquires the non-raw spinlock_t enable_lock in
clk_enable_lock() and then calls jz4780_core1_enable(), which acquires the
non-raw spinlock_t cgu->lock and polls CGU_REG_LCR for up to 5 ms while
smp_lock is held with interrupts disabled.

[ ... ]

> +static const struct plat_smp_ops xburst_smp_ops = {
> +	.send_ipi_single = xburst_send_ipi_single,
> +	.send_ipi_mask = xburst_send_ipi_mask,
> +	.init_secondary = xburst_init_secondary,
> +	.smp_finish = xburst_smp_finish,
> +	.boot_secondary = xburst_boot_secondary,
> +	.smp_setup = xburst_smp_setup,
> +	.prepare_cpus = xburst_prepare_cpus,
> +};

[Severity: High]
When CONFIG_HOTPLUG_CPU=y is enabled (for example via CONFIG_MIPS_CPS=y in
generic_defconfig), does CPU1 fail to come online at boot, and does offlining
a CPU crash in __cpu_disable()?

In arch/mips/kernel/smp.c, smp_prepare_cpus() only initializes
cpu_present_mask from cpu_possible_mask when CONFIG_HOTPLUG_CPU is disabled.
Because neither xburst_smp_setup() nor xburst_prepare_cpus() calls
set_cpu_present(cpu, true), CPU1 is never marked present and
bringup_nonboot_cpus() never boots it.  In addition, __cpu_disable() and
__cpu_die() in arch/mips/include/asm/smp.h unconditionally call
mp_ops->cpu_disable() and mp_ops->cpu_die(), which are NULL in
xburst_smp_ops.

[ ... ]

> diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
> index 80e8a04a642e0..46526997a4c64 100644
> --- a/arch/mips/kernel/idle.c
> +++ b/arch/mips/kernel/idle.c
> @@ -18,6 +18,7 @@
>  #include <asm/cpu-type.h>
>  #include <asm/idle.h>
>  #include <asm/mipsregs.h>
> +#include <asm/r4kcache.h>
>  
>  /*
>   * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
> @@ -71,6 +72,23 @@ static void __cpuidle rm7k_wait_irqoff(void)
>  		"	.set	pop					\n");
>  }
>  
> +/* XBurst gates its private cache clock in WAIT; write back dirty data first. */
> +static void __cpuidle xburst_wait_irqoff(void)
> +{
> +	unsigned long pending = read_c0_cause() & read_c0_status() & CAUSEF_IP;
> +
> +	if (!need_resched() && !pending) {
> +		r4k_blast_dcache();
> +		__asm__ __volatile__(
> +			".set push\n"
> +			".set mips3\n"
> +			"sync\n"
> +			"wait\n"
> +			".set pop\n"
> +			: : : "memory");
> +	}
> +}
> +
>  /*
>   * Au1 'wait' is only useful when the 32kHz counter is used as timer,
>   * since coreclock (and the cp0 counter) stops upon executing it. Only an
> @@ -156,10 +174,16 @@ void __init check_wait(void)
>  	case CPU_CAVIUM_OCTEON_PLUS:
>  	case CPU_CAVIUM_OCTEON2:
>  	case CPU_CAVIUM_OCTEON3:
> -	case CPU_XBURST:
>  	case CPU_LOONGSON32:
>  		cpu_wait = r4k_wait;
>  		break;
> +	case CPU_XBURST:
> +		if (IS_ENABLED(CONFIG_MACH_JZ4780) &&
> +		    IS_ENABLED(CONFIG_SMP))
> +			cpu_wait = xburst_wait_irqoff;
> +		else
> +			cpu_wait = r4k_wait;
> +		break;

[Severity: High]
Does check_wait() select xburst_wait_irqoff() on single-core XBurst SoCs
(such as JZ4740, JZ4725B, JZ4770, X1000, and X1830) whenever a shared
Ingenic kernel is built with CONFIG_SMP=y?

CONFIG_MACH_INGENIC_GENERIC selects CONFIG_MACH_JZ4780 alongside the
single-core XBurst SoCs, and all of them report CPU_XBURST.  Using
compile-time IS_ENABLED() checks instead of a runtime check (such as
num_possible_cpus() > 1) forces every idle entry on UP XBurst machines to
write back and invalidate the entire 32 KiB L1 D-cache via
r4k_blast_dcache() and execute wait with local interrupts disabled, which
can also prevent interrupts from waking MIPS32r1 cores (JZ4740, JZ4725B).

Also, in xburst_wait_irqoff(), pending interrupts are only checked before
r4k_blast_dcache(), leaving a window during the full D-cache flush where a
newly pending interrupt is not re-checked before executing wait, and the
inline assembly uses .set mips3 rather than .set arch=r4000 like the other
wait helpers in this file.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261112041422.2997275-1-f.fainelli@gmail.com?part=2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs
  2026-11-12  4:14 [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
                   ` (2 preceding siblings ...)
  2026-11-12  4:14 ` [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
@ 2026-11-12  5:00 ` Florian Fainelli
  3 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2026-11-12  5:00 UTC (permalink / raw)
  To: linux-mips
  Cc: Thomas Bogendoerfer, Paul Burton, Paul Cercueil, Stephen Boyd,
	Brian Masney, Jerome Brunet,
	周琰杰 (Zhou Yanjie), Jiaxun Yang, open list,
	open list:COMMON CLK FRAMEWORK, hns, paul



On 11/11/2026 8:14 PM, Florian Fainelli wrote:
> This patch series resurrects SMP support for the CI20 board. This was
> submitted back in 2020 by Zhou Yanjie.
> 
> Changes in v3:
> 
> • Align the second line of the readl_poll_timeout_atomic() per Brian's
>    feedback
> • Collected Paul's R-b and T-b tags
> 
> Changes in v2:
> 
> • Moved SMP sources to arch/mips/ingenic/ and the header to arch/mips/include/asm/
> • Removed CONFIG_MIPS_INGENIC_SMP, using CONFIG_MACH_JZ4780 and CONFIG_SMP directly
> • Renamed JZ4780-specific SMP symbols to XBurst names
> • Changed CPU enumeration to assign consecutive logical IDs and removed the explicit two-core limit
> • Changed mailbox IRQ allocation failure from panic to logging and returning
> • Shortened commit descriptions, removed Codex attribution, and adjusted source credits and sign-offs
> • Kept the clock polling patch and CI20 defconfig changes unchanged,
>    added Paul's R-b for patch #1
> • Updated the kernel baseline to include additional upstream fixes

Looks like Sashiko found some issues to address, I will do that, re-test 
and re-spin.
-- 
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-11-12  5:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12  4:14 [PATCH v3 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
2026-11-12  4:14 ` [PATCH v3 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically Florian Fainelli
2026-11-12  4:14 ` [PATCH v3 2/3] MIPS: Ingenic: Add XBurst SMP support Florian Fainelli
2026-11-12  4:49   ` sashiko-bot
2026-11-12  4:14 ` [PATCH v3 3/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
2026-11-12  4:31   ` sashiko-bot
2026-11-12  5:00 ` [PATCH v3 0/3] " Florian Fainelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox