All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Smith <alex.smith@imgtec.com>
To: Huacai Chen <chenhc@lemote.com>
Cc: Ralf Baechle <ralf@linux-mips.org>,
	John Crispin <john@phrozen.org>,
	"Steven J. Hill" <Steven.Hill@imgtec.com>,
	Aurelien Jarno <aurelien@aurel32.net>,
	<linux-mips@linux-mips.org>, Fuxin Zhang <zhangfx@lemote.com>,
	Zhangjin Wu <wuzhangjin@gmail.com>,
	Hongliang Tao <taohl@lemote.com>, Hua Yan <yanh@lemote.com>
Subject: Re: [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support
Date: Thu, 9 Jan 2014 13:19:32 +0000	[thread overview]
Message-ID: <52CEA1E4.5040406@imgtec.com> (raw)
In-Reply-To: <1389149068-24376-11-git-send-email-chenhc@lemote.com>

On 08/01/14 02:44, Huacai Chen wrote:
> IPI registers of Loongson-3 include IPI_SET, IPI_CLEAR, IPI_STATUS,
> IPI_EN and IPI_MAILBOX_BUF. Each bit of IPI_STATUS indicate a type of
> IPI and IPI_EN indicate whether the IPI is enabled. The sender write 1
> to IPI_SET bits generate IPIs in IPI_STATUS, and receiver write 1 to
> bits of IPI_CLEAR to clear IPIs. IPI_MAILBOX_BUF are used to deliver
> more information about IPIs.
>
> Why we change code in arch/mips/loongson/common/setup.c?
>
> If without this change, when SMP configured, system cannot boot since
> it hang at printk() in cgroup_init_early(). The root cause is:
>
> console_trylock()
>    \-->down_trylock(&console_sem)
>      \-->raw_spin_unlock_irqrestore(&sem->lock, flags)
>        \-->_raw_spin_unlock_irqrestore()(SMP/UP have different versions)
>          \-->__raw_spin_unlock_irqrestore()  (following is the SMP case)
>            \-->do_raw_spin_unlock()
>              \-->arch_spin_unlock()
>                \-->nudge_writes()
>                  \-->mb()
>                    \-->wbflush()
>                      \-->__wbflush()
>
> In previous code __wbflush() is initialized in plat_mem_setup(), but
> cgroup_init_early() is called before plat_mem_setup(). Therefore, In
> this patch we make changes to avoid boot failure.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |    2 +
>   arch/mips/include/asm/mach-loongson/loongson.h |    1 +
>   arch/mips/loongson/common/init.c               |    3 +
>   arch/mips/loongson/common/setup.c              |    8 +-
>   arch/mips/loongson/loongson-3/Makefile         |    2 +
>   arch/mips/loongson/loongson-3/irq.c            |   20 ++
>   arch/mips/loongson/loongson-3/smp.c            |  279 ++++++++++++++++++++++++
>   arch/mips/loongson/loongson-3/smp.h            |   24 ++
>   8 files changed, 334 insertions(+), 5 deletions(-)
>   create mode 100644 arch/mips/loongson/loongson-3/smp.c
>   create mode 100644 arch/mips/loongson/loongson-3/smp.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> index 5711e3b..d2f0e2a 100644
> --- a/arch/mips/include/asm/mach-loongson/irq.h
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -22,5 +22,7 @@
>
>   #endif
>
> +extern void loongson3_ipi_interrupt(struct pt_regs *regs);
> +
>   #include_next <irq.h>
>   #endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index 69e9d9e..f185907 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -27,6 +27,7 @@ extern void mach_prepare_shutdown(void);
>   /* environment arguments from bootloader */
>   extern u32 cpu_clock_freq;
>   extern u32 memsize, highmemsize;
> +extern struct plat_smp_ops loongson3_smp_ops;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index 81ba3b4..a7c521b 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -33,6 +33,9 @@ void __init prom_init(void)
>
>   	/*init the uart base address */
>   	prom_init_uart_base();
> +#if defined(CONFIG_SMP)
> +	register_smp_ops(&loongson3_smp_ops);
> +#endif
>   }
>
>   void __init prom_free_prom_memory(void)
> diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
> index 8223f8a..bb4ac92 100644
> --- a/arch/mips/loongson/common/setup.c
> +++ b/arch/mips/loongson/common/setup.c
> @@ -18,9 +18,6 @@
>   #include <linux/screen_info.h>
>   #endif
>
> -void (*__wbflush)(void);
> -EXPORT_SYMBOL(__wbflush);
> -
>   static void wbflush_loongson(void)
>   {
>   	asm(".set\tpush\n\t"
> @@ -32,10 +29,11 @@ static void wbflush_loongson(void)
>   	    ".set mips0\n\t");
>   }
>
> +void (*__wbflush)(void) = wbflush_loongson;
> +EXPORT_SYMBOL(__wbflush);
> +
>   void __init plat_mem_setup(void)
>   {
> -	__wbflush = wbflush_loongson;
> -
>   #ifdef CONFIG_VT
>   #if defined(CONFIG_VGA_CONSOLE)
>   	conswitchp = &vga_con;
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> index b9968cd..70152b2 100644
> --- a/arch/mips/loongson/loongson-3/Makefile
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -2,3 +2,5 @@
>   # Makefile for Loongson-3 family machines
>   #
>   obj-y			+= irq.o
> +
> +obj-$(CONFIG_SMP)	+= smp.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> index 3b52d56..d8920a8 100644
> --- a/arch/mips/loongson/loongson-3/irq.c
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -40,6 +40,10 @@ void mach_irq_dispatch(unsigned int pending)
>   {
>   	if (pending & CAUSEF_IP7)
>   		do_IRQ(LOONGSON_TIMER_IRQ);
> +#if defined(CONFIG_SMP)
> +	else if (pending & CAUSEF_IP6)
> +		loongson3_ipi_interrupt(NULL);
> +#endif
>   	else if (pending & CAUSEF_IP3)
>   		ht_irqdispatch();
>   	else if (pending & CAUSEF_IP2)
> @@ -59,10 +63,26 @@ static inline void mask_loongson_irq(struct irq_data *d)
>   {
>   	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_disable_hazard();
> +
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
>   }
>
>   static inline void unmask_loongson_irq(struct irq_data *d)
>   {
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
> +
>   	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_enable_hazard();
>   }
> diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
> new file mode 100644
> index 0000000..a264bcb
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.c
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
> + * Author: Chen Huacai, chenhc@lemote.com
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */

Don't need the FSF address again, as Aurelien said for patch 5.

> +
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/sched.h>
> +#include <linux/smp.h>
> +#include <linux/cpufreq.h>
> +#include <asm/processor.h>
> +#include <asm/time.h>
> +#include <asm/clock.h>
> +#include <asm/tlbflush.h>
> +#include <loongson.h>
> +
> +#include "smp.h"
> +
> +/* read a 64bit value from ipi register */
> +uint64_t loongson3_ipi_read64(void *addr)
> +{
> +	return readq(addr);
> +};
> +
> +/* write a 64bit value to ipi register */
> +void loongson3_ipi_write64(uint64_t action, void *addr)
> +{
> +	writeq(action, addr);
> +	__wbflush();
> +};
> +
> +/* read a 32bit value from ipi register */
> +uint32_t loongson3_ipi_read32(void *addr)
> +{
> +	return readl(addr);
> +};
> +
> +/* write a 32bit value to ipi register */
> +void loongson3_ipi_write32(uint32_t action, void *addr)
> +{
> +	writel(action, addr);
> +	__wbflush();
> +};

I don't see these used anywhere else outside this file, so add static. 
Also, remove the semicolons after the final brace on each function.

> +
> +static void *ipi_set0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + SET0),
> +};
> +
> +static void *ipi_clear0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + CLEAR0),
> +};
> +
> +static void *ipi_status0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + STATUS0),
> +};
> +
> +static void *ipi_en0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + EN0),
> +};
> +
> +static void *ipi_mailbox_buf[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core3_offset + BUF),
> +};
> +
> +/*
> + * Simple enough, just poke the appropriate ipi register
> + */
> +static void loongson3_send_ipi_single(int cpu, unsigned int action)
> +{
> +	loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
> +}
> +
> +static void
> +loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
> +{
> +	unsigned int i;
> +
> +	for_each_cpu(i, mask)
> +		loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
> +}
> +
> +void loongson3_ipi_interrupt(struct pt_regs *regs)
> +{
> +	int cpu = smp_processor_id();
> +	unsigned int action;
> +
> +	/* Load the ipi register to figure out what we're supposed to do */
> +	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
> +
> +	/* Clear the ipi register to clear the interrupt */
> +	loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
> +
> +	if (action & SMP_RESCHEDULE_YOURSELF)
> +		scheduler_ipi();
> +
> +	if (action & SMP_CALL_FUNCTION)
> +		smp_call_function_interrupt();
> +}
> +
> +/*
> + * SMP init and finish on secondary CPUs
> + */
> +void loongson3_init_secondary(void)
> +{
> +	int i;
> +	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
> +			     STATUSF_IP3 | STATUSF_IP2;
> +
> +	/* Set interrupt mask, but don't enable */
> +	change_c0_status(ST0_IM, imask);
> +
> +	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
> +		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
> +}
> +
> +void loongson3_smp_finish(void)
> +{
> +	write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
> +	local_irq_enable();
> +	loongson3_ipi_write64(0,
> +			(void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
> +	pr_info("CPU#%d finished, CP0_ST=%x\n",
> +			smp_processor_id(), read_c0_status());
> +}
> +
> +void __init loongson3_smp_setup(void)
> +{
> +	int i, num;
> +
> +	init_cpu_possible(cpu_none_mask);
> +	set_cpu_possible(0, true);
> +
> +	__cpu_number_map[0] = 0;
> +	__cpu_logical_map[0] = 0;
> +
> +	/* For unified kernel, NR_CPUS is the maximum possible value,
> +	 * loongson_sysconf.nr_cpus is the really present value */
> +	for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
> +		set_cpu_possible(i, true);
> +		__cpu_number_map[i] = ++num;
> +		__cpu_logical_map[num] = i;
> +	}
> +	pr_info("Detected %i available secondary CPU(s)\n", num);
> +}
> +
> +void __init loongson3_prepare_cpus(unsigned int max_cpus)
> +{
> +}
> +
> +/*
> + * Setup the PC, SP, and GP of a secondary processor and start it runing!
> + */
> +void loongson3_boot_secondary(int cpu, struct task_struct *idle)
> +{
> +	unsigned long startargs[4];
> +
> +	pr_info("Booting CPU#%d...\n", cpu);
> +
> +	/* startargs[] are initial PC, SP and GP for secondary CPU */
> +	startargs[0] = (unsigned long)&smp_bootstrap;
> +	startargs[1] = (unsigned long)__KSTK_TOS(idle);
> +	startargs[2] = (unsigned long)task_thread_info(idle);
> +	startargs[3] = 0;
> +
> +	pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
> +			cpu, startargs[0], startargs[1], startargs[2]);
> +
> +	loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
> +	loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
> +	loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
> +	loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
> +}
> +
> +/*
> + * Final cleanup after all secondaries booted
> + */
> +void __init loongson3_cpus_done(void)
> +{
> +}
> +
> +struct plat_smp_ops loongson3_smp_ops = {
> +	.send_ipi_single = loongson3_send_ipi_single,
> +	.send_ipi_mask = loongson3_send_ipi_mask,
> +	.init_secondary = loongson3_init_secondary,
> +	.smp_finish = loongson3_smp_finish,
> +	.cpus_done = loongson3_cpus_done,
> +	.boot_secondary = loongson3_boot_secondary,
> +	.smp_setup = loongson3_smp_setup,
> +	.prepare_cpus = loongson3_prepare_cpus,
> +};

