Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright IBM Corp. 2001, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *	       Martin Schwidefsky <schwidefsky@de.ibm.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/sysinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/cpcmd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/topology.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/fpu/api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) int topology_max_mnest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static inline int __stsi(void *sysinfo, int fc, int sel1, int sel2, int *lvl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	register int r0 asm("0") = (fc << 28) | sel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	register int r1 asm("1") = sel2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		"	stsi	0(%3)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		"0:	jz	2f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		"1:	lhi	%1,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		"2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		EX_TABLE(0b, 1b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		: "+d" (r0), "+d" (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		: "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		: "cc", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	*lvl = ((unsigned int) r0) >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * stsi - store system information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * Returns the current configuration level if function code 0 was specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * Otherwise returns 0 on success or a negative value on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) int stsi(void *sysinfo, int fc, int sel1, int sel2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	int lvl, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	rc = __stsi(sysinfo, fc, sel1, sel2, &lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	return fc ? 0 : lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) EXPORT_SYMBOL(stsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static bool convert_ext_name(unsigned char encoding, char *name, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	switch (encoding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	case 1: /* EBCDIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		EBCASC(name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	case 2:	/* UTF-8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (stsi(info, 1, 1, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	EBCASC(info->manufacturer, sizeof(info->manufacturer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	EBCASC(info->type, sizeof(info->type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	EBCASC(info->model, sizeof(info->model));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	EBCASC(info->sequence, sizeof(info->sequence));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	EBCASC(info->plant, sizeof(info->plant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	EBCASC(info->model_capacity, sizeof(info->model_capacity));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	seq_printf(m, "Manufacturer:         %-16.16s\n", info->manufacturer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	seq_printf(m, "Type:                 %-4.4s\n", info->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (info->lic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		seq_printf(m, "LIC Identifier:       %016lx\n", info->lic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	 * Sigh: the model field has been renamed with System z9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * to model_capacity and a new model field has been added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * after the plant field. To avoid confusing older programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * the "Model:" prints "model_capacity model" or just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * "model_capacity" if the model string is empty .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	seq_printf(m, "Model:                %-16.16s", info->model_capacity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (info->model[0] != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		seq_printf(m, " %-16.16s", info->model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	seq_printf(m, "Sequence Code:        %-16.16s\n", info->sequence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	seq_printf(m, "Plant:                %-4.4s\n", info->plant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	seq_printf(m, "Model Capacity:       %-16.16s %08u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		   info->model_capacity, info->model_cap_rating);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	if (info->model_perm_cap_rating)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			   info->model_perm_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			   info->model_perm_cap_rating);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (info->model_temp_cap_rating)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			   info->model_temp_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			   info->model_temp_cap_rating);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (info->ncr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		seq_printf(m, "Nominal Cap. Rating:  %08u\n", info->ncr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (info->npr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (info->ntr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (info->cai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		seq_printf(m, "Capacity Adj. Ind.:   %d\n", info->cai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		seq_printf(m, "Capacity Ch. Reason:  %d\n", info->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		seq_printf(m, "Capacity Transient:   %d\n", info->t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (info->p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			seq_printf(m, "Type %d Percentage:    %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				   i, info->typepct[i - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (!MACHINE_HAS_TOPOLOGY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	if (stsi(info, 15, 1, topology_max_mnest))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	seq_printf(m, "CPU Topology HW:     ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		seq_printf(m, " %d", info->mag[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #ifdef CONFIG_SCHED_TOPOLOGY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	store_topology(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	seq_printf(m, "CPU Topology SW:     ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		seq_printf(m, " %d", info->mag[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	struct sysinfo_1_2_2_extension *ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (stsi(info, 1, 2, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	ext = (struct sysinfo_1_2_2_extension *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		((unsigned long) info + info->acc_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	seq_printf(m, "CPUs Total:           %d\n", info->cpus_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	seq_printf(m, "CPUs Configured:      %d\n", info->cpus_configured);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	seq_printf(m, "CPUs Standby:         %d\n", info->cpus_standby);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	seq_printf(m, "CPUs Reserved:        %d\n", info->cpus_reserved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (info->mt_installed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		seq_printf(m, "CPUs G-MTID:          %d\n", info->mt_gtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		seq_printf(m, "CPUs S-MTID:          %d\n", info->mt_stid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	 * Sigh 2. According to the specification the alternate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	 * capability field is a 32 bit floating point number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * if the higher order 8 bits are not zero. Printing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * a floating point number in the kernel is a no-no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * always print the number as 32 bit unsigned integer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 * The user-space needs to know about the strange
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	 * encoding of the alternate cpu capability.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	seq_printf(m, "Capability:           %u", info->capability);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	if (info->format == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		seq_printf(m, " %u", ext->alt_capability);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (info->nominal_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		seq_printf(m, "Nominal Capability:   %d\n", info->nominal_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (info->secondary_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	for (i = 2; i <= info->cpus_total; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		seq_printf(m, "Adjustment %02d-way:    %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			   i, info->adjustment[i-2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		if (info->format == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			seq_printf(m, " %u", ext->alt_adjustment[i-2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	if (stsi(info, 2, 2, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	EBCASC(info->name, sizeof(info->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	seq_printf(m, "LPAR Number:          %d\n", info->lpar_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	seq_printf(m, "LPAR Characteristics: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (info->characteristics & LPAR_CHAR_DEDICATED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		seq_printf(m, "Dedicated ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (info->characteristics & LPAR_CHAR_SHARED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		seq_printf(m, "Shared ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	if (info->characteristics & LPAR_CHAR_LIMITED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		seq_printf(m, "Limited ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	seq_printf(m, "LPAR Name:            %-8.8s\n", info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	seq_printf(m, "LPAR Adjustment:      %d\n", info->caf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	seq_printf(m, "LPAR CPUs Total:      %d\n", info->cpus_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	seq_printf(m, "LPAR CPUs Standby:    %d\n", info->cpus_standby);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	seq_printf(m, "LPAR CPUs Reserved:   %d\n", info->cpus_reserved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	seq_printf(m, "LPAR CPUs Dedicated:  %d\n", info->cpus_dedicated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	seq_printf(m, "LPAR CPUs Shared:     %d\n", info->cpus_shared);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (info->mt_installed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		seq_printf(m, "LPAR CPUs G-MTID:     %d\n", info->mt_gtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		seq_printf(m, "LPAR CPUs S-MTID:     %d\n", info->mt_stid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		seq_printf(m, "LPAR CPUs PS-MTID:    %d\n", info->mt_psmtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (convert_ext_name(info->vsne, info->ext_name, sizeof(info->ext_name))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		seq_printf(m, "LPAR Extended Name:   %-.256s\n", info->ext_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		seq_printf(m, "LPAR UUID:            %pUb\n", &info->uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void print_ext_name(struct seq_file *m, int lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			   struct sysinfo_3_2_2 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	size_t len = sizeof(info->ext_names[lvl]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	if (!convert_ext_name(info->vm[lvl].evmne, info->ext_names[lvl], len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	seq_printf(m, "VM%02d Extended Name:   %-.256s\n", lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		   info->ext_names[lvl]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static void print_uuid(struct seq_file *m, int i, struct sysinfo_3_2_2 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (uuid_is_null(&info->vm[i].uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	seq_printf(m, "VM%02d UUID:            %pUb\n", i, &info->vm[i].uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (stsi(info, 3, 2, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	for (i = 0; i < info->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		seq_printf(m, "VM%02d Name:            %-8.8s\n", i, info->vm[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		seq_printf(m, "VM%02d Adjustment:      %d\n", i, info->vm[i].caf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		seq_printf(m, "VM%02d CPUs Total:      %d\n", i, info->vm[i].cpus_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		seq_printf(m, "VM%02d CPUs Standby:    %d\n", i, info->vm[i].cpus_standby);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		seq_printf(m, "VM%02d CPUs Reserved:   %d\n", i, info->vm[i].cpus_reserved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		print_ext_name(m, i, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		print_uuid(m, i, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int sysinfo_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	void *info = (void *)get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	level = stsi(NULL, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	if (level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		stsi_1_1_1(m, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		stsi_15_1_x(m, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		stsi_1_2_2(m, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (level >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		stsi_2_2_2(m, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (level >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		stsi_3_2_2(m, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	free_page((unsigned long)info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int __init sysinfo_create_proc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	proc_create_single("sysinfo", 0444, NULL, sysinfo_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) device_initcall(sysinfo_create_proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #endif /* CONFIG_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * Service levels interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static DECLARE_RWSEM(service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static LIST_HEAD(service_level_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int register_service_level(struct service_level *slr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	struct service_level *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	down_write(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	list_for_each_entry(ptr, &service_level_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		if (ptr == slr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			up_write(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	list_add_tail(&slr->list, &service_level_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	up_write(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) EXPORT_SYMBOL(register_service_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int unregister_service_level(struct service_level *slr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	struct service_level *ptr, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	int rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	down_write(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	list_for_each_entry_safe(ptr, next, &service_level_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		if (ptr != slr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		list_del(&ptr->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	up_write(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) EXPORT_SYMBOL(unregister_service_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void *service_level_start(struct seq_file *m, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	down_read(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	return seq_list_start(&service_level_list, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void *service_level_next(struct seq_file *m, void *p, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	return seq_list_next(p, &service_level_list, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static void service_level_stop(struct seq_file *m, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	up_read(&service_level_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int service_level_show(struct seq_file *m, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	struct service_level *slr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	slr = list_entry(p, struct service_level, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	slr->seq_print(m, slr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static const struct seq_operations service_level_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	.start		= service_level_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	.next		= service_level_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	.stop		= service_level_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	.show		= service_level_show
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static void service_level_vm_print(struct seq_file *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 				   struct service_level *slr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	char *query_buffer, *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	query_buffer = kmalloc(1024, GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	if (!query_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	cpcmd("QUERY CPLEVEL", query_buffer, 1024, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	str = strchr(query_buffer, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	if (str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		*str = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	seq_printf(m, "VM: %s\n", query_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	kfree(query_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static struct service_level service_level_vm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	.seq_print = service_level_vm_print
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static __init int create_proc_service_level(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	proc_create_seq("service_levels", 0, NULL, &service_level_seq_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (MACHINE_IS_VM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		register_service_level(&service_level_vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) subsys_initcall(create_proc_service_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)  * CPU capability might have changed. Therefore recalculate loops_per_jiffy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) void s390_adjust_jiffies(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	struct sysinfo_1_2_2 *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	unsigned long capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	struct kernel_fpu fpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	info = (void *) get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	if (stsi(info, 1, 2, 2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		 * Major sigh. The cpu capability encoding is "special".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		 * If the first 9 bits of info->capability are 0 then it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		 * is a 32 bit unsigned integer in the range 0 .. 2^23.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		 * If the first 9 bits are != 0 then it is a 32 bit float.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		 * In addition a lower value indicates a proportionally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		 * higher cpu capacity. Bogomips are the other way round.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		 * To get to a halfway suitable number we divide 1e7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		 * by the cpu capability number. Yes, that means a floating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		 * point division ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		kernel_fpu_begin(&fpu, KERNEL_FPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			"	sfpc	%3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			"	l	%0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			"	tmlh	%0,0xff80\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 			"	jnz	0f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			"	cefbr	%%f2,%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 			"	j	1f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 			"0:	le	%%f2,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			"1:	cefbr	%%f0,%2\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			"	debr	%%f0,%%f2\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			"	cgebr	%0,5,%%f0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			: "=&d" (capability)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			: "Q" (info->capability), "d" (10000000), "d" (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			: "cc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		kernel_fpu_end(&fpu, KERNEL_FPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		 * Really old machine without stsi block for basic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		 * cpu information. Report 42.0 bogomips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		capability = 42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	loops_per_jiffy = capability * (500000/HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	free_page((unsigned long) info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * calibrate the delay loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) void calibrate_delay(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	s390_adjust_jiffies();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	/* Print the good old Bogomips line .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	printk(KERN_DEBUG "Calibrating delay loop (skipped)... "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	       "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	       (loops_per_jiffy/(5000/HZ)) % 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) #define STSI_FILE(fc, s1, s2)						       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int stsi_open_##fc##_##s1##_##s2(struct inode *inode, struct file *file)\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {									       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	file->private_data = (void *) get_zeroed_page(GFP_KERNEL);	       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	if (!file->private_data)					       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		return -ENOMEM;						       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	if (stsi(file->private_data, fc, s1, s2)) {			       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		free_page((unsigned long)file->private_data);		       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		file->private_data = NULL;				       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		return -EACCES;						       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	}								       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	return nonseekable_open(inode, file);				       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }									       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 									       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static const struct file_operations stsi_##fc##_##s1##_##s2##_fs_ops = {       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	.open		= stsi_open_##fc##_##s1##_##s2,			       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	.release	= stsi_release,					       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	.read		= stsi_read,					       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	.llseek		= no_llseek,					       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int stsi_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	free_page((unsigned long)file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static ssize_t stsi_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	return simple_read_from_buffer(buf, size, ppos, file->private_data, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) STSI_FILE( 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) STSI_FILE( 1, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) STSI_FILE( 1, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) STSI_FILE( 2, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) STSI_FILE( 2, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) STSI_FILE( 3, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) STSI_FILE(15, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) STSI_FILE(15, 1, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) STSI_FILE(15, 1, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) STSI_FILE(15, 1, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) STSI_FILE(15, 1, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct stsi_file {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	const struct file_operations *fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static struct stsi_file stsi_file[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	{.fops = &stsi_1_1_1_fs_ops,  .name =  "1_1_1"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	{.fops = &stsi_1_2_1_fs_ops,  .name =  "1_2_1"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	{.fops = &stsi_1_2_2_fs_ops,  .name =  "1_2_2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	{.fops = &stsi_2_2_1_fs_ops,  .name =  "2_2_1"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	{.fops = &stsi_2_2_2_fs_ops,  .name =  "2_2_2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	{.fops = &stsi_3_2_2_fs_ops,  .name =  "3_2_2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	{.fops = &stsi_15_1_2_fs_ops, .name = "15_1_2"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	{.fops = &stsi_15_1_3_fs_ops, .name = "15_1_3"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	{.fops = &stsi_15_1_4_fs_ops, .name = "15_1_4"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	{.fops = &stsi_15_1_5_fs_ops, .name = "15_1_5"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	{.fops = &stsi_15_1_6_fs_ops, .name = "15_1_6"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static u8 stsi_0_0_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static __init int stsi_init_debugfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	struct dentry *stsi_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	struct stsi_file *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	int lvl, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	stsi_root = debugfs_create_dir("stsi", arch_debugfs_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	lvl = stsi(NULL, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	if (lvl > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		stsi_0_0_0 = lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	debugfs_create_u8("0_0_0", 0400, stsi_root, &stsi_0_0_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	for (i = 0; i < ARRAY_SIZE(stsi_file); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		sf = &stsi_file[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		debugfs_create_file(sf->name, 0400, stsi_root, NULL, sf->fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY) && MACHINE_HAS_TOPOLOGY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		char link_to[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		sprintf(link_to, "15_1_%d", topology_mnest_limit());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		debugfs_create_symlink("topology", stsi_root, link_to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) device_initcall(stsi_init_debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #endif /* CONFIG_DEBUG_FS */