Skip to contentSkip to conversation

MIPS: Loongson: new features and improvements

PATCH Superseded Huacai Chen 4 participants 34 messages Jan 27, 2018 – Mar 1, 2018

Subsystems (7)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v2 cover MIPS: Loongson: new features and improvements

This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in /proc/cpuinfo which is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introduces WAR_LLSC_MB to improve stability.

V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.

Huacai Chen(12):
MIPS: Loongson: Add Loongson-3A R3.1 basic support.
MIPS: Loongson-3: Define and use some CP0 registers.
MIPS: Loongson-3: Enable Store Fill Buffer at runtime.
MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3.
MIPS: Loongson fix name confict - MEM_RESERVED.
MIPS: Ensure pmd_present() returns false after pmd_mknotpresent().
MIPS: Add __cpu_full_name[] to make CPU names more human-readable.
MIPS: Align kernel load address to 64KB.
MIPS: Loongson: Add kexec/kdump support.
MIPS: Loongson: Make CPUFreq usable for Loongson-3.
MIPS: Loongson-3: Fix CPU UART irq delivery problem.
MIPS: Loongson: Introduce and use WAR_LLSC_MB.

---
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   5 +-
 arch/mips/include/asm/atomic.h                     |  18 +-
 arch/mips/include/asm/barrier.h                    |   6 +
 arch/mips/include/asm/bitops.h                     |  15 ++
 arch/mips/include/asm/cmpxchg.h                    |   9 +-
 arch/mips/include/asm/cpu-info.h                   |   2 +
 arch/mips/include/asm/cpu.h                        |  51 ++---
 arch/mips/include/asm/edac.h                       |   5 +-
 arch/mips/include/asm/futex.h                      |  18 +-
 arch/mips/include/asm/io.h                         |   2 +-
 arch/mips/include/asm/local.h                      |  10 +-
 arch/mips/include/asm/mach-loongson64/boot_param.h |   3 +-
 .../asm/mach-loongson64/kernel-entry-init.h        |  38 ++--
 arch/mips/include/asm/mach-loongson64/loongson.h   |   1 +
 arch/mips/include/asm/mipsregs.h                   |   2 +
 arch/mips/include/asm/pgtable-64.h                 |   5 +
 arch/mips/include/asm/pgtable.h                    |   5 +-
 arch/mips/include/asm/r4kcache.h                   |  34 +++
 arch/mips/include/asm/time.h                       |   2 +
 arch/mips/kernel/cpu-probe.c                       |  28 ++-
 arch/mips/kernel/proc.c                            |   7 +
 arch/mips/kernel/relocate_kernel.S                 |  30 +++
 arch/mips/kernel/smp.c                             |   3 +-
 arch/mips/kernel/syscall.c                         |   2 +
 arch/mips/kernel/time.c                            |   2 +
 arch/mips/loongson64/Kconfig                       |   1 +
 arch/mips/loongson64/Platform                      |   3 +
 arch/mips/loongson64/common/env.c                  |  24 ++-
 arch/mips/loongson64/common/mem.c                  |   2 +-
 arch/mips/loongson64/common/platform.c             |  13 +-
 arch/mips/loongson64/common/reset.c                | 119 +++++++++++
 arch/mips/loongson64/loongson-3/Makefile           |   2 +-
 arch/mips/loongson64/loongson-3/clock.c            | 191 +++++++++++++++++
 arch/mips/loongson64/loongson-3/irq.c              |  41 +---
 arch/mips/loongson64/loongson-3/numa.c             |   2 +-
 arch/mips/loongson64/loongson-3/smp.c              |   8 +-
 arch/mips/loongson64/loongson-3/smp.h              |   1 +
 arch/mips/mm/c-r4k.c                               |  42 +++-
 arch/mips/mm/tlbex.c                               |  11 +
 drivers/cpufreq/Kconfig                            |  13 ++
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/loongson3_cpufreq.c                | 236 +++++++++++++++++++++
 drivers/platform/mips/cpu_hwmon.c                  |   3 +-
 43 files changed, 893 insertions(+), 123 deletions(-)
 create mode 100644 arch/mips/loongson64/loongson-3/clock.c
 create mode 100644 drivers/cpufreq/loongson3_cpufreq.c

--
2.7.0

#1 lore raw

PATCH v2 1/12 MIPS: Loongson: Add Loongson-3A R3.1 basic support

Loongson-3A R3.1 is the bugfix revision of Loongson-3A R3.

All Loongson-3 CPU family:

Code-name         Brand-name       PRId
Loongson-3A R1    Loongson-3A1000  0x6305
Loongson-3A R2    Loongson-3A2000  0x6308
Loongson-3A R3    Loongson-3A3000  0x6309
Loongson-3A R3.1  Loongson-3A3000  0x630d
Loongson-3B R1    Loongson-3B1000  0x6306
Loongson-3B R2    Loongson-3B1500  0x6307
---
 arch/mips/include/asm/cpu.h           | 51 ++++++++++++++++++-----------------
 arch/mips/kernel/cpu-probe.c          |  3 ++-
 arch/mips/loongson64/common/env.c     |  3 ++-
 arch/mips/loongson64/loongson-3/smp.c |  3 ++-
 drivers/platform/mips/cpu_hwmon.c     |  3 ++-
 5 files changed, 34 insertions(+), 29 deletions(-)
arch/mips/include/asm/cpu.h +26 -25
index d39324c..4fbb069 100644
@@ -225,31 +225,32 @@
  * Definitions for 7:0 on legacy processors
  */
 
-#define PRID_REV_TX4927		0x0022
-#define PRID_REV_TX4937		0x0030
-#define PRID_REV_R4400		0x0040
-#define PRID_REV_R3000A		0x0030
-#define PRID_REV_R3000		0x0020
-#define PRID_REV_R2000A		0x0010
-#define PRID_REV_TX3912		0x0010
-#define PRID_REV_TX3922		0x0030
-#define PRID_REV_TX3927		0x0040
-#define PRID_REV_VR4111		0x0050
-#define PRID_REV_VR4181		0x0050	/* Same as VR4111 */
-#define PRID_REV_VR4121		0x0060
-#define PRID_REV_VR4122		0x0070
-#define PRID_REV_VR4181A	0x0070	/* Same as VR4122 */
-#define PRID_REV_VR4130		0x0080
-#define PRID_REV_34K_V1_0_2	0x0022
-#define PRID_REV_LOONGSON1B	0x0020
-#define PRID_REV_LOONGSON1C	0x0020	/* Same as Loongson-1B */
-#define PRID_REV_LOONGSON2E	0x0002
-#define PRID_REV_LOONGSON2F	0x0003
-#define PRID_REV_LOONGSON3A_R1	0x0005
-#define PRID_REV_LOONGSON3B_R1	0x0006
-#define PRID_REV_LOONGSON3B_R2	0x0007
-#define PRID_REV_LOONGSON3A_R2	0x0008
-#define PRID_REV_LOONGSON3A_R3	0x0009
+#define PRID_REV_TX4927			0x0022
+#define PRID_REV_TX4937			0x0030
+#define PRID_REV_R4400			0x0040
+#define PRID_REV_R3000A			0x0030
+#define PRID_REV_R3000			0x0020
+#define PRID_REV_R2000A			0x0010
+#define PRID_REV_TX3912			0x0010
+#define PRID_REV_TX3922			0x0030
+#define PRID_REV_TX3927			0x0040
+#define PRID_REV_VR4111			0x0050
+#define PRID_REV_VR4181			0x0050	/* Same as VR4111 */
+#define PRID_REV_VR4121			0x0060
+#define PRID_REV_VR4122			0x0070
+#define PRID_REV_VR4181A		0x0070	/* Same as VR4122 */
+#define PRID_REV_VR4130			0x0080
+#define PRID_REV_34K_V1_0_2		0x0022
+#define PRID_REV_LOONGSON1B		0x0020
+#define PRID_REV_LOONGSON1C		0x0020	/* Same as Loongson-1B */
+#define PRID_REV_LOONGSON2E		0x0002
+#define PRID_REV_LOONGSON2F		0x0003
+#define PRID_REV_LOONGSON3A_R1		0x0005
+#define PRID_REV_LOONGSON3B_R1		0x0006
+#define PRID_REV_LOONGSON3B_R2		0x0007
+#define PRID_REV_LOONGSON3A_R2		0x0008
+#define PRID_REV_LOONGSON3A_R3_0	0x0009
+#define PRID_REV_LOONGSON3A_R3_1	0x000d
 
 /*
  * Older processors used to encode processor version and revision in two
arch/mips/kernel/cpu-probe.c +2 -1
index cf3fd54..83317d6 100644
@@ -1834,7 +1834,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 			set_elf_platform(cpu, "loongson3a");
 			set_isa(c, MIPS_CPU_ISA_M64R2);
 			break;
-		case PRID_REV_LOONGSON3A_R3:
+		case PRID_REV_LOONGSON3A_R3_0:
+		case PRID_REV_LOONGSON3A_R3_1:
 			c->cputype = CPU_LOONGSON3;
 			__cpu_name[cpu] = "ICT Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
arch/mips/loongson64/common/env.c +2 -1
index 1e8a955..8f68ee0 100644
@@ -198,7 +198,8 @@ void __init prom_init_env(void)
 			break;
 		case PRID_REV_LOONGSON3A_R1:
 		case PRID_REV_LOONGSON3A_R2:
-		case PRID_REV_LOONGSON3A_R3:
+		case PRID_REV_LOONGSON3A_R3_0:
+		case PRID_REV_LOONGSON3A_R3_1:
 			cpu_clock_freq = 900000000;
 			break;
 		case PRID_REV_LOONGSON3B_R1:
arch/mips/loongson64/loongson-3/smp.c +2 -1
index 8501109..fea95d0 100644
@@ -682,7 +682,8 @@ void play_dead(void)
 			(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
 		break;
 	case PRID_REV_LOONGSON3A_R2:
-	case PRID_REV_LOONGSON3A_R3:
+	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;
drivers/platform/mips/cpu_hwmon.c +2 -1
index 322de58..f66521c 100644
@@ -30,7 +30,8 @@ int loongson3_cpu_temp(int cpu)
 	case PRID_REV_LOONGSON3B_R2:
 		reg = ((reg >> 8) & 0xff) - 100;
 		break;
-	case PRID_REV_LOONGSON3A_R3:
+	case PRID_REV_LOONGSON3A_R3_0:
+	case PRID_REV_LOONGSON3A_R3_1:
 		reg = (reg & 0xffff)*731/0x4000 - 273;
 		break;
 	}
Signature · 1 line
2.7.0
#2 lore raw

PATCH v2 2/12 MIPS: Loongson64: Define and use some CP0 registers

In reply to Huacai Chen

This patche defines CP0_CONFIG3, CP0_CONFIG6, CP0_PAGEGRAIN and uses them in kernel-entry-init.h for Loongson64.

---
 .../asm/mach-loongson64/kernel-entry-init.h        | 24 +++++++++++-----------
 arch/mips/include/asm/mipsregs.h                   |  2 ++
 2 files changed, 14 insertions(+), 12 deletions(-)
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +12 -12
index 8393bc54..3127391 100644
@@ -19,18 +19,18 @@
 	.set	push
 	.set	mips64
 	/* Set LPA on LOONGSON3 config3 */
-	mfc0	t0, $16, 3
+	mfc0	t0, CP0_CONFIG3
 	or	t0, (0x1 << 7)
-	mtc0	t0, $16, 3
+	mtc0	t0, CP0_CONFIG3
 	/* Set ELPA on LOONGSON3 pagegrain */
-	mfc0	t0, $5, 1
+	mfc0	t0, CP0_PAGEGRAIN
 	or	t0, (0x1 << 29)
-	mtc0	t0, $5, 1
+	mtc0	t0, CP0_PAGEGRAIN
 #ifdef CONFIG_LOONGSON3_ENHANCEMENT
 	/* Enable STFill Buffer */