Add static on all of the functions above referenced in 
loongson3_smp_ops, they aren't referenced outside this file.

> diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
> new file mode 100644
> index 0000000..dc9ce69
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.h
> @@ -0,0 +1,24 @@
> +/* for Loongson-3A smp support */
> +
> +/* 4 groups(nodes) in maximum in numa case */
> +#define  smp_core_group0_base    0x900000003ff01000
> +#define  smp_core_group1_base    0x900010003ff01000
> +#define  smp_core_group2_base    0x900020003ff01000
> +#define  smp_core_group3_base    0x900030003ff01000
> +
> +/* 4 cores in each group(node) */
> +#define  smp_core0_offset  0x000
> +#define  smp_core1_offset  0x100
> +#define  smp_core2_offset  0x200
> +#define  smp_core3_offset  0x300

Macros defining constants should have capitalized names.

> +
> +/* ipi registers offsets */
> +#define  STATUS0  0x00
> +#define  EN0      0x04
> +#define  SET0     0x08
> +#define  CLEAR0   0x0c
> +#define  STATUS1  0x10
> +#define  MASK1    0x14
> +#define  SET1     0x18
> +#define  CLEAR1   0x1c
> +#define  BUF      0x20
>

Even though it's only included from smp.c, headers should probably have 
include guard #ifdefs.

