mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paul Cercueil <paul@crapouillou.net>
To: Florian Fainelli <f.fainelli@gmail.com>, linux-mips@vger.kernel.org
Cc: "周琰杰 (Zhou Yanjie)" <zhouyanjie@wanyeetech.com>,
	"Thomas Bogendoerfer" <tsbogend@alpha.franken.de>,
	"Paul Burton" <paulburton@kernel.org>,
	"Stephen Boyd" <sboyd@kernel.org>,
	"Brian Masney" <bmasney+clk@redhat.com>,
	"Jerome Brunet" <jbrunet+clk@baylibre.com>,
	"Jiaxun Yang" <jiaxun.yang@flygoat.com>,
	"open list" <linux-kernel@vger.kernel.org>,
	"open list:COMMON CLK FRAMEWORK" <linux-clk@vger.kernel.org>,
	hns@goldelico.com, paul@boddie.org.uk
Subject: Re: [PATCH v2 2/3] MIPS: Ingenic: Add XBurst SMP support
Date: Tue, 10 Nov 2026 16:30:46 +0100	[thread overview]
Message-ID: <1a29bb3bb70e761393b36520f9bb2a16ed466f14.camel@crapouillou.net> (raw)
In-Reply-To: <20261110043131.1985993-3-f.fainelli@gmail.com>

Hi Florian,

Le lundi 09 novembre 2026 à 20:31 -0800, Florian Fainelli a écrit :
> 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
> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
> [florian: forward ported to latest version]
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>

Reviewed-by: Paul Cercueil <paul@crapouillou.net>

Cheers,
-Paul

> ---
>  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) ||

  reply	other threads:[~2026-11-10 15:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10  4:31 [PATCH v2 0/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
2026-11-10  4:31 ` [PATCH v2 1/3] clk: ingenic: Poll JZ4780 CPU1 power status atomically Florian Fainelli
2026-11-10  4:31 ` [PATCH v2 2/3] MIPS: Ingenic: Add XBurst SMP support Florian Fainelli
2026-11-10 15:30   ` Paul Cercueil [this message]
2026-11-10  4:31 ` [PATCH v2 3/3] MIPS: CI20: Enable SMP with two CPUs Florian Fainelli
2026-11-10 15:31   ` Paul Cercueil
2026-11-10 15:44 ` [PATCH v2 0/3] " Paul Cercueil
2026-11-10 17:14   ` Florian Fainelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1a29bb3bb70e761393b36520f9bb2a16ed466f14.camel@crapouillou.net \
    --to=paul@crapouillou.net \
    --cc=bmasney+clk@redhat.com \
    --cc=f.fainelli@gmail.com \
    --cc=hns@goldelico.com \
    --cc=jbrunet+clk@baylibre.com \
    --cc=jiaxun.yang@flygoat.com \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=paul@boddie.org.uk \
    --cc=paulburton@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=tsbogend@alpha.franken.de \
    --cc=zhouyanjie@wanyeetech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®