-	mfc0	t0, $16, 6
+	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
-	mtc0	t0, $16, 6
+	mtc0	t0, CP0_CONFIG6
 #endif
 	_ehb
 	.set	pop
@@ -45,18 +45,18 @@
 	.set	push
 	.set	mips64
 	/* Set LPA on LOONGSON3 config3 */
-	mfc0	t0, $16, 3
+	mfc0	t0, CP0_CONFIG3
 	or	t0, (0x1 << 7)
-	mtc0	t0, $16, 3
+	mtc0	t0, CP0_CONFIG3
 	/* Set ELPA on LOONGSON3 pagegrain */
-	mfc0	t0, $5, 1
+	mfc0	t0, CP0_PAGEGRAIN
 	or	t0, (0x1 << 29)
-	mtc0	t0, $5, 1
+	mtc0	t0, CP0_PAGEGRAIN
 #ifdef CONFIG_LOONGSON3_ENHANCEMENT
 	/* Enable STFill Buffer */
-	mfc0	t0, $16, 6
+	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
-	mtc0	t0, $16, 6
+	mtc0	t0, CP0_CONFIG6
 #endif
 	_ehb
 	.set	pop
arch/mips/include/asm/mipsregs.h +2 -0
index 0b58864..69307b3 100644
@@ -51,6 +51,7 @@
 #define CP0_GLOBALNUMBER $3, 1
 #define CP0_CONTEXT $4
 #define CP0_PAGEMASK $5
+#define CP0_PAGEGRAIN $5, 1
 #define CP0_SEGCTL0 $5, 2
 #define CP0_SEGCTL1 $5, 3
 #define CP0_SEGCTL2 $5, 4
@@ -77,6 +78,7 @@
 #define CP0_CONFIG $16
 #define CP0_CONFIG3 $16, 3
 #define CP0_CONFIG5 $16, 5
+#define CP0_CONFIG6 $16, 6
 #define CP0_LLADDR $17
 #define CP0_WATCHLO $18
 #define CP0_WATCHHI $19
Signature · 1 line
2.7.0
Reviewed-by on v2 2/12
#3 lore raw

Re: [PATCH V2 02/12] MIPS: Loongson64: Define and use some CP0 registers

Quoted 2 lines · Huacai Chen

This patche defines CP0_CONFIG3, CP0_CONFIG6, CP0_PAGEGRAIN and uses them in kernel-entry-init.h for Loongson64.

Please write commit messages in the imerative mood (i.e. like you're telling the code how to change), and without referring to the patch itself, E.g.

Quoted 2 lines

Define CP0_CONFIG3, CP0_CONFIG6, CP0_PAGEGRAIN and use them in kernel-entry-init.h for Loongson64.

Thanks for splitting this patch out.

Cheers
James

#4 lore raw

PATCH v2 3/12 MIPS: Loongson-3: Enable Store Fill Buffer at runtime

In reply to Huacai Chen

New Loongson-3 (Loongson-3A R2, Loongson-3A R3, and newer) has SFB (Store Fill Buffer) which can improve the performance of memory access. Now, SFB enablement is controlled by CONFIG_LOONGSON3_ENHANCEMENT, and the generic kernel has no benefit from SFB (even it is running on a new Loongson-3 machine). With this patch, we can enable SFB at runtime by detecting the CPU type (the expense is war_io_reorder_wmb() will always be a 'sync', which will hurt the performance of old Loongson-3).

---
 arch/mips/include/asm/io.h                                |  2 +-
 arch/mips/include/asm/mach-loongson64/kernel-entry-init.h | 14 ++++++++++----
 2 files changed, 11 insertions(+), 5 deletions(-)
arch/mips/include/asm/io.h +1 -1
index 0cbf3af..5146efa 100644
@@ -304,7 +304,7 @@ static inline void iounmap(const volatile void __iomem *addr)
 #undef __IS_KSEG1
 }
 
-#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT)
+#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_CPU_LOONGSON3)
 #define war_io_reorder_wmb()		wmb()
 #else
 #define war_io_reorder_wmb()		do { } while (0)
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +10 -4
index 3127391..4b7f58a 100644
@@ -26,12 +26,15 @@
 	mfc0	t0, CP0_PAGEGRAIN
 	or	t0, (0x1 << 29)
 	mtc0	t0, CP0_PAGEGRAIN
-#ifdef CONFIG_LOONGSON3_ENHANCEMENT
 	/* Enable STFill Buffer */
+	mfc0	t0, CP0_PRID
+	andi	t0, 0xffff
+	slti	t0, 0x6308
+	bnez	t0, 1f
 	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
 	mtc0	t0, CP0_CONFIG6
-#endif
+1:
 	_ehb
 	.set	pop
 #endif
@@ -52,12 +55,15 @@
 	mfc0	t0, CP0_PAGEGRAIN
 	or	t0, (0x1 << 29)
 	mtc0	t0, CP0_PAGEGRAIN
-#ifdef CONFIG_LOONGSON3_ENHANCEMENT
 	/* Enable STFill Buffer */
+	mfc0	t0, CP0_PRID
+	andi	t0, 0xffff
+	slti	t0, 0x6308
+	bnez	t0, 1f
 	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
 	mtc0	t0, CP0_CONFIG6
-#endif
+1:
 	_ehb
 	.set	pop
 #endif
Signature · 1 line
2.7.0
Reviewed-by on v2 3/12
#5 lore raw

Re: [PATCH V2 03/12] MIPS: Loongson-3: Enable Store Fill Buffer at runtime

arch/mips/include/asm/mach-loongson64/kernel-entry-init.h line 31

Quoted 12 lines · Huacai Chen
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +2 -1
index 3127391..4b7f58a 100644
@@ -26,12 +26,15 @@
 	mfc0	t0, CP0_PAGEGRAIN
 	or	t0, (0x1 << 29)
 	mtc0	t0, CP0_PAGEGRAIN
-#ifdef CONFIG_LOONGSON3_ENHANCEMENT
 	/* Enable STFill Buffer */
+	mfc0	t0, CP0_PRID
+	andi	t0, 0xffff

Maybe worth including <asm/cpu.h and doing:
andi t0, (PRID_IMP_MASK | PRID_REV_MASK)

arch/mips/include/asm/mach-loongson64/kernel-entry-init.h line 32

Quoted 1 line
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +1 -0
+	slti	t0, 0x6308

and:

	slti	t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2)

With something like that here and in the other place:

Cheers
James

#6 lore raw

PATCH v2 4/12 MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3

In reply to Huacai Chen

For multi-node Loongson-3 (NUMA configuration), r4k_blast_scache() can only flush Node-0's scache. So we add r4k_blast_scache_node() by using (CAC_BASE | (node_id << NODE_ADDRSPACE_SHIFT)) instead of CKSEG0 as the start address.

---
 arch/mips/include/asm/r4kcache.h | 34 ++++++++++++++++++++++++++++++++
 arch/mips/mm/c-r4k.c             | 42 +++++++++++++++++++++++++++++++++-------
 2 files changed, 69 insertions(+), 7 deletions(-)
arch/mips/include/asm/r4kcache.h +34 -0
index 7f12d7e..c1f2806 100644
@@ -747,4 +747,38 @@ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
 
+#ifndef pa_to_nid
+#define pa_to_nid(addr) 0
+#endif
+
+#ifndef NODE_ADDRSPACE_SHIFT
+#define nid_to_addrbase(nid) 0
+#else
+#define nid_to_addrbase(nid) (nid << NODE_ADDRSPACE_SHIFT)
+#endif
+
+#define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize)	\
+static inline void blast_##pfx##cache##lsize##_node(long node)		\
+{									\
+	unsigned long start = CAC_BASE | nid_to_addrbase(node);		\
+	unsigned long end = start + current_cpu_data.desc.waysize;	\
+	unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit;	\
+	unsigned long ws_end = current_cpu_data.desc.ways <<		\
+			       current_cpu_data.desc.waybit;		\
+	unsigned long ws, addr;						\
+									\
+	__##pfx##flush_prologue						\
+									\
+	for (ws = 0; ws < ws_end; ws += ws_inc)				\
+		for (addr = start; addr < end; addr += lsize * 32)	\
+			cache##lsize##_unroll32(addr|ws, indexop);	\
+									\
+	__##pfx##flush_epilogue						\
+}
+
+__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
+__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
+__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
+__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
+
 #endif /* _ASM_R4KCACHE_H */
arch/mips/mm/c-r4k.c +35 -7

76 lines not on this page · raw message

Signature · 1 line
2.7.0
#7 lore raw

Re: [PATCH V2 04/12] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3

Quoted 17 lines · Huacai Chen

For multi-node Loongson-3 (NUMA configuration), r4k_blast_scache() can only flush Node-0's scache. So we add r4k_blast_scache_node() by using (CAC_BASE | (node_id << NODE_ADDRSPACE_SHIFT)) instead of CKSEG0 as the start address.

---
 arch/mips/include/asm/r4kcache.h | 34 ++++++++++++++++++++++++++++++++
 arch/mips/mm/c-r4k.c             | 42 +++++++++++++++++++++++++++++++++-------
 2 files changed, 69 insertions(+), 7 deletions(-)
arch/mips/include/asm/r4kcache.h +0 -0
index 7f12d7e..c1f2806 100644

arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 754

Quoted 8 lines
arch/mips/include/asm/r4kcache.h +5 -0
@@ -747,4 +747,38 @@ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
 
+#ifndef pa_to_nid
+#define pa_to_nid(addr) 0
+#endif
+
+#ifndef NODE_ADDRSPACE_SHIFT

To be sure you get the right definition of both of these if they exist, and wherever this header is included, we should explicitly #include the appropriate header (asm/mmzone.h?) from this header.

arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 757

Quoted 3 lines
arch/mips/include/asm/r4kcache.h +3 -0
+#define nid_to_addrbase(nid) 0
+#else
+#define nid_to_addrbase(nid) (nid << NODE_ADDRSPACE_SHIFT)

Technically this should have parentheses around nid.

It seems slightly inconsistent to have pa_to_nid() defined in mmzone.h, but not the reverse nid_to_addrbase(). NODE_ADDRSPACE_SHIFT is very loongson specific afterall.

Would it make sense to move it into arch/mips/include/asm/mach-loongson64/mmzone.h and put the 0 definition in #ifndef nid_to_addrbase?

arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 760

Quoted 3 lines
arch/mips/include/asm/r4kcache.h +3 -0
+#endif
+
+#define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize)	\

I think this is worthy of a quick comment to explain that this is very specific to Loongson3.

Quoted 5 lines
arch/mips/include/asm/r4kcache.h +0 -0
 #endif /* _ASM_R4KCACHE_H */
arch/mips/mm/c-r4k.c +0 -0
index 6f534b20..155f5f5 100644

...

arch/mips/mm/c-r4k.c static inline void local_r4k___flush_cache_all(void * args) · line 501

Quoted 6 lines
arch/mips/mm/c-r4k.c +2 -0
@@ -480,6 +497,10 @@ static inline void local_r4k___flush_cache_all(void * args)
 		r4k_blast_scache();
 		break;
 
+	case CPU_LOONGSON3:
+		r4k_blast_scache_node(get_ebase_cpunum() >> 2);

I assume this can't use cpu_to_node() because it needs to work even when NUMA=n? If so, I think it deserves a brief comment to explain that.

Quoted 7 lines
arch/mips/mm/c-r4k.c +2 -0
+		break;
+
 	case CPU_BMIPS5000:
 		r4k_blast_scache();
 		__sync();
@@ -839,9 +860,12 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 

arch/mips/mm/c-r4k.c static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) · line 867

Quoted 10 lines
arch/mips/mm/c-r4k.c +5 -3
 	preempt_disable();
 	if (cpu_has_inclusive_pcaches) {
-		if (size >= scache_size)
-			r4k_blast_scache();
-		else
+		if (size >= scache_size) {
+			if (current_cpu_type() != CPU_LOONGSON3)
+				r4k_blast_scache();
+			else
+				r4k_blast_scache_node(pa_to_nid(addr));

If I read this right, addr is a virtual address so this feels a bit hacky, but I suppose its harmless since it'll probably always be memory in xkphys space where pa_to_nid() will do the right thing. Perhaps a comment along the lines of:
/* This assumes that addr is in XKPhys */

arch/mips/mm/c-r4k.c static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) · line 868

Quoted 1 line
arch/mips/mm/c-r4k.c +1 -0
+		} else