Thanks,
Alex

WARNING: multiple messages have this Message-ID (diff)
From: Alex Smith <alex.smith@imgtec.com>
To: Huacai Chen <chenhc@lemote.com>
Cc: Ralf Baechle <ralf@linux-mips.org>,
	John Crispin <john@phrozen.org>,
	"Steven J. Hill" <Steven.Hill@imgtec.com>,
	Aurelien Jarno <aurelien@aurel32.net>,
	linux-mips@linux-mips.org, Fuxin Zhang <zhangfx@lemote.com>,
	Zhangjin Wu <wuzhangjin@gmail.com>,
	Hongliang Tao <taohl@lemote.com>, Hua Yan <yanh@lemote.com>
Subject: Re: [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support
Date: Thu, 9 Jan 2014 13:19:32 +0000	[thread overview]
Message-ID: <52CEA1E4.5040406@imgtec.com> (raw)
Message-ID: <20140109131932.OXGbSxc19OJx4NkWu4uzxOIkAaHReoYtkOm_3DQnn94@z> (raw)
In-Reply-To: <1389149068-24376-11-git-send-email-chenhc@lemote.com>

On 08/01/14 02:44, Huacai Chen wrote:
> IPI registers of Loongson-3 include IPI_SET, IPI_CLEAR, IPI_STATUS,
> IPI_EN and IPI_MAILBOX_BUF. Each bit of IPI_STATUS indicate a type of
> IPI and IPI_EN indicate whether the IPI is enabled. The sender write 1
> to IPI_SET bits generate IPIs in IPI_STATUS, and receiver write 1 to
> bits of IPI_CLEAR to clear IPIs. IPI_MAILBOX_BUF are used to deliver
> more information about IPIs.
>
> Why we change code in arch/mips/loongson/common/setup.c?
>
> If without this change, when SMP configured, system cannot boot since
> it hang at printk() in cgroup_init_early(). The root cause is:
>
> console_trylock()
>    \-->down_trylock(&console_sem)
>      \-->raw_spin_unlock_irqrestore(&sem->lock, flags)
>        \-->_raw_spin_unlock_irqrestore()(SMP/UP have different versions)
>          \-->__raw_spin_unlock_irqrestore()  (following is the SMP case)
>            \-->do_raw_spin_unlock()
>              \-->arch_spin_unlock()
>                \-->nudge_writes()
>                  \-->mb()
>                    \-->wbflush()
>                      \-->__wbflush()
>
> In previous code __wbflush() is initialized in plat_mem_setup(), but
> cgroup_init_early() is called before plat_mem_setup(). Therefore, In
> this patch we make changes to avoid boot failure.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |    2 +
>   arch/mips/include/asm/mach-loongson/loongson.h |    1 +
>   arch/mips/loongson/common/init.c               |    3 +
>   arch/mips/loongson/common/setup.c              |    8 +-
>   arch/mips/loongson/loongson-3/Makefile         |    2 +
>   arch/mips/loongson/loongson-3/irq.c            |   20 ++
>   arch/mips/loongson/loongson-3/smp.c            |  279 ++++++++++++++++++++++++
>   arch/mips/loongson/loongson-3/smp.h            |   24 ++
>   8 files changed, 334 insertions(+), 5 deletions(-)
>   create mode 100644 arch/mips/loongson/loongson-3/smp.c
>   create mode 100644 arch/mips/loongson/loongson-3/smp.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> index 5711e3b..d2f0e2a 100644
> --- a/arch/mips/include/asm/mach-loongson/irq.h
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -22,5 +22,7 @@
>
>   #endif
>
> +extern void loongson3_ipi_interrupt(struct pt_regs *regs);
> +
>   #include_next <irq.h>
>   #endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index 69e9d9e..f185907 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -27,6 +27,7 @@ extern void mach_prepare_shutdown(void);
>   /* environment arguments from bootloader */
>   extern u32 cpu_clock_freq;
>   extern u32 memsize, highmemsize;
> +extern struct plat_smp_ops loongson3_smp_ops;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index 81ba3b4..a7c521b 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -33,6 +33,9 @@ void __init prom_init(void)
>
>   	/*init the uart base address */
>   	prom_init_uart_base();
> +#if defined(CONFIG_SMP)
> +	register_smp_ops(&loongson3_smp_ops);
> +#endif
>   }
>
>   void __init prom_free_prom_memory(void)
> diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
> index 8223f8a..bb4ac92 100644
> --- a/arch/mips/loongson/common/setup.c
> +++ b/arch/mips/loongson/common/setup.c
> @@ -18,9 +18,6 @@
>   #include <linux/screen_info.h>
>   #endif
>
> -void (*__wbflush)(void);
> -EXPORT_SYMBOL(__wbflush);
> -
>   static void wbflush_loongson(void)
>   {
>   	asm(".set\tpush\n\t"
> @@ -32,10 +29,11 @@ static void wbflush_loongson(void)
>   	    ".set mips0\n\t");
>   }
>
> +void (*__wbflush)(void) = wbflush_loongson;
> +EXPORT_SYMBOL(__wbflush);
> +
>   void __init plat_mem_setup(void)
>   {
> -	__wbflush = wbflush_loongson;
> -
>   #ifdef CONFIG_VT
>   #if defined(CONFIG_VGA_CONSOLE)
>   	conswitchp = &vga_con;
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> index b9968cd..70152b2 100644
> --- a/arch/mips/loongson/loongson-3/Makefile
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -2,3 +2,5 @@
>   # Makefile for Loongson-3 family machines
>   #
>   obj-y			+= irq.o
> +
> +obj-$(CONFIG_SMP)	+= smp.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> index 3b52d56..d8920a8 100644
> --- a/arch/mips/loongson/loongson-3/irq.c
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -40,6 +40,10 @@ void mach_irq_dispatch(unsigned int pending)
>   {
>   	if (pending & CAUSEF_IP7)
>   		do_IRQ(LOONGSON_TIMER_IRQ);
> +#if defined(CONFIG_SMP)
> +	else if (pending & CAUSEF_IP6)
> +		loongson3_ipi_interrupt(NULL);
> +#endif
>   	else if (pending & CAUSEF_IP3)
>   		ht_irqdispatch();
>   	else if (pending & CAUSEF_IP2)
> @@ -59,10 +63,26 @@ static inline void mask_loongson_irq(struct irq_data *d)
>   {
>   	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_disable_hazard();
> +
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
>   }
>
>   static inline void unmask_loongson_irq(struct irq_data *d)
>   {
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
> +
>   	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_enable_hazard();
>   }
> diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
> new file mode 100644
> index 0000000..a264bcb
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.c
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
> + * Author: Chen Huacai, chenhc@lemote.com
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */

Don't need the FSF address again, as Aurelien said for patch 5.

> +
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/sched.h>
> +#include <linux/smp.h>
> +#include <linux/cpufreq.h>
> +#include <asm/processor.h>
> +#include <asm/time.h>
> +#include <asm/clock.h>
> +#include <asm/tlbflush.h>
> +#include <loongson.h>
> +
> +#include "smp.h"
> +
> +/* read a 64bit value from ipi register */
> +uint64_t loongson3_ipi_read64(void *addr)
> +{
> +	return readq(addr);
> +};
> +
> +/* write a 64bit value to ipi register */
> +void loongson3_ipi_write64(uint64_t action, void *addr)
> +{
> +	writeq(action, addr);
> +	__wbflush();
> +};
> +
> +/* read a 32bit value from ipi register */
> +uint32_t loongson3_ipi_read32(void *addr)
> +{
> +	return readl(addr);
> +};
> +
> +/* write a 32bit value to ipi register */
> +void loongson3_ipi_write32(uint32_t action, void *addr)
> +{
> +	writel(action, addr);
> +	__wbflush();
> +};

I don't see these used anywhere else outside this file, so add static. 
Also, remove the semicolons after the final brace on each function.

> +
> +static void *ipi_set0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + SET0),
> +};
> +
> +static void *ipi_clear0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + CLEAR0),
> +};
> +
> +static void *ipi_status0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + STATUS0),
> +};
> +
> +static void *ipi_en0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + EN0),
> +};
> +
> +static void *ipi_mailbox_buf[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core3_offset + BUF),
> +};
> +
> +/*
> + * Simple enough, just poke the appropriate ipi register
> + */
> +static void loongson3_send_ipi_single(int cpu, unsigned int action)
> +{
> +	loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
> +}
> +
> +static void
> +loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
> +{
> +	unsigned int i;
> +
> +	for_each_cpu(i, mask)
> +		loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
> +}
> +
> +void loongson3_ipi_interrupt(struct pt_regs *regs)
> +{
> +	int cpu = smp_processor_id();
> +	unsigned int action;
> +
> +	/* Load the ipi register to figure out what we're supposed to do */
> +	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
> +
> +	/* Clear the ipi register to clear the interrupt */
> +	loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
> +
> +	if (action & SMP_RESCHEDULE_YOURSELF)
> +		scheduler_ipi();
> +
> +	if (action & SMP_CALL_FUNCTION)
> +		smp_call_function_interrupt();
> +}
> +
> +/*
> + * SMP init and finish on secondary CPUs
> + */
> +void loongson3_init_secondary(void)
> +{
> +	int i;
> +	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
> +			     STATUSF_IP3 | STATUSF_IP2;
> +
> +	/* Set interrupt mask, but don't enable */
> +	change_c0_status(ST0_IM, imask);
> +
> +	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
> +		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
> +}
> +
> +void loongson3_smp_finish(void)
> +{
> +	write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
> +	local_irq_enable();
> +	loongson3_ipi_write64(0,
> +			(void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
> +	pr_info("CPU#%d finished, CP0_ST=%x\n",
> +			smp_processor_id(), read_c0_status());
> +}
> +
> +void __init loongson3_smp_setup(void)
> +{
> +	int i, num;
> +
> +	init_cpu_possible(cpu_none_mask);
> +	set_cpu_possible(0, true);
> +
> +	__cpu_number_map[0] = 0;
> +	__cpu_logical_map[0] = 0;
> +
> +	/* For unified kernel, NR_CPUS is the maximum possible value,
> +	 * loongson_sysconf.nr_cpus is the really present value */
> +	for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
> +		set_cpu_possible(i, true);
> +		__cpu_number_map[i] = ++num;
> +		__cpu_logical_map[num] = i;
> +	}
> +	pr_info("Detected %i available secondary CPU(s)\n", num);
> +}
> +
> +void __init loongson3_prepare_cpus(unsigned int max_cpus)
> +{
> +}
> +
> +/*
> + * Setup the PC, SP, and GP of a secondary processor and start it runing!
> + */
> +void loongson3_boot_secondary(int cpu, struct task_struct *idle)
> +{
> +	unsigned long startargs[4];
> +
> +	pr_info("Booting CPU#%d...\n", cpu);
> +
> +	/* startargs[] are initial PC, SP and GP for secondary CPU */
> +	startargs[0] = (unsigned long)&smp_bootstrap;
> +	startargs[1] = (unsigned long)__KSTK_TOS(idle);
> +	startargs[2] = (unsigned long)task_thread_info(idle);
> +	startargs[3] = 0;
> +
> +	pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
> +			cpu, startargs[0], startargs[1], startargs[2]);
> +
> +	loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
> +	loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
> +	loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
> +	loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
> +}
> +
> +/*
> + * Final cleanup after all secondaries booted
> + */
> +void __init loongson3_cpus_done(void)
> +{
> +}
> +
> +struct plat_smp_ops loongson3_smp_ops = {
> +	.send_ipi_single = loongson3_send_ipi_single,
> +	.send_ipi_mask = loongson3_send_ipi_mask,
> +	.init_secondary = loongson3_init_secondary,
> +	.smp_finish = loongson3_smp_finish,
> +	.cpus_done = loongson3_cpus_done,
> +	.boot_secondary = loongson3_boot_secondary,
> +	.smp_setup = loongson3_smp_setup,
> +	.prepare_cpus = loongson3_prepare_cpus,
> +};

