diff options
Diffstat (limited to 'arch/s390/kernel/sysinfo.c')
-rw-r--r-- | arch/s390/kernel/sysinfo.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 2af4ee67fe5..62f89d98e88 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c | |||
@@ -24,18 +24,38 @@ | |||
24 | 24 | ||
25 | int topology_max_mnest; | 25 | int topology_max_mnest; |
26 | 26 | ||
27 | static inline int stsi_0(void) | 27 | /* |
28 | * stsi - store system information | ||
29 | * | ||
30 | * Returns the current configuration level if function code 0 was specified. | ||
31 | * Otherwise returns 0 on success or a negative value on error. | ||
32 | */ | ||
33 | int stsi(void *sysinfo, int fc, int sel1, int sel2) | ||
28 | { | 34 | { |
29 | int rc = stsi(NULL, 0, 0, 0); | 35 | register int r0 asm("0") = (fc << 28) | sel1; |
30 | 36 | register int r1 asm("1") = sel2; | |
31 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | 37 | int rc = 0; |
38 | |||
39 | asm volatile( | ||
40 | " stsi 0(%3)\n" | ||
41 | "0: jz 2f\n" | ||
42 | "1: lhi %1,%4\n" | ||
43 | "2:\n" | ||
44 | EX_TABLE(0b, 1b) | ||
45 | : "+d" (r0), "+d" (rc) | ||
46 | : "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP) | ||
47 | : "cc", "memory"); | ||
48 | if (rc) | ||
49 | return rc; | ||
50 | return fc ? 0 : ((unsigned int) r0) >> 28; | ||
32 | } | 51 | } |
52 | EXPORT_SYMBOL(stsi); | ||
33 | 53 | ||
34 | static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) | 54 | static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) |
35 | { | 55 | { |
36 | int i; | 56 | int i; |
37 | 57 | ||
38 | if (stsi(info, 1, 1, 1) == -ENOSYS) | 58 | if (stsi(info, 1, 1, 1)) |
39 | return; | 59 | return; |
40 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); | 60 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); |
41 | EBCASC(info->type, sizeof(info->type)); | 61 | EBCASC(info->type, sizeof(info->type)); |
@@ -97,7 +117,8 @@ static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) | |||
97 | seq_putc(m, '\n'); | 117 | seq_putc(m, '\n'); |
98 | if (!MACHINE_HAS_TOPOLOGY) | 118 | if (!MACHINE_HAS_TOPOLOGY) |
99 | return; | 119 | return; |
100 | stsi(info, 15, 1, topology_max_mnest); | 120 | if (stsi(info, 15, 1, topology_max_mnest)) |
121 | return; | ||
101 | seq_printf(m, "CPU Topology HW: "); | 122 | seq_printf(m, "CPU Topology HW: "); |
102 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | 123 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
103 | seq_printf(m, " %d", info->mag[i]); | 124 | seq_printf(m, " %d", info->mag[i]); |
@@ -116,7 +137,7 @@ static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) | |||
116 | struct sysinfo_1_2_2_extension *ext; | 137 | struct sysinfo_1_2_2_extension *ext; |
117 | int i; | 138 | int i; |
118 | 139 | ||
119 | if (stsi(info, 1, 2, 2) == -ENOSYS) | 140 | if (stsi(info, 1, 2, 2)) |
120 | return; | 141 | return; |
121 | ext = (struct sysinfo_1_2_2_extension *) | 142 | ext = (struct sysinfo_1_2_2_extension *) |
122 | ((unsigned long) info + info->acc_offset); | 143 | ((unsigned long) info + info->acc_offset); |
@@ -152,7 +173,7 @@ static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) | |||
152 | 173 | ||
153 | static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) | 174 | static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) |
154 | { | 175 | { |
155 | if (stsi(info, 2, 2, 2) == -ENOSYS) | 176 | if (stsi(info, 2, 2, 2)) |
156 | return; | 177 | return; |
157 | EBCASC(info->name, sizeof(info->name)); | 178 | EBCASC(info->name, sizeof(info->name)); |
158 | seq_putc(m, '\n'); | 179 | seq_putc(m, '\n'); |
@@ -179,7 +200,7 @@ static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) | |||
179 | { | 200 | { |
180 | int i; | 201 | int i; |
181 | 202 | ||
182 | if (stsi(info, 3, 2, 2) == -ENOSYS) | 203 | if (stsi(info, 3, 2, 2)) |
183 | return; | 204 | return; |
184 | for (i = 0; i < info->count; i++) { | 205 | for (i = 0; i < info->count; i++) { |
185 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); | 206 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); |
@@ -202,7 +223,7 @@ static int sysinfo_show(struct seq_file *m, void *v) | |||
202 | 223 | ||
203 | if (!info) | 224 | if (!info) |
204 | return 0; | 225 | return 0; |
205 | level = stsi_0(); | 226 | level = stsi(NULL, 0, 0, 0); |
206 | if (level >= 1) | 227 | if (level >= 1) |
207 | stsi_1_1_1(m, info); | 228 | stsi_1_1_1(m, info); |
208 | if (level >= 1) | 229 | if (level >= 1) |
@@ -365,7 +386,7 @@ void s390_adjust_jiffies(void) | |||
365 | if (!info) | 386 | if (!info) |
366 | return; | 387 | return; |
367 | 388 | ||
368 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | 389 | if (stsi(info, 1, 2, 2) == 0) { |
369 | /* | 390 | /* |
370 | * Major sigh. The cpu capability encoding is "special". | 391 | * Major sigh. The cpu capability encoding is "special". |
371 | * If the first 9 bits of info->capability are 0 then it | 392 | * If the first 9 bits of info->capability are 0 then it |