s390/sysinfo,topology: provide raw stsi 15,1,x data via debugfs
Provide the raw stsi 15,1,x data contents via debugfs. This makes it much easier to debug unexpected scheduling domains on machines that provide cpu topology information. Therefore this file adds a new 's390/stsi' debugfs directory with a file for each possible topology nesting level that is allowed by the architecture. The files will be created regardless if the machine supports all, or any, level. If a level is not supported, or no data is available, user space can recognize this with a -EINVAL error code when trying to read such data. In addition a 'topology' symlink is created that points to the file that contains the data that is used to create the scheduling domains. Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
050f99b1b8
commit
ae5ca67aca
|
@ -142,6 +142,15 @@ struct sysinfo_3_2_2 {
|
|||
|
||||
extern int topology_max_mnest;
|
||||
|
||||
/*
|
||||
* Returns the maximum nesting level supported by the cpu topology code.
|
||||
* The current maximum level is 4 which is the drawer level.
|
||||
*/
|
||||
static inline int topology_mnest_limit(void)
|
||||
{
|
||||
return min(topology_max_mnest, 4);
|
||||
}
|
||||
|
||||
#define TOPOLOGY_NR_MAG 6
|
||||
|
||||
struct topology_core {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/sysinfo.h>
|
||||
#include <asm/cpcmd.h>
|
||||
#include <asm/topology.h>
|
||||
|
@ -485,3 +487,81 @@ void calibrate_delay(void)
|
|||
"%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
|
||||
(loops_per_jiffy/(5000/HZ)) % 100);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#define STSI_FILE(fc, s1, s2) \
|
||||
static int stsi_open_##fc##_##s1##_##s2(struct inode *inode, struct file *file)\
|
||||
{ \
|
||||
file->private_data = (void *) get_zeroed_page(GFP_KERNEL); \
|
||||
if (!file->private_data) \
|
||||
return -ENOMEM; \
|
||||
if (stsi(file->private_data, fc, s1, s2)) { \
|
||||
free_page((unsigned long)file->private_data); \
|
||||
file->private_data = NULL; \
|
||||
return -EACCES; \
|
||||
} \
|
||||
return nonseekable_open(inode, file); \
|
||||
} \
|
||||
\
|
||||
static const struct file_operations stsi_##fc##_##s1##_##s2##_fs_ops = { \
|
||||
.open = stsi_open_##fc##_##s1##_##s2, \
|
||||
.release = stsi_release, \
|
||||
.read = stsi_read, \
|
||||
.llseek = no_llseek, \
|
||||
};
|
||||
|
||||
static int stsi_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
free_page((unsigned long)file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t stsi_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
return simple_read_from_buffer(buf, size, ppos, file->private_data, PAGE_SIZE);
|
||||
}
|
||||
|
||||
STSI_FILE(15, 1, 2);
|
||||
STSI_FILE(15, 1, 3);
|
||||
STSI_FILE(15, 1, 4);
|
||||
STSI_FILE(15, 1, 5);
|
||||
STSI_FILE(15, 1, 6);
|
||||
|
||||
struct stsi_file {
|
||||
const struct file_operations *fops;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct stsi_file stsi_file[] __initdata = {
|
||||
{.fops = &stsi_15_1_2_fs_ops, .name = "15_1_2"},
|
||||
{.fops = &stsi_15_1_3_fs_ops, .name = "15_1_3"},
|
||||
{.fops = &stsi_15_1_4_fs_ops, .name = "15_1_4"},
|
||||
{.fops = &stsi_15_1_5_fs_ops, .name = "15_1_5"},
|
||||
{.fops = &stsi_15_1_6_fs_ops, .name = "15_1_6"},
|
||||
};
|
||||
|
||||
static __init int stsi_init_debugfs(void)
|
||||
{
|
||||
struct dentry *stsi_root;
|
||||
struct stsi_file *sf;
|
||||
int i;
|
||||
|
||||
stsi_root = debugfs_create_dir("stsi", arch_debugfs_dir);
|
||||
if (IS_ERR_OR_NULL(stsi_root))
|
||||
return 0;
|
||||
for (i = 0; i < ARRAY_SIZE(stsi_file); i++) {
|
||||
sf = &stsi_file[i];
|
||||
debugfs_create_file(sf->name, 0400, stsi_root, NULL, sf->fops);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY) && MACHINE_HAS_TOPOLOGY) {
|
||||
char link_to[10];
|
||||
|
||||
sprintf(link_to, "15_1_%d", topology_mnest_limit());
|
||||
debugfs_create_symlink("topology", stsi_root, link_to);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
device_initcall(stsi_init_debugfs);
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
|
|
@ -246,7 +246,7 @@ static void update_cpu_masks(void)
|
|||
|
||||
void store_topology(struct sysinfo_15_1_x *info)
|
||||
{
|
||||
stsi(info, 15, 1, min(topology_max_mnest, 4));
|
||||
stsi(info, 15, 1, topology_mnest_limit());
|
||||
}
|
||||
|
||||
static int __arch_update_cpu_topology(void)
|
||||
|
|
Loading…
Reference in New Issue