
Heterogeneous memory systems provide memory nodes with different latency and bandwidth performance attributes. Provide a new kernel interface for subsystems to register the attributes under the memory target node's initiator access class. If the system provides this information, applications may query these attributes when deciding which node to request memory. The following example shows the new sysfs hierarchy for a node exporting performance attributes: # tree -P "read*|write*"/sys/devices/system/node/nodeY/accessZ/initiators/ /sys/devices/system/node/nodeY/accessZ/initiators/ |-- read_bandwidth |-- read_latency |-- write_bandwidth `-- write_latency The bandwidth is exported as MB/s and latency is reported in nanoseconds. The values are taken from the platform as reported by the manufacturer. Memory accesses from an initiator node that is not one of the memory's access "Z" initiator nodes linked in the same directory may observe different performance than reported here. When a subsystem makes use of this interface, initiators of a different access number may not have the same performance relative to initiators in other access numbers, or omitted from the any access class' initiators. Descriptions for memory access initiator performance access attributes are added to sysfs stable documentation. Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Keith Busch <keith.busch@intel.com> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Brice Goglin <Brice.Goglin@inria.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
155 lines
4.0 KiB
C
155 lines
4.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* include/linux/node.h - generic node definition
|
|
*
|
|
* This is mainly for topological representation. We define the
|
|
* basic 'struct node' here, which can be embedded in per-arch
|
|
* definitions of processors.
|
|
*
|
|
* Basic handling of the devices is done in drivers/base/node.c
|
|
* and system devices are handled in drivers/base/sys.c.
|
|
*
|
|
* Nodes are exported via driverfs in the class/node/devices/
|
|
* directory.
|
|
*/
|
|
#ifndef _LINUX_NODE_H_
|
|
#define _LINUX_NODE_H_
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/list.h>
|
|
#include <linux/workqueue.h>
|
|
|
|
/**
|
|
* struct node_hmem_attrs - heterogeneous memory performance attributes
|
|
*
|
|
* @read_bandwidth: Read bandwidth in MB/s
|
|
* @write_bandwidth: Write bandwidth in MB/s
|
|
* @read_latency: Read latency in nanoseconds
|
|
* @write_latency: Write latency in nanoseconds
|
|
*/
|
|
struct node_hmem_attrs {
|
|
unsigned int read_bandwidth;
|
|
unsigned int write_bandwidth;
|
|
unsigned int read_latency;
|
|
unsigned int write_latency;
|
|
};
|
|
|
|
#ifdef CONFIG_HMEM_REPORTING
|
|
void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
|
|
unsigned access);
|
|
#else
|
|
static inline void node_set_perf_attrs(unsigned int nid,
|
|
struct node_hmem_attrs *hmem_attrs,
|
|
unsigned access)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
struct node {
|
|
struct device dev;
|
|
struct list_head access_list;
|
|
|
|
#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
|
|
struct work_struct node_work;
|
|
#endif
|
|
};
|
|
|
|
struct memory_block;
|
|
extern struct node *node_devices[];
|
|
typedef void (*node_registration_func_t)(struct node *);
|
|
|
|
#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_NUMA)
|
|
extern int link_mem_sections(int nid, unsigned long start_pfn,
|
|
unsigned long end_pfn);
|
|
#else
|
|
static inline int link_mem_sections(int nid, unsigned long start_pfn,
|
|
unsigned long end_pfn)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
extern void unregister_node(struct node *node);
|
|
#ifdef CONFIG_NUMA
|
|
/* Core of the node registration - only memory hotplug should use this */
|
|
extern int __register_one_node(int nid);
|
|
|
|
/* Registers an online node */
|
|
static inline int register_one_node(int nid)
|
|
{
|
|
int error = 0;
|
|
|
|
if (node_online(nid)) {
|
|
struct pglist_data *pgdat = NODE_DATA(nid);
|
|
unsigned long start_pfn = pgdat->node_start_pfn;
|
|
unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
|
|
|
|
error = __register_one_node(nid);
|
|
if (error)
|
|
return error;
|
|
/* link memory sections under this node */
|
|
error = link_mem_sections(nid, start_pfn, end_pfn);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
extern void unregister_one_node(int nid);
|
|
extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);
|
|
extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
|
|
extern int register_mem_sect_under_node(struct memory_block *mem_blk,
|
|
void *arg);
|
|
extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
|
|
unsigned long phys_index);
|
|
|
|
extern int register_memory_node_under_compute_node(unsigned int mem_nid,
|
|
unsigned int cpu_nid,
|
|
unsigned access);
|
|
|
|
#ifdef CONFIG_HUGETLBFS
|
|
extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
|
|
node_registration_func_t unregister);
|
|
#endif
|
|
#else
|
|
static inline int __register_one_node(int nid)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int register_one_node(int nid)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int unregister_one_node(int nid)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int register_mem_sect_under_node(struct memory_block *mem_blk,
|
|
void *arg)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
|
|
unsigned long phys_index)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void register_hugetlbfs_with_node(node_registration_func_t reg,
|
|
node_registration_func_t unreg)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#define to_node(device) container_of(device, struct node, dev)
|
|
|
|
#endif /* _LINUX_NODE_H_ */
|