2005-04-17 02:20:36 +04:00
/*
2017-09-21 22:55:01 +03:00
* arch / parisc / kernel / topology . c
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* Copyright ( C ) 2017 Helge Deller < deller @ gmx . de >
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* based on arch / arm / kernel / topology . c
2005-04-17 02:20:36 +04:00
*
2017-09-21 22:55:01 +03:00
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
2005-04-17 02:20:36 +04:00
*/
2017-09-21 22:55:01 +03:00
# include <linux/percpu.h>
# include <linux/sched.h>
# include <linux/sched/topology.h>
2005-04-17 02:20:36 +04:00
2017-09-21 22:55:01 +03:00
# include <asm/topology.h>
2005-04-17 02:20:36 +04:00
2017-09-21 22:55:01 +03:00
/*
* 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 )
2005-04-17 02:20:36 +04:00
{
2017-09-21 22:55:01 +03:00
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 int dualcores_found __initdata ;
/*
* store_cpu_topology is called at boot when only one cpu is running
* and with the mutex cpu_hotplug . lock locked , when several cpus have booted ,
* which prevents simultaneous write access to cpu_topology array
*/
void __init store_cpu_topology ( unsigned int cpuid )
{
struct cputopo_parisc * cpuid_topo = & cpu_topology [ cpuid ] ;
struct cpuinfo_parisc * p ;
int max_socket = - 1 ;
unsigned long cpu ;
/* If the cpu topology has been already set, just return */
if ( cpuid_topo - > core_id ! = - 1 )
return ;
2005-04-17 02:20:36 +04:00
2017-09-21 22:55:01 +03:00
/* create cpu topology mapping */
cpuid_topo - > thread_id = - 1 ;
cpuid_topo - > core_id = 0 ;
p = & per_cpu ( cpu_data , cpuid ) ;
for_each_online_cpu ( cpu ) {
const struct cpuinfo_parisc * cpuinfo = & per_cpu ( cpu_data , cpu ) ;
if ( cpu = = cpuid ) /* ignore current cpu */
continue ;
if ( cpuinfo - > cpu_loc = = p - > cpu_loc ) {
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 ;
dualcores_found = 1 ;
continue ;
}
}
if ( cpuid_topo - > socket_id = = - 1 )
max_socket = max ( max_socket , cpu_topology [ cpu ] . socket_id ) ;
2005-04-17 02:20:36 +04:00
}
2017-09-21 22:55:01 +03:00
if ( cpuid_topo - > socket_id = = - 1 )
cpuid_topo - > socket_id = max_socket + 1 ;
update_siblings_masks ( cpuid ) ;
pr_info ( " CPU%u: thread %d, cpu %d, socket %d \n " ,
cpuid , cpu_topology [ cpuid ] . thread_id ,
cpu_topology [ cpuid ] . core_id ,
cpu_topology [ cpuid ] . socket_id ) ;
2005-04-17 02:20:36 +04:00
}
2017-09-21 22:55:01 +03:00
static struct sched_domain_topology_level parisc_mc_topology [ ] = {
# ifdef CONFIG_SCHED_MC
{ cpu_coregroup_mask , cpu_core_flags , SD_INIT_NAME ( MC ) } ,
# endif
{ cpu_cpu_mask , SD_INIT_NAME ( DIE ) } ,
{ NULL , } ,
} ;
/*
* init_cpu_topology is called at boot when only one cpu is running
* which prevent simultaneous write access to cpu_topology array
*/
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 ) ;
}