2005-04-16 15:20:36 -07: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 .
*
* This file contains NUMA specific variables and functions which can
* be split away from DISCONTIGMEM and are used on NUMA machines with
* contiguous memory .
* 2002 / 08 / 07 Erich Focht < efocht @ ess . nec . de >
* Populate cpu entries in sysfs for non - numa systems as well
* Intel Corporation - Ashok Raj
2006-02-27 11:37:45 +08:00
* 02 / 27 / 2006 Zhang , Yanmin
* Populate cpu cache entries in sysfs for cpu cache info
2005-04-16 15:20:36 -07:00
*/
# include <linux/config.h>
# include <linux/cpu.h>
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/node.h>
# include <linux/init.h>
# include <linux/bootmem.h>
# include <linux/nodemask.h>
2006-02-27 11:37:45 +08:00
# include <linux/notifier.h>
2005-04-16 15:20:36 -07:00
# include <asm/mmzone.h>
# include <asm/numa.h>
# include <asm/cpu.h>
# ifdef CONFIG_NUMA
static struct node * sysfs_nodes ;
# endif
static struct ia64_cpu * sysfs_cpus ;
int arch_register_cpu ( int num )
{
struct node * parent = NULL ;
# ifdef CONFIG_NUMA
parent = & sysfs_nodes [ cpu_to_node ( num ) ] ;
# endif /* CONFIG_NUMA */
2006-01-19 16:18:47 -08:00
# if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
2005-03-31 22:51:10 -05:00
/*
* If CPEI cannot be re - targetted , and this is
* CPEI target , then dont create the control file
*/
if ( ! can_cpei_retarget ( ) & & is_cpu_cpei_target ( num ) )
sysfs_cpus [ num ] . cpu . no_control = 1 ;
2005-07-13 21:09:00 -07:00
# endif
2005-03-31 22:51:10 -05:00
2005-04-16 15:20:36 -07:00
return register_cpu ( & sysfs_cpus [ num ] . cpu , num , parent ) ;
}
# ifdef CONFIG_HOTPLUG_CPU
void arch_unregister_cpu ( int num )
{
struct node * parent = NULL ;
# ifdef CONFIG_NUMA
int node = cpu_to_node ( num ) ;
parent = & sysfs_nodes [ node ] ;
# endif /* CONFIG_NUMA */
return unregister_cpu ( & sysfs_cpus [ num ] . cpu , parent ) ;
}
EXPORT_SYMBOL ( arch_register_cpu ) ;
EXPORT_SYMBOL ( arch_unregister_cpu ) ;
# endif /*CONFIG_HOTPLUG_CPU*/
static int __init topology_init ( void )
{
int i , err = 0 ;
# ifdef CONFIG_NUMA
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
sysfs_nodes = kzalloc ( sizeof ( struct node ) * MAX_NUMNODES , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! sysfs_nodes ) {
err = - ENOMEM ;
goto out ;
}
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
/*
* MCD - Do we want to register all ONLINE nodes , or all POSSIBLE nodes ?
*/
for_each_online_node ( i ) {
2005-04-16 15:20:36 -07:00
if ( ( err = register_node ( & sysfs_nodes [ i ] , i , 0 ) ) )
goto out ;
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
}
2005-04-16 15:20:36 -07:00
# endif
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
sysfs_cpus = kzalloc ( sizeof ( struct ia64_cpu ) * NR_CPUS , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! sysfs_cpus ) {
err = - ENOMEM ;
goto out ;
}
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
for_each_present_cpu ( i ) {
2005-04-16 15:20:36 -07:00
if ( ( err = arch_register_cpu ( i ) ) )
goto out ;
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
}
2005-04-16 15:20:36 -07:00
out :
return err ;
}
[PATCH] Export cpu topology in sysfs
The patch implements cpu topology exportation by sysfs.
Items (attributes) are similar to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
represent the physical package id of cpu X;
2) /sys/devices/system/cpu/cpuX/topology/core_id:
represent the cpu core id to cpu X;
3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
represent the thread siblings to cpu X in the same core;
4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
driver/base/topology.c, is to export the 5 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
The 4 defines are:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
#define topology_thread_siblings(cpu)
#define topology_core_siblings(cpu)
The type of **_id is int.
The type of siblings is cpumask_t.
To be consistent on all architectures, the 4 attributes should have
deafult values if their values are unavailable. Below is the rule.
1) physical_package_id: If cpu has no physical package id, -1 is the
default value.
2) core_id: If cpu doesn't support multi-core, its core id is 0.
3) thread_siblings: Just include itself, if the cpu doesn't support
HT/multi-thread.
4) core_siblings: Just include itself, if the cpu doesn't support
multi-core and HT/Multi-thread.
So be careful when declaring the 4 defines in include/asm-XXX/topology.h.
If an attribute isn't defined on an architecture, it won't be exported.
Thank Nathan, Greg, Andi, Paul and Venki.
The patch provides defines for i386/x86_64/ia64.
Signed-off-by: Zhang, Yanmin <yanmin.zhang@intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-03 03:04:36 -08:00
subsys_initcall ( topology_init ) ;
2006-02-27 11:37:45 +08:00
/*
* Export cpu cache information through sysfs
*/
/*
* A bunch of string array to get pretty printing
*/
static const char * cache_types [ ] = {
" " , /* not used */
" Instruction " ,
" Data " ,
" Unified " /* unified */
} ;
static const char * cache_mattrib [ ] = {
" WriteThrough " ,
" WriteBack " ,
" " , /* reserved */
" " /* reserved */
} ;
struct cache_info {
pal_cache_config_info_t cci ;
cpumask_t shared_cpu_map ;
int level ;
int type ;
struct kobject kobj ;
} ;
struct cpu_cache_info {
struct cache_info * cache_leaves ;
int num_cache_leaves ;
struct kobject kobj ;
} ;
static struct cpu_cache_info all_cpu_cache_info [ NR_CPUS ] ;
# define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y])
# ifdef CONFIG_SMP
static void cache_shared_cpu_map_setup ( unsigned int cpu ,
struct cache_info * this_leaf )
{
pal_cache_shared_info_t csi ;
int num_shared , i = 0 ;
unsigned int j ;
if ( cpu_data ( cpu ) - > threads_per_core < = 1 & &
cpu_data ( cpu ) - > cores_per_socket < = 1 ) {
cpu_set ( cpu , this_leaf - > shared_cpu_map ) ;
return ;
}
if ( ia64_pal_cache_shared_info ( this_leaf - > level ,
this_leaf - > type ,
0 ,
& csi ) ! = PAL_STATUS_SUCCESS )
return ;
num_shared = ( int ) csi . num_shared ;
do {
for_each_cpu ( j )
if ( cpu_data ( cpu ) - > socket_id = = cpu_data ( j ) - > socket_id
& & cpu_data ( j ) - > core_id = = csi . log1_cid
& & cpu_data ( j ) - > thread_id = = csi . log1_tid )
cpu_set ( j , this_leaf - > shared_cpu_map ) ;
i + + ;
} while ( i < num_shared & &
ia64_pal_cache_shared_info ( this_leaf - > level ,
this_leaf - > type ,
i ,
& csi ) = = PAL_STATUS_SUCCESS ) ;
}
# else
static void cache_shared_cpu_map_setup ( unsigned int cpu ,
struct cache_info * this_leaf )
{
cpu_set ( cpu , this_leaf - > shared_cpu_map ) ;
return ;
}
# endif
static ssize_t show_coherency_line_size ( struct cache_info * this_leaf ,
char * buf )
{
return sprintf ( buf , " %u \n " , 1 < < this_leaf - > cci . pcci_line_size ) ;
}
static ssize_t show_ways_of_associativity ( struct cache_info * this_leaf ,
char * buf )
{
return sprintf ( buf , " %u \n " , this_leaf - > cci . pcci_assoc ) ;
}
static ssize_t show_attributes ( struct cache_info * this_leaf , char * buf )
{
return sprintf ( buf ,
" %s \n " ,
cache_mattrib [ this_leaf - > cci . pcci_cache_attr ] ) ;
}
static ssize_t show_size ( struct cache_info * this_leaf , char * buf )
{
return sprintf ( buf , " %uK \n " , this_leaf - > cci . pcci_cache_size / 1024 ) ;
}
static ssize_t show_number_of_sets ( struct cache_info * this_leaf , char * buf )
{
unsigned number_of_sets = this_leaf - > cci . pcci_cache_size ;
number_of_sets / = this_leaf - > cci . pcci_assoc ;
number_of_sets / = 1 < < this_leaf - > cci . pcci_line_size ;
return sprintf ( buf , " %u \n " , number_of_sets ) ;
}
static ssize_t show_shared_cpu_map ( struct cache_info * this_leaf , char * buf )
{
ssize_t len ;
cpumask_t shared_cpu_map ;
cpus_and ( shared_cpu_map , this_leaf - > shared_cpu_map , cpu_online_map ) ;
len = cpumask_scnprintf ( buf , NR_CPUS + 1 , shared_cpu_map ) ;
len + = sprintf ( buf + len , " \n " ) ;
return len ;
}
static ssize_t show_type ( struct cache_info * this_leaf , char * buf )
{
int type = this_leaf - > type + this_leaf - > cci . pcci_unified ;
return sprintf ( buf , " %s \n " , cache_types [ type ] ) ;
}
static ssize_t show_level ( struct cache_info * this_leaf , char * buf )
{
return sprintf ( buf , " %u \n " , this_leaf - > level ) ;
}
struct cache_attr {
struct attribute attr ;
ssize_t ( * show ) ( struct cache_info * , char * ) ;
ssize_t ( * store ) ( struct cache_info * , const char * , size_t count ) ;
} ;
# ifdef define_one_ro
# undef define_one_ro
# endif
# define define_one_ro(_name) \
static struct cache_attr _name = \
__ATTR ( _name , 0444 , show_ # # _name , NULL )
define_one_ro ( level ) ;
define_one_ro ( type ) ;
define_one_ro ( coherency_line_size ) ;
define_one_ro ( ways_of_associativity ) ;
define_one_ro ( size ) ;
define_one_ro ( number_of_sets ) ;
define_one_ro ( shared_cpu_map ) ;
define_one_ro ( attributes ) ;
static struct attribute * cache_default_attrs [ ] = {
& type . attr ,
& level . attr ,
& coherency_line_size . attr ,
& ways_of_associativity . attr ,
& attributes . attr ,
& size . attr ,
& number_of_sets . attr ,
& shared_cpu_map . attr ,
NULL
} ;
# define to_object(k) container_of(k, struct cache_info, kobj)
# define to_attr(a) container_of(a, struct cache_attr, attr)
static ssize_t cache_show ( struct kobject * kobj , struct attribute * attr , char * buf )
{
struct cache_attr * fattr = to_attr ( attr ) ;
struct cache_info * this_leaf = to_object ( kobj ) ;
ssize_t ret ;
ret = fattr - > show ? fattr - > show ( this_leaf , buf ) : 0 ;
return ret ;
}
static struct sysfs_ops cache_sysfs_ops = {
. show = cache_show
} ;
static struct kobj_type cache_ktype = {
. sysfs_ops = & cache_sysfs_ops ,
. default_attrs = cache_default_attrs ,
} ;
static struct kobj_type cache_ktype_percpu_entry = {
. sysfs_ops = & cache_sysfs_ops ,
} ;
static void __cpuinit cpu_cache_sysfs_exit ( unsigned int cpu )
{
2006-04-20 10:11:09 -07:00
kfree ( all_cpu_cache_info [ cpu ] . cache_leaves ) ;
all_cpu_cache_info [ cpu ] . cache_leaves = NULL ;
2006-02-27 11:37:45 +08:00
all_cpu_cache_info [ cpu ] . num_cache_leaves = 0 ;
memset ( & all_cpu_cache_info [ cpu ] . kobj , 0 , sizeof ( struct kobject ) ) ;
return ;
}
static int __cpuinit cpu_cache_sysfs_init ( unsigned int cpu )
{
u64 i , levels , unique_caches ;
pal_cache_config_info_t cci ;
int j ;
s64 status ;
struct cache_info * this_cache ;
int num_cache_leaves = 0 ;
if ( ( status = ia64_pal_cache_summary ( & levels , & unique_caches ) ) ! = 0 ) {
printk ( KERN_ERR " ia64_pal_cache_summary=%ld \n " , status ) ;
return - 1 ;
}
this_cache = kzalloc ( sizeof ( struct cache_info ) * unique_caches ,
GFP_KERNEL ) ;
if ( this_cache = = NULL )
return - ENOMEM ;
for ( i = 0 ; i < levels ; i + + ) {
for ( j = 2 ; j > 0 ; j - - ) {
if ( ( status = ia64_pal_cache_config_info ( i , j , & cci ) ) ! =
PAL_STATUS_SUCCESS )
continue ;
this_cache [ num_cache_leaves ] . cci = cci ;
this_cache [ num_cache_leaves ] . level = i + 1 ;
this_cache [ num_cache_leaves ] . type = j ;
cache_shared_cpu_map_setup ( cpu ,
& this_cache [ num_cache_leaves ] ) ;
num_cache_leaves + + ;
}
}
all_cpu_cache_info [ cpu ] . cache_leaves = this_cache ;
all_cpu_cache_info [ cpu ] . num_cache_leaves = num_cache_leaves ;
memset ( & all_cpu_cache_info [ cpu ] . kobj , 0 , sizeof ( struct kobject ) ) ;
return 0 ;
}
/* Add cache interface for CPU device */
static int __cpuinit cache_add_dev ( struct sys_device * sys_dev )
{
unsigned int cpu = sys_dev - > id ;
unsigned long i , j ;
struct cache_info * this_object ;
int retval = 0 ;
cpumask_t oldmask ;
if ( all_cpu_cache_info [ cpu ] . kobj . parent )
return 0 ;
oldmask = current - > cpus_allowed ;
retval = set_cpus_allowed ( current , cpumask_of_cpu ( cpu ) ) ;
if ( unlikely ( retval ) )
return retval ;
retval = cpu_cache_sysfs_init ( cpu ) ;
set_cpus_allowed ( current , oldmask ) ;
if ( unlikely ( retval < 0 ) )
return retval ;
all_cpu_cache_info [ cpu ] . kobj . parent = & sys_dev - > kobj ;
kobject_set_name ( & all_cpu_cache_info [ cpu ] . kobj , " %s " , " cache " ) ;
all_cpu_cache_info [ cpu ] . kobj . ktype = & cache_ktype_percpu_entry ;
retval = kobject_register ( & all_cpu_cache_info [ cpu ] . kobj ) ;
for ( i = 0 ; i < all_cpu_cache_info [ cpu ] . num_cache_leaves ; i + + ) {
this_object = LEAF_KOBJECT_PTR ( cpu , i ) ;
this_object - > kobj . parent = & all_cpu_cache_info [ cpu ] . kobj ;
kobject_set_name ( & ( this_object - > kobj ) , " index%1lu " , i ) ;
this_object - > kobj . ktype = & cache_ktype ;
retval = kobject_register ( & ( this_object - > kobj ) ) ;
if ( unlikely ( retval ) ) {
for ( j = 0 ; j < i ; j + + ) {
kobject_unregister (
& ( LEAF_KOBJECT_PTR ( cpu , j ) - > kobj ) ) ;
}
kobject_unregister ( & all_cpu_cache_info [ cpu ] . kobj ) ;
cpu_cache_sysfs_exit ( cpu ) ;
break ;
}
}
return retval ;
}
/* Remove cache interface for CPU device */
static int __cpuinit cache_remove_dev ( struct sys_device * sys_dev )
{
unsigned int cpu = sys_dev - > id ;
unsigned long i ;
for ( i = 0 ; i < all_cpu_cache_info [ cpu ] . num_cache_leaves ; i + + )
kobject_unregister ( & ( LEAF_KOBJECT_PTR ( cpu , i ) - > kobj ) ) ;
if ( all_cpu_cache_info [ cpu ] . kobj . parent ) {
kobject_unregister ( & all_cpu_cache_info [ cpu ] . kobj ) ;
memset ( & all_cpu_cache_info [ cpu ] . kobj ,
0 ,
sizeof ( struct kobject ) ) ;
}
cpu_cache_sysfs_exit ( cpu ) ;
return 0 ;
}
/*
* When a cpu is hot - plugged , do a check and initiate
* cache kobject if necessary
*/
2006-04-24 19:35:21 -07:00
static int cache_cpu_callback ( struct notifier_block * nfb ,
2006-02-27 11:37:45 +08:00
unsigned long action , void * hcpu )
{
unsigned int cpu = ( unsigned long ) hcpu ;
struct sys_device * sys_dev ;
sys_dev = get_cpu_sysdev ( cpu ) ;
switch ( action ) {
case CPU_ONLINE :
cache_add_dev ( sys_dev ) ;
break ;
case CPU_DEAD :
cache_remove_dev ( sys_dev ) ;
break ;
}
return NOTIFY_OK ;
}
static struct notifier_block cache_cpu_notifier =
{
. notifier_call = cache_cpu_callback
} ;
static int __cpuinit cache_sysfs_init ( void )
{
int i ;
for_each_online_cpu ( i ) {
cache_cpu_callback ( & cache_cpu_notifier , CPU_ONLINE ,
( void * ) ( long ) i ) ;
}
register_cpu_notifier ( & cache_cpu_notifier ) ;
return 0 ;
}
device_initcall ( cache_sysfs_init ) ;