Please keep braces consistent, i.e. add to the trailing else statement too.

Other than those niggles, the actual mechanism looks reasonable to me.

Thanks
James

#8 lore raw

PATCH v2 5/12 MIPS: Loongson fix name confict - MEM_RESERVED

In reply to Huacai Chen

MEM_RESERVED is used as a value of enum mem_type in include/linux/ edac.h. This will make failure to build for Loongson in some case:
for example with CONFIG_RAS enabled.

So here rename MEM_RESERVED to SYSTEM_RAM_RESERVED in Loongson code.

---
 arch/mips/include/asm/mach-loongson64/boot_param.h | 2 +-
 arch/mips/loongson64/common/mem.c                  | 2 +-
 arch/mips/loongson64/loongson-3/numa.c             | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
arch/mips/include/asm/mach-loongson64/boot_param.h +1 -1
index 4f69f08..8c286be 100644
@@ -4,7 +4,7 @@
 
 #define SYSTEM_RAM_LOW		1
 #define SYSTEM_RAM_HIGH		2
-#define MEM_RESERVED		3
+#define SYSTEM_RAM_RESERVED	3
 #define PCI_IO			4
 #define PCI_MEM			5
 #define LOONGSON_CFG_REG	6
arch/mips/loongson64/common/mem.c +1 -1
index b01d524..c549e52 100644
@@ -79,7 +79,7 @@ void __init prom_init_memory(void)
 					(u64)loongson_memmap->map[i].mem_size << 20,
 					BOOT_MEM_RAM);
 				break;
-			case MEM_RESERVED:
+			case SYSTEM_RAM_RESERVED:
 				add_memory_region(loongson_memmap->map[i].mem_start,
 					(u64)loongson_memmap->map[i].mem_size << 20,
 					BOOT_MEM_RESERVED);
arch/mips/loongson64/loongson-3/numa.c +1 -1
index f17ef52..9717106 100644
@@ -166,7 +166,7 @@ static void __init szmem(unsigned int node)
 			memblock_add_node(PFN_PHYS(start_pfn),
 				PFN_PHYS(end_pfn - start_pfn), node);
 			break;
-		case MEM_RESERVED:
+		case SYSTEM_RAM_RESERVED:
 			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
 				(u32)node_id, mem_type, mem_start, mem_size);
 			add_memory_region((node_id << 44) + mem_start,
Signature · 1 line
2.7.0
#9 lore raw

PATCH v2 6/12 MIPS: Ensure pmd_present() returns false after pmd_mknotpresent()

In reply to Huacai Chen

This patch is borrowed from ARM64 to ensure pmd_present() returns false after pmd_mknotpresent(). This is needed for THP.

Cc: <[email protected]> # 3.8+
References: 5bb1cc0ff9a6 ("arm64: Ensure pmd_present() returns false after pmd_mknotpresent()")

---
 arch/mips/include/asm/pgtable-64.h | 5 +++++
 1 file changed, 5 insertions(+)
arch/mips/include/asm/pgtable-64.h +5 -0
index 0036ea0..93a9dce 100644
@@ -265,6 +265,11 @@ static inline int pmd_bad(pmd_t pmd)
 
 static inline int pmd_present(pmd_t pmd)
 {
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+	if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
+		return pmd_val(pmd) & _PAGE_PRESENT;
+#endif
+
 	return pmd_val(pmd) != (unsigned long) invalid_pte_table;
 }
 
Signature · 1 line
2.7.0
#10 lore raw

PATCH v2 7/12 MIPS: Add __cpu_full_name[] to make CPU names more human-readable

In reply to Huacai Chen

In /proc/cpuinfo, we keep "cpu model" as is, since GCC should use it for -march=native. Besides, we add __cpu_full_name[] to describe the processor in a more human-readable manner. The full name is displayed as "model name" in cpuinfo, which is needed by some userspace tools such as gnome-system-monitor.

The CPU frequency in "model name" is the default value (highest), and there is also a "CPU MHz" whose value can be changed by cpufreq.

This is only used by Loongson now (ICT is dropped in cpu name, and cpu name can be overwritten by BIOS).

---
 arch/mips/include/asm/cpu-info.h                   |  2 ++
 arch/mips/include/asm/mach-loongson64/boot_param.h |  1 +
 arch/mips/include/asm/time.h                       |  2 ++
 arch/mips/kernel/cpu-probe.c                       | 25 ++++++++++++++++------
 arch/mips/kernel/proc.c                            |  7 ++++++
 arch/mips/kernel/time.c                            |  2 ++
 arch/mips/loongson64/common/env.c                  | 13 +++++++++++
 arch/mips/loongson64/loongson-3/smp.c              |  1 +
 arch/mips/loongson64/loongson-3/smp.h              |  1 +
 9 files changed, 48 insertions(+), 6 deletions(-)
arch/mips/include/asm/cpu-info.h +2 -0
index a41059d..6128a37 100644
@@ -116,7 +116,9 @@ extern void cpu_probe(void);
 extern void cpu_report(void);
 
 extern const char *__cpu_name[];
+extern const char *__cpu_full_name[];
 #define cpu_name_string()	__cpu_name[raw_smp_processor_id()]
+#define cpu_full_name_string()	__cpu_full_name[raw_smp_processor_id()]
 
 struct seq_file;
 struct notifier_block;
arch/mips/include/asm/mach-loongson64/boot_param.h +1 -0
index 8c286be..1d69e4c 100644
@@ -58,6 +58,7 @@ struct efi_cpuinfo_loongson {
 	u16 reserved_cores_mask;
 	u32 cpu_clock_freq; /* cpu_clock */
 	u32 nr_cpus;
+	char cpuname[64];
 } __packed;
 
 #define MAX_UARTS 64
arch/mips/include/asm/time.h +2 -0
index 17d4cd2..efbfc48 100644
@@ -35,6 +35,8 @@ extern int rtc_mips_set_mmss(unsigned long);
  */
 extern void plat_time_init(void);
 
+extern unsigned int mips_cpu_frequency;
+
 /*
  * mips_hpt_frequency - must be set if you intend to use an R4k-compatible
  * counter as a timer interrupt source.
arch/mips/kernel/cpu-probe.c +19 -6
index 83317d6..b7acf35 100644
@@ -1461,30 +1461,40 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 		switch (c->processor_id & PRID_REV_MASK) {
 		case PRID_REV_LOONGSON2E:
 			c->cputype = CPU_LOONGSON2;
-			__cpu_name[cpu] = "ICT Loongson-2";
+			__cpu_name[cpu] = "Loongson-2";
 			set_elf_platform(cpu, "loongson2e");
 			set_isa(c, MIPS_CPU_ISA_III);
 			c->fpu_msk31 |= FPU_CSR_CONDX;
+			__cpu_full_name[cpu] = "Loongson-2E";
 			break;
 		case PRID_REV_LOONGSON2F:
 			c->cputype = CPU_LOONGSON2;
-			__cpu_name[cpu] = "ICT Loongson-2";
+			__cpu_name[cpu] = "Loongson-2";
 			set_elf_platform(cpu, "loongson2f");
 			set_isa(c, MIPS_CPU_ISA_III);
 			c->fpu_msk31 |= FPU_CSR_CONDX;
+			__cpu_full_name[cpu] = "Loongson-2F";
 			break;
 		case PRID_REV_LOONGSON3A_R1:
 			c->cputype = CPU_LOONGSON3;
-			__cpu_name[cpu] = "ICT Loongson-3";
+			__cpu_name[cpu] = "Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
 			set_isa(c, MIPS_CPU_ISA_M64R1);
+			__cpu_full_name[cpu] = "Loongson-3A R1 (Loongson-3A1000)";
 			break;
 		case PRID_REV_LOONGSON3B_R1:
+			c->cputype = CPU_LOONGSON3;
+			__cpu_name[cpu] = "Loongson-3";
+			set_elf_platform(cpu, "loongson3b");
+			set_isa(c, MIPS_CPU_ISA_M64R1);
+			__cpu_full_name[cpu] = "Loongson-3B R1 (Loongson-3B1000)";
+			break;
 		case PRID_REV_LOONGSON3B_R2:
 			c->cputype = CPU_LOONGSON3;
-			__cpu_name[cpu] = "ICT Loongson-3";
+			__cpu_name[cpu] = "Loongson-3";
 			set_elf_platform(cpu, "loongson3b");
 			set_isa(c, MIPS_CPU_ISA_M64R1);
+			__cpu_full_name[cpu] = "Loongson-3B R2 (Loongson-3B1500)";
 			break;
 		}
 
@@ -1830,16 +1840,18 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		switch (c->processor_id & PRID_REV_MASK) {
 		case PRID_REV_LOONGSON3A_R2:
 			c->cputype = CPU_LOONGSON3;
-			__cpu_name[cpu] = "ICT Loongson-3";
+			__cpu_name[cpu] = "Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
 			set_isa(c, MIPS_CPU_ISA_M64R2);
+			__cpu_full_name[cpu] = "Loongson-3A R2 (Loongson-3A2000)";
 			break;
 		case PRID_REV_LOONGSON3A_R3_0:
 		case PRID_REV_LOONGSON3A_R3_1:
 			c->cputype = CPU_LOONGSON3;
-			__cpu_name[cpu] = "ICT Loongson-3";
+			__cpu_name[cpu] = "Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
 			set_isa(c, MIPS_CPU_ISA_M64R2);
+			__cpu_full_name[cpu] = "Loongson-3A R3 (Loongson-3A3000)";
 			break;
 		}
 
@@ -1959,6 +1971,7 @@ EXPORT_SYMBOL(__ua_limit);
 #endif
 
 const char *__cpu_name[NR_CPUS];
+const char *__cpu_full_name[NR_CPUS];
 const char *__elf_platform;
 
 void cpu_probe(void)
arch/mips/kernel/proc.c +7 -0
index b2de408..b4c31b0 100644
@@ -15,6 +15,7 @@
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/prom.h>
+#include <asm/time.h>
 
 unsigned int vced_count, vcei_count;
 
@@ -63,6 +64,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 	seq_printf(m, fmt, __cpu_name[n],
 		      (version >> 4) & 0x0f, version & 0x0f,
 		      (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
+	if (__cpu_full_name[n])
+		seq_printf(m, "model name\t\t: %s\n", __cpu_full_name[n]);
+	if (mips_cpu_frequency)
+		seq_printf(m, "CPU MHz\t\t\t: %u.%02u\n",
+			      mips_cpu_frequency / 1000000,
+			      (mips_cpu_frequency / 10000) % 100);
 	seq_printf(m, "BogoMIPS\t\t: %u.%02u\n",
 		      cpu_data[n].udelay_val / (500000/HZ),
 		      (cpu_data[n].udelay_val / (5000/HZ)) % 100);
arch/mips/kernel/time.c +2 -0
index a6ebc81..5c096c2 100644
@@ -69,6 +69,8 @@ EXPORT_SYMBOL(perf_irq);
  * 2) calculate a couple of cached variables for later usage
  */
 
+unsigned int mips_cpu_frequency;
+EXPORT_SYMBOL_GPL(mips_cpu_frequency);
 unsigned int mips_hpt_frequency;
 EXPORT_SYMBOL_GPL(mips_hpt_frequency);
 
arch/mips/loongson64/common/env.c +13 -0
index 8f68ee0..2928ac5 100644
@@ -18,6 +18,7 @@
  * option) any later version.
  */
 #include <linux/export.h>
+#include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <loongson.h>
 #include <boot_param.h>
@@ -25,6 +26,7 @@
 
 u32 cpu_clock_freq;
 EXPORT_SYMBOL(cpu_clock_freq);
