diff mbox series

[01/12] parisc: Switch from GENERIC_CPU_DEVICES to GENERIC_ARCH_TOPOLOGY

Message ID 20220325143833.402631-1-deller@gmx.de (mailing list archive)
State Superseded
Headers show
Series [01/12] parisc: Switch from GENERIC_CPU_DEVICES to GENERIC_ARCH_TOPOLOGY | expand

Commit Message

Helge Deller March 25, 2022, 2:38 p.m. UTC
Switch away from the own cpu topology code to common code which is used
by ARM64 and RISCV. That allows us to enable hotplug later on too.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 arch/parisc/Kconfig                |  2 +-
 arch/parisc/include/asm/topology.h | 20 +--------
 arch/parisc/kernel/processor.c     |  2 +
 arch/parisc/kernel/topology.c      | 72 +++++++-----------------------
 4 files changed, 19 insertions(+), 77 deletions(-)

--
2.35.1

Comments

Helge Deller March 25, 2022, 2:53 p.m. UTC | #1
On 3/25/22 15:38, Helge Deller wrote:
> Switch away from the own cpu topology code to common code which is used
> by ARM64 and RISCV. That allows us to enable hotplug later on too.

With this series I was able to use CPU hotplugging on the PA-RISC machines.
I sucessfully tested it on qemu (32bit kernel) and on a 2-way C8000 (64bit kernel).

For qemu the patch I committed today is required:
https://github.com/hdeller/seabios-hppa/commit/5cec13f11d3917cf3bceaf68ce23e9fa5f206a35

There is still some issue with the irq balancing on qemu with the emulated GSC, e.g. in this
example with 3 CPUs you can only disable CPU0 or CPU2, which both don't use any IRQs.
During shutdown of CPU1 the irqs 17-20 needs to be moved to another CPU which doesn't
work reliable yet.

Example:

root@debian:~# cat /proc/interrupts
           CPU0       CPU1       CPU2
 17:          0          0          0        GSC-ASIC  parport0
 18:          0       1759          0         GSC-PCI  ttyS0
 19:          0       3572          0         GSC-PCI  sym53c8xx
 20:          0       2359          0         GSC-PCI  enp0s1
 64:        224     148358     128518             CPU  timer
 65:         16       4224        677             CPU  IPI
 66:          0          0          0             CPU  lasi
 67:          0       8758          0             CPU  Dino
STK:       2240       6080       3072   Kernel stack usage

root@debian:~# chcpu -d 2	# disables CPU2
CPU 2 disabled

root@debian:~# cat /proc/interrupts
           CPU0       CPU1
 17:          0          0        GSC-ASIC  parport0
 18:          0       1843         GSC-PCI  ttyS0
 19:          0       3662         GSC-PCI  sym53c8xx
 20:...

root@debian:~# chcpu -e 2	# enable CPU2
[    6.466714] Releasing cpu 2 now, hpa=fffb2000
CPU 2 enabled

root@debian:~# cat /proc/interrupts
           CPU0       CPU1       CPU2
 17:          0          0          0        GSC-ASIC  parport0
 18:          0       1915          0         GSC-PCI  ttyS0
 19:          0       3668          0         GSC-PCI  sym53c8xx
...

CPU hotplugging on the C8000 seems to work reliable.

Helge
Rolf Eike Beer March 25, 2022, 4:46 p.m. UTC | #2
Am Freitag, 25. März 2022, 15:38:22 CET schrieb Helge Deller:
> Switch away from the own cpu topology code to common code which is used
> by ARM64 and RISCV. That allows us to enable hotplug later on too.

> diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
> index e88a6ce7c96d..72d9aeb54fbe 100644
> --- a/arch/parisc/kernel/topology.c
> +++ b/arch/parisc/kernel/topology.c
> @@ -71,6 +37,12 @@ void __init store_cpu_topology(unsigned int cpuid)
>  	if (cpuid_topo->core_id != -1)
>  		return;
> 
> +#ifdef CONFIG_HOTPLUG_CPU
> +	per_cpu(cpu_devices, cpuid).hotpluggable = 1;
> +#endif
> +	if (register_cpu(&per_cpu(cpu_devices, cpuid), cpuid))
> +		printk("Failed to register CPU device");
> +

This seems to be missing a level, and I think also printing the id of the 
failing CPU wouldn't hurt either.
diff mbox series

Patch

diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 00cb889bd9a6..6bd42c82a019 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -37,7 +37,7 @@  config PARISC
 	select GENERIC_PCI_IOMAP
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_SMP_IDLE_THREAD
-	select GENERIC_CPU_DEVICES
+	select GENERIC_ARCH_TOPOLOGY
 	select GENERIC_LIB_DEVMEM_IS_ALLOWED
 	select SYSCTL_ARCH_UNALIGN_ALLOW
 	select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/parisc/include/asm/topology.h b/arch/parisc/include/asm/topology.h
index 6f0750c74e47..734eddf096f7 100644
--- a/arch/parisc/include/asm/topology.h
+++ b/arch/parisc/include/asm/topology.h
@@ -4,25 +4,7 @@ 
 #ifdef CONFIG_PARISC_CPU_TOPOLOGY

 #include <linux/cpumask.h>
