1
0
Fork 0
alistair23-linux/arch/mips/loongson64/loongson-3/smp.c

748 lines
25 KiB
C
Raw Normal View History

treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157 Based on 3 normalized pattern(s): 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 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 [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] 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 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 [author] [graeme] [gregory] [gg]@[slimlogic] [co] [uk] [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] [based] [on] [twl6030]_[usb] [c] [author] [hema] [hk] [hemahk]@[ti] [com] 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 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 1105 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Richard Fontana <rfontana@redhat.com> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070033.202006027@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-27 00:55:06 -06:00
// SPDX-License-Identifier: GPL-2.0-or-later
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/*
* Copyright (C) 2010, 2011, 2012, Lemote, Inc.
* Author: Chen Huacai, chenhc@lemote.com
*/
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/sched.h>
#include <linux/sched/hotplug.h>
#include <linux/sched/task_stack.h>
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
#include <linux/smp.h>
#include <linux/cpufreq.h>
#include <linux/kexec.h>
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
#include <asm/processor.h>
#include <asm/time.h>
#include <asm/clock.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
#include <loongson.h>
#include <workarounds.h>
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
#include "smp.h"
DEFINE_PER_CPU(int, cpu_state);
static void *ipi_set0_regs[16];
static void *ipi_clear0_regs[16];
static void *ipi_status0_regs[16];
static void *ipi_en0_regs[16];
static void *ipi_mailbox_buf[16];
static uint32_t core0_c0count[NR_CPUS];
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/* read a 32bit value from ipi register */
#define loongson3_ipi_read32(addr) readl(addr)
/* read a 64bit value from ipi register */
#define loongson3_ipi_read64(addr) readq(addr)
/* write a 32bit value to ipi register */
#define loongson3_ipi_write32(action, addr) \
do { \
writel(action, addr); \
__wbflush(); \
} while (0)
/* write a 64bit value to ipi register */
#define loongson3_ipi_write64(action, addr) \
do { \
writeq(action, addr); \
__wbflush(); \
} while (0)
static void ipi_set0_regs_init(void)
{
ipi_set0_regs[0] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
ipi_set0_regs[1] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
ipi_set0_regs[2] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
ipi_set0_regs[3] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
ipi_set0_regs[4] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
ipi_set0_regs[5] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
ipi_set0_regs[6] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
ipi_set0_regs[7] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
ipi_set0_regs[8] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
ipi_set0_regs[9] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
ipi_set0_regs[10] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
ipi_set0_regs[11] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
ipi_set0_regs[12] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
ipi_set0_regs[13] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
ipi_set0_regs[14] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
ipi_set0_regs[15] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
static void ipi_clear0_regs_init(void)
{
ipi_clear0_regs[0] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
ipi_clear0_regs[1] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
ipi_clear0_regs[2] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
ipi_clear0_regs[3] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
ipi_clear0_regs[4] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
ipi_clear0_regs[5] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
ipi_clear0_regs[6] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
ipi_clear0_regs[7] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
ipi_clear0_regs[8] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
ipi_clear0_regs[9] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
ipi_clear0_regs[10] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
ipi_clear0_regs[11] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
ipi_clear0_regs[12] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
ipi_clear0_regs[13] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
ipi_clear0_regs[14] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
ipi_clear0_regs[15] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
static void ipi_status0_regs_init(void)
{
ipi_status0_regs[0] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
ipi_status0_regs[1] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
ipi_status0_regs[2] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
ipi_status0_regs[3] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
ipi_status0_regs[4] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
ipi_status0_regs[5] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
ipi_status0_regs[6] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
ipi_status0_regs[7] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
ipi_status0_regs[8] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
ipi_status0_regs[9] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
ipi_status0_regs[10] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
ipi_status0_regs[11] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
ipi_status0_regs[12] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
ipi_status0_regs[13] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
ipi_status0_regs[14] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
ipi_status0_regs[15] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
static void ipi_en0_regs_init(void)
{
ipi_en0_regs[0] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
ipi_en0_regs[1] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
ipi_en0_regs[2] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
ipi_en0_regs[3] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
ipi_en0_regs[4] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
ipi_en0_regs[5] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
ipi_en0_regs[6] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
ipi_en0_regs[7] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
ipi_en0_regs[8] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
ipi_en0_regs[9] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
ipi_en0_regs[10] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
ipi_en0_regs[11] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
ipi_en0_regs[12] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
ipi_en0_regs[13] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
ipi_en0_regs[14] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
ipi_en0_regs[15] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
static void ipi_mailbox_buf_init(void)
{
ipi_mailbox_buf[0] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
ipi_mailbox_buf[1] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
ipi_mailbox_buf[2] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
ipi_mailbox_buf[3] = (void *)
(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
ipi_mailbox_buf[4] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
ipi_mailbox_buf[5] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
ipi_mailbox_buf[6] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
ipi_mailbox_buf[7] = (void *)
(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
ipi_mailbox_buf[8] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
ipi_mailbox_buf[9] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
ipi_mailbox_buf[10] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
ipi_mailbox_buf[11] = (void *)
(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
ipi_mailbox_buf[12] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
ipi_mailbox_buf[13] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
ipi_mailbox_buf[14] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
ipi_mailbox_buf[15] = (void *)
(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/*
* 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_logical_map(cpu)]);
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
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[cpu_logical_map(i)]);
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
#define IPI_IRQ_OFFSET 6
void loongson3_send_irq_by_ipi(int cpu, int irqs)
{
loongson3_ipi_write32(irqs << IPI_IRQ_OFFSET, ipi_set0_regs[cpu_logical_map(cpu)]);
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
void loongson3_ipi_interrupt(struct pt_regs *regs)
{
int i, cpu = smp_processor_id();
unsigned int action, c0count, irqs;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/* Load the ipi register to figure out what we're supposed to do */
action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]);
irqs = action >> IPI_IRQ_OFFSET;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/* Clear the ipi register to clear the interrupt */
loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]);
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
if (action & SMP_CALL_FUNCTION) {
irq_enter();
generic_smp_call_function_interrupt();
irq_exit();
}
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
c0count = read_c0_count();
c0count = c0count ? c0count : 1;
for (i = 1; i < nr_cpu_ids; i++)
core0_c0count[i] = c0count;
__wbflush(); /* Let others see the result ASAP */
}
if (irqs) {
int irq;
while ((irq = ffs(irqs))) {
do_IRQ(irq-1);
irqs &= ~(1<<(irq-1));
}
}
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
#define MAX_LOOPS 800
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
/*
* SMP init and finish on secondary CPUs
*/
static void loongson3_init_secondary(void)
{
int i;
uint32_t initcount;
unsigned int cpu = smp_processor_id();
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
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 < num_possible_cpus(); i++)
loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(i)]);
per_cpu(cpu_state, cpu) = CPU_ONLINE;
cpu_set_core(&cpu_data[cpu],
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package);
cpu_data[cpu].package =
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
i = 0;
core0_c0count[cpu] = 0;
loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
while (!core0_c0count[cpu]) {
i++;
cpu_relax();
}
if (i > MAX_LOOPS)
i = MAX_LOOPS;
if (cpu_data[cpu].package)
initcount = core0_c0count[cpu] + i;
else /* Local access is faster for loops */
initcount = core0_c0count[cpu] + i/2;
write_c0_count(initcount);
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
static void loongson3_smp_finish(void)
{
int cpu = smp_processor_id();
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
local_irq_enable();
loongson3_ipi_write64(0,
ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0);
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
pr_info("CPU#%d finished, CP0_ST=%x\n",
smp_processor_id(), read_c0_status());
}
static void __init loongson3_smp_setup(void)
{
int i = 0, num = 0; /* i: physical id, num: logical id */
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
init_cpu_possible(cpu_none_mask);
/* For unified kernel, NR_CPUS is the maximum possible value,
* loongson_sysconf.nr_cpus is the really present value */
while (i < loongson_sysconf.nr_cpus) {
if (loongson_sysconf.reserved_cpus_mask & (1<<i)) {
/* Reserved physical CPU cores */
__cpu_number_map[i] = -1;
} else {
__cpu_number_map[i] = num;
__cpu_logical_map[num] = i;
set_cpu_possible(num, true);
num++;
}
i++;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
pr_info("Detected %i available CPU(s)\n", num);
while (num < loongson_sysconf.nr_cpus) {
__cpu_logical_map[num] = -1;
num++;
}
ipi_set0_regs_init();
ipi_clear0_regs_init();
ipi_status0_regs_init();
ipi_en0_regs_init();
ipi_mailbox_buf_init();
cpu_set_core(&cpu_data[0],
cpu_logical_map(0) % loongson_sysconf.cores_per_package);
cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
static void __init loongson3_prepare_cpus(unsigned int max_cpus)
{
init_cpu_present(cpu_possible_mask);
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
/*
* Setup the PC, SP, and GP of a secondary processor and start it runing!
*/
static int loongson3_boot_secondary(int cpu, struct task_struct *idle)
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
{
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],
ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x18);
loongson3_ipi_write64(startargs[2],
ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x10);
loongson3_ipi_write64(startargs[1],
ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x8);
loongson3_ipi_write64(startargs[0],
ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0);
return 0;
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
}
#ifdef CONFIG_HOTPLUG_CPU
static int loongson3_cpu_disable(void)
{
unsigned long flags;
unsigned int cpu = smp_processor_id();
if (cpu == 0)
return -EBUSY;
set_cpu_online(cpu, false);
calculate_cpu_foreign_map();
local_irq_save(flags);
fixup_irqs();
local_irq_restore(flags);
local_flush_tlb_all();
return 0;
}
static void loongson3_cpu_die(unsigned int cpu)
{
while (per_cpu(cpu_state, cpu) != CPU_DEAD)
cpu_relax();
mb();
}
/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
* flush all L1 entries at first. Then, another core (usually Core 0) can
* safely disable the clock of the target core. loongson3_play_dead() is
* called via CKSEG1 (uncached and unmmaped) */
static void loongson3a_r1_play_dead(int *state_addr)
{
register int val;
register long cpuid, core, node, count;
register void *addr, *base, *initfunc;
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
" cache 0, 1(%[addr]) \n"
" cache 0, 2(%[addr]) \n"
" cache 0, 3(%[addr]) \n"
" cache 1, 0(%[addr]) \n" /* flush L1 DCache */
" cache 1, 1(%[addr]) \n"
" cache 1, 2(%[addr]) \n"
" cache 1, 3(%[addr]) \n"
" addiu %[sets], %[sets], -1 \n"
" bnez %[sets], 1b \n"
" addiu %[addr], %[addr], 0x20 \n"
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n"
" sync \n"
" cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
" .set pop \n"
: [addr] "=&r" (addr), [val] "=&r" (val)
: [state_addr] "r" (state_addr),
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set mips64 \n"
" mfc0 %[cpuid], $15, 1 \n"
" andi %[cpuid], 0x3ff \n"
" dli %[base], 0x900000003ff01000 \n"
" andi %[core], %[cpuid], 0x3 \n"
" sll %[core], 8 \n" /* get core id */
" or %[base], %[base], %[core] \n"
" andi %[node], %[cpuid], 0xc \n"
" dsll %[node], 42 \n" /* get node id */
" or %[base], %[base], %[node] \n"
"1: li %[count], 0x100 \n" /* wait for init loop */
"2: bnez %[count], 2b \n" /* limit mailbox access */
" addiu %[count], -1 \n"
" ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
" beqz %[initfunc], 1b \n"
" nop \n"
" ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n"
" jr %[initfunc] \n" /* jump to initial PC */
" nop \n"
" .set pop \n"
: [core] "=&r" (core), [node] "=&r" (node),
[base] "=&r" (base), [cpuid] "=&r" (cpuid),
[count] "=&r" (count), [initfunc] "=&r" (initfunc)
: /* No Input */
: "a1");
}
static void loongson3a_r2r3_play_dead(int *state_addr)
{
register int val;
register long cpuid, core, node, count;
register void *addr, *base, *initfunc;
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
" cache 0, 1(%[addr]) \n"
" cache 0, 2(%[addr]) \n"
" cache 0, 3(%[addr]) \n"
" cache 1, 0(%[addr]) \n" /* flush L1 DCache */
" cache 1, 1(%[addr]) \n"
" cache 1, 2(%[addr]) \n"
" cache 1, 3(%[addr]) \n"
" addiu %[sets], %[sets], -1 \n"
" bnez %[sets], 1b \n"
" addiu %[addr], %[addr], 0x40 \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */
" cache 2, 1(%[addr]) \n"
" cache 2, 2(%[addr]) \n"
" cache 2, 3(%[addr]) \n"
" cache 2, 4(%[addr]) \n"
" cache 2, 5(%[addr]) \n"
" cache 2, 6(%[addr]) \n"
" cache 2, 7(%[addr]) \n"
" cache 2, 8(%[addr]) \n"
" cache 2, 9(%[addr]) \n"
" cache 2, 10(%[addr]) \n"
" cache 2, 11(%[addr]) \n"
" cache 2, 12(%[addr]) \n"
" cache 2, 13(%[addr]) \n"
" cache 2, 14(%[addr]) \n"
" cache 2, 15(%[addr]) \n"
" addiu %[vsets], %[vsets], -1 \n"
" bnez %[vsets], 2b \n"
" addiu %[addr], %[addr], 0x40 \n"
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n"
" sync \n"
" cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
" .set pop \n"
: [addr] "=&r" (addr), [val] "=&r" (val)
: [state_addr] "r" (state_addr),
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
[vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set mips64 \n"
" mfc0 %[cpuid], $15, 1 \n"
" andi %[cpuid], 0x3ff \n"
" dli %[base], 0x900000003ff01000 \n"
" andi %[core], %[cpuid], 0x3 \n"
" sll %[core], 8 \n" /* get core id */
" or %[base], %[base], %[core] \n"
" andi %[node], %[cpuid], 0xc \n"
" dsll %[node], 42 \n" /* get node id */
" or %[base], %[base], %[node] \n"
"1: li %[count], 0x100 \n" /* wait for init loop */
"2: bnez %[count], 2b \n" /* limit mailbox access */
" addiu %[count], -1 \n"
" ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
" beqz %[initfunc], 1b \n"
" nop \n"
" ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n"
" jr %[initfunc] \n" /* jump to initial PC */
" nop \n"
" .set pop \n"
: [core] "=&r" (core), [node] "=&r" (node),
[base] "=&r" (base), [cpuid] "=&r" (cpuid),
[count] "=&r" (count), [initfunc] "=&r" (initfunc)
: /* No Input */
: "a1");
}
static void loongson3b_play_dead(int *state_addr)
{
register int val;
register long cpuid, core, node, count;
register void *addr, *base, *initfunc;
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" li %[addr], 0x80000000 \n" /* KSEG0 */
"1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
" cache 0, 1(%[addr]) \n"
" cache 0, 2(%[addr]) \n"
" cache 0, 3(%[addr]) \n"
" cache 1, 0(%[addr]) \n" /* flush L1 DCache */
" cache 1, 1(%[addr]) \n"
" cache 1, 2(%[addr]) \n"
" cache 1, 3(%[addr]) \n"
" addiu %[sets], %[sets], -1 \n"
" bnez %[sets], 1b \n"
" addiu %[addr], %[addr], 0x20 \n"
" li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n"
" sync \n"
" cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
" .set pop \n"
: [addr] "=&r" (addr), [val] "=&r" (val)
: [state_addr] "r" (state_addr),
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set mips64 \n"
" mfc0 %[cpuid], $15, 1 \n"
" andi %[cpuid], 0x3ff \n"
" dli %[base], 0x900000003ff01000 \n"
" andi %[core], %[cpuid], 0x3 \n"
" sll %[core], 8 \n" /* get core id */
" or %[base], %[base], %[core] \n"
" andi %[node], %[cpuid], 0xc \n"
" dsll %[node], 42 \n" /* get node id */
" or %[base], %[base], %[node] \n"
" dsrl %[node], 30 \n" /* 15:14 */
" or %[base], %[base], %[node] \n"
"1: li %[count], 0x100 \n" /* wait for init loop */
"2: bnez %[count], 2b \n" /* limit mailbox access */
" addiu %[count], -1 \n"
" ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
" beqz %[initfunc], 1b \n"
" nop \n"
" ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n"
" jr %[initfunc] \n" /* jump to initial PC */
" nop \n"
" .set pop \n"
: [core] "=&r" (core), [node] "=&r" (node),
[base] "=&r" (base), [cpuid] "=&r" (cpuid),
[count] "=&r" (count), [initfunc] "=&r" (initfunc)
: /* No Input */
: "a1");
}
void play_dead(void)
{
int *state_addr;
unsigned int cpu = smp_processor_id();
void (*play_dead_at_ckseg1)(int *);
idle_task_exit();
switch (read_c0_prid() & PRID_REV_MASK) {
case PRID_REV_LOONGSON3A_R1:
default:
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
break;
case PRID_REV_LOONGSON3A_R2_0:
case PRID_REV_LOONGSON3A_R2_1:
case PRID_REV_LOONGSON3A_R3_0:
case PRID_REV_LOONGSON3A_R3_1:
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
break;
case PRID_REV_LOONGSON3B_R1:
case PRID_REV_LOONGSON3B_R2:
play_dead_at_ckseg1 =
(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
break;
}
state_addr = &per_cpu(cpu_state, cpu);
mb();
play_dead_at_ckseg1(state_addr);
}
static int loongson3_disable_clock(unsigned int cpu)
{
uint64_t core_id = cpu_core(&cpu_data[cpu]);
uint64_t package_id = cpu_data[cpu].package;
if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
} else {
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
}
return 0;
}
static int loongson3_enable_clock(unsigned int cpu)
{
uint64_t core_id = cpu_core(&cpu_data[cpu]);
uint64_t package_id = cpu_data[cpu].package;
if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
} else {
if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
}
return 0;
}
static int register_loongson3_notifier(void)
{
return cpuhp_setup_state_nocalls(CPUHP_MIPS_SOC_PREPARE,
"mips/loongson:prepare",
loongson3_enable_clock,
loongson3_disable_clock);
}
early_initcall(register_loongson3_notifier);
#endif
MIPS: SMP: Constify smp ops smp_ops providers do not modify their ops structures, so they should be made const for robustness. Since currently the MIPS kernel is not mapped with memory protection, this does not in itself provide any security benefit, but it still makes sense to make this change. There are also slight code size efficincies from the structure being made read-only, saving 128 bytes of kernel text on a pistachio_defconfig. Before: text data bss dec hex filename 7187239 1772752 470224 9430215 8fe4c7 vmlinux After: text data bss dec hex filename 7187111 1772752 470224 9430087 8fe447 vmlinux Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Marcin Nowakowski <marcin.nowakowski@imgtec.com> Cc: Bart Van Assche <bart.vanassche@sandisk.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Huacai Chen <chenhc@lemote.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Kevin Cernekee <cernekee@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Doug Ledford <dledford@redhat.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: Joe Perches <joe@perches.com> Cc: Florian Fainelli <f.fainelli@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Steven J. Hill <steven.hill@cavium.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/16784/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2017-07-19 02:21:03 -06:00
const struct plat_smp_ops loongson3_smp_ops = {
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
.send_ipi_single = loongson3_send_ipi_single,
.send_ipi_mask = loongson3_send_ipi_mask,
.init_secondary = loongson3_init_secondary,
.smp_finish = loongson3_smp_finish,
.boot_secondary = loongson3_boot_secondary,
.smp_setup = loongson3_smp_setup,
.prepare_cpus = loongson3_prepare_cpus,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = loongson3_cpu_disable,
.cpu_die = loongson3_cpu_die,
#endif
#ifdef CONFIG_KEXEC
.kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
#endif
MIPS: Loongson 3: Add Loongson-3 SMP support 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> Tested-by: Alex Smith <alex.smith@imgtec.com> Reviewed-by: Alex Smith <alex.smith@imgtec.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/6638 Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-03-21 04:44:08 -06:00
};