+char cpu_full_name[64];
 struct efi_memory_map_loongson *loongson_memmap;
 struct loongson_system_configuration loongson_sysconf;
 
@@ -45,6 +47,7 @@ do {									\
 void __init prom_init_env(void)
 {
 	/* pmon passes arguments in 32bit pointers */
+	char freq[12];
 	unsigned int processor_id;
 
 #ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
@@ -151,6 +154,10 @@ void __init prom_init_env(void)
 	loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
 		loongson_sysconf.cores_per_node - 1) /
 		loongson_sysconf.cores_per_node;
+	if (!strncmp(ecpu->cpuname, "Loongson", 8))
+		strncpy(cpu_full_name, ecpu->cpuname, sizeof(cpu_full_name));
+	if (cpu_full_name[0] == 0)
+		strncpy(cpu_full_name, __cpu_full_name[0], sizeof(cpu_full_name));
 
 	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
 	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -211,5 +218,11 @@ void __init prom_init_env(void)
 			break;
 		}
 	}
+	mips_cpu_frequency = cpu_clock_freq;
 	pr_info("CpuClock = %u\n", cpu_clock_freq);
+
+	/* Append default cpu frequency with round-off */
+	sprintf(freq, " @ %uMHz", (cpu_clock_freq + 500000) / 1000000);
+	strncat(cpu_full_name, freq, sizeof(cpu_full_name));
+	__cpu_full_name[0] = cpu_full_name;
 }
arch/mips/loongson64/loongson-3/smp.c +1 -0
index fea95d0..470e9c1 100644
@@ -340,6 +340,7 @@ static void loongson3_init_secondary(void)
 		initcount = core0_c0count[cpu] + i/2;
 
 	write_c0_count(initcount);
+	__cpu_full_name[cpu] = cpu_full_name;
 }
 
 static void loongson3_smp_finish(void)
arch/mips/loongson64/loongson-3/smp.h +1 -0
index 957bde8..6112d9d 100644
@@ -3,6 +3,7 @@
 #define __LOONGSON_SMP_H_
 
 /* for Loongson-3 smp support */
+extern char cpu_full_name[64];
 extern unsigned long long smp_group[4];
 
 /* 4 groups(nodes) in maximum in numa case */
Signature · 1 line
2.7.0
#11 lore raw

PATCH v2 8/12 MIPS: Align kernel load address to 64KB

KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest PAGE_SIZE.

---
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +2 -3
index 37fe58c..1dcaef4 100644
@@ -45,11 +45,10 @@ int main(int argc, char *argv[])
 	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
 
 	/*
-	 * Align with 16 bytes: "greater than that used for any standard data
-	 * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition).
+	 * Align with 64KB: KEXEC assume kernel align to PAGE_SIZE
 	 */
 
-	vmlinuz_load_addr += (16 - vmlinux_size % 16);
+	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
 
 	printf("0x%llx\n", vmlinuz_load_addr);
 
Signature · 1 line
2.7.0
#12 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 2 lines · Huacai Chen

KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest PAGE_SIZE.

Please expand, maybe referring to sanity_check_segment_list() which does the actual check. Maybe something like this:

Kexec needs the new kernel's load address to be aligned on a page boundary (see sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.

Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.

I suppose it'd be a bit ugly for the kexec userland code to increase the size of the load segment downwards to make it page aligned...

Quoted 11 lines
---
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +0 -0
index 37fe58c..1dcaef4 100644

arch/mips/boot/compressed/calc_vmlinuz_load_addr.c int main(int argc, char *argv[]) · line 48

Quoted 6 lines
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +1 -2
@@ -45,11 +45,10 @@ int main(int argc, char *argv[])
 	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
 
 	/*
-	 * Align with 16 bytes: "greater than that used for any standard data
-	 * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition).
+	 * Align with 64KB: KEXEC assume kernel align to PAGE_SIZE

"Align to 64KB: kexec needs load sections to be aligned to PAGE_SIZE, which may be as large as 64KB depending on the kernel configuration".

arch/mips/boot/compressed/calc_vmlinuz_load_addr.c int main(int argc, char *argv[]) · line 51

Quoted 4 lines
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +1 -1
 	 */
 
-	vmlinuz_load_addr += (16 - vmlinux_size % 16);
+	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);

Personally I find (64 * 1024) (or even SZ_64K) easier to read, but no big deal.

Thanks
James

#13 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 6 lines · James Hogan
Quoted 2 lines

KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest PAGE_SIZE.

Please expand, maybe referring to sanity_check_segment_list() which does the actual check. Maybe something like this:

Quoted 6 lines

Kexec needs the new kernel's load address to be aligned on a page boundary (see sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.

Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.

But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.

Maciej

#14 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 15 lines · Maciej W. Rozycki
Quoted 6 lines · James Hogan
Quoted 2 lines

KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest PAGE_SIZE.

Please expand, maybe referring to sanity_check_segment_list() which does the actual check. Maybe something like this:

Quoted 6 lines

Kexec needs the new kernel's load address to be aligned on a page boundary (see sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.

Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.

Quoted 6 lines

But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.

I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).

Cheers
James

#15 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 10 lines · James Hogan
Quoted 9 lines
Quoted 2 lines

Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.

But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.

Quoted 3 lines

I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).

As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?

Maciej

#16 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 12 lines · Maciej W. Rozycki
Quoted 10 lines · James Hogan
Quoted 9 lines
Quoted 2 lines

Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.

But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.

Quoted 8 lines
Quoted 3 lines

I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).

As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?

Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.

The only alternative is for the kexec userland tools to be able to automatically adjust the load segments to load a bit more before the start of the kernel image so that its aligned, and i'm not sure how universally safe that would be.

Cheers
James

#17 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 8 lines · James Hogan
Quoted 4 lines

As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?

Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.

Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.

Here's an example program header dump from `vmlinux':

$ readelf -l vmlinux

Elf file type is EXEC (Executable file) Entry point 0x80506e70
There are 3 program headers, starting at offset 52

Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  ABIFLAGS       0x4b02e8 0x805ac2e8 0x805ac2e8 0x00018 0x00018 R   0x8
  LOAD           0x004000 0x80100000 0x80100000 0x534650 0x569710 RWE 0x4000
  NOTE           0x4145a8 0x805105a8 0x805105a8 0x00024 0x00024 R   0x4

Section to Segment mapping:
Segment Sections...

   00     .MIPS.abiflags
   01     .text __ex_table .notes .rodata .MIPS.abiflags .pci_fixup __ksymtab __ksymtab_gpl __kcrctab __kcrctab_gpl __ksymtab_strings __param __modver .data .init.text .init.data .exit.text .bss
   02     .notes

$

As you can see there's only one loadable segment (the usual case) and its alignment is 0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.

Maciej

#18 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 11 lines · Maciej W. Rozycki
Quoted 8 lines · James Hogan
Quoted 4 lines

As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?

Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.

Quoted 7 lines

Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.

The kernel doesn't always get an elf through kexec_load(2), but rather a list of load segments. In any case though its not about knowing the page size of 2nd kernel, its about kexec working with page size chunks. See the comment in sanity_check_segment_list().

Quoted 4 lines

Here's an example program header dump from `vmlinux':

$ readelf -l vmlinux

Yeh but its not a vmlinux, its a vmlinuz. Thats the whole point. Though it sounds like you'd have the same problem with vmlinux too if you tried reducing the page size, so perhaps its fine for compressed kernels to just align to the page size of the 2nd kernel, so they're no worse than vmlinux.

Quoted 13 lines

Elf file type is EXEC (Executable file) Entry point 0x80506e70
There are 3 program headers, starting at offset 52

Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  ABIFLAGS       0x4b02e8 0x805ac2e8 0x805ac2e8 0x00018 0x00018 R   0x8
  LOAD           0x004000 0x80100000 0x80100000 0x534650 0x569710 RWE 0x4000
  NOTE           0x4145a8 0x805105a8 0x805105a8 0x00024 0x00024 R   0x4

Section to Segment mapping:
Segment Sections...

Quoted 8 lines
   00     .MIPS.abiflags
   01     .text __ex_table .notes .rodata .MIPS.abiflags .pci_fixup __ksymtab __ksymtab_gpl __kcrctab __kcrctab_gpl __ksymtab_strings __param __modver .data .init.text .init.data .exit.text .bss
   02     .notes

$

As you can see there's only one loadable segment (the usual case) and its alignment is 0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.

For malta_defconfig *vmlinuz* however (CONFIG_PAGE_SIZE_16KB=y), I get this:
LOAD 0x008320 0x80828320 0x80828320 0x35e580 0x8605a0 RWE 0x10000

Cheers
James

#19 lore raw

Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB

Quoted 8 lines · James Hogan
Quoted 7 lines

Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.

Quoted 4 lines

The kernel doesn't always get an elf through kexec_load(2), but rather a list of load segments. In any case though its not about knowing the page size of 2nd kernel, its about kexec working with page size chunks. See the comment in sanity_check_segment_list().

So this is 1st kernel's page size AFAICT. And I can see `struct
kexec_segment' drops ELF program header information, sigh.

Quoted 9 lines
Quoted 3 lines

Here's an example program header dump from `vmlinux':

$ readelf -l vmlinux

Yeh but its not a vmlinux, its a vmlinuz. Thats the whole point. Though it sounds like you'd have the same problem with vmlinux too if you tried reducing the page size, so perhaps its fine for compressed kernels to just align to the page size of the 2nd kernel, so they're no worse than vmlinux.

