diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/Makefile | 2 | ||||
-rw-r--r-- | drivers/s390/sysinfo.c | 63 |
2 files changed, 64 insertions, 1 deletions
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 9803c9352d78..5a888704a8d0 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for the S/390 specific device drivers | 2 | # Makefile for the S/390 specific device drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | ||
6 | |||
5 | obj-y += s390mach.o sysinfo.o s390_rdev.o | 7 | obj-y += s390mach.o sysinfo.o s390_rdev.o |
6 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ | 8 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ |
7 | 9 | ||
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c index 1e788e815ce7..090743d2f914 100644 --- a/drivers/s390/sysinfo.c +++ b/drivers/s390/sysinfo.c | |||
@@ -9,8 +9,14 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/delay.h> | ||
12 | #include <asm/ebcdic.h> | 13 | #include <asm/ebcdic.h> |
13 | 14 | ||
15 | /* Sigh, math-emu. Don't ask. */ | ||
16 | #include <asm/sfp-util.h> | ||
17 | #include <math-emu/soft-fp.h> | ||
18 | #include <math-emu/single.h> | ||
19 | |||
14 | struct sysinfo_1_1_1 { | 20 | struct sysinfo_1_1_1 { |
15 | char reserved_0[32]; | 21 | char reserved_0[32]; |
16 | char manufacturer[16]; | 22 | char manufacturer[16]; |
@@ -198,7 +204,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | |||
198 | * if the higher order 8 bits are not zero. Printing | 204 | * if the higher order 8 bits are not zero. Printing |
199 | * a floating point number in the kernel is a no-no, | 205 | * a floating point number in the kernel is a no-no, |
200 | * always print the number as 32 bit unsigned integer. | 206 | * always print the number as 32 bit unsigned integer. |
201 | * The user-space needs to know about the stange | 207 | * The user-space needs to know about the strange |
202 | * encoding of the alternate cpu capability. | 208 | * encoding of the alternate cpu capability. |
203 | */ | 209 | */ |
204 | len += sprintf(page + len, "Capability: %u %u\n", | 210 | len += sprintf(page + len, "Capability: %u %u\n", |
@@ -351,3 +357,58 @@ static __init int create_proc_sysinfo(void) | |||
351 | 357 | ||
352 | __initcall(create_proc_sysinfo); | 358 | __initcall(create_proc_sysinfo); |
353 | 359 | ||
360 | /* | ||
361 | * CPU capability might have changed. Therefore recalculate loops_per_jiffy. | ||
362 | */ | ||
363 | void s390_adjust_jiffies(void) | ||
364 | { | ||
365 | struct sysinfo_1_2_2 *info; | ||
366 | const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */ | ||
367 | FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); | ||
368 | FP_DECL_EX; | ||
369 | unsigned int capability; | ||
370 | |||
371 | info = (void *) get_zeroed_page(GFP_KERNEL); | ||
372 | if (!info) | ||
373 | return; | ||
374 | |||
375 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | ||
376 | /* | ||
377 | * Major sigh. The cpu capability encoding is "special". | ||
378 | * If the first 9 bits of info->capability are 0 then it | ||
379 | * is a 32 bit unsigned integer in the range 0 .. 2^23. | ||
380 | * If the first 9 bits are != 0 then it is a 32 bit float. | ||
381 | * In addition a lower value indicates a proportionally | ||
382 | * higher cpu capacity. Bogomips are the other way round. | ||
383 | * To get to a halfway suitable number we divide 1e7 | ||
384 | * by the cpu capability number. Yes, that means a floating | ||
385 | * point division .. math-emu here we come :-) | ||
386 | */ | ||
387 | FP_UNPACK_SP(SA, &fmil); | ||
388 | if ((info->capability >> 23) == 0) | ||
389 | FP_FROM_INT_S(SB, info->capability, 32, int); | ||
390 | else | ||
391 | FP_UNPACK_SP(SB, &info->capability); | ||
392 | FP_DIV_S(SR, SA, SB); | ||
393 | FP_TO_INT_S(capability, SR, 32, 0); | ||
394 | } else | ||
395 | /* | ||
396 | * Really old machine without stsi block for basic | ||
397 | * cpu information. Report 42.0 bogomips. | ||
398 | */ | ||
399 | capability = 42; | ||
400 | loops_per_jiffy = capability * (500000/HZ); | ||
401 | free_page((unsigned long) info); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * calibrate the delay loop | ||
406 | */ | ||
407 | void __init calibrate_delay(void) | ||
408 | { | ||
409 | s390_adjust_jiffies(); | ||
410 | /* Print the good old Bogomips line .. */ | ||
411 | printk(KERN_DEBUG "Calibrating delay loop (skipped)... " | ||
412 | "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), | ||
413 | (loops_per_jiffy/(5000/HZ)) % 100); | ||
414 | } | ||