diff options
Diffstat (limited to 'arch/s390/kernel/processor.c')
| -rw-r--r-- | arch/s390/kernel/processor.c | 114 | 
1 files changed, 83 insertions, 31 deletions
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index de7451065c34..81d0808085e6 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -13,12 +13,45 @@  #include <linux/delay.h>  #include <linux/cpu.h>  #include <asm/diag.h> +#include <asm/facility.h>  #include <asm/elf.h>  #include <asm/lowcore.h>  #include <asm/param.h>  #include <asm/smp.h> -static DEFINE_PER_CPU(struct cpuid, cpu_id); +struct cpu_info { +	unsigned int cpu_mhz_dynamic; +	unsigned int cpu_mhz_static; +	struct cpuid cpu_id; +}; + +static DEFINE_PER_CPU(struct cpu_info, cpu_info); + +static bool machine_has_cpu_mhz; + +void __init cpu_detect_mhz_feature(void) +{ +	if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL) +		machine_has_cpu_mhz = 1; +} + +static void update_cpu_mhz(void *arg) +{ +	unsigned long mhz; +	struct cpu_info *c; + +	mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0); +	c = this_cpu_ptr(&cpu_info); +	c->cpu_mhz_dynamic = mhz >> 32; +	c->cpu_mhz_static = mhz & 0xffffffff; +} + +void s390_update_cpu_mhz(void) +{ +	s390_adjust_jiffies(); +	if (machine_has_cpu_mhz) +		on_each_cpu(update_cpu_mhz, NULL, 0); +}  void notrace cpu_relax(void)  { @@ -35,9 +68,11 @@ EXPORT_SYMBOL(cpu_relax);   */  void cpu_init(void)  { -	struct cpuid *id = this_cpu_ptr(&cpu_id); +	struct cpuid *id = this_cpu_ptr(&cpu_info.cpu_id);  	get_cpu_id(id); +	if (machine_has_cpu_mhz) +		update_cpu_mhz(NULL);  	atomic_inc(&init_mm.mm_count);  	current->active_mm = &init_mm;  	BUG_ON(current->mm); @@ -53,10 +88,7 @@ int cpu_have_feature(unsigned int num)  }  EXPORT_SYMBOL(cpu_have_feature); -/* - * show_cpuinfo - Get information on one CPU for use by procfs. - */ -static int show_cpuinfo(struct seq_file *m, void *v) +static void show_cpu_summary(struct seq_file *m, void *v)  {  	static const char *hwcap_str[] = {  		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", @@ -65,34 +97,55 @@ static int show_cpuinfo(struct seq_file *m, void *v)  	static const char * const int_hwcap_str[] = {  		"sie"  	}; -	unsigned long n = (unsigned long) v - 1; -	int i; - -	if (!n) { -		s390_adjust_jiffies(); -		seq_printf(m, "vendor_id       : IBM/S390\n" -			   "# processors    : %i\n" -			   "bogomips per cpu: %lu.%02lu\n", -			   num_online_cpus(), loops_per_jiffy/(500000/HZ), -			   (loops_per_jiffy/(5000/HZ))%100); -		seq_puts(m, "features\t: "); -		for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) -			if (hwcap_str[i] && (elf_hwcap & (1UL << i))) -				seq_printf(m, "%s ", hwcap_str[i]); -		for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++) -			if (int_hwcap_str[i] && (int_hwcap & (1UL << i))) -				seq_printf(m, "%s ", int_hwcap_str[i]); -		seq_puts(m, "\n"); -		show_cacheinfo(m); -	} -	if (cpu_online(n)) { -		struct cpuid *id = &per_cpu(cpu_id, n); -		seq_printf(m, "processor %li: " +	int i, cpu; + +	seq_printf(m, "vendor_id       : IBM/S390\n" +		   "# processors    : %i\n" +		   "bogomips per cpu: %lu.%02lu\n", +		   num_online_cpus(), loops_per_jiffy/(500000/HZ), +		   (loops_per_jiffy/(5000/HZ))%100); +	seq_printf(m, "max thread id   : %d\n", smp_cpu_mtid); +	seq_puts(m, "features\t: "); +	for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) +		if (hwcap_str[i] && (elf_hwcap & (1UL << i))) +			seq_printf(m, "%s ", hwcap_str[i]); +	for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++) +		if (int_hwcap_str[i] && (int_hwcap & (1UL << i))) +			seq_printf(m, "%s ", int_hwcap_str[i]); +	seq_puts(m, "\n"); +	show_cacheinfo(m); +	for_each_online_cpu(cpu) { +		struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu); + +		seq_printf(m, "processor %d: "  			   "version = %02X,  "  			   "identification = %06X,  "  			   "machine = %04X\n", -			   n, id->version, id->ident, id->machine); +			   cpu, id->version, id->ident, id->machine);  	} +} + +static void show_cpu_mhz(struct seq_file *m, unsigned long n) +{ +	struct cpu_info *c = per_cpu_ptr(&cpu_info, n); + +	seq_printf(m, "cpu MHz dynamic : %d\n", c->cpu_mhz_dynamic); +	seq_printf(m, "cpu MHz static  : %d\n", c->cpu_mhz_static); +} + +/* + * show_cpuinfo - Get information on one CPU for use by procfs. + */ +static int show_cpuinfo(struct seq_file *m, void *v) +{ +	unsigned long n = (unsigned long) v - 1; + +	if (!n) +		show_cpu_summary(m, v); +	if (!machine_has_cpu_mhz) +		return 0; +	seq_printf(m, "\ncpu number      : %ld\n", n); +	show_cpu_mhz(m, n);  	return 0;  } @@ -126,4 +179,3 @@ const struct seq_operations cpuinfo_op = {  	.stop	= c_stop,  	.show	= show_cpuinfo,  }; -  |