Well, even if compressed you need to preserve the original structures
somehow so that once uncompressed the memory image is the same as if `vmlinux' was loaded directly.

Quoted 7 lines
Quoted 3 lines

As you can see there's only one loadable segment (the usual case) and its alignment is 0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.

For malta_defconfig *vmlinuz* however (CONFIG_PAGE_SIZE_16KB=y), I get this:
LOAD 0x008320 0x80828320 0x80828320 0x35e580 0x8605a0 RWE 0x10000

Hmm, now you've left me stumped, so I'll shut up.

Maciej

#20 lore raw

PATCH v2 9/12 MIPS: Loongson: Add kexec/kdump support

In reply to Huacai Chen
---
 arch/mips/kernel/relocate_kernel.S    |  30 +++++++++
 arch/mips/loongson64/common/env.c     |   8 +++
 arch/mips/loongson64/common/reset.c   | 119 ++++++++++++++++++++++++++++++++++
 arch/mips/loongson64/loongson-3/smp.c |   4 ++
 4 files changed, 161 insertions(+)
arch/mips/kernel/relocate_kernel.S +30 -0
index c6bbf21..e73edc7 100644
@@ -135,6 +135,36 @@ LEAF(kexec_smp_wait)
 #else
 	sync
 #endif
+
+#ifdef CONFIG_CPU_LOONGSON3
+	/* s0:prid s1:initfn */
+	/* t0:base t1:cpuid t2:node t3:core t9:count */
+	mfc0  t1, $15, 1
+	andi  t1, 0x3ff
+	dli   t0, 0x900000003ff01000
+	andi  t3, t1, 0x3
+	sll   t3, 8               /* get core id */
+	or    t0, t0, t3
+	andi  t2, t1, 0xc
+	dsll  t2, 42              /* get node id */
+	or    t0, t0, t2
+	mfc0  s0, $15, 0
+	andi  s0, s0, 0xf
+	blt   s0, 0x6, 1f         /* Loongson-3A1000 */
+	bgt   s0, 0x7, 1f         /* Loongson-3A2000/3A3000 */
+	dsrl  t2, 30              /* Loongson-3B1000/3B1500 need bit15:14 */
+	or    t0, t0, t2
+1:	li    t9, 0x100           /* wait for init loop */
+2:	addiu t9, -1              /* limit mailbox access */
+	bnez  t9, 2b
+	ld    s1, 0x20(t0)        /* get PC via mailbox */
+	beqz  s1, 1b
+	ld    sp, 0x28(t0)        /* get SP via mailbox */
+	ld    gp, 0x30(t0)        /* get GP via mailbox */
+	ld    a1, 0x38(t0)
+	jr    s1                  /* jump to initial PC */
+#endif
+
 	j		s1
 	END(kexec_smp_wait)
 #endif
arch/mips/loongson64/common/env.c +8 -0
index 2928ac5..990a2d69 100644
@@ -72,6 +72,7 @@ void __init prom_init_env(void)
 
 	pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize);
 #else
+	int i;
 	struct boot_params *boot_p;
 	struct loongson_params *loongson_p;
 	struct system_loongson *esys;
@@ -149,6 +150,13 @@ void __init prom_init_env(void)
 	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
 	loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id;
 	loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask;
+#ifdef CONFIG_KEXEC
+	loongson_sysconf.boot_cpu_id = get_ebase_cpunum();
+	for (i = 0; i < loongson_sysconf.boot_cpu_id; i++)
+		loongson_sysconf.reserved_cpus_mask |= (1<<i);
+	pr_info("Boot CPU ID is being fixed from %d to %d\n",
+		ecpu->cpu_startup_core_id, loongson_sysconf.boot_cpu_id);
+#endif
 	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
 		loongson_sysconf.nr_cpus = NR_CPUS;
 	loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
arch/mips/loongson64/common/reset.c +119 -0

140 lines not on this page · raw message

arch/mips/loongson64/loongson-3/smp.c +4 -0
index 470e9c1..1e21ac4 100644
@@ -387,6 +387,10 @@ static void __init loongson3_smp_setup(void)
 	ipi_status0_regs_init();
 	ipi_en0_regs_init();
 	ipi_mailbox_buf_init();
+
+	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
+		loongson3_ipi_write64(0, (void *)(ipi_mailbox_buf[i]+0x0));
+
 	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;
Signature · 1 line
2.7.0
#21 lore raw

Re: [PATCH V2 09/12] MIPS: Loongson: Add kexec/kdump support

Quoted 1 line · Huacai Chen

Please add a commit message.

Worth Cc'ing kexec maintainers?

Quoted 12 lines
---
 arch/mips/kernel/relocate_kernel.S    |  30 +++++++++
 arch/mips/loongson64/common/env.c     |   8 +++
 arch/mips/loongson64/common/reset.c   | 119 ++++++++++++++++++++++++++++++++++
 arch/mips/loongson64/loongson-3/smp.c |   4 ++
 4 files changed, 161 insertions(+)
arch/mips/kernel/relocate_kernel.S +0 -0
index c6bbf21..e73edc7 100644

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 142

Quoted 8 lines
arch/mips/kernel/relocate_kernel.S +5 -0
@@ -135,6 +135,36 @@ LEAF(kexec_smp_wait)
 #else
 	sync
 #endif
+
+#ifdef CONFIG_CPU_LOONGSON3
+	/* s0:prid s1:initfn */
+	/* t0:base t1:cpuid t2:node t3:core t9:count */
+	mfc0  t1, $15, 1

Can you use CP0_EBASE from mipsregs.h?

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 143

Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1 -0
+	andi  t1, 0x3ff

MIPS_EBASE_CPUNUM

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 144

Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1 -0
+	dli   t0, 0x900000003ff01000

Whats that?

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 147

Quoted 3 lines
arch/mips/kernel/relocate_kernel.S +3 -0
+	andi  t3, t1, 0x3
+	sll   t3, 8               /* get core id */
+	or    t0, t0, t3

Do you have the INS instruction on loongson? Does it make sense to do this, even if only for readability?

	dins	t0, t1, 8, 2

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 150

Quoted 3 lines
arch/mips/kernel/relocate_kernel.S +3 -0
+	andi  t2, t1, 0xc
+	dsll  t2, 42              /* get node id */
+	or    t0, t0, t2

Does it make sense to do this, especially for readability (44 vs 42)?

	dext	t2, t1, 2, 2
	dins	t0, t2, 44, 2

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 151

Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1 -0
+	mfc0  s0, $15, 0

CP0_PRID

arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 156

Quoted 6 lines
arch/mips/kernel/relocate_kernel.S +5 -0
+	andi  s0, s0, 0xf
+	blt   s0, 0x6, 1f         /* Loongson-3A1000 */
+	bgt   s0, 0x7, 1f         /* Loongson-3A2000/3A3000 */
 
+	dsrl  t2, 30              /* Loongson-3B1000/3B1500 need bit15:14 */
+	or    t0, t0, t2

maybe:

	dins	t0, t2, 14, 2
Quoted 27 lines
arch/mips/kernel/relocate_kernel.S +11 -0
+1:	li    t9, 0x100           /* wait for init loop */
+2:	addiu t9, -1              /* limit mailbox access */
+	bnez  t9, 2b
+	ld    s1, 0x20(t0)        /* get PC via mailbox */
+	beqz  s1, 1b
+	ld    sp, 0x28(t0)        /* get SP via mailbox */
+	ld    gp, 0x30(t0)        /* get GP via mailbox */
+	ld    a1, 0x38(t0)
+	jr    s1                  /* jump to initial PC */
+#endif
+
 	j		s1
 	END(kexec_smp_wait)

#endif

arch/mips/loongson64/common/env.c +1 -0
index 2928ac5..990a2d69 100644
@@ -72,6 +72,7 @@ void __init prom_init_env(void)
 
 	pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize);
 #else
+	int i;
 	struct boot_params *boot_p;
 	struct loongson_params *loongson_p;
 	struct system_loongson *esys;

arch/mips/loongson64/common/env.c void __init prom_init_env(void) · line 156

Quoted 7 lines
arch/mips/loongson64/common/env.c +4 -0
@@ -149,6 +150,13 @@ void __init prom_init_env(void)
 	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
 	loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id;
 	loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask;
+#ifdef CONFIG_KEXEC
+	loongson_sysconf.boot_cpu_id = get_ebase_cpunum();
+	for (i = 0; i < loongson_sysconf.boot_cpu_id; i++)
+		loongson_sysconf.reserved_cpus_mask |= (1<<i);

maybe this?

	loongson_sysconf.reserved_cpus_mask |=
		(1 << loongson_sysconf.boot_cpu_id) - 1;
Quoted 12 lines
arch/mips/loongson64/common/env.c +3 -0
+	pr_info("Boot CPU ID is being fixed from %d to %d\n",
+		ecpu->cpu_startup_core_id, loongson_sysconf.boot_cpu_id);
+#endif
 	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
 		loongson_sysconf.nr_cpus = NR_CPUS;
 	loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
arch/mips/loongson64/common/reset.c +0 -0
index a60715e..5f65a4e 100644
@@ -11,9 +11,14 @@
  */

arch/mips/loongson64/common/reset.c line 21

Quoted 10 lines
arch/mips/loongson64/common/reset.c +5 -0
 #include <linux/init.h>
 #include <linux/pm.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/kexec.h>
 
 #include <asm/idle.h>
 #include <asm/reboot.h>
+#include <asm/bootinfo.h>

alphabetical ordering wherever possible please.

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 93

Quoted 13 lines
arch/mips/loongson64/common/reset.c +6 -0
 #include <loongson.h>
 #include <boot_param.h>
@@ -80,12 +85,126 @@ static void loongson_halt(void)
 	}
 }
 
+#ifdef CONFIG_KEXEC
+
+/* 0X80000000~0X80200000 is safe */
+#define MAX_ARGS	64
+#define KEXEC_CTRL_CODE	0XFFFFFFFF80100000UL
+#define KEXEC_ARGV_ADDR	0XFFFFFFFF80108000UL

lower case 0x please.

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 99

Quoted 6 lines
arch/mips/loongson64/common/reset.c +6 -0
+#define KEXEC_ARGV_SIZE	3060
+#define KEXEC_ENVP_SIZE	4500
+
+void *kexec_argv;
+void *kexec_envp;
+extern const size_t relocate_new_kernel_size;

A couple of other architectures have moved this declaration to asm/kexec.h.

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 108

Quoted 9 lines
arch/mips/loongson64/common/reset.c +9 -0
+
+static int loongson_kexec_prepare(struct kimage *image)
+{
+	int i, argc = 0;
+	unsigned int *argv;
+	char *str, *ptr, *bootloader = "kexec";
+
+	/* argv at offset 0, argv[] at offset KEXEC_ARGV_SIZE/2 */
+	argv = (unsigned int *)kexec_argv;

the cast is redundant as kexec_argv is void *.

Quoted 38 lines
arch/mips/loongson64/common/reset.c +38 -0
+	argv[argc++] = (unsigned int)(KEXEC_ARGV_ADDR + KEXEC_ARGV_SIZE/2);
+
+	for (i = 0; i < image->nr_segments; i++) {
+		if (!strncmp(bootloader, (char *)image->segment[i].buf,
+				strlen(bootloader))) {
+			/*
+			 * convert command line string to array
+			 * of parameters (as bootloader does).
+			 */
+			int offt;
+			memcpy(kexec_argv + KEXEC_ARGV_SIZE/2, image->segment[i].buf, KEXEC_ARGV_SIZE/2);
+			str = (char *)kexec_argv + KEXEC_ARGV_SIZE/2;
+			ptr = strchr(str, ' ');
+
+			while (ptr && (argc < MAX_ARGS)) {
+				*ptr = '\0';
+				if (ptr[1] != ' ') {
+					offt = (int)(ptr - str + 1);
+					argv[argc] = KEXEC_ARGV_ADDR + KEXEC_ARGV_SIZE/2 + offt;
+					argc++;
+				}
+				ptr = strchr(ptr + 1, ' ');
+			}
+			break;
+		}
+	}
+
+	kexec_args[0] = argc;
+	kexec_args[1] = fw_arg1;
+	kexec_args[2] = fw_arg2;
+	image->control_code_page = virt_to_page((void *)KEXEC_CTRL_CODE);
+
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static void kexec_smp_down(void *ignored)
+{

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 156

Quoted 10 lines
arch/mips/loongson64/common/reset.c +10 -0
+	int cpu = smp_processor_id();
+
+	local_irq_disable();
+	set_cpu_online(cpu, false);
+	while (!atomic_read(&kexec_ready_to_reboot))
+		cpu_relax();
+
+	asm volatile (
+	"	sync					\n"
+	"	synci	($0)				\n");

The intermediate assembly looks nicer, and you'd get fewer checkpatch complaints, if you do something more like this:

	asm volatile ("sync\n\t"
		      "synci ($0)");

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 169

Quoted 13 lines
arch/mips/loongson64/common/reset.c +13 -0
+
+	relocated_kexec_smp_wait(NULL);
+}
+#endif
+
+static void loongson_kexec_shutdown(void)
+{
+#ifdef CONFIG_SMP
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		if (!cpu_online(cpu))
+			cpu_up(cpu); /* Everyone should go to reboot_code_buffer */

long line

arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 172

Quoted 3 lines
arch/mips/loongson64/common/reset.c +3 -0
+
+	smp_call_function(kexec_smp_down, NULL, 0);
+	smp_wmb();

This probably needs a comment to explain what smp_rmb() it pairs with, or what writes need a barrier between them and why. It certainly isn't clear from reading the code.

Quoted 14 lines
arch/mips/loongson64/common/reset.c +8 -0
+	while (num_online_cpus() > 1) {
+		mdelay(1);
+		cpu_relax();
+	}
+#endif
+	memcpy((void *)fw_arg1, kexec_argv, KEXEC_ARGV_SIZE);
+	memcpy((void *)fw_arg2, kexec_envp, KEXEC_ENVP_SIZE);
+}
 
arch/mips/loongson64/loongson-3/smp.c +0 -0
index 470e9c1..1e21ac4 100644

arch/mips/loongson64/loongson-3/smp.c static void __init loongson3_smp_setup(void) · line 392

Quoted 6 lines
arch/mips/loongson64/loongson-3/smp.c +3 -0
@@ -387,6 +387,10 @@ static void __init loongson3_smp_setup(void)
 	ipi_status0_regs_init();
 	ipi_en0_regs_init();
 	ipi_mailbox_buf_init();
+
+	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
+		loongson3_ipi_write64(0, (void *)(ipi_mailbox_buf[i]+0x0));

what does that do? Please consider adding a comment.

Cheers
James

#22 lore raw

PATCH v2 10/12 MIPS: Loongson: Make CPUFreq usable for Loongson-3

In reply to Huacai Chen

Loongson-3A/3B support frequency scaling. But due to hardware limitation, Loongson-3A's frequency scaling is not independent for each core, we suggest enable Loongson-3A's CPUFreq only when there is one core online. Loongson-3B can adjust frequency independently for each core, so it can be always enabled.

Each package has only one register (ChipConfig or FreqCtrl) to control frequency, so we need spinlocks to protect register access for multi- cores. However, we cannot use spinlock when a core becomes into "wait" status (frequency = 0), so we only enable "wait" when there is one core in a package online.

arch/mips/kernel/smp.c is modified to guarantee udelay_val has the correct value while both CPU hotplug and CPUFreq are enabled.

---
 arch/mips/include/asm/mach-loongson64/loongson.h |   1 +
 arch/mips/kernel/smp.c                           |   3 +-
 arch/mips/loongson64/Kconfig                     |   1 +
 arch/mips/loongson64/common/platform.c           |  13 +-
 arch/mips/loongson64/loongson-3/Makefile         |   2 +-
 arch/mips/loongson64/loongson-3/clock.c          | 191 ++++++++++++++++++
 drivers/cpufreq/Kconfig                          |  13 ++
 drivers/cpufreq/Makefile                         |   1 +
 drivers/cpufreq/loongson3_cpufreq.c              | 236 +++++++++++++++++++++++
 9 files changed, 456 insertions(+), 5 deletions(-)
 create mode 100644 arch/mips/loongson64/loongson-3/clock.c
 create mode 100644 drivers/cpufreq/loongson3_cpufreq.c
arch/mips/include/asm/mach-loongson64/loongson.h +1 -0
index d0ae5d5..845f6dd 100644
@@ -277,6 +277,7 @@ extern u64 loongson_freqctrl[MAX_PACKAGES];
 #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
 #include <linux/cpufreq.h>
 extern struct cpufreq_frequency_table loongson2_clockmod_table[];
+extern struct cpufreq_frequency_table loongson3_clockmod_table[];
 #endif
 
 /*
arch/mips/kernel/smp.c +2 -1
index d84b906..915eba5 100644
@@ -370,7 +370,8 @@ asmlinkage void start_secondary(void)
 	calibrate_delay();
 	preempt_disable();
 	cpu = smp_processor_id();
-	cpu_data[cpu].udelay_val = loops_per_jiffy;
+	if (!cpu_data[cpu].udelay_val)
+		cpu_data[cpu].udelay_val = loops_per_jiffy;
 
 	cpumask_set_cpu(cpu, &cpu_coherent_mask);
 	notify_cpu_starting(cpu);
arch/mips/loongson64/Kconfig +1 -0
index 0d249fc..e6b28ff 100644
@@ -70,6 +70,7 @@ config LOONGSON_MACH3X
 	select CSRC_R4K
 	select CEVT_R4K
 	select CPU_HAS_WB
+	select HAVE_CLK
 	select HW_HAS_PCI
 	select ISA
 	select HT_PCI
arch/mips/loongson64/common/platform.c +10 -3
index 0ed3832..733a13f 100644
@@ -17,15 +17,22 @@ static struct platform_device loongson2_cpufreq_device = {
 	.id = -1,
 };
 
-static int __init loongson2_cpufreq_init(void)
+static struct platform_device loongson3_cpufreq_device = {
+	.name = "loongson3_cpufreq",
+	.id = -1,
+};
+
+static int __init loongson_cpufreq_init(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
 	/* Only 2F revision and it's successors support CPUFreq */
-	if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON2F)
+	if ((c->processor_id & PRID_REV_MASK) == PRID_REV_LOONGSON2F)
 		return platform_device_register(&loongson2_cpufreq_device);
+	if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R1)
+		return platform_device_register(&loongson3_cpufreq_device);
 
 	return -ENODEV;
 }
 
-arch_initcall(loongson2_cpufreq_init);
+arch_initcall(loongson_cpufreq_init);
arch/mips/loongson64/loongson-3/Makefile +1 -1
index 44bc148..7b035b7 100644
@@ -1,7 +1,7 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y			+= irq.o cop2-ex.o platform.o acpi_init.o
+obj-y			+= irq.o cop2-ex.o platform.o acpi_init.o clock.o
 
 obj-$(CONFIG_SMP)	+= smp.o
 
arch/mips/loongson64/loongson-3/clock.c new file +191 -0

191 lines not on this page · raw message

drivers/cpufreq/Kconfig +13 -0
index d8addbc..ea89910c 100644
@@ -286,6 +286,19 @@ config LOONGSON2_CPUFREQ
 
 	  If in doubt, say N.
 
+config LOONGSON3_CPUFREQ
+	tristate "Loongson3 CPUFreq Driver"
+	depends on LOONGSON_MACH3X
+	help
+	  This option adds a CPUFreq driver for loongson processors which
+	  support software configurable cpu frequency.
+
+	  Loongson-3A and it's successors support this feature.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
 config LOONGSON1_CPUFREQ
 	tristate "Loongson1 CPUFreq Driver"
 	depends on LOONGSON1_LS1B
drivers/cpufreq/Makefile +1 -0
index 812f9e0..52e52c4 100644
@@ -106,6 +106,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3)		+= cris-artpec3-cpufreq.o
 obj-$(CONFIG_ETRAXFS)			+= cris-etraxfs-cpufreq.o
 obj-$(CONFIG_IA64_ACPI_CPUFREQ)		+= ia64-acpi-cpufreq.o
 obj-$(CONFIG_LOONGSON2_CPUFREQ)		+= loongson2_cpufreq.o
+obj-$(CONFIG_LOONGSON3_CPUFREQ)		+= loongson3_cpufreq.o
 obj-$(CONFIG_LOONGSON1_CPUFREQ)		+= loongson1-cpufreq.o
 obj-$(CONFIG_SH_CPU_FREQ)		+= sh-cpufreq.o
 obj-$(CONFIG_SPARC_US2E_CPUFREQ)	+= sparc-us2e-cpufreq.o
drivers/cpufreq/loongson3_cpufreq.c new file +236 -0

236 lines not on this page · raw message

Signature · 1 line
2.7.0
#23 lore raw

PATCH v2 11/12 MIPS: Loongson-3: Fix CPU UART irq delivery problem

Masking/unmasking the CPU UART irq in CP0_Status (and redirecting it to other CPUs) may cause interrupts be lost, especially in multi-package machines (Package-0's UART irq cannot be delivered to others). So make mask_loongson_irq() and unmask_loongson_irq() be no-ops.

---
 arch/mips/loongson64/loongson-3/irq.c | 41 ++---------------------------------
 1 file changed, 2 insertions(+), 39 deletions(-)
arch/mips/loongson64/loongson-3/irq.c +2 -39
index cbeb20f..e8381ec 100644
@@ -102,45 +102,8 @@ static struct irqaction cascade_irqaction = {
 	.name = "cascade",
 };
 
-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();
-		int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node;
-		int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node;
-		u64 intenclr_addr = smp_group[node_id] |
-			(u64)(&LOONGSON_INT_ROUTER_INTENCLR);
-		u64 introuter_lpc_addr = smp_group[node_id] |
-			(u64)(&LOONGSON_INT_ROUTER_LPC);
-
-		*(volatile u32 *)intenclr_addr = 1 << 10;
-		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
-	}
-}
-
-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();
-		int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node;
-		int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node;
-		u64 intenset_addr = smp_group[node_id] |
-			(u64)(&LOONGSON_INT_ROUTER_INTENSET);
-		u64 introuter_lpc_addr = smp_group[node_id] |
-			(u64)(&LOONGSON_INT_ROUTER_LPC);
-
-		*(volatile u32 *)intenset_addr = 1 << 10;
-		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
-	}
-
-	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
-	irq_enable_hazard();
-}
+static inline void mask_loongson_irq(struct irq_data *d) { }
+static inline void unmask_loongson_irq(struct irq_data *d) { }
 
  /* For MIPS IRQs which shared by all cores */
 static struct irq_chip loongson_irq_chip = {
Signature · 1 line
2.7.0
#24 lore raw

Re: [PATCH V2 11/12] MIPS: Loongson-3: Fix CPU UART irq delivery problem

Quoted 6 lines · Huacai Chen

Masking/unmasking the CPU UART irq in CP0_Status (and redirecting it to other CPUs) may cause interrupts be lost, especially in multi-package machines (Package-0's UART irq cannot be delivered to others). So make mask_loongson_irq() and unmask_loongson_irq() be no-ops.

...

arch/mips/loongson64/loongson-3/irq.c static struct irqaction cascade_irqaction = { · line 110

Quoted 6 lines
arch/mips/loongson64/loongson-3/irq.c +0 -6
-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 */

Wouldn't removing this self-described "workaround" bring back the original problem?

At the very least you need a much better explanation of why these workarounds are no longer applicable and can be safely removed.

Cheers
James

#25 lore raw

PATCH v2 12/12 MIPS: Loongson: Introduce and use WAR_LLSC_MB

In reply to Huacai Chen

On the Loongson-2G/2H/3A/3B there is a hardware flaw that ll/sc and lld/scd is very weak ordering. We should add sync instructions before each ll/lld and after the last sc/scd to workaround. Otherwise, this flaw will cause deadlock occationally (e.g. when doing heavy load test with LTP).

---
 arch/mips/include/asm/atomic.h  | 18 ++++++++++++++++--
 arch/mips/include/asm/barrier.h |  6 ++++++
 arch/mips/include/asm/bitops.h  | 15 +++++++++++++++
 arch/mips/include/asm/cmpxchg.h |  9 +++++++--
 arch/mips/include/asm/edac.h    |  5 ++++-
 arch/mips/include/asm/futex.h   | 18 ++++++++++++------
 arch/mips/include/asm/local.h   | 10 ++++++++--
 arch/mips/include/asm/pgtable.h |  5 ++++-
 arch/mips/kernel/syscall.c      |  2 ++
 arch/mips/loongson64/Platform   |  3 +++
 arch/mips/mm/tlbex.c            | 11 +++++++++++
 11 files changed, 88 insertions(+), 14 deletions(-)
arch/mips/include/asm/atomic.h +16 -2
index 0ab176b..99a6d01 100644
@@ -62,6 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	ll	%0, %1		# atomic_" #op "\n"   \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \
@@ -69,6 +70,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)  \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");	      \
 	} else {							      \
 		unsigned long flags;					      \
 									      \
@@ -103,6 +105,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v)	      \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	ll	%1, %2	# atomic_" #op "_return	\n"   \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	sc	%0, %2				\n"   \
@@ -151,6 +154,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)	      \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	ll	%1, %2	# atomic_fetch_" #op "	\n"   \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	sc	%0, %2				\n"   \
@@ -159,6 +163,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)	      \
 			  "+" GCC_OFF_SMALL_ASM() (v->counter)		      \
 			: "Ir" (i));					      \
 		} while (unlikely(!result));				      \
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");	      \
 									      \
 		result = temp;						      \
 	} else {							      \
@@ -242,7 +247,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 
 		__asm__ __volatile__(
 		"	.set	"MIPS_ISA_LEVEL"			\n"
-		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
+		"1:			# atomic_sub_if_positive	\n"
+		__WAR_LLSC_MB
+		"	ll	%1, %2					\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
 		"	sc	%0, %2					\n"
@@ -404,6 +411,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	lld	%0, %1		# atomic64_" #op "\n" \
 			"	" #asm_op " %0, %2			\n"   \
 			"	scd	%0, %1				\n"   \
@@ -411,6 +419,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)      \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");	      \
 	} else {							      \
 		unsigned long flags;					      \
 									      \
@@ -445,6 +454,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	lld	%1, %2	# atomic64_" #op "_return\n"  \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	scd	%0, %2				\n"   \
@@ -494,6 +504,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v)  \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	lld	%1, %2	# atomic64_fetch_" #op "\n"   \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	scd	%0, %2				\n"   \
@@ -503,6 +514,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v)  \
 			: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)	      \
 			: "memory");					      \
 		} while (unlikely(!result));				      \
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");	      \
 									      \
 		result = temp;						      \
 	} else {							      \
@@ -587,7 +599,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 
 		__asm__ __volatile__(
 		"	.set	"MIPS_ISA_LEVEL"			\n"
-		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
+		"1:			# atomic64_sub_if_positive	\n"
+		__WAR_LLSC_MB
+		"	lld	%1, %2					\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
 		"	scd	%0, %2					\n"
arch/mips/include/asm/barrier.h +6 -0
index 0e8e6af..268d921 100644
@@ -203,6 +203,12 @@
 #define __WEAK_LLSC_MB		"		\n"
 #endif
 
+#if defined(CONFIG_LOONGSON3) && defined(CONFIG_SMP) /* Loongson-3's LLSC workaround */
+#define __WAR_LLSC_MB		"	sync	\n"
+#else
+#define __WAR_LLSC_MB		"		\n"
+#endif
+
 #define smp_llsc_mb()	__asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
arch/mips/include/asm/bitops.h +15 -0
index da1b871..0612cff 100644
@@ -70,17 +70,20 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} while (unlikely(!temp));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -88,6 +91,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else
 		__mips_set_bit(nr, addr);
 }
@@ -122,17 +126,20 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit));
 		} while (unlikely(!temp));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
@@ -140,6 +147,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (~(1UL << bit)));
 		} while (unlikely(!temp));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else
 		__mips_clear_bit(nr, addr);
 }
@@ -191,6 +199,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1		# change_bit	\n"
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -198,6 +207,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else
 		__mips_change_bit(nr, addr);
 }
@@ -240,6 +250,7 @@ static inline int test_and_set_bit(unsigned long nr,
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -294,6 +305,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -350,6 +362,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
+			__WAR_LLSC_MB
 			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
@@ -366,6 +379,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	xor	%2, %3				\n"
@@ -423,6 +437,7 @@ static inline int test_and_change_bit(unsigned long nr,
 		do {
 			__asm__ __volatile__(
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			__WAR_LLSC_MB
 			"	" __LL	"%0, %1 # test_and_change_bit	\n"
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
arch/mips/include/asm/cmpxchg.h +7 -2
index 89e9fb7..1f9c091 100644
@@ -48,7 +48,9 @@ extern unsigned long __xchg_called_with_bad_pointer(void)
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	" MIPS_ISA_ARCH_LEVEL "		\n"	\
-		"1:	" ld "	%0, %2		# __xchg_asm	\n"	\
+		"1:				# __xchg_asm	\n"	\
+		__WAR_LLSC_MB						\
+		"	" ld "	%0, %2				\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z3				\n"	\
 		"	.set	" MIPS_ISA_ARCH_LEVEL "		\n"	\
@@ -118,7 +120,9 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
-		"1:	" ld "	%0, %2		# __cmpxchg_asm \n"	\
+		"1:				# __cmpxchg_asm \n"	\
+		__WAR_LLSC_MB						\
+		"	" ld "	%0, %2				\n"	\
 		"	bne	%0, %z3, 2f			\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z4				\n"	\
@@ -127,6 +131,7 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
 		"\t" __scbeqz "	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
+		__WAR_LLSC_MB						\
 		: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m)		\
 		: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
arch/mips/include/asm/edac.h +4 -1
index fc46776..b07a3a9 100644
@@ -22,13 +22,16 @@ static inline void edac_atomic_scrub(void *va, u32 size)
 
 		__asm__ __volatile__ (
 		"	.set	mips2					\n"
-		"1:	ll	%0, %1		# edac_atomic_scrub	\n"
+		"1:				# edac_atomic_scrub	\n"
+		__WAR_LLSC_MB
+		"	ll	%0, %1					\n"
 		"	addu	%0, $0					\n"
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*virt_addr)
 		: GCC_OFF_SMALL_ASM() (*virt_addr));
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 
 		virt_addr++;
 	}
arch/mips/include/asm/futex.h +12 -6
index a9e61ea..d497ee9 100644
@@ -54,7 +54,9 @@
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
-		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
+		"1:				 # __futex_atomic_op\n"	\
+		__WAR_LLSC_MB						\
+		"	"user_ll("%1", "%4")"			\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
 		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
@@ -70,8 +72,9 @@
 		"	j	3b				\n"	\
 		"	.previous				\n"	\
 		"	.section __ex_table,\"a\"		\n"	\
-		"	"__UA_ADDR "\t1b, 4b			\n"	\
-		"	"__UA_ADDR "\t2b, 4b			\n"	\
+		"	"__UA_ADDR "\t(1b + 0), 4b		\n"	\
+		"	"__UA_ADDR "\t(1b + 4), 4b		\n"	\
+		"	"__UA_ADDR "\t(2b + 0), 4b		\n"	\
 		"	.previous				\n"	\
 		: "=r" (ret), "=&r" (oldval),				\
 		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
@@ -167,7 +170,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
-		"1:	"user_ll("%1", "%3")"				\n"
+		"1:							\n"
+		__WAR_LLSC_MB
+		"	"user_ll("%1", "%3")"				\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
@@ -183,8 +188,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
-		"	"__UA_ADDR "\t1b, 4b				\n"
-		"	"__UA_ADDR "\t2b, 4b				\n"
+		"	"__UA_ADDR "\t(1b + 0), 4b			\n"
+		"	"__UA_ADDR "\t(1b + 4), 4b			\n"
+		"	"__UA_ADDR "\t(2b + 0), 4b			\n"
 		"	.previous					\n"
 		: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
 		: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
arch/mips/include/asm/local.h +8 -2
index ac8264e..4105b7a 100644
@@ -50,7 +50,9 @@ static __inline__ long local_add_return(long i, local_t * l)
 
 		__asm__ __volatile__(
 		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
-		"1:"	__LL	"%1, %2		# local_add_return	\n"
+		"1:				# local_add_return	\n"
+			__WAR_LLSC_MB
+			__LL	"%1, %2					\n"
 		"	addu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
 		"	beqz	%0, 1b					\n"
@@ -59,6 +61,7 @@ static __inline__ long local_add_return(long i, local_t * l)
 		: "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
 		: "Ir" (i), "m" (l->a.counter)
 		: "memory");
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else {
 		unsigned long flags;
 
@@ -95,7 +98,9 @@ static __inline__ long local_sub_return(long i, local_t * l)
 
 		__asm__ __volatile__(
 		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
-		"1:"	__LL	"%1, %2		# local_sub_return	\n"
+		"1:				# local_sub_return	\n"
+			__WAR_LLSC_MB
+			__LL	"%1, %2					\n"
 		"	subu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
 		"	beqz	%0, 1b					\n"
@@ -104,6 +109,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
 		: "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
 		: "Ir" (i), "m" (l->a.counter)
 		: "memory");
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else {
 		unsigned long flags;
 
arch/mips/include/asm/pgtable.h +4 -1
index 1a508a7..729e001 100644
@@ -233,7 +233,9 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
 			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	.set	push				\n"
 			"	.set	noreorder			\n"
-			"1:"	__LL	"%[tmp], %[buddy]		\n"
+			"1:						\n"
+				__WAR_LLSC_MB
+				__LL	"%[tmp], %[buddy]		\n"
 			"	bnez	%[tmp], 2f			\n"
 			"	 or	%[tmp], %[tmp], %[global]	\n"
 				__SC	"%[tmp], %[buddy]		\n"
@@ -244,6 +246,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
 			"	.set	mips0				\n"
 			: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
 			: [global] "r" (page_global));
+			__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 		}
 #else /* !CONFIG_SMP */
 		if (pte_none(*buddy))
arch/mips/kernel/syscall.c +2 -0
index 58c6f63..342fbff 100644
@@ -133,6 +133,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
 		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"	li	%[err], 0				\n"
 		"1:							\n"
+		__WAR_LLSC_MB
 		user_ll("%[old]", "(%[addr])")
 		"	move	%[tmp], %[new]				\n"
 		"2:							\n"
@@ -156,6 +157,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
 		  [new] "r" (new),
 		  [efault] "i" (-EFAULT)
 		: "memory");
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");
 	} else {
 		do {
 			preempt_disable();
arch/mips/loongson64/Platform +3 -0
index 0fce460..3700dcf 100644
@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3)	+= -Wa,--trap
+ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),)
+  cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc
+endif
 #
 # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
 # as MIPS64 R2; older versions as just R1.  This leaves the possibility open
arch/mips/mm/tlbex.c +11 -0
index 3d3dfba..a507ba7 100644
@@ -919,6 +919,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		 * to mimic that here by taking a load/istream page
 		 * fault.
 		 */
+		if (current_cpu_type() == CPU_LOONGSON3)
+			uasm_i_sync(p, 0);
 		UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
 		uasm_i_jr(p, ptr);
 
@@ -1545,6 +1547,7 @@ static void build_loongson3_tlb_refill_handler(void)
 
 	if (check_for_high_segbits) {
 		uasm_l_large_segbits_fault(&l, p);
+		uasm_i_sync(&p, 0);
 		UASM_i_LA(&p, K1, (unsigned long)tlb_do_page_fault_0);
 		uasm_i_jr(&p, K1);
 		uasm_i_nop(&p);
@@ -1645,6 +1648,8 @@ static void
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
+	if (current_cpu_type() == CPU_LOONGSON3)
+		uasm_i_sync(p, 0);
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
 	if (cpu_has_64bits)
 		uasm_i_lld(p, pte, 0, ptr);
@@ -2262,6 +2267,8 @@ static void build_r4000_tlb_load_handler(void)
 #endif
 
 	uasm_l_nopage_tlbl(&l, p);
+	if (current_cpu_type() == CPU_LOONGSON3)
+		uasm_i_sync(&p, 0);
 	build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
 	if ((unsigned long)tlb_do_page_fault_0 & 1) {
@@ -2317,6 +2324,8 @@ static void build_r4000_tlb_store_handler(void)
 #endif
 
 	uasm_l_nopage_tlbs(&l, p);
+	if (current_cpu_type() == CPU_LOONGSON3)
+		uasm_i_sync(&p, 0);
 	build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
 	if ((unsigned long)tlb_do_page_fault_1 & 1) {
@@ -2373,6 +2382,8 @@ static void build_r4000_tlb_modify_handler(void)
 #endif
 
 	uasm_l_nopage_tlbm(&l, p);
+	if (current_cpu_type() == CPU_LOONGSON3)
+		uasm_i_sync(&p, 0);
 	build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
 	if ((unsigned long)tlb_do_page_fault_1 & 1) {
Signature · 1 line
2.7.0
#26 lore raw

Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB

Quoted 5 lines · Huacai Chen

On the Loongson-2G/2H/3A/3B there is a hardware flaw that ll/sc and lld/scd is very weak ordering. We should add sync instructions before each ll/lld and after the last sc/scd to workaround. Otherwise, this flaw will cause deadlock occationally (e.g. when doing heavy load test with LTP).

How confident are you that this is the minimal change required to fix the issue? Is the problem well understood?

It'd be helpful to have some more details about the flaw if you have them.

I.e. does it really have to be done on every loop iteration (such that using WEAK_REORDERING_BEYOND_LLSC is insufficient)?

Quoted 13 lines
arch/mips/include/asm/atomic.h +1 -0
index 0ab176b..99a6d01 100644
@@ -62,6 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 		do {							      \
 			__asm__ __volatile__(				      \
 			"	.set	"MIPS_ISA_LEVEL"		\n"   \
+			__WAR_LLSC_MB					      \
 			"	ll	%0, %1		# atomic_" #op "\n"   \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \

arch/mips/include/asm/atomic.h static __inline__ void atomic_##op(int i, atomic_t * v) \ · line 73

Quoted 4 lines
arch/mips/include/asm/atomic.h +1 -0
@@ -69,6 +70,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)  \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
+		__asm__ __volatile__(__WAR_LLSC_MB : : :"memory");	      \

This still results in an additional compiler barrier on other platforms, so if it must remain it needs abstracting.

arch/mips/include/asm/barrier.h line 210

Quoted 13 lines
arch/mips/include/asm/barrier.h +5 -0
index 0e8e6af..268d921 100644
@@ -203,6 +203,12 @@
 #define __WEAK_LLSC_MB		"		\n"
 #endif
 
+#if defined(CONFIG_LOONGSON3) && defined(CONFIG_SMP) /* Loongson-3's LLSC workaround */
+#define __WAR_LLSC_MB		"	sync	\n"
+#else
+#define __WAR_LLSC_MB		"		\n"
+#endif

A comment explaining the whole issue would be helpful for others trying to decipher this.

arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28

Quoted 11 lines
arch/mips/loongson64/Platform +3 -0
index 0fce460..3700dcf 100644
@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3)	+= -Wa,--trap
+ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),)
+  cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc
+endif

Could this be a separate patch?

This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?

arch/mips/mm/tlbex.c build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, · line 923

Quoted 10 lines
arch/mips/mm/tlbex.c +2 -0
index 3d3dfba..a507ba7 100644
@@ -919,6 +919,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		 * to mimic that here by taking a load/istream page
 		 * fault.
 		 */
+		if (current_cpu_type() == CPU_LOONGSON3)
+			uasm_i_sync(p, 0);

I suggest abstracting this out with a nice comment explaining why it is necessary.

Cheers
James

#27 lore raw

Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB

Quoted 14 lines · James Hogan

arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28

Quoted 11 lines
arch/mips/loongson64/Platform +3 -0
index 0fce460..3700dcf 100644
@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3)	+= -Wa,--trap
+ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),)
+  cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc
+endif

Could this be a separate patch?

Quoted 4 lines

This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?

FYI, support for `-mfix-loongson3-llsc' in GAS has only recently been
proposed: <https://sourceware.org/ml/binutils/2018-01/msg00303.html> and is still pending review.