-
-struct cputopo_parisc {
-	int thread_id;
-	int core_id;
-	int socket_id;
-	cpumask_t thread_sibling;
-	cpumask_t core_sibling;
-};
-
-extern struct cputopo_parisc cpu_topology[NR_CPUS];
-
-#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id)
-#define topology_core_id(cpu)		(cpu_topology[cpu].core_id)
-#define topology_core_cpumask(cpu)	(&cpu_topology[cpu].core_sibling)
-#define topology_sibling_cpumask(cpu)	(&cpu_topology[cpu].thread_sibling)
-
-void init_cpu_topology(void);
-void store_cpu_topology(unsigned int cpuid);
-const struct cpumask *cpu_coregroup_mask(int cpu);
+#include <linux/arch_topology.h>

 #else

diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index ccaf075d0750..d0bfd61a4623 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -19,6 +19,7 @@ 
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <asm/topology.h>
 #include <asm/param.h>
 #include <asm/cache.h>
 #include <asm/hardware.h>	/* for register_parisc_driver() stuff */
@@ -459,5 +460,6 @@  static struct parisc_driver cpu_driver __refdata = {
  */
 void __init processor_init(void)
 {
+	reset_cpu_topology();
 	register_parisc_driver(&cpu_driver);
 }
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
index e88a6ce7c96d..72d9aeb54fbe 100644
--- a/arch/parisc/kernel/topology.c
+++ b/arch/parisc/kernel/topology.c
@@ -13,45 +13,11 @@ 
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/sched/topology.h>
+#include <linux/cpu.h>

 #include <asm/topology.h>

- /*
-  * cpu topology table
-  */
-struct cputopo_parisc cpu_topology[NR_CPUS] __read_mostly;
-EXPORT_SYMBOL_GPL(cpu_topology);
-
-const struct cpumask *cpu_coregroup_mask(int cpu)
-{
-	return &cpu_topology[cpu].core_sibling;
-}
-
-static void update_siblings_masks(unsigned int cpuid)
-{
-	struct cputopo_parisc *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
-	int cpu;
-
-	/* update core and thread sibling masks */
-	for_each_possible_cpu(cpu) {
-		cpu_topo = &cpu_topology[cpu];
-
-		if (cpuid_topo->socket_id != cpu_topo->socket_id)
-			continue;
-
-		cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
-		if (cpu != cpuid)
-			cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
-
-		if (cpuid_topo->core_id != cpu_topo->core_id)
-			continue;
-
-		cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
-		if (cpu != cpuid)
-			cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
-	}
-	smp_wmb();
-}
+static DEFINE_PER_CPU(struct cpu, cpu_devices);

 static int dualcores_found __initdata;

@@ -62,7 +28,7 @@  static int dualcores_found __initdata;
  */
 void __init store_cpu_topology(unsigned int cpuid)
 {
-	struct cputopo_parisc *cpuid_topo = &cpu_topology[cpuid];
+	struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
 	struct cpuinfo_parisc *p;
 	int max_socket = -1;
 	unsigned long cpu;
@@ -71,6 +37,12 @@  void __init store_cpu_topology(unsigned int cpuid)
 	if (cpuid_topo->core_id != -1)
 		return;

+#ifdef CONFIG_HOTPLUG_CPU
+	per_cpu(cpu_devices, cpuid).hotpluggable = 1;
+#endif
+	if (register_cpu(&per_cpu(cpu_devices, cpuid), cpuid))
+		printk("Failed to register CPU device");
+
 	/* create cpu topology mapping */
 	cpuid_topo->thread_id = -1;
 	cpuid_topo->core_id = 0;
@@ -86,25 +58,25 @@  void __init store_cpu_topology(unsigned int cpuid)
 			cpuid_topo->core_id = cpu_topology[cpu].core_id;
 			if (p->cpu_loc) {
 				cpuid_topo->core_id++;
-				cpuid_topo->socket_id = cpu_topology[cpu].socket_id;
+				cpuid_topo->package_id = cpu_topology[cpu].package_id;
 				dualcores_found = 1;
 				continue;
 			}
 		}

-		if (cpuid_topo->socket_id == -1)
-			max_socket = max(max_socket, cpu_topology[cpu].socket_id);
+		if (cpuid_topo->package_id == -1)
+			max_socket = max(max_socket, cpu_topology[cpu].package_id);
 	}

-	if (cpuid_topo->socket_id == -1)
-		cpuid_topo->socket_id = max_socket + 1;
+	if (cpuid_topo->package_id == -1)
+		cpuid_topo->package_id = max_socket + 1;

 	update_siblings_masks(cpuid);

 	pr_info("CPU%u: cpu core %d of socket %d\n",
 		cpuid,
 		cpu_topology[cpuid].core_id,
-		cpu_topology[cpuid].socket_id);
+		cpu_topology[cpuid].package_id);
 }

 static struct sched_domain_topology_level parisc_mc_topology[] = {
@@ -122,20 +94,6 @@  static struct sched_domain_topology_level parisc_mc_topology[] = {
  */
 void __init init_cpu_topology(void)
 {
-	unsigned int cpu;
-
-	/* init core mask and capacity */
-	for_each_possible_cpu(cpu) {
-		struct cputopo_parisc *cpu_topo = &(cpu_topology[cpu]);
-
-		cpu_topo->thread_id = -1;
-		cpu_topo->core_id =  -1;
-		cpu_topo->socket_id = -1;
-		cpumask_clear(&cpu_topo->core_sibling);
-		cpumask_clear(&cpu_topo->thread_sibling);
-	}
-	smp_wmb();
-
 	/* Set scheduler topology descriptor */
 	if (dualcores_found)
 		set_sched_topology(parisc_mc_topology);