Add static on all of the functions above referenced in 
loongson3_smp_ops, they aren't referenced outside this file.

> diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
> new file mode 100644
> index 0000000..dc9ce69
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.h
> @@ -0,0 +1,24 @@
> +/* for Loongson-3A smp support */
> +
> +/* 4 groups(nodes) in maximum in numa case */
> +#define  smp_core_group0_base    0x900000003ff01000
> +#define  smp_core_group1_base    0x900010003ff01000
> +#define  smp_core_group2_base    0x900020003ff01000
> +#define  smp_core_group3_base    0x900030003ff01000
> +
> +/* 4 cores in each group(node) */
> +#define  smp_core0_offset  0x000
> +#define  smp_core1_offset  0x100
> +#define  smp_core2_offset  0x200
> +#define  smp_core3_offset  0x300

Macros defining constants should have capitalized names.

> +
> +/* ipi registers offsets */
> +#define  STATUS0  0x00
> +#define  EN0      0x04
> +#define  SET0     0x08
> +#define  CLEAR0   0x0c
> +#define  STATUS1  0x10
> +#define  MASK1    0x14
> +#define  SET1     0x18
> +#define  CLEAR1   0x1c
> +#define  BUF      0x20
>

Even though it's only included from smp.c, headers should probably have 
include guard #ifdefs.