Maciej

#28 lore raw

Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB

Quoted 16 lines · Maciej W. Rozycki
Quoted 14 lines · James Hogan

arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28

Quoted 11 lines
arch/mips/loongson64/Platform +3 -0
index 0fce460..3700dcf 100644
@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3)	+= -Wa,--trap
+ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),)
+  cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc
+endif

Could this be a separate patch?

Quoted 8 lines
Quoted 4 lines

This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?

FYI, support for `-mfix-loongson3-llsc' in GAS has only recently been
proposed: <https://sourceware.org/ml/binutils/2018-01/msg00303.html> and is still pending review.

Thanks for that link Maciej. GNU changelogs are useless, so this is the interesting bit:

Review

Quoted 5 lines

+@item -mfix-loongson3-llsc
+@itemx -mno-fix-loongson3-llsc

(quoted diff) +3 -0
+Insert @code{sync} instruction before @samp{ll} or @samp{lld} instrction
+to work around Loongson3 @samp{LL}/@samp{SC} errata.
+This issue exists in all Loongson3 CPUs.

Cheers
James

#29 lore raw

Re: [PATCH V2 10/12] MIPS: Loongson: Make CPUFreq usable for Loongson-3

In reply to Huacai Chen
Quoted 4 lines · Huacai Chen

Loongson-3A/3B support frequency scaling. But due to hardware limitation, Loongson-3A's frequency scaling is not independent for each core, we suggest enable Loongson-3A's CPUFreq only when there is one core online.

Does the code do anything to enforce that?

If not, should it?

Will it just work suboptimally if you tried?

Quoted 9 lines
 arch/mips/include/asm/mach-loongson64/loongson.h |   1 +
 arch/mips/kernel/smp.c                           |   3 +-
 arch/mips/loongson64/Kconfig                     |   1 +
 arch/mips/loongson64/common/platform.c           |  13 +-
 arch/mips/loongson64/loongson-3/Makefile         |   2 +-
 arch/mips/loongson64/loongson-3/clock.c          | 191 ++++++++++++++++++
 drivers/cpufreq/Kconfig                          |  13 ++
 drivers/cpufreq/Makefile                         |   1 +
 drivers/cpufreq/loongson3_cpufreq.c              | 236 +++++++++++++++++++++++

This could presumably be fairly neatly divided into 3 separate changes:
- New clocks driver
- New cpufreq driver
- Minimal platform changes in arch/mips to instantiate the drivers

Please can you use the common clock framework i.e. a driver in drivers/clk/, rather than adding yet another implementation of the clk api in arch/mips/.

Each change needs the appropriate maintainers on Cc or you'll never get the required review.

Cheers
James

#30 lore raw
In reply to Huacai Chen
Quoted 7 lines · Huacai Chen

This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in /proc/cpuinfo which is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introduces WAR_LLSC_MB to improve stability.

Quoted 5 lines

V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.

I few general suggestions that I hope will help you to get your patches applied quicker:

- Please have a separate series for each group of related changes in future. It makes them more manageable, makes dependencies clearer, and avoids unchanged resends of unrelated patches when you respin the whole series. Series are mainly to group tightly related patches, or because of dependencies of later patches on earlier ones (and even if you have a series of 30 dependent patches, you can still sometimes split it into groups and mention in the cover letters which other pending series each series depends on).

- More importantly, avoid moving patches between series or adding unrelated patches to a series if possible (so probably best not to split this series now). It makes it harder to see what has changed, whether past feedback has been addressed, and whether new/removed patches are new/abandoned or simply moved from/to a different series.

- Please don't resend a series without changes, ping it if you are concerned. It clutters patchwork for no good reason and makes it harder to see if past feedback has been addressed.

- Please run checkpatch on all patches before submission, and fix any reasonable warnings and errors (i.e. there are various lines exceeding 80 characters in this series which should be split, but some are acceptable where its to keep a string together).

- Please include Fixes tags where appropriate, especially where you've Cc'd stable.

- If you Cc stable, please state how far back it should be backported wherever possible,
E.g. Cc: <[email protected]> # 4.14+
This may help finding what version a commit is first included in:
https://www.linux-mips.org/archives/linux-mips/2017-07/msg00149.html

- Please run get_maintainer.pl on each patch to make sure you cc the appropriate maintainers and lists (and Cc them on the cover letter too). Its fine to skip LKML for lots of MIPS patches, but don't miss out the appropriate subsystem maintainers and lists for patches touching drivers/ or they'll never get acked and never get applied.

- Split arch/mips/ and drivers/ patches wherever possible.

Cheers
James

#31 lore raw

Hi, James,

I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....

For example:
https://patchwork.linux-mips.org/patch/17723/
https://patchwork.linux-mips.org/patch/18587/
https://patchwork.linux-mips.org/patch/18682/

Anyway, thank you for your susggestions, I will rework other patches.

Huacai

Quoted 60 lines · James Hogan
Quoted 7 lines · Huacai Chen

This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in /proc/cpuinfo which is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introduces WAR_LLSC_MB to improve stability.

Quoted 5 lines

V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.

I few general suggestions that I hope will help you to get your patches applied quicker:

- Please have a separate series for each group of related changes in future. It makes them more manageable, makes dependencies clearer, and avoids unchanged resends of unrelated patches when you respin the whole series. Series are mainly to group tightly related patches, or because of dependencies of later patches on earlier ones (and even if you have a series of 30 dependent patches, you can still sometimes split it into groups and mention in the cover letters which other pending series each series depends on).

- More importantly, avoid moving patches between series or adding unrelated patches to a series if possible (so probably best not to split this series now). It makes it harder to see what has changed, whether past feedback has been addressed, and whether new/removed patches are new/abandoned or simply moved from/to a different series.

- Please don't resend a series without changes, ping it if you are concerned. It clutters patchwork for no good reason and makes it harder to see if past feedback has been addressed.

- Please run checkpatch on all patches before submission, and fix any reasonable warnings and errors (i.e. there are various lines exceeding 80 characters in this series which should be split, but some are acceptable where its to keep a string together).

- Please include Fixes tags where appropriate, especially where you've Cc'd stable.

- If you Cc stable, please state how far back it should be backported wherever possible,
E.g. Cc: <[email protected]> # 4.14+
This may help finding what version a commit is first included in:
https://www.linux-mips.org/archives/linux-mips/2017-07/msg00149.html

- Please run get_maintainer.pl on each patch to make sure you cc the appropriate maintainers and lists (and Cc them on the cover letter too). Its fine to skip LKML for lots of MIPS patches, but don't miss out the appropriate subsystem maintainers and lists for patches touching drivers/ or they'll never get acked and never get applied.

- Split arch/mips/ and drivers/ patches wherever possible.

Cheers
James

#32 lore raw
Quoted 5 lines · Huacai Chen

Hi, James,

I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....

Then please feel free to reply to the patch and ask if anybody has feedback, stating how important the patch is for you, so it can be prioritised. Resends as part of other series just adds to the noise.

Quoted 3 lines

For example:
https://patchwork.linux-mips.org/patch/17723/

Yes, that one needs a proper look.

Quoted 1 line

https://patchwork.linux-mips.org/patch/18587/

This one apparently knowingly breaks the feature on other platforms, so can't really be applied as is. I think Matt Redfearn & I were thinking his single IPI stuff could potentially be helpful there too.

Quoted 1 line

https://patchwork.linux-mips.org/patch/18682/

You sent that this morning so its hardly had time to be ignored, and I had already spotted it on my phone and intended to apply it today. Also I disagree that "Commit x breaks Loongson64 platforms, so fix it" counts as well described, even if it is simple, and obvious (to me at least) what you're talking about.

E.g. a better description would along the lines of:

Commit 7a407aa5e0d3 ("MIPS: Push ARCH_MIGHT_HAVE_PC_SERIO down to platform level") moves the global MIPS ARCH_MIGHT_HAVE_PC_SERIO select down to various platforms, but doesn't add it to Loongson64 platforms which need it, so add the selects to these platforms too.

Quoted 2 lines

Anyway, thank you for your susggestions, I will rework other patches.

Thank you.

Cheers
James

#33 lore raw
Quoted 15 lines · James Hogan
Quoted 5 lines · Huacai Chen

Hi, James,

I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....

Then please feel free to reply to the patch and ask if anybody has feedback, stating how important the patch is for you, so it can be prioritised. Resends as part of other series just adds to the noise.

Quoted 3 lines

For example:
https://patchwork.linux-mips.org/patch/17723/

Quoted 7 lines

Yes, that one needs a proper look.

Quoted 1 line

https://patchwork.linux-mips.org/patch/18587/

This one apparently knowingly breaks the feature on other platforms, so can't really be applied as is. I think Matt Redfearn & I were thinking his single IPI stuff could potentially be helpful there too.

I think this does't break other platforms, because:
1, arch_trigger_cpumask_backtrace() will not be called in normal cases; 2, If arch_trigger_cpumask_backtrace() really be called, the old code also doesn't work (deadlock).

Quoted 9 lines
Quoted 2 lines

https://patchwork.linux-mips.org/patch/18682/

You sent that this morning so its hardly had time to be ignored, and I had already spotted it on my phone and intended to apply it today. Also I disagree that "Commit x breaks Loongson64 platforms, so fix it" counts as well described, even if it is simple, and obvious (to me at least) what you're talking about.

Quoted 6 lines

E.g. a better description would along the lines of:

Commit 7a407aa5e0d3 ("MIPS: Push ARCH_MIGHT_HAVE_PC_SERIO down to platform level") moves the global MIPS ARCH_MIGHT_HAVE_PC_SERIO select down to various platforms, but doesn't add it to Loongson64 platforms which need it, so add the selects to these platforms too.

I'll update my commit messages.

Quoted 8 lines
Quoted 3 lines

Anyway, thank you for your susggestions, I will rework other patches.

Thank you.

Cheers
James