Thanks,
Alex

  reply	other threads:[~2014-01-09 13:20 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H4tx=sCk=iUwuCfnCS+rbmtu5Y_UcpAn6JXDoobA+OGrQ@mail.gmail.com>
2014-01-09 21:36       ` Aurelien Jarno
2014-01-12  9:03         ` Huacai Chen
2014-01-12  9:57           ` Aurelien Jarno
2014-01-12 12:10             ` Aaro Koskinen
2014-01-18  1:54               ` John Crispin
2014-01-08  2:44 ` [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-09 12:43     ` Alex Smith
2014-01-09 12:43       ` Alex Smith
     [not found]     ` <CAAhV-H64BXsw5CBL-KW1eqXkYcadhHF2NeBH9YmWQz046Lpzzw@mail.gmail.com>
2014-01-09 21:37       ` Aurelien Jarno
2014-01-09 12:37   ` Alex Smith
2014-01-09 12:37     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H57tDmYByjVwhf3teFZkGowR4E9+OO1vO0kP3iAKTNJVw@mail.gmail.com>
2014-01-09 21:38       ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-09 12:52   ` Alex Smith
2014-01-09 12:52     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB) Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H4h43N2OR4znwVv3miVbGkWJLapdgr9Jou1j4R8-9TRyA@mail.gmail.com>
2014-01-09 22:08       ` Aurelien Jarno
     [not found]         ` <CAAhV-H7WFdt-4jYG5qPV36UWJQnSfkSa2J-3CAs2+QLqwHVhuA@mail.gmail.com>
2014-01-11 15:24           ` Aurelien Jarno
2014-01-09 12:56   ` Alex Smith
2014-01-09 12:56     ` Alex Smith
     [not found]     ` <CAAhV-H7ZO0gNzQ5wQ-yD=NiP2AJrc3-bWLXHo-HDngf27c9+gQ@mail.gmail.com>
2014-01-11 15:25       ` Aurelien Jarno
2014-01-12  9:12         ` Huacai Chen
2014-01-12  9:57           ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options Huacai Chen
2014-01-09 13:07   ` Alex Smith
2014-01-09 13:07     ` Alex Smith
2014-01-11 15:24     ` Aurelien Jarno
2014-01-13  3:02       ` Huacai Chen
2014-01-13  4:30         ` Aurelien Jarno
2014-01-13 10:15           ` Huacai Chen
2014-01-13 10:38             ` Aurelien Jarno
2014-01-13 12:15               ` Huacai Chen
2014-01-08  2:44 ` [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support Huacai Chen
2014-01-09 13:19   ` Alex Smith [this message]
2014-01-09 13:19     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support Huacai Chen
2014-01-11 15:24   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 12/12] MIPS: Loongson: Add a Loongson-3 default config file Huacai Chen
2014-01-08  7:26 ` [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support John Crispin
2014-01-18  9:38 ` Andreas Barth
     [not found]   ` <0466fa9d60b91233d2157d5ce0b51333.squirrel@mail.lemote.com>
2014-02-06 23:27     ` Andreas Barth

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=52CEA1E4.5040406@imgtec.com \
    --to=alex.smith@imgtec.com \
    --cc=Steven.Hill@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=chenhc@lemote.com \
    --cc=john@phrozen.org \
    --cc=linux-mips@linux-mips.org \
    --cc=ralf@linux-mips.org \
    --cc=taohl@lemote.com \
    --cc=wuzhangjin@gmail.com \
    --cc=yanh@lemote.com \
    --cc=zhangfx@lemote.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.