diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 13:02:14 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 13:02:14 -0400 |
| commit | 9fd815b55f31be48dbb3dd23922587d247a4e497 (patch) | |
| tree | 63814130acf3e472cc660ae71208c146f16dc5d6 | |
| parent | 31bbb9b58d1e8ebcf2b28c95c2250a9f8e31e397 (diff) | |
| parent | ed87b27e00d2ca240f62f3903583a2f1541fb9ef (diff) | |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (22 commits)
[S390] Update default configuration.
[S390] hibernate: Do real CPU swap at resume time
[S390] dasd: tolerate devices that have no feature codes
[S390] zcrypt: Do not add/remove devices in s/r callbacks
[S390] hibernate: make sure pfn_is_nosave handles lowcore pages
[S390] smp: introduce LC_ORDER and simplify lowcore handling
[S390] ptrace: use common code for simple peek/poke operations
[S390] fix disabled_wait inline assembly clobber list
[S390] Change kernel_page_present coding style.
[S390] hibernation: reset system after resume
[S390] hibernation: fix guest page hinting related crash
[S390] Get rid of init_module/delete_module compat functions.
[S390] Convert sys_execve to function with parameters.
[S390] Convert sys_clone to function with parameters.
[S390] qdio: change state of all primed input buffers
[S390] qdio: reduce per device debug messages
[S390] cio: introduce consistent subchannel scanning
[S390] cio: idset use actual number of ssids
[S390] cio: dont kfree vmalloced memory
[S390] cio: introduce css_settle
...
26 files changed, 478 insertions, 417 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 4e91a2573cc4..ab4464486b7a 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # | 1 | # |
| 2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
| 3 | # Linux kernel version: 2.6.30 | 3 | # Linux kernel version: 2.6.31 |
| 4 | # Mon Jun 22 11:08:16 2009 | 4 | # Tue Sep 22 17:43:13 2009 |
| 5 | # | 5 | # |
| 6 | CONFIG_SCHED_MC=y | 6 | CONFIG_SCHED_MC=y |
| 7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
| @@ -24,6 +24,7 @@ CONFIG_PGSTE=y | |||
| 24 | CONFIG_VIRT_CPU_ACCOUNTING=y | 24 | CONFIG_VIRT_CPU_ACCOUNTING=y |
| 25 | CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y | 25 | CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y |
| 26 | CONFIG_S390=y | 26 | CONFIG_S390=y |
| 27 | CONFIG_SCHED_OMIT_FRAME_POINTER=y | ||
| 27 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | 28 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" |
| 28 | CONFIG_CONSTRUCTORS=y | 29 | CONFIG_CONSTRUCTORS=y |
| 29 | 30 | ||
| @@ -48,11 +49,12 @@ CONFIG_AUDIT=y | |||
| 48 | # | 49 | # |
| 49 | # RCU Subsystem | 50 | # RCU Subsystem |
| 50 | # | 51 | # |
| 51 | CONFIG_CLASSIC_RCU=y | 52 | CONFIG_TREE_RCU=y |
| 52 | # CONFIG_TREE_RCU is not set | 53 | # CONFIG_TREE_PREEMPT_RCU is not set |
| 53 | # CONFIG_PREEMPT_RCU is not set | 54 | # CONFIG_RCU_TRACE is not set |
| 55 | CONFIG_RCU_FANOUT=64 | ||
| 56 | # CONFIG_RCU_FANOUT_EXACT is not set | ||
| 54 | # CONFIG_TREE_RCU_TRACE is not set | 57 | # CONFIG_TREE_RCU_TRACE is not set |
| 55 | # CONFIG_PREEMPT_RCU_TRACE is not set | ||
| 56 | CONFIG_IKCONFIG=y | 58 | CONFIG_IKCONFIG=y |
| 57 | CONFIG_IKCONFIG_PROC=y | 59 | CONFIG_IKCONFIG_PROC=y |
| 58 | CONFIG_LOG_BUF_SHIFT=17 | 60 | CONFIG_LOG_BUF_SHIFT=17 |
| @@ -103,11 +105,12 @@ CONFIG_TIMERFD=y | |||
| 103 | CONFIG_EVENTFD=y | 105 | CONFIG_EVENTFD=y |
| 104 | CONFIG_SHMEM=y | 106 | CONFIG_SHMEM=y |
| 105 | CONFIG_AIO=y | 107 | CONFIG_AIO=y |
| 106 | CONFIG_HAVE_PERF_COUNTERS=y | 108 | CONFIG_HAVE_PERF_EVENTS=y |
| 107 | 109 | ||
| 108 | # | 110 | # |
| 109 | # Performance Counters | 111 | # Kernel Performance Events And Counters |
| 110 | # | 112 | # |
| 113 | # CONFIG_PERF_EVENTS is not set | ||
| 111 | # CONFIG_PERF_COUNTERS is not set | 114 | # CONFIG_PERF_COUNTERS is not set |
| 112 | CONFIG_VM_EVENT_COUNTERS=y | 115 | CONFIG_VM_EVENT_COUNTERS=y |
| 113 | # CONFIG_STRIP_ASM_SYMS is not set | 116 | # CONFIG_STRIP_ASM_SYMS is not set |
| @@ -116,7 +119,6 @@ CONFIG_SLAB=y | |||
| 116 | # CONFIG_SLUB is not set | 119 | # CONFIG_SLUB is not set |
| 117 | # CONFIG_SLOB is not set | 120 | # CONFIG_SLOB is not set |
| 118 | # CONFIG_PROFILING is not set | 121 | # CONFIG_PROFILING is not set |
| 119 | # CONFIG_MARKERS is not set | ||
| 120 | CONFIG_HAVE_OPROFILE=y | 122 | CONFIG_HAVE_OPROFILE=y |
| 121 | CONFIG_KPROBES=y | 123 | CONFIG_KPROBES=y |
| 122 | CONFIG_HAVE_SYSCALL_WRAPPERS=y | 124 | CONFIG_HAVE_SYSCALL_WRAPPERS=y |
| @@ -176,6 +178,7 @@ CONFIG_NO_HZ=y | |||
| 176 | CONFIG_HIGH_RES_TIMERS=y | 178 | CONFIG_HIGH_RES_TIMERS=y |
| 177 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | 179 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
| 178 | CONFIG_64BIT=y | 180 | CONFIG_64BIT=y |
| 181 | # CONFIG_KTIME_SCALAR is not set | ||
| 179 | CONFIG_SMP=y | 182 | CONFIG_SMP=y |
| 180 | CONFIG_NR_CPUS=32 | 183 | CONFIG_NR_CPUS=32 |
| 181 | CONFIG_HOTPLUG_CPU=y | 184 | CONFIG_HOTPLUG_CPU=y |
| @@ -257,7 +260,6 @@ CONFIG_FORCE_MAX_ZONEORDER=9 | |||
| 257 | CONFIG_PFAULT=y | 260 | CONFIG_PFAULT=y |
| 258 | # CONFIG_SHARED_KERNEL is not set | 261 | # CONFIG_SHARED_KERNEL is not set |
| 259 | # CONFIG_CMM is not set | 262 | # CONFIG_CMM is not set |
| 260 | # CONFIG_PAGE_STATES is not set | ||
| 261 | # CONFIG_APPLDATA_BASE is not set | 263 | # CONFIG_APPLDATA_BASE is not set |
| 262 | CONFIG_HZ_100=y | 264 | CONFIG_HZ_100=y |
| 263 | # CONFIG_HZ_250 is not set | 265 | # CONFIG_HZ_250 is not set |
| @@ -280,6 +282,7 @@ CONFIG_PM_SLEEP_SMP=y | |||
| 280 | CONFIG_PM_SLEEP=y | 282 | CONFIG_PM_SLEEP=y |
| 281 | CONFIG_HIBERNATION=y | 283 | CONFIG_HIBERNATION=y |
| 282 | CONFIG_PM_STD_PARTITION="" | 284 | CONFIG_PM_STD_PARTITION="" |
| 285 | # CONFIG_PM_RUNTIME is not set | ||
| 283 | CONFIG_NET=y | 286 | CONFIG_NET=y |
| 284 | 287 | ||
| 285 | # | 288 | # |
| @@ -394,6 +397,7 @@ CONFIG_IP_SCTP=m | |||
| 394 | # CONFIG_SCTP_HMAC_NONE is not set | 397 | # CONFIG_SCTP_HMAC_NONE is not set |
| 395 | # CONFIG_SCTP_HMAC_SHA1 is not set | 398 | # CONFIG_SCTP_HMAC_SHA1 is not set |
| 396 | CONFIG_SCTP_HMAC_MD5=y | 399 | CONFIG_SCTP_HMAC_MD5=y |
| 400 | # CONFIG_RDS is not set | ||
| 397 | # CONFIG_TIPC is not set | 401 | # CONFIG_TIPC is not set |
| 398 | # CONFIG_ATM is not set | 402 | # CONFIG_ATM is not set |
| 399 | # CONFIG_BRIDGE is not set | 403 | # CONFIG_BRIDGE is not set |
| @@ -487,6 +491,7 @@ CONFIG_CCW=y | |||
| 487 | # Generic Driver Options | 491 | # Generic Driver Options |
| 488 | # | 492 | # |
| 489 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 493 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
| 494 | # CONFIG_DEVTMPFS is not set | ||
| 490 | CONFIG_STANDALONE=y | 495 | CONFIG_STANDALONE=y |
| 491 | CONFIG_PREVENT_FIRMWARE_BUILD=y | 496 | CONFIG_PREVENT_FIRMWARE_BUILD=y |
| 492 | CONFIG_FW_LOADER=y | 497 | CONFIG_FW_LOADER=y |
| @@ -501,6 +506,7 @@ CONFIG_BLK_DEV=y | |||
| 501 | CONFIG_BLK_DEV_LOOP=m | 506 | CONFIG_BLK_DEV_LOOP=m |
| 502 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | 507 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set |
| 503 | CONFIG_BLK_DEV_NBD=m | 508 | CONFIG_BLK_DEV_NBD=m |
| 509 | # CONFIG_BLK_DEV_OSD is not set | ||
| 504 | CONFIG_BLK_DEV_RAM=y | 510 | CONFIG_BLK_DEV_RAM=y |
| 505 | CONFIG_BLK_DEV_RAM_COUNT=16 | 511 | CONFIG_BLK_DEV_RAM_COUNT=16 |
| 506 | CONFIG_BLK_DEV_RAM_SIZE=4096 | 512 | CONFIG_BLK_DEV_RAM_SIZE=4096 |
| @@ -594,8 +600,11 @@ CONFIG_BLK_DEV_DM=y | |||
| 594 | CONFIG_DM_CRYPT=y | 600 | CONFIG_DM_CRYPT=y |
| 595 | CONFIG_DM_SNAPSHOT=y | 601 | CONFIG_DM_SNAPSHOT=y |
| 596 | CONFIG_DM_MIRROR=y | 602 | CONFIG_DM_MIRROR=y |
| 603 | # CONFIG_DM_LOG_USERSPACE is not set | ||
| 597 | CONFIG_DM_ZERO=y | 604 | CONFIG_DM_ZERO=y |
| 598 | CONFIG_DM_MULTIPATH=m | 605 | CONFIG_DM_MULTIPATH=m |
| 606 | # CONFIG_DM_MULTIPATH_QL is not set | ||
| 607 | # CONFIG_DM_MULTIPATH_ST is not set | ||
| 599 | # CONFIG_DM_DELAY is not set | 608 | # CONFIG_DM_DELAY is not set |
| 600 | # CONFIG_DM_UEVENT is not set | 609 | # CONFIG_DM_UEVENT is not set |
| 601 | CONFIG_NETDEVICES=y | 610 | CONFIG_NETDEVICES=y |
| @@ -615,7 +624,6 @@ CONFIG_NET_ETHERNET=y | |||
| 615 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | 624 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set |
| 616 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | 625 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set |
| 617 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | 626 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set |
| 618 | # CONFIG_KS8842 is not set | ||
| 619 | CONFIG_NETDEV_1000=y | 627 | CONFIG_NETDEV_1000=y |
| 620 | CONFIG_NETDEV_10000=y | 628 | CONFIG_NETDEV_10000=y |
| 621 | # CONFIG_TR is not set | 629 | # CONFIG_TR is not set |
| @@ -678,6 +686,7 @@ CONFIG_SCLP_CONSOLE=y | |||
| 678 | CONFIG_SCLP_VT220_TTY=y | 686 | CONFIG_SCLP_VT220_TTY=y |
| 679 | CONFIG_SCLP_VT220_CONSOLE=y | 687 | CONFIG_SCLP_VT220_CONSOLE=y |
| 680 | CONFIG_SCLP_CPI=m | 688 | CONFIG_SCLP_CPI=m |
| 689 | CONFIG_SCLP_ASYNC=m | ||
| 681 | CONFIG_S390_TAPE=m | 690 | CONFIG_S390_TAPE=m |
| 682 | 691 | ||
| 683 | # | 692 | # |
| @@ -737,6 +746,7 @@ CONFIG_FS_POSIX_ACL=y | |||
| 737 | # CONFIG_GFS2_FS is not set | 746 | # CONFIG_GFS2_FS is not set |
| 738 | # CONFIG_OCFS2_FS is not set | 747 | # CONFIG_OCFS2_FS is not set |
| 739 | # CONFIG_BTRFS_FS is not set | 748 | # CONFIG_BTRFS_FS is not set |
| 749 | # CONFIG_NILFS2_FS is not set | ||
| 740 | CONFIG_FILE_LOCKING=y | 750 | CONFIG_FILE_LOCKING=y |
| 741 | CONFIG_FSNOTIFY=y | 751 | CONFIG_FSNOTIFY=y |
| 742 | CONFIG_DNOTIFY=y | 752 | CONFIG_DNOTIFY=y |
| @@ -798,7 +808,6 @@ CONFIG_MISC_FILESYSTEMS=y | |||
| 798 | # CONFIG_SYSV_FS is not set | 808 | # CONFIG_SYSV_FS is not set |
| 799 | # CONFIG_UFS_FS is not set | 809 | # CONFIG_UFS_FS is not set |
| 800 | # CONFIG_EXOFS_FS is not set | 810 | # CONFIG_EXOFS_FS is not set |
| 801 | # CONFIG_NILFS2_FS is not set | ||
| 802 | CONFIG_NETWORK_FILESYSTEMS=y | 811 | CONFIG_NETWORK_FILESYSTEMS=y |
| 803 | CONFIG_NFS_FS=y | 812 | CONFIG_NFS_FS=y |
| 804 | CONFIG_NFS_V3=y | 813 | CONFIG_NFS_V3=y |
| @@ -885,11 +894,13 @@ CONFIG_DEBUG_MEMORY_INIT=y | |||
| 885 | # CONFIG_DEBUG_LIST is not set | 894 | # CONFIG_DEBUG_LIST is not set |
| 886 | # CONFIG_DEBUG_SG is not set | 895 | # CONFIG_DEBUG_SG is not set |
| 887 | # CONFIG_DEBUG_NOTIFIERS is not set | 896 | # CONFIG_DEBUG_NOTIFIERS is not set |
| 897 | # CONFIG_DEBUG_CREDENTIALS is not set | ||
| 888 | # CONFIG_RCU_TORTURE_TEST is not set | 898 | # CONFIG_RCU_TORTURE_TEST is not set |
| 889 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | 899 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set |
| 890 | # CONFIG_KPROBES_SANITY_TEST is not set | 900 | # CONFIG_KPROBES_SANITY_TEST is not set |
| 891 | # CONFIG_BACKTRACE_SELF_TEST is not set | 901 | # CONFIG_BACKTRACE_SELF_TEST is not set |
| 892 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | 902 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set |
| 903 | CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y | ||
| 893 | # CONFIG_LKDTM is not set | 904 | # CONFIG_LKDTM is not set |
| 894 | # CONFIG_FAULT_INJECTION is not set | 905 | # CONFIG_FAULT_INJECTION is not set |
| 895 | # CONFIG_LATENCYTOP is not set | 906 | # CONFIG_LATENCYTOP is not set |
| @@ -979,11 +990,13 @@ CONFIG_CRYPTO_PCBC=m | |||
| 979 | # | 990 | # |
| 980 | CONFIG_CRYPTO_HMAC=m | 991 | CONFIG_CRYPTO_HMAC=m |
| 981 | # CONFIG_CRYPTO_XCBC is not set | 992 | # CONFIG_CRYPTO_XCBC is not set |
| 993 | CONFIG_CRYPTO_VMAC=m | ||
| 982 | 994 | ||
| 983 | # | 995 | # |
| 984 | # Digest | 996 | # Digest |
| 985 | # | 997 | # |
| 986 | CONFIG_CRYPTO_CRC32C=m | 998 | CONFIG_CRYPTO_CRC32C=m |
| 999 | CONFIG_CRYPTO_GHASH=m | ||
| 987 | # CONFIG_CRYPTO_MD4 is not set | 1000 | # CONFIG_CRYPTO_MD4 is not set |
| 988 | CONFIG_CRYPTO_MD5=m | 1001 | CONFIG_CRYPTO_MD5=m |
| 989 | # CONFIG_CRYPTO_MICHAEL_MIC is not set | 1002 | # CONFIG_CRYPTO_MICHAEL_MIC is not set |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 6bc9426a6fbf..f2ef4b619ce1 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
| @@ -86,6 +86,7 @@ | |||
| 86 | #define __LC_PGM_OLD_PSW 0x0150 | 86 | #define __LC_PGM_OLD_PSW 0x0150 |
| 87 | #define __LC_MCK_OLD_PSW 0x0160 | 87 | #define __LC_MCK_OLD_PSW 0x0160 |
| 88 | #define __LC_IO_OLD_PSW 0x0170 | 88 | #define __LC_IO_OLD_PSW 0x0170 |
| 89 | #define __LC_RESTART_PSW 0x01a0 | ||
| 89 | #define __LC_EXT_NEW_PSW 0x01b0 | 90 | #define __LC_EXT_NEW_PSW 0x01b0 |
| 90 | #define __LC_SVC_NEW_PSW 0x01c0 | 91 | #define __LC_SVC_NEW_PSW 0x01c0 |
| 91 | #define __LC_PGM_NEW_PSW 0x01d0 | 92 | #define __LC_PGM_NEW_PSW 0x01d0 |
| @@ -189,6 +190,14 @@ union save_area { | |||
| 189 | #define SAVE_AREA_BASE SAVE_AREA_BASE_S390X | 190 | #define SAVE_AREA_BASE SAVE_AREA_BASE_S390X |
| 190 | #endif | 191 | #endif |
| 191 | 192 | ||
| 193 | #ifndef __s390x__ | ||
| 194 | #define LC_ORDER 0 | ||
| 195 | #else | ||
| 196 | #define LC_ORDER 1 | ||
| 197 | #endif | ||
| 198 | |||
| 199 | #define LC_PAGES (1UL << LC_ORDER) | ||
| 200 | |||
| 192 | struct _lowcore | 201 | struct _lowcore |
| 193 | { | 202 | { |
| 194 | #ifndef __s390x__ | 203 | #ifndef __s390x__ |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index cf8eed3fa779..b42715458312 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
| @@ -295,7 +295,7 @@ static inline void ATTRIB_NORET disabled_wait(unsigned long code) | |||
| 295 | " oi 0x384(1),0x10\n"/* fake protection bit */ | 295 | " oi 0x384(1),0x10\n"/* fake protection bit */ |
| 296 | " lpswe 0(%1)" | 296 | " lpswe 0(%1)" |
| 297 | : "=m" (ctl_buf) | 297 | : "=m" (ctl_buf) |
| 298 | : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0"); | 298 | : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0", "1"); |
| 299 | #endif /* __s390x__ */ | 299 | #endif /* __s390x__ */ |
| 300 | while (1); | 300 | while (1); |
| 301 | } | 301 | } |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index fa9905ce7d0b..63e46433e81d 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
| 8 | #include <linux/kbuild.h> | 8 | #include <linux/kbuild.h> |
| 9 | #include <asm/vdso.h> | 9 | #include <asm/vdso.h> |
| 10 | #include <asm/sigp.h> | ||
| 10 | 11 | ||
| 11 | int main(void) | 12 | int main(void) |
| 12 | { | 13 | { |
| @@ -59,6 +60,10 @@ int main(void) | |||
| 59 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | 60 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); |
| 60 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | 61 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); |
| 61 | DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); | 62 | DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); |
| 62 | 63 | /* constants for SIGP */ | |
| 64 | DEFINE(__SIGP_STOP, sigp_stop); | ||
| 65 | DEFINE(__SIGP_RESTART, sigp_restart); | ||
| 66 | DEFINE(__SIGP_SENSE, sigp_sense); | ||
| 67 | DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset); | ||
| 63 | return 0; | 68 | return 0; |
| 64 | } | 69 | } |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 9ab188d67a3d..5519cb745106 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
| @@ -443,66 +443,28 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) | |||
| 443 | * sys32_execve() executes a new program after the asm stub has set | 443 | * sys32_execve() executes a new program after the asm stub has set |
| 444 | * things up for us. This should basically do what I want it to. | 444 | * things up for us. This should basically do what I want it to. |
| 445 | */ | 445 | */ |
| 446 | asmlinkage long sys32_execve(void) | 446 | asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, |
| 447 | compat_uptr_t __user *envp) | ||
| 447 | { | 448 | { |
| 448 | struct pt_regs *regs = task_pt_regs(current); | 449 | struct pt_regs *regs = task_pt_regs(current); |
| 449 | char *filename; | 450 | char *filename; |
| 450 | unsigned long result; | 451 | long rc; |
| 451 | int rc; | 452 | |
| 452 | 453 | filename = getname(name); | |
| 453 | filename = getname(compat_ptr(regs->orig_gpr2)); | 454 | rc = PTR_ERR(filename); |
| 454 | if (IS_ERR(filename)) { | 455 | if (IS_ERR(filename)) |
| 455 | result = PTR_ERR(filename); | 456 | return rc; |
| 456 | goto out; | 457 | rc = compat_do_execve(filename, argv, envp, regs); |
| 457 | } | 458 | if (rc) |
| 458 | rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), | 459 | goto out; |
| 459 | compat_ptr(regs->gprs[4]), regs); | ||
| 460 | if (rc) { | ||
| 461 | result = rc; | ||
| 462 | goto out_putname; | ||
| 463 | } | ||
| 464 | current->thread.fp_regs.fpc=0; | 460 | current->thread.fp_regs.fpc=0; |
| 465 | asm volatile("sfpc %0,0" : : "d" (0)); | 461 | asm volatile("sfpc %0,0" : : "d" (0)); |
| 466 | result = regs->gprs[2]; | 462 | rc = regs->gprs[2]; |
| 467 | out_putname: | ||
| 468 | putname(filename); | ||
| 469 | out: | 463 | out: |
| 470 | return result; | 464 | putname(filename); |
| 471 | } | 465 | return rc; |
| 472 | |||
| 473 | |||
| 474 | #ifdef CONFIG_MODULES | ||
| 475 | |||
| 476 | asmlinkage long | ||
| 477 | sys32_init_module(void __user *umod, unsigned long len, | ||
| 478 | const char __user *uargs) | ||
| 479 | { | ||
| 480 | return sys_init_module(umod, len, uargs); | ||
| 481 | } | ||
| 482 | |||
| 483 | asmlinkage long | ||
| 484 | sys32_delete_module(const char __user *name_user, unsigned int flags) | ||
| 485 | { | ||
| 486 | return sys_delete_module(name_user, flags); | ||
| 487 | } | ||
| 488 | |||
| 489 | #else /* CONFIG_MODULES */ | ||
| 490 | |||
| 491 | asmlinkage long | ||
| 492 | sys32_init_module(void __user *umod, unsigned long len, | ||
| 493 | const char __user *uargs) | ||
| 494 | { | ||
| 495 | return -ENOSYS; | ||
| 496 | } | 466 | } |
| 497 | 467 | ||
| 498 | asmlinkage long | ||
| 499 | sys32_delete_module(const char __user *name_user, unsigned int flags) | ||
| 500 | { | ||
| 501 | return -ENOSYS; | ||
| 502 | } | ||
| 503 | |||
| 504 | #endif /* CONFIG_MODULES */ | ||
| 505 | |||
| 506 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, | 468 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, |
| 507 | size_t count, u32 poshi, u32 poslo) | 469 | size_t count, u32 poshi, u32 poslo) |
| 508 | { | 470 | { |
| @@ -801,23 +763,6 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) | |||
| 801 | return sys_write(fd, buf, count); | 763 | return sys_write(fd, buf, count); |
| 802 | } | 764 | } |
| 803 | 765 | ||
| 804 | asmlinkage long sys32_clone(void) | ||
| 805 | { | ||
| 806 | struct pt_regs *regs = task_pt_regs(current); | ||
| 807 | unsigned long clone_flags; | ||
| 808 | unsigned long newsp; | ||
| 809 | int __user *parent_tidptr, *child_tidptr; | ||
| 810 | |||
| 811 | clone_flags = regs->gprs[3] & 0xffffffffUL; | ||
| 812 | newsp = regs->orig_gpr2 & 0x7fffffffUL; | ||
| 813 | parent_tidptr = compat_ptr(regs->gprs[4]); | ||
| 814 | child_tidptr = compat_ptr(regs->gprs[5]); | ||
| 815 | if (!newsp) | ||
| 816 | newsp = regs->gprs[15]; | ||
| 817 | return do_fork(clone_flags, newsp, regs, 0, | ||
| 818 | parent_tidptr, child_tidptr); | ||
| 819 | } | ||
| 820 | |||
| 821 | /* | 766 | /* |
| 822 | * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. | 767 | * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. |
| 823 | * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} | 768 | * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} |
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 836a28842900..c07f9ca05ade 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h | |||
| @@ -198,7 +198,8 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, | |||
| 198 | compat_sigset_t __user *oset, size_t sigsetsize); | 198 | compat_sigset_t __user *oset, size_t sigsetsize); |
| 199 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); | 199 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); |
| 200 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); | 200 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); |
| 201 | long sys32_execve(void); | 201 | long sys32_execve(char __user *name, compat_uptr_t __user *argv, |
| 202 | compat_uptr_t __user *envp); | ||
| 202 | long sys32_init_module(void __user *umod, unsigned long len, | 203 | long sys32_init_module(void __user *umod, unsigned long len, |
| 203 | const char __user *uargs); | 204 | const char __user *uargs); |
| 204 | long sys32_delete_module(const char __user *name_user, unsigned int flags); | 205 | long sys32_delete_module(const char __user *name_user, unsigned int flags); |
| @@ -222,7 +223,6 @@ unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg); | |||
| 222 | long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg); | 223 | long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg); |
| 223 | long sys32_read(unsigned int fd, char __user * buf, size_t count); | 224 | long sys32_read(unsigned int fd, char __user * buf, size_t count); |
| 224 | long sys32_write(unsigned int fd, char __user * buf, size_t count); | 225 | long sys32_write(unsigned int fd, char __user * buf, size_t count); |
| 225 | long sys32_clone(void); | ||
| 226 | long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise); | 226 | long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise); |
| 227 | long sys32_fadvise64_64(struct fadvise64_64_args __user *args); | 227 | long sys32_fadvise64_64(struct fadvise64_64_args __user *args); |
| 228 | long sys32_sigaction(int sig, const struct old_sigaction32 __user *act, | 228 | long sys32_sigaction(int sig, const struct old_sigaction32 __user *act, |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 624790042d41..682fb69dba21 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
| @@ -568,18 +568,18 @@ compat_sys_sigprocmask_wrapper: | |||
| 568 | llgtr %r4,%r4 # compat_old_sigset_t * | 568 | llgtr %r4,%r4 # compat_old_sigset_t * |
| 569 | jg compat_sys_sigprocmask # branch to system call | 569 | jg compat_sys_sigprocmask # branch to system call |
| 570 | 570 | ||
| 571 | .globl sys32_init_module_wrapper | 571 | .globl sys_init_module_wrapper |
| 572 | sys32_init_module_wrapper: | 572 | sys_init_module_wrapper: |
| 573 | llgtr %r2,%r2 # void * | 573 | llgtr %r2,%r2 # void * |
| 574 | llgfr %r3,%r3 # unsigned long | 574 | llgfr %r3,%r3 # unsigned long |
| 575 | llgtr %r4,%r4 # char * | 575 | llgtr %r4,%r4 # char * |
| 576 | jg sys32_init_module # branch to system call | 576 | jg sys_init_module # branch to system call |
| 577 | 577 | ||
| 578 | .globl sys32_delete_module_wrapper | 578 | .globl sys_delete_module_wrapper |
| 579 | sys32_delete_module_wrapper: | 579 | sys_delete_module_wrapper: |
| 580 | llgtr %r2,%r2 # const char * | 580 | llgtr %r2,%r2 # const char * |
| 581 | llgfr %r3,%r3 # unsigned int | 581 | llgfr %r3,%r3 # unsigned int |
| 582 | jg sys32_delete_module # branch to system call | 582 | jg sys_delete_module # branch to system call |
| 583 | 583 | ||
| 584 | .globl sys32_quotactl_wrapper | 584 | .globl sys32_quotactl_wrapper |
| 585 | sys32_quotactl_wrapper: | 585 | sys32_quotactl_wrapper: |
| @@ -1840,3 +1840,18 @@ sys_perf_event_open_wrapper: | |||
| 1840 | lgfr %r5,%r5 # int | 1840 | lgfr %r5,%r5 # int |
| 1841 | llgfr %r6,%r6 # unsigned long | 1841 | llgfr %r6,%r6 # unsigned long |
| 1842 | jg sys_perf_event_open # branch to system call | 1842 | jg sys_perf_event_open # branch to system call |
| 1843 | |||
| 1844 | .globl sys_clone_wrapper | ||
| 1845 | sys_clone_wrapper: | ||
| 1846 | llgfr %r2,%r2 # unsigned long | ||
| 1847 | llgfr %r3,%r3 # unsigned long | ||
| 1848 | llgtr %r4,%r4 # int * | ||
| 1849 | llgtr %r5,%r5 # int * | ||
| 1850 | jg sys_clone # branch to system call | ||
| 1851 | |||
| 1852 | .globl sys32_execve_wrapper | ||
| 1853 | sys32_execve_wrapper: | ||
| 1854 | llgtr %r2,%r2 # char * | ||
| 1855 | llgtr %r3,%r3 # compat_uptr_t * | ||
| 1856 | llgtr %r4,%r4 # compat_uptr_t * | ||
| 1857 | jg sys32_execve # branch to system call | ||
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 950c59c6688b..e1e5e767ab56 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
| @@ -42,10 +42,12 @@ long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); | |||
| 42 | long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, | 42 | long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, |
| 43 | u32 len_low); | 43 | u32 len_low); |
| 44 | long sys_fork(void); | 44 | long sys_fork(void); |
| 45 | long sys_clone(void); | 45 | long sys_clone(unsigned long newsp, unsigned long clone_flags, |
| 46 | int __user *parent_tidptr, int __user *child_tidptr); | ||
| 46 | long sys_vfork(void); | 47 | long sys_vfork(void); |
| 47 | void execve_tail(void); | 48 | void execve_tail(void); |
| 48 | long sys_execve(void); | 49 | long sys_execve(char __user *name, char __user * __user *argv, |
| 50 | char __user * __user *envp); | ||
| 49 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); | 51 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); |
| 50 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 52 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
| 51 | struct old_sigaction __user *oact); | 53 | struct old_sigaction __user *oact); |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5a43f27eec13..59fe6ecc6ed3 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/elfcore.h> | 32 | #include <linux/elfcore.h> |
| 33 | #include <linux/kernel_stat.h> | 33 | #include <linux/kernel_stat.h> |
| 34 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
| 35 | #include <linux/compat.h> | ||
| 35 | #include <asm/compat.h> | 36 | #include <asm/compat.h> |
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
| @@ -230,17 +231,11 @@ SYSCALL_DEFINE0(fork) | |||
| 230 | return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); | 231 | return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); |
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | SYSCALL_DEFINE0(clone) | 234 | SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, |
| 235 | int __user *, parent_tidptr, int __user *, child_tidptr) | ||
| 234 | { | 236 | { |
| 235 | struct pt_regs *regs = task_pt_regs(current); | 237 | struct pt_regs *regs = task_pt_regs(current); |
| 236 | unsigned long clone_flags; | ||
| 237 | unsigned long newsp; | ||
| 238 | int __user *parent_tidptr, *child_tidptr; | ||
| 239 | 238 | ||
| 240 | clone_flags = regs->gprs[3]; | ||
| 241 | newsp = regs->orig_gpr2; | ||
| 242 | parent_tidptr = (int __user *) regs->gprs[4]; | ||
| 243 | child_tidptr = (int __user *) regs->gprs[5]; | ||
| 244 | if (!newsp) | 239 | if (!newsp) |
| 245 | newsp = regs->gprs[15]; | 240 | newsp = regs->gprs[15]; |
| 246 | return do_fork(clone_flags, newsp, regs, 0, | 241 | return do_fork(clone_flags, newsp, regs, 0, |
| @@ -274,30 +269,25 @@ asmlinkage void execve_tail(void) | |||
| 274 | /* | 269 | /* |
| 275 | * sys_execve() executes a new program. | 270 | * sys_execve() executes a new program. |
| 276 | */ | 271 | */ |
| 277 | SYSCALL_DEFINE0(execve) | 272 | SYSCALL_DEFINE3(execve, char __user *, name, char __user * __user *, argv, |
| 273 | char __user * __user *, envp) | ||
| 278 | { | 274 | { |
| 279 | struct pt_regs *regs = task_pt_regs(current); | 275 | struct pt_regs *regs = task_pt_regs(current); |
| 280 | char *filename; | 276 | char *filename; |
| 281 | unsigned long result; | 277 | long rc; |
| 282 | int rc; | ||
| 283 | 278 | ||
| 284 | filename = getname((char __user *) regs->orig_gpr2); | 279 | filename = getname(name); |
| 285 | if (IS_ERR(filename)) { | 280 | rc = PTR_ERR(filename); |
| 286 | result = PTR_ERR(filename); | 281 | if (IS_ERR(filename)) |
| 282 | return rc; | ||
| 283 | rc = do_execve(filename, argv, envp, regs); | ||
| 284 | if (rc) | ||
| 287 | goto out; | 285 | goto out; |
| 288 | } | ||
| 289 | rc = do_execve(filename, (char __user * __user *) regs->gprs[3], | ||
| 290 | (char __user * __user *) regs->gprs[4], regs); | ||
| 291 | if (rc) { | ||
| 292 | result = rc; | ||
| 293 | goto out_putname; | ||
| 294 | } | ||
| 295 | execve_tail(); | 286 | execve_tail(); |
| 296 | result = regs->gprs[2]; | 287 | rc = regs->gprs[2]; |
| 297 | out_putname: | ||
| 298 | putname(filename); | ||
| 299 | out: | 288 | out: |
| 300 | return result; | 289 | putname(filename); |
| 290 | return rc; | ||
| 301 | } | 291 | } |
| 302 | 292 | ||
| 303 | /* | 293 | /* |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f3ddd7ac06c5..a8738676b26c 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
| @@ -339,24 +339,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 339 | int copied, ret; | 339 | int copied, ret; |
| 340 | 340 | ||
| 341 | switch (request) { | 341 | switch (request) { |
| 342 | case PTRACE_PEEKTEXT: | ||
| 343 | case PTRACE_PEEKDATA: | ||
| 344 | /* Remove high order bit from address (only for 31 bit). */ | ||
| 345 | addr &= PSW_ADDR_INSN; | ||
| 346 | /* read word at location addr. */ | ||
| 347 | return generic_ptrace_peekdata(child, addr, data); | ||
| 348 | |||
| 349 | case PTRACE_PEEKUSR: | 342 | case PTRACE_PEEKUSR: |
| 350 | /* read the word at location addr in the USER area. */ | 343 | /* read the word at location addr in the USER area. */ |
| 351 | return peek_user(child, addr, data); | 344 | return peek_user(child, addr, data); |
| 352 | 345 | ||
| 353 | case PTRACE_POKETEXT: | ||
| 354 | case PTRACE_POKEDATA: | ||
| 355 | /* Remove high order bit from address (only for 31 bit). */ | ||
| 356 | addr &= PSW_ADDR_INSN; | ||
| 357 | /* write the word at location addr. */ | ||
| 358 | return generic_ptrace_pokedata(child, addr, data); | ||
| 359 | |||
| 360 | case PTRACE_POKEUSR: | 346 | case PTRACE_POKEUSR: |
| 361 | /* write the word at location addr in the USER area */ | 347 | /* write the word at location addr in the USER area */ |
| 362 | return poke_user(child, addr, data); | 348 | return poke_user(child, addr, data); |
| @@ -386,8 +372,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 386 | copied += sizeof(unsigned long); | 372 | copied += sizeof(unsigned long); |
| 387 | } | 373 | } |
| 388 | return 0; | 374 | return 0; |
| 375 | default: | ||
| 376 | /* Removing high order bit from addr (only for 31 bit). */ | ||
| 377 | addr &= PSW_ADDR_INSN; | ||
| 378 | return ptrace_request(child, request, addr, data); | ||
| 389 | } | 379 | } |
| 390 | return ptrace_request(child, request, addr, data); | ||
| 391 | } | 380 | } |
| 392 | 381 | ||
| 393 | #ifdef CONFIG_COMPAT | 382 | #ifdef CONFIG_COMPAT |
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index 20639dfe0c42..e27ca63076d1 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S | |||
| @@ -24,8 +24,6 @@ LC_EXT_INT_CODE = 0x86 # addr of ext int code | |||
| 24 | # R3 = external interruption parameter if R2=0 | 24 | # R3 = external interruption parameter if R2=0 |
| 25 | # | 25 | # |
| 26 | 26 | ||
| 27 | .section ".init.text","ax" | ||
| 28 | |||
| 29 | _sclp_wait_int: | 27 | _sclp_wait_int: |
| 30 | stm %r6,%r15,24(%r15) # save registers | 28 | stm %r6,%r15,24(%r15) # save registers |
| 31 | basr %r13,0 # get base register | 29 | basr %r13,0 # get base register |
| @@ -318,9 +316,8 @@ _sclp_print_early: | |||
| 318 | .long _sclp_work_area | 316 | .long _sclp_work_area |
| 319 | .Lascebc: | 317 | .Lascebc: |
| 320 | .long _ascebc | 318 | .long _ascebc |
| 321 | .previous | ||
| 322 | 319 | ||
| 323 | .section ".init.data","a" | 320 | .section .data,"aw",@progbits |
| 324 | .balign 4096 | 321 | .balign 4096 |
| 325 | _sclp_work_area: | 322 | _sclp_work_area: |
| 326 | .fill 4096 | 323 | .fill 4096 |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 56c16876b919..b4b6396e6cf0 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
| @@ -475,10 +475,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) | |||
| 475 | { | 475 | { |
| 476 | unsigned long async_stack, panic_stack; | 476 | unsigned long async_stack, panic_stack; |
| 477 | struct _lowcore *lowcore; | 477 | struct _lowcore *lowcore; |
| 478 | int lc_order; | ||
| 479 | 478 | ||
| 480 | lc_order = sizeof(long) == 8 ? 1 : 0; | 479 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); |
| 481 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); | ||
| 482 | if (!lowcore) | 480 | if (!lowcore) |
| 483 | return -ENOMEM; | 481 | return -ENOMEM; |
| 484 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | 482 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); |
| @@ -509,16 +507,14 @@ static int __cpuinit smp_alloc_lowcore(int cpu) | |||
| 509 | out: | 507 | out: |
| 510 | free_page(panic_stack); | 508 | free_page(panic_stack); |
| 511 | free_pages(async_stack, ASYNC_ORDER); | 509 | free_pages(async_stack, ASYNC_ORDER); |
| 512 | free_pages((unsigned long) lowcore, lc_order); | 510 | free_pages((unsigned long) lowcore, LC_ORDER); |
| 513 | return -ENOMEM; | 511 | return -ENOMEM; |
| 514 | } | 512 | } |
| 515 | 513 | ||
| 516 | static void smp_free_lowcore(int cpu) | 514 | static void smp_free_lowcore(int cpu) |
| 517 | { | 515 | { |
| 518 | struct _lowcore *lowcore; | 516 | struct _lowcore *lowcore; |
| 519 | int lc_order; | ||
| 520 | 517 | ||
| 521 | lc_order = sizeof(long) == 8 ? 1 : 0; | ||
| 522 | lowcore = lowcore_ptr[cpu]; | 518 | lowcore = lowcore_ptr[cpu]; |
| 523 | #ifndef CONFIG_64BIT | 519 | #ifndef CONFIG_64BIT |
| 524 | if (MACHINE_HAS_IEEE) | 520 | if (MACHINE_HAS_IEEE) |
| @@ -528,7 +524,7 @@ static void smp_free_lowcore(int cpu) | |||
| 528 | #endif | 524 | #endif |
| 529 | free_page(lowcore->panic_stack - PAGE_SIZE); | 525 | free_page(lowcore->panic_stack - PAGE_SIZE); |
| 530 | free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER); | 526 | free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER); |
| 531 | free_pages((unsigned long) lowcore, lc_order); | 527 | free_pages((unsigned long) lowcore, LC_ORDER); |
| 532 | lowcore_ptr[cpu] = NULL; | 528 | lowcore_ptr[cpu] = NULL; |
| 533 | } | 529 | } |
| 534 | 530 | ||
| @@ -664,7 +660,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
| 664 | unsigned long async_stack, panic_stack; | 660 | unsigned long async_stack, panic_stack; |
| 665 | struct _lowcore *lowcore; | 661 | struct _lowcore *lowcore; |
| 666 | unsigned int cpu; | 662 | unsigned int cpu; |
| 667 | int lc_order; | ||
| 668 | 663 | ||
| 669 | smp_detect_cpus(); | 664 | smp_detect_cpus(); |
| 670 | 665 | ||
| @@ -674,8 +669,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
| 674 | print_cpu_info(); | 669 | print_cpu_info(); |
| 675 | 670 | ||
| 676 | /* Reallocate current lowcore, but keep its contents. */ | 671 | /* Reallocate current lowcore, but keep its contents. */ |
| 677 | lc_order = sizeof(long) == 8 ? 1 : 0; | 672 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); |
| 678 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); | ||
| 679 | panic_stack = __get_free_page(GFP_KERNEL); | 673 | panic_stack = __get_free_page(GFP_KERNEL); |
| 680 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | 674 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); |
| 681 | BUG_ON(!lowcore || !panic_stack || !async_stack); | 675 | BUG_ON(!lowcore || !panic_stack || !async_stack); |
| @@ -1047,42 +1041,6 @@ out: | |||
| 1047 | static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, | 1041 | static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, |
| 1048 | dispatching_store); | 1042 | dispatching_store); |
| 1049 | 1043 | ||
| 1050 | /* | ||
| 1051 | * If the resume kernel runs on another cpu than the suspended kernel, | ||
| 1052 | * we have to switch the cpu IDs in the logical map. | ||
| 1053 | */ | ||
| 1054 | void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id, | ||
| 1055 | struct _lowcore *suspend_lowcore) | ||
| 1056 | { | ||
| 1057 | int cpu, suspend_cpu_id, resume_cpu_id; | ||
| 1058 | u32 suspend_phys_cpu_id; | ||
| 1059 | |||
| 1060 | suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr]; | ||
| 1061 | suspend_cpu_id = suspend_lowcore->cpu_nr; | ||
| 1062 | |||
| 1063 | for_each_present_cpu(cpu) { | ||
| 1064 | if (__cpu_logical_map[cpu] == resume_phys_cpu_id) { | ||
| 1065 | resume_cpu_id = cpu; | ||
| 1066 | goto found; | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | panic("Could not find resume cpu in logical map.\n"); | ||
| 1070 | |||
| 1071 | found: | ||
| 1072 | printk("Resume cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id); | ||
| 1073 | printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id); | ||
| 1074 | |||
| 1075 | __cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id; | ||
| 1076 | __cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id; | ||
| 1077 | |||
| 1078 | lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | u32 smp_get_phys_cpu_id(void) | ||
| 1082 | { | ||
| 1083 | return __cpu_logical_map[smp_processor_id()]; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static int __init topology_init(void) | 1044 | static int __init topology_init(void) |
| 1087 | { | 1045 | { |
| 1088 | int cpu; | 1046 | int cpu; |
diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c index 086bee970cae..cf9e5c6d5527 100644 --- a/arch/s390/kernel/suspend.c +++ b/arch/s390/kernel/suspend.c | |||
| @@ -6,36 +6,26 @@ | |||
| 6 | * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com> | 6 | * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com> |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/suspend.h> | ||
| 10 | #include <linux/reboot.h> | ||
| 11 | #include <linux/pfn.h> | 9 | #include <linux/pfn.h> |
| 12 | #include <linux/mm.h> | ||
| 13 | #include <asm/sections.h> | ||
| 14 | #include <asm/system.h> | 10 | #include <asm/system.h> |
| 15 | #include <asm/ipl.h> | ||
| 16 | 11 | ||
| 17 | /* | 12 | /* |
| 18 | * References to section boundaries | 13 | * References to section boundaries |
| 19 | */ | 14 | */ |
| 20 | extern const void __nosave_begin, __nosave_end; | 15 | extern const void __nosave_begin, __nosave_end; |
| 21 | 16 | ||
| 22 | /* | ||
| 23 | * check if given pfn is in the 'nosave' or in the read only NSS section | ||
| 24 | */ | ||
| 25 | int pfn_is_nosave(unsigned long pfn) | 17 | int pfn_is_nosave(unsigned long pfn) |
| 26 | { | 18 | { |
| 27 | unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; | 19 | unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); |
| 28 | unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) | 20 | unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); |
| 29 | >> PAGE_SHIFT; | ||
| 30 | unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; | ||
| 31 | unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); | ||
| 32 | 21 | ||
| 22 | /* Always save lowcore pages (LC protection might be enabled). */ | ||
| 23 | if (pfn <= LC_PAGES) | ||
| 24 | return 0; | ||
| 33 | if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) | 25 | if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) |
| 34 | return 1; | 26 | return 1; |
| 35 | if (pfn >= stext_pfn && pfn <= eshared_pfn) { | 27 | /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ |
| 36 | if (ipl_info.type == IPL_TYPE_NSS) | 28 | if (tprot(PFN_PHYS(pfn))) |
| 37 | return 1; | ||
| 38 | } else if ((tprot(pfn * PAGE_SIZE) && pfn > 0)) | ||
| 39 | return 1; | 29 | return 1; |
| 40 | return 0; | 30 | return 0; |
| 41 | } | 31 | } |
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 7cd6b096f0d1..fe927d0bc20b 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <asm/page.h> | 10 | #include <asm/page.h> |
| 11 | #include <asm/ptrace.h> | 11 | #include <asm/ptrace.h> |
| 12 | #include <asm/thread_info.h> | ||
| 12 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
| 13 | 14 | ||
| 14 | /* | 15 | /* |
| @@ -41,6 +42,9 @@ swsusp_arch_suspend: | |||
| 41 | /* Get pointer to save area */ | 42 | /* Get pointer to save area */ |
| 42 | lghi %r1,0x1000 | 43 | lghi %r1,0x1000 |
| 43 | 44 | ||
| 45 | /* Save CPU address */ | ||
| 46 | stap __LC_CPU_ADDRESS(%r1) | ||
| 47 | |||
| 44 | /* Store registers */ | 48 | /* Store registers */ |
| 45 | mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ | 49 | mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ |
| 46 | stfpc 0x31c(%r1) /* store fpu control */ | 50 | stfpc 0x31c(%r1) /* store fpu control */ |
| @@ -102,11 +106,10 @@ swsusp_arch_resume: | |||
| 102 | aghi %r15,-STACK_FRAME_OVERHEAD | 106 | aghi %r15,-STACK_FRAME_OVERHEAD |
| 103 | stg %r1,__SF_BACKCHAIN(%r15) | 107 | stg %r1,__SF_BACKCHAIN(%r15) |
| 104 | 108 | ||
| 105 | #ifdef CONFIG_SMP | 109 | /* Make all free pages stable */ |
| 106 | /* Save boot cpu number */ | 110 | lghi %r2,1 |
| 107 | brasl %r14,smp_get_phys_cpu_id | 111 | brasl %r14,arch_set_page_states |
| 108 | lgr %r10,%r2 | 112 | |
| 109 | #endif | ||
| 110 | /* Deactivate DAT */ | 113 | /* Deactivate DAT */ |
| 111 | stnsm __SF_EMPTY(%r15),0xfb | 114 | stnsm __SF_EMPTY(%r15),0xfb |
| 112 | 115 | ||
| @@ -133,6 +136,69 @@ swsusp_arch_resume: | |||
| 133 | 2: | 136 | 2: |
| 134 | ptlb /* flush tlb */ | 137 | ptlb /* flush tlb */ |
| 135 | 138 | ||
| 139 | /* Reset System */ | ||
| 140 | larl %r1,restart_entry | ||
| 141 | larl %r2,.Lrestart_diag308_psw | ||
| 142 | og %r1,0(%r2) | ||
| 143 | stg %r1,0(%r0) | ||
| 144 | larl %r1,.Lnew_pgm_check_psw | ||
| 145 | epsw %r2,%r3 | ||
| 146 | stm %r2,%r3,0(%r1) | ||
| 147 | mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) | ||
| 148 | lghi %r0,0 | ||
| 149 | diag %r0,%r0,0x308 | ||
| 150 | restart_entry: | ||
| 151 | lhi %r1,1 | ||
| 152 | sigp %r1,%r0,0x12 | ||
| 153 | sam64 | ||
| 154 | larl %r1,.Lnew_pgm_check_psw | ||
| 155 | lpswe 0(%r1) | ||
| 156 | pgm_check_entry: | ||
| 157 | |||
| 158 | /* Switch to original suspend CPU */ | ||
| 159 | larl %r1,.Lresume_cpu /* Resume CPU address: r2 */ | ||
| 160 | stap 0(%r1) | ||
| 161 | llgh %r2,0(%r1) | ||
| 162 | lghi %r3,0x1000 | ||
| 163 | llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */ | ||
| 164 | cgr %r1,%r2 | ||
| 165 | je restore_registers /* r1 = r2 -> nothing to do */ | ||
| 166 | larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ | ||
| 167 | mvc __LC_RESTART_PSW(16,%r0),0(%r4) | ||
| 168 | 3: | ||
| 169 | sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET | ||
| 170 | brc 8,4f /* accepted */ | ||
| 171 | brc 2,3b /* busy, try again */ | ||
| 172 | |||
| 173 | /* Suspend CPU not available -> panic */ | ||
| 174 | larl %r15,init_thread_union | ||
| 175 | ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) | ||
| 176 | larl %r2,.Lpanic_string | ||
| 177 | larl %r3,_sclp_print_early | ||
| 178 | lghi %r1,0 | ||
| 179 | sam31 | ||
| 180 | sigp %r1,%r0,0x12 | ||
| 181 | basr %r14,%r3 | ||
| 182 | larl %r3,.Ldisabled_wait_31 | ||
| 183 | lpsw 0(%r3) | ||
| 184 | 4: | ||
| 185 | /* Switch to suspend CPU */ | ||
| 186 | sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */ | ||
| 187 | brc 2,4b /* busy, try again */ | ||
| 188 | 5: | ||
| 189 | sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ | ||
| 190 | 6: j 6b | ||
| 191 | |||
| 192 | restart_suspend: | ||
| 193 | larl %r1,.Lresume_cpu | ||
| 194 | llgh %r2,0(%r1) | ||
| 195 | 7: | ||
| 196 | sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */ | ||
| 197 | brc 2,7b /* busy, try again */ | ||
| 198 | tmll %r9,0x40 /* Test if resume CPU is stopped */ | ||
| 199 | jz 7b | ||
| 200 | |||
| 201 | restore_registers: | ||
| 136 | /* Restore registers */ | 202 | /* Restore registers */ |
| 137 | lghi %r13,0x1000 /* %r1 = pointer to save arae */ | 203 | lghi %r13,0x1000 /* %r1 = pointer to save arae */ |
| 138 | 204 | ||
| @@ -166,19 +232,33 @@ swsusp_arch_resume: | |||
| 166 | /* Pointer to save area */ | 232 | /* Pointer to save area */ |
| 167 | lghi %r13,0x1000 | 233 | lghi %r13,0x1000 |
| 168 | 234 | ||
| 169 | #ifdef CONFIG_SMP | ||
| 170 | /* Switch CPUs */ | ||
| 171 | lgr %r2,%r10 /* get cpu id */ | ||
| 172 | llgf %r3,0x318(%r13) | ||
| 173 | brasl %r14,smp_switch_boot_cpu_in_resume | ||
| 174 | #endif | ||
| 175 | /* Restore prefix register */ | 235 | /* Restore prefix register */ |
| 176 | spx 0x318(%r13) | 236 | spx 0x318(%r13) |
| 177 | 237 | ||
| 178 | /* Activate DAT */ | 238 | /* Activate DAT */ |
| 179 | stosm __SF_EMPTY(%r15),0x04 | 239 | stosm __SF_EMPTY(%r15),0x04 |
| 180 | 240 | ||
| 241 | /* Make all free pages unstable */ | ||
| 242 | lghi %r2,0 | ||
| 243 | brasl %r14,arch_set_page_states | ||
| 244 | |||
| 181 | /* Return 0 */ | 245 | /* Return 0 */ |
| 182 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) | 246 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) |
| 183 | lghi %r2,0 | 247 | lghi %r2,0 |
| 184 | br %r14 | 248 | br %r14 |
| 249 | |||
| 250 | .section .data.nosave,"aw",@progbits | ||
| 251 | .align 8 | ||
| 252 | .Ldisabled_wait_31: | ||
| 253 | .long 0x000a0000,0x00000000 | ||
| 254 | .Lpanic_string: | ||
| 255 | .asciz "Resume not possible because suspend CPU is no longer available" | ||
| 256 | .align 8 | ||
| 257 | .Lrestart_diag308_psw: | ||
| 258 | .long 0x00080000,0x80000000 | ||
| 259 | .Lrestart_suspend_psw: | ||
| 260 | .quad 0x0000000180000000,restart_suspend | ||
| 261 | .Lnew_pgm_check_psw: | ||
| 262 | .quad 0,pgm_check_entry | ||
| 263 | .Lresume_cpu: | ||
| 264 | .byte 0,0 | ||
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 0b5083681e77..30eca070d426 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
| @@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) | |||
| 19 | SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) | 19 | SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) |
| 20 | SYSCALL(sys_link,sys_link,sys32_link_wrapper) | 20 | SYSCALL(sys_link,sys_link,sys32_link_wrapper) |
| 21 | SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ | 21 | SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ |
| 22 | SYSCALL(sys_execve,sys_execve,sys32_execve) | 22 | SYSCALL(sys_execve,sys_execve,sys32_execve_wrapper) |
| 23 | SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) | 23 | SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) |
| 24 | SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ | 24 | SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ |
| 25 | SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) | 25 | SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) |
| @@ -128,7 +128,7 @@ SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) | |||
| 128 | SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) | 128 | SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) |
| 129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) | 129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) |
| 130 | SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) | 130 | SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) |
| 131 | SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ | 131 | SYSCALL(sys_clone,sys_clone,sys_clone_wrapper) /* 120 */ |
| 132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) | 132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) |
| 133 | SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper) | 133 | SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper) |
| 134 | NI_SYSCALL /* modify_ldt for i386 */ | 134 | NI_SYSCALL /* modify_ldt for i386 */ |
| @@ -136,8 +136,8 @@ SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) | |||
| 136 | SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ | 136 | SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ |
| 137 | SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask_wrapper) | 137 | SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask_wrapper) |
| 138 | NI_SYSCALL /* old "create module" */ | 138 | NI_SYSCALL /* old "create module" */ |
| 139 | SYSCALL(sys_init_module,sys_init_module,sys32_init_module_wrapper) | 139 | SYSCALL(sys_init_module,sys_init_module,sys_init_module_wrapper) |
| 140 | SYSCALL(sys_delete_module,sys_delete_module,sys32_delete_module_wrapper) | 140 | SYSCALL(sys_delete_module,sys_delete_module,sys_delete_module_wrapper) |
| 141 | NI_SYSCALL /* 130: old get_kernel_syms */ | 141 | NI_SYSCALL /* 130: old get_kernel_syms */ |
| 142 | SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper) | 142 | SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper) |
| 143 | SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper) | 143 | SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper) |
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index f92ec203ad92..098923ae458f 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c | |||
| @@ -50,28 +50,64 @@ void __init cmma_init(void) | |||
| 50 | cmma_flag = 0; | 50 | cmma_flag = 0; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | void arch_free_page(struct page *page, int order) | 53 | static inline void set_page_unstable(struct page *page, int order) |
| 54 | { | 54 | { |
| 55 | int i, rc; | 55 | int i, rc; |
| 56 | 56 | ||
| 57 | if (!cmma_flag) | ||
| 58 | return; | ||
| 59 | for (i = 0; i < (1 << order); i++) | 57 | for (i = 0; i < (1 << order); i++) |
| 60 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" | 58 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" |
| 61 | : "=&d" (rc) | 59 | : "=&d" (rc) |
| 62 | : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), | 60 | : "a" (page_to_phys(page + i)), |
| 63 | "i" (ESSA_SET_UNUSED)); | 61 | "i" (ESSA_SET_UNUSED)); |
| 64 | } | 62 | } |
| 65 | 63 | ||
| 66 | void arch_alloc_page(struct page *page, int order) | 64 | void arch_free_page(struct page *page, int order) |
| 67 | { | 65 | { |
| 68 | int i, rc; | ||
| 69 | |||
| 70 | if (!cmma_flag) | 66 | if (!cmma_flag) |
| 71 | return; | 67 | return; |
| 68 | set_page_unstable(page, order); | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void set_page_stable(struct page *page, int order) | ||
| 72 | { | ||
| 73 | int i, rc; | ||
| 74 | |||
| 72 | for (i = 0; i < (1 << order); i++) | 75 | for (i = 0; i < (1 << order); i++) |
| 73 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" | 76 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" |
| 74 | : "=&d" (rc) | 77 | : "=&d" (rc) |
| 75 | : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), | 78 | : "a" (page_to_phys(page + i)), |
| 76 | "i" (ESSA_SET_STABLE)); | 79 | "i" (ESSA_SET_STABLE)); |
| 77 | } | 80 | } |
| 81 | |||
| 82 | void arch_alloc_page(struct page *page, int order) | ||
| 83 | { | ||
| 84 | if (!cmma_flag) | ||
| 85 | return; | ||
| 86 | set_page_stable(page, order); | ||
| 87 | } | ||
| 88 | |||
| 89 | void arch_set_page_states(int make_stable) | ||
| 90 | { | ||
| 91 | unsigned long flags, order, t; | ||
| 92 | struct list_head *l; | ||
| 93 | struct page *page; | ||
| 94 | struct zone *zone; | ||
| 95 | |||
| 96 | if (!cmma_flag) | ||
| 97 | return; | ||
| 98 | if (make_stable) | ||
| 99 | drain_local_pages(NULL); | ||
| 100 | for_each_populated_zone(zone) { | ||
| 101 | spin_lock_irqsave(&zone->lock, flags); | ||
| 102 | for_each_migratetype_order(order, t) { | ||
| 103 | list_for_each(l, &zone->free_area[order].free_list[t]) { | ||
| 104 | page = list_entry(l, struct page, lru); | ||
| 105 | if (make_stable) | ||
| 106 | set_page_stable(page, order); | ||
| 107 | else | ||
| 108 | set_page_unstable(page, order); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | spin_unlock_irqrestore(&zone->lock, flags); | ||
| 112 | } | ||
| 113 | } | ||
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index c70215247071..c60bfb309ce6 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
| @@ -314,21 +314,18 @@ int s390_enable_sie(void) | |||
| 314 | } | 314 | } |
| 315 | EXPORT_SYMBOL_GPL(s390_enable_sie); | 315 | EXPORT_SYMBOL_GPL(s390_enable_sie); |
| 316 | 316 | ||
| 317 | #ifdef CONFIG_DEBUG_PAGEALLOC | 317 | #if defined(CONFIG_DEBUG_PAGEALLOC) && defined(CONFIG_HIBERNATION) |
| 318 | #ifdef CONFIG_HIBERNATION | ||
| 319 | bool kernel_page_present(struct page *page) | 318 | bool kernel_page_present(struct page *page) |
| 320 | { | 319 | { |
| 321 | unsigned long addr; | 320 | unsigned long addr; |
| 322 | int cc; | 321 | int cc; |
| 323 | 322 | ||
| 324 | addr = page_to_phys(page); | 323 | addr = page_to_phys(page); |
| 325 | asm("lra %1,0(%1)\n" | 324 | asm volatile( |
| 326 | "ipm %0\n" | 325 | " lra %1,0(%1)\n" |
| 327 | "srl %0,28" | 326 | " ipm %0\n" |
| 328 | :"=d"(cc),"+a"(addr)::"cc"); | 327 | " srl %0,28" |
| 328 | : "=d" (cc), "+a" (addr) : : "cc"); | ||
| 329 | return cc == 0; | 329 | return cc == 0; |
| 330 | } | 330 | } |
| 331 | 331 | #endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */ | |
| 332 | #endif /* CONFIG_HIBERNATION */ | ||
| 333 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||
| 334 | |||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bd9fe2e36dce..ab3521755588 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -935,6 +935,7 @@ static int dasd_eckd_read_features(struct dasd_device *device) | |||
| 935 | struct dasd_eckd_private *private; | 935 | struct dasd_eckd_private *private; |
| 936 | 936 | ||
| 937 | private = (struct dasd_eckd_private *) device->private; | 937 | private = (struct dasd_eckd_private *) device->private; |
| 938 | memset(&private->features, 0, sizeof(struct dasd_rssd_features)); | ||
| 938 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, | 939 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, |
| 939 | (sizeof(struct dasd_psf_prssd_data) + | 940 | (sizeof(struct dasd_psf_prssd_data) + |
| 940 | sizeof(struct dasd_rssd_features)), | 941 | sizeof(struct dasd_rssd_features)), |
| @@ -982,7 +983,9 @@ static int dasd_eckd_read_features(struct dasd_device *device) | |||
| 982 | features = (struct dasd_rssd_features *) (prssdp + 1); | 983 | features = (struct dasd_rssd_features *) (prssdp + 1); |
| 983 | memcpy(&private->features, features, | 984 | memcpy(&private->features, features, |
| 984 | sizeof(struct dasd_rssd_features)); | 985 | sizeof(struct dasd_rssd_features)); |
| 985 | } | 986 | } else |
| 987 | dev_warn(&device->cdev->dev, "Reading device feature codes" | ||
| 988 | " failed with rc=%d\n", rc); | ||
| 986 | dasd_sfree_request(cqr, cqr->memdev); | 989 | dasd_sfree_request(cqr, cqr->memdev); |
| 987 | return rc; | 990 | return rc; |
| 988 | } | 991 | } |
| @@ -1144,9 +1147,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1144 | } | 1147 | } |
| 1145 | 1148 | ||
| 1146 | /* Read Feature Codes */ | 1149 | /* Read Feature Codes */ |
| 1147 | rc = dasd_eckd_read_features(device); | 1150 | dasd_eckd_read_features(device); |
| 1148 | if (rc) | ||
| 1149 | goto out_err3; | ||
| 1150 | 1151 | ||
| 1151 | /* Read Device Characteristics */ | 1152 | /* Read Device Characteristics */ |
| 1152 | rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, | 1153 | rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, |
| @@ -3241,9 +3242,7 @@ int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 3241 | } | 3242 | } |
| 3242 | 3243 | ||
| 3243 | /* Read Feature Codes */ | 3244 | /* Read Feature Codes */ |
| 3244 | rc = dasd_eckd_read_features(device); | 3245 | dasd_eckd_read_features(device); |
| 3245 | if (rc) | ||
| 3246 | goto out_err; | ||
| 3247 | 3246 | ||
| 3248 | /* Read Device Characteristics */ | 3247 | /* Read Device Characteristics */ |
| 3249 | memset(&private->rdc_data, 0, sizeof(private->rdc_data)); | 3248 | memset(&private->rdc_data, 0, sizeof(private->rdc_data)); |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 393c73c47f87..91c25706fa83 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -31,8 +31,7 @@ | |||
| 31 | #include "chp.h" | 31 | #include "chp.h" |
| 32 | 32 | ||
| 33 | int css_init_done = 0; | 33 | int css_init_done = 0; |
| 34 | static int need_reprobe = 0; | 34 | int max_ssid; |
| 35 | static int max_ssid = 0; | ||
| 36 | 35 | ||
| 37 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; | 36 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; |
| 38 | 37 | ||
| @@ -315,12 +314,18 @@ int css_probe_device(struct subchannel_id schid) | |||
| 315 | int ret; | 314 | int ret; |
| 316 | struct subchannel *sch; | 315 | struct subchannel *sch; |
| 317 | 316 | ||
| 318 | sch = css_alloc_subchannel(schid); | 317 | if (cio_is_console(schid)) |
| 319 | if (IS_ERR(sch)) | 318 | sch = cio_get_console_subchannel(); |
| 320 | return PTR_ERR(sch); | 319 | else { |
| 320 | sch = css_alloc_subchannel(schid); | ||
| 321 | if (IS_ERR(sch)) | ||
| 322 | return PTR_ERR(sch); | ||
| 323 | } | ||
| 321 | ret = css_register_subchannel(sch); | 324 | ret = css_register_subchannel(sch); |
| 322 | if (ret) | 325 | if (ret) { |
| 323 | put_device(&sch->dev); | 326 | if (!cio_is_console(schid)) |
| 327 | put_device(&sch->dev); | ||
| 328 | } | ||
| 324 | return ret; | 329 | return ret; |
| 325 | } | 330 | } |
| 326 | 331 | ||
| @@ -409,10 +414,14 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) | |||
| 409 | 414 | ||
| 410 | static struct idset *slow_subchannel_set; | 415 | static struct idset *slow_subchannel_set; |
| 411 | static spinlock_t slow_subchannel_lock; | 416 | static spinlock_t slow_subchannel_lock; |
| 417 | static wait_queue_head_t css_eval_wq; | ||
| 418 | static atomic_t css_eval_scheduled; | ||
| 412 | 419 | ||
| 413 | static int __init slow_subchannel_init(void) | 420 | static int __init slow_subchannel_init(void) |
| 414 | { | 421 | { |
| 415 | spin_lock_init(&slow_subchannel_lock); | 422 | spin_lock_init(&slow_subchannel_lock); |
| 423 | atomic_set(&css_eval_scheduled, 0); | ||
| 424 | init_waitqueue_head(&css_eval_wq); | ||
| 416 | slow_subchannel_set = idset_sch_new(); | 425 | slow_subchannel_set = idset_sch_new(); |
| 417 | if (!slow_subchannel_set) { | 426 | if (!slow_subchannel_set) { |
| 418 | CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); | 427 | CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); |
| @@ -468,9 +477,17 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) | |||
| 468 | 477 | ||
| 469 | static void css_slow_path_func(struct work_struct *unused) | 478 | static void css_slow_path_func(struct work_struct *unused) |
| 470 | { | 479 | { |
| 480 | unsigned long flags; | ||
| 481 | |||
| 471 | CIO_TRACE_EVENT(4, "slowpath"); | 482 | CIO_TRACE_EVENT(4, "slowpath"); |
| 472 | for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, | 483 | for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, |
| 473 | NULL); | 484 | NULL); |
| 485 | spin_lock_irqsave(&slow_subchannel_lock, flags); | ||
| 486 | if (idset_is_empty(slow_subchannel_set)) { | ||
| 487 | atomic_set(&css_eval_scheduled, 0); | ||
| 488 | wake_up(&css_eval_wq); | ||
| 489 | } | ||
| 490 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | ||
| 474 | } | 491 | } |
| 475 | 492 | ||
| 476 | static DECLARE_WORK(slow_path_work, css_slow_path_func); | 493 | static DECLARE_WORK(slow_path_work, css_slow_path_func); |
| @@ -482,6 +499,7 @@ void css_schedule_eval(struct subchannel_id schid) | |||
| 482 | 499 | ||
| 483 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 500 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
| 484 | idset_sch_add(slow_subchannel_set, schid); | 501 | idset_sch_add(slow_subchannel_set, schid); |
| 502 | atomic_set(&css_eval_scheduled, 1); | ||
| 485 | queue_work(slow_path_wq, &slow_path_work); | 503 | queue_work(slow_path_wq, &slow_path_work); |
| 486 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 504 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
| 487 | } | 505 | } |
| @@ -492,80 +510,53 @@ void css_schedule_eval_all(void) | |||
| 492 | 510 | ||
| 493 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 511 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
| 494 | idset_fill(slow_subchannel_set); | 512 | idset_fill(slow_subchannel_set); |
| 513 | atomic_set(&css_eval_scheduled, 1); | ||
| 495 | queue_work(slow_path_wq, &slow_path_work); | 514 | queue_work(slow_path_wq, &slow_path_work); |
| 496 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 515 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
| 497 | } | 516 | } |
| 498 | 517 | ||
| 499 | void css_wait_for_slow_path(void) | 518 | static int __unset_registered(struct device *dev, void *data) |
| 500 | { | 519 | { |
| 501 | flush_workqueue(slow_path_wq); | 520 | struct idset *set = data; |
| 502 | } | 521 | struct subchannel *sch = to_subchannel(dev); |
| 503 | |||
| 504 | /* Reprobe subchannel if unregistered. */ | ||
| 505 | static int reprobe_subchannel(struct subchannel_id schid, void *data) | ||
| 506 | { | ||
| 507 | int ret; | ||
| 508 | |||
| 509 | CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n", | ||
| 510 | schid.ssid, schid.sch_no); | ||
| 511 | if (need_reprobe) | ||
| 512 | return -EAGAIN; | ||
| 513 | |||
| 514 | ret = css_probe_device(schid); | ||
| 515 | switch (ret) { | ||
| 516 | case 0: | ||
| 517 | break; | ||
| 518 | case -ENXIO: | ||
| 519 | case -ENOMEM: | ||
| 520 | case -EIO: | ||
| 521 | /* These should abort looping */ | ||
| 522 | break; | ||
| 523 | default: | ||
| 524 | ret = 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | 522 | ||
| 530 | static void reprobe_after_idle(struct work_struct *unused) | 523 | idset_sch_del(set, sch->schid); |
| 531 | { | 524 | return 0; |
| 532 | /* Make sure initial subchannel scan is done. */ | ||
| 533 | wait_event(ccw_device_init_wq, | ||
| 534 | atomic_read(&ccw_device_init_count) == 0); | ||
| 535 | if (need_reprobe) | ||
| 536 | css_schedule_reprobe(); | ||
| 537 | } | 525 | } |
| 538 | 526 | ||
| 539 | static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle); | 527 | void css_schedule_eval_all_unreg(void) |
| 540 | |||
| 541 | /* Work function used to reprobe all unregistered subchannels. */ | ||
| 542 | static void reprobe_all(struct work_struct *unused) | ||
| 543 | { | 528 | { |
| 544 | int ret; | 529 | unsigned long flags; |
| 545 | 530 | struct idset *unreg_set; | |
| 546 | CIO_MSG_EVENT(4, "reprobe start\n"); | ||
| 547 | 531 | ||
| 548 | /* Make sure initial subchannel scan is done. */ | 532 | /* Find unregistered subchannels. */ |
| 549 | if (atomic_read(&ccw_device_init_count) != 0) { | 533 | unreg_set = idset_sch_new(); |
| 550 | queue_work(ccw_device_work, &reprobe_idle_work); | 534 | if (!unreg_set) { |
| 535 | /* Fallback. */ | ||
| 536 | css_schedule_eval_all(); | ||
| 551 | return; | 537 | return; |
| 552 | } | 538 | } |
| 553 | need_reprobe = 0; | 539 | idset_fill(unreg_set); |
| 554 | ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); | 540 | bus_for_each_dev(&css_bus_type, NULL, unreg_set, __unset_registered); |
| 555 | 541 | /* Apply to slow_subchannel_set. */ | |
| 556 | CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, | 542 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
| 557 | need_reprobe); | 543 | idset_add_set(slow_subchannel_set, unreg_set); |
| 544 | atomic_set(&css_eval_scheduled, 1); | ||
| 545 | queue_work(slow_path_wq, &slow_path_work); | ||
| 546 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | ||
| 547 | idset_free(unreg_set); | ||
| 558 | } | 548 | } |
| 559 | 549 | ||
| 560 | static DECLARE_WORK(css_reprobe_work, reprobe_all); | 550 | void css_wait_for_slow_path(void) |
| 551 | { | ||
| 552 | flush_workqueue(slow_path_wq); | ||
| 553 | } | ||
| 561 | 554 | ||
| 562 | /* Schedule reprobing of all unregistered subchannels. */ | 555 | /* Schedule reprobing of all unregistered subchannels. */ |
| 563 | void css_schedule_reprobe(void) | 556 | void css_schedule_reprobe(void) |
| 564 | { | 557 | { |
| 565 | need_reprobe = 1; | 558 | css_schedule_eval_all_unreg(); |
| 566 | queue_work(slow_path_wq, &css_reprobe_work); | ||
| 567 | } | 559 | } |
| 568 | |||
| 569 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | 560 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); |
| 570 | 561 | ||
| 571 | /* | 562 | /* |
| @@ -601,49 +592,6 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
| 601 | css_evaluate_subchannel(mchk_schid, 0); | 592 | css_evaluate_subchannel(mchk_schid, 0); |
| 602 | } | 593 | } |
| 603 | 594 | ||
| 604 | static int __init | ||
| 605 | __init_channel_subsystem(struct subchannel_id schid, void *data) | ||
| 606 | { | ||
| 607 | struct subchannel *sch; | ||
| 608 | int ret; | ||
| 609 | |||
| 610 | if (cio_is_console(schid)) | ||
| 611 | sch = cio_get_console_subchannel(); | ||
| 612 | else { | ||
| 613 | sch = css_alloc_subchannel(schid); | ||
| 614 | if (IS_ERR(sch)) | ||
| 615 | ret = PTR_ERR(sch); | ||
| 616 | else | ||
| 617 | ret = 0; | ||
| 618 | switch (ret) { | ||
| 619 | case 0: | ||
| 620 | break; | ||
| 621 | case -ENOMEM: | ||
| 622 | panic("Out of memory in init_channel_subsystem\n"); | ||
| 623 | /* -ENXIO: no more subchannels. */ | ||
| 624 | case -ENXIO: | ||
| 625 | return ret; | ||
| 626 | /* -EIO: this subchannel set not supported. */ | ||
| 627 | case -EIO: | ||
| 628 | return ret; | ||
| 629 | default: | ||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | } | ||
| 633 | /* | ||
| 634 | * We register ALL valid subchannels in ioinfo, even those | ||
| 635 | * that have been present before init_channel_subsystem. | ||
| 636 | * These subchannels can't have been registered yet (kmalloc | ||
| 637 | * not working) so we do it now. This is true e.g. for the | ||
| 638 | * console subchannel. | ||
| 639 | */ | ||
| 640 | if (css_register_subchannel(sch)) { | ||
| 641 | if (!cio_is_console(schid)) | ||
| 642 | put_device(&sch->dev); | ||
| 643 | } | ||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | |||
| 647 | static void __init | 595 | static void __init |
| 648 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | 596 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) |
| 649 | { | 597 | { |
| @@ -854,19 +802,30 @@ static struct notifier_block css_power_notifier = { | |||
| 854 | * The struct subchannel's are created during probing (except for the | 802 | * The struct subchannel's are created during probing (except for the |
| 855 | * static console subchannel). | 803 | * static console subchannel). |
| 856 | */ | 804 | */ |
| 857 | static int __init | 805 | static int __init css_bus_init(void) |
| 858 | init_channel_subsystem (void) | ||
| 859 | { | 806 | { |
| 860 | int ret, i; | 807 | int ret, i; |
| 861 | 808 | ||
| 862 | ret = chsc_determine_css_characteristics(); | 809 | ret = chsc_determine_css_characteristics(); |
| 863 | if (ret == -ENOMEM) | 810 | if (ret == -ENOMEM) |
| 864 | goto out; /* No need to continue. */ | 811 | goto out; |
| 865 | 812 | ||
| 866 | ret = chsc_alloc_sei_area(); | 813 | ret = chsc_alloc_sei_area(); |
| 867 | if (ret) | 814 | if (ret) |
| 868 | goto out; | 815 | goto out; |
| 869 | 816 | ||
| 817 | /* Try to enable MSS. */ | ||
| 818 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); | ||
| 819 | switch (ret) { | ||
| 820 | case 0: /* Success. */ | ||
| 821 | max_ssid = __MAX_SSID; | ||
| 822 | break; | ||
| 823 | case -ENOMEM: | ||
| 824 | goto out; | ||
| 825 | default: | ||
| 826 | max_ssid = 0; | ||
| 827 | } | ||
| 828 | |||
| 870 | ret = slow_subchannel_init(); | 829 | ret = slow_subchannel_init(); |
| 871 | if (ret) | 830 | if (ret) |
| 872 | goto out; | 831 | goto out; |
| @@ -878,17 +837,6 @@ init_channel_subsystem (void) | |||
| 878 | if ((ret = bus_register(&css_bus_type))) | 837 | if ((ret = bus_register(&css_bus_type))) |
| 879 | goto out; | 838 | goto out; |
| 880 | 839 | ||
| 881 | /* Try to enable MSS. */ | ||
| 882 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); | ||
| 883 | switch (ret) { | ||
| 884 | case 0: /* Success. */ | ||
| 885 | max_ssid = __MAX_SSID; | ||
| 886 | break; | ||
| 887 | case -ENOMEM: | ||
| 888 | goto out_bus; | ||
| 889 | default: | ||
| 890 | max_ssid = 0; | ||
| 891 | } | ||
| 892 | /* Setup css structure. */ | 840 | /* Setup css structure. */ |
| 893 | for (i = 0; i <= __MAX_CSSID; i++) { | 841 | for (i = 0; i <= __MAX_CSSID; i++) { |
| 894 | struct channel_subsystem *css; | 842 | struct channel_subsystem *css; |
| @@ -934,7 +882,6 @@ init_channel_subsystem (void) | |||
| 934 | /* Enable default isc for I/O subchannels. */ | 882 | /* Enable default isc for I/O subchannels. */ |
| 935 | isc_register(IO_SCH_ISC); | 883 | isc_register(IO_SCH_ISC); |
| 936 | 884 | ||
| 937 | for_each_subchannel(__init_channel_subsystem, NULL); | ||
| 938 | return 0; | 885 | return 0; |
| 939 | out_file: | 886 | out_file: |
| 940 | if (css_chsc_characteristics.secm) | 887 | if (css_chsc_characteristics.secm) |
| @@ -955,17 +902,76 @@ out_unregister: | |||
| 955 | &dev_attr_cm_enable); | 902 | &dev_attr_cm_enable); |
| 956 | device_unregister(&css->device); | 903 | device_unregister(&css->device); |
| 957 | } | 904 | } |
| 958 | out_bus: | ||
| 959 | bus_unregister(&css_bus_type); | 905 | bus_unregister(&css_bus_type); |
| 960 | out: | 906 | out: |
| 961 | crw_unregister_handler(CRW_RSC_CSS); | 907 | crw_unregister_handler(CRW_RSC_CSS); |
| 962 | chsc_free_sei_area(); | 908 | chsc_free_sei_area(); |
| 963 | kfree(slow_subchannel_set); | 909 | idset_free(slow_subchannel_set); |
| 964 | pr_alert("The CSS device driver initialization failed with " | 910 | pr_alert("The CSS device driver initialization failed with " |
| 965 | "errno=%d\n", ret); | 911 | "errno=%d\n", ret); |
| 966 | return ret; | 912 | return ret; |
| 967 | } | 913 | } |
| 968 | 914 | ||
| 915 | static void __init css_bus_cleanup(void) | ||
| 916 | { | ||
| 917 | struct channel_subsystem *css; | ||
| 918 | int i; | ||
| 919 | |||
| 920 | for (i = 0; i <= __MAX_CSSID; i++) { | ||
| 921 | css = channel_subsystems[i]; | ||
| 922 | device_unregister(&css->pseudo_subchannel->dev); | ||
| 923 | css->pseudo_subchannel = NULL; | ||
| 924 | if (css_chsc_characteristics.secm) | ||
| 925 | device_remove_file(&css->device, &dev_attr_cm_enable); | ||
| 926 | device_unregister(&css->device); | ||
| 927 | } | ||
| 928 | bus_unregister(&css_bus_type); | ||
| 929 | crw_unregister_handler(CRW_RSC_CSS); | ||
| 930 | chsc_free_sei_area(); | ||
| 931 | idset_free(slow_subchannel_set); | ||
| 932 | isc_unregister(IO_SCH_ISC); | ||
| 933 | } | ||
| 934 | |||
| 935 | static int __init channel_subsystem_init(void) | ||
| 936 | { | ||
| 937 | int ret; | ||
| 938 | |||
| 939 | ret = css_bus_init(); | ||
| 940 | if (ret) | ||
| 941 | return ret; | ||
| 942 | |||
| 943 | ret = io_subchannel_init(); | ||
| 944 | if (ret) | ||
| 945 | css_bus_cleanup(); | ||
| 946 | |||
| 947 | return ret; | ||
| 948 | } | ||
| 949 | subsys_initcall(channel_subsystem_init); | ||
| 950 | |||
| 951 | static int css_settle(struct device_driver *drv, void *unused) | ||
| 952 | { | ||
| 953 | struct css_driver *cssdrv = to_cssdriver(drv); | ||
| 954 | |||
| 955 | if (cssdrv->settle) | ||
| 956 | cssdrv->settle(); | ||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | |||
| 960 | /* | ||
| 961 | * Wait for the initialization of devices to finish, to make sure we are | ||
| 962 | * done with our setup if the search for the root device starts. | ||
| 963 | */ | ||
| 964 | static int __init channel_subsystem_init_sync(void) | ||
| 965 | { | ||
| 966 | /* Start initial subchannel evaluation. */ | ||
| 967 | css_schedule_eval_all(); | ||
| 968 | /* Wait for the evaluation of subchannels to finish. */ | ||
| 969 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); | ||
| 970 | /* Wait for the subchannel type specific initialization to finish */ | ||
| 971 | return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); | ||
| 972 | } | ||
| 973 | subsys_initcall_sync(channel_subsystem_init_sync); | ||
| 974 | |||
| 969 | int sch_is_pseudo_sch(struct subchannel *sch) | 975 | int sch_is_pseudo_sch(struct subchannel *sch) |
| 970 | { | 976 | { |
| 971 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; | 977 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; |
| @@ -1135,7 +1141,5 @@ void css_driver_unregister(struct css_driver *cdrv) | |||
| 1135 | } | 1141 | } |
| 1136 | EXPORT_SYMBOL_GPL(css_driver_unregister); | 1142 | EXPORT_SYMBOL_GPL(css_driver_unregister); |
| 1137 | 1143 | ||
| 1138 | subsys_initcall(init_channel_subsystem); | ||
| 1139 | |||
| 1140 | MODULE_LICENSE("GPL"); | 1144 | MODULE_LICENSE("GPL"); |
| 1141 | EXPORT_SYMBOL(css_bus_type); | 1145 | EXPORT_SYMBOL(css_bus_type); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 9763eeec7458..68d6b0bf151c 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
| @@ -75,6 +75,7 @@ struct chp_link; | |||
| 75 | * @freeze: callback for freezing during hibernation snapshotting | 75 | * @freeze: callback for freezing during hibernation snapshotting |
| 76 | * @thaw: undo work done in @freeze | 76 | * @thaw: undo work done in @freeze |
| 77 | * @restore: callback for restoring after hibernation | 77 | * @restore: callback for restoring after hibernation |
| 78 | * @settle: wait for asynchronous work to finish | ||
| 78 | * @name: name of the device driver | 79 | * @name: name of the device driver |
| 79 | */ | 80 | */ |
| 80 | struct css_driver { | 81 | struct css_driver { |
| @@ -92,6 +93,7 @@ struct css_driver { | |||
| 92 | int (*freeze)(struct subchannel *); | 93 | int (*freeze)(struct subchannel *); |
| 93 | int (*thaw) (struct subchannel *); | 94 | int (*thaw) (struct subchannel *); |
| 94 | int (*restore)(struct subchannel *); | 95 | int (*restore)(struct subchannel *); |
| 96 | void (*settle)(void); | ||
| 95 | const char *name; | 97 | const char *name; |
| 96 | }; | 98 | }; |
| 97 | 99 | ||
| @@ -109,6 +111,7 @@ extern void css_sch_device_unregister(struct subchannel *); | |||
| 109 | extern int css_probe_device(struct subchannel_id); | 111 | extern int css_probe_device(struct subchannel_id); |
| 110 | extern struct subchannel *get_subchannel_by_schid(struct subchannel_id); | 112 | extern struct subchannel *get_subchannel_by_schid(struct subchannel_id); |
| 111 | extern int css_init_done; | 113 | extern int css_init_done; |
| 114 | extern int max_ssid; | ||
| 112 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | 115 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), |
| 113 | int (*fn_unknown)(struct subchannel_id, | 116 | int (*fn_unknown)(struct subchannel_id, |
| 114 | void *), void *data); | 117 | void *), void *data); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6527f3f34493..f780bdd3a04e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -131,6 +131,10 @@ static void io_subchannel_shutdown(struct subchannel *); | |||
| 131 | static int io_subchannel_sch_event(struct subchannel *, int); | 131 | static int io_subchannel_sch_event(struct subchannel *, int); |
| 132 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, | 132 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, |
| 133 | int); | 133 | int); |
| 134 | static void recovery_func(unsigned long data); | ||
| 135 | struct workqueue_struct *ccw_device_work; | ||
| 136 | wait_queue_head_t ccw_device_init_wq; | ||
| 137 | atomic_t ccw_device_init_count; | ||
| 134 | 138 | ||
| 135 | static struct css_device_id io_subchannel_ids[] = { | 139 | static struct css_device_id io_subchannel_ids[] = { |
| 136 | { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, | 140 | { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, |
| @@ -151,6 +155,13 @@ static int io_subchannel_prepare(struct subchannel *sch) | |||
| 151 | return 0; | 155 | return 0; |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 158 | static void io_subchannel_settle(void) | ||
| 159 | { | ||
| 160 | wait_event(ccw_device_init_wq, | ||
| 161 | atomic_read(&ccw_device_init_count) == 0); | ||
| 162 | flush_workqueue(ccw_device_work); | ||
| 163 | } | ||
| 164 | |||
| 154 | static struct css_driver io_subchannel_driver = { | 165 | static struct css_driver io_subchannel_driver = { |
| 155 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
| 156 | .subchannel_type = io_subchannel_ids, | 167 | .subchannel_type = io_subchannel_ids, |
| @@ -162,16 +173,10 @@ static struct css_driver io_subchannel_driver = { | |||
| 162 | .remove = io_subchannel_remove, | 173 | .remove = io_subchannel_remove, |
| 163 | .shutdown = io_subchannel_shutdown, | 174 | .shutdown = io_subchannel_shutdown, |
| 164 | .prepare = io_subchannel_prepare, | 175 | .prepare = io_subchannel_prepare, |
| 176 | .settle = io_subchannel_settle, | ||
| 165 | }; | 177 | }; |
| 166 | 178 | ||
| 167 | struct workqueue_struct *ccw_device_work; | 179 | int __init io_subchannel_init(void) |
| 168 | wait_queue_head_t ccw_device_init_wq; | ||
| 169 | atomic_t ccw_device_init_count; | ||
| 170 | |||
| 171 | static void recovery_func(unsigned long data); | ||
| 172 | |||
| 173 | static int __init | ||
| 174 | init_ccw_bus_type (void) | ||
| 175 | { | 180 | { |
| 176 | int ret; | 181 | int ret; |
| 177 | 182 | ||
| @@ -181,10 +186,10 @@ init_ccw_bus_type (void) | |||
| 181 | 186 | ||
| 182 | ccw_device_work = create_singlethread_workqueue("cio"); | 187 | ccw_device_work = create_singlethread_workqueue("cio"); |
| 183 | if (!ccw_device_work) | 188 | if (!ccw_device_work) |
| 184 | return -ENOMEM; /* FIXME: better errno ? */ | 189 | return -ENOMEM; |
| 185 | slow_path_wq = create_singlethread_workqueue("kslowcrw"); | 190 | slow_path_wq = create_singlethread_workqueue("kslowcrw"); |
| 186 | if (!slow_path_wq) { | 191 | if (!slow_path_wq) { |
| 187 | ret = -ENOMEM; /* FIXME: better errno ? */ | 192 | ret = -ENOMEM; |
| 188 | goto out_err; | 193 | goto out_err; |
| 189 | } | 194 | } |
| 190 | if ((ret = bus_register (&ccw_bus_type))) | 195 | if ((ret = bus_register (&ccw_bus_type))) |
| @@ -194,9 +199,6 @@ init_ccw_bus_type (void) | |||
| 194 | if (ret) | 199 | if (ret) |
| 195 | goto out_err; | 200 | goto out_err; |
| 196 | 201 | ||
| 197 | wait_event(ccw_device_init_wq, | ||
| 198 | atomic_read(&ccw_device_init_count) == 0); | ||
| 199 | flush_workqueue(ccw_device_work); | ||
| 200 | return 0; | 202 | return 0; |
| 201 | out_err: | 203 | out_err: |
| 202 | if (ccw_device_work) | 204 | if (ccw_device_work) |
| @@ -206,16 +208,6 @@ out_err: | |||
| 206 | return ret; | 208 | return ret; |
| 207 | } | 209 | } |
| 208 | 210 | ||
| 209 | static void __exit | ||
| 210 | cleanup_ccw_bus_type (void) | ||
| 211 | { | ||
| 212 | css_driver_unregister(&io_subchannel_driver); | ||
| 213 | bus_unregister(&ccw_bus_type); | ||
| 214 | destroy_workqueue(ccw_device_work); | ||
| 215 | } | ||
| 216 | |||
| 217 | subsys_initcall(init_ccw_bus_type); | ||
| 218 | module_exit(cleanup_ccw_bus_type); | ||
| 219 | 211 | ||
| 220 | /************************ device handling **************************/ | 212 | /************************ device handling **************************/ |
| 221 | 213 | ||
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index e3975107a578..ed39a2caaf47 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
| @@ -74,6 +74,7 @@ dev_fsm_final_state(struct ccw_device *cdev) | |||
| 74 | extern struct workqueue_struct *ccw_device_work; | 74 | extern struct workqueue_struct *ccw_device_work; |
| 75 | extern wait_queue_head_t ccw_device_init_wq; | 75 | extern wait_queue_head_t ccw_device_init_wq; |
| 76 | extern atomic_t ccw_device_init_count; | 76 | extern atomic_t ccw_device_init_count; |
| 77 | int __init io_subchannel_init(void); | ||
| 77 | 78 | ||
| 78 | void io_subchannel_recog_done(struct ccw_device *cdev); | 79 | void io_subchannel_recog_done(struct ccw_device *cdev); |
| 79 | void io_subchannel_init_config(struct subchannel *sch); | 80 | void io_subchannel_init_config(struct subchannel *sch); |
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index cf8f24a4b5eb..4d10981c7cc1 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c | |||
| @@ -78,7 +78,7 @@ static inline int idset_get_first(struct idset *set, int *ssid, int *id) | |||
| 78 | 78 | ||
| 79 | struct idset *idset_sch_new(void) | 79 | struct idset *idset_sch_new(void) |
| 80 | { | 80 | { |
| 81 | return idset_new(__MAX_SSID + 1, __MAX_SUBCHANNEL + 1); | 81 | return idset_new(max_ssid + 1, __MAX_SUBCHANNEL + 1); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | void idset_sch_add(struct idset *set, struct subchannel_id schid) | 84 | void idset_sch_add(struct idset *set, struct subchannel_id schid) |
| @@ -110,3 +110,23 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) | |||
| 110 | } | 110 | } |
| 111 | return rc; | 111 | return rc; |
| 112 | } | 112 | } |
| 113 | |||
| 114 | int idset_is_empty(struct idset *set) | ||
| 115 | { | ||
| 116 | int bitnum; | ||
| 117 | |||
| 118 | bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); | ||
| 119 | if (bitnum >= set->num_ssid * set->num_id) | ||
| 120 | return 1; | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | void idset_add_set(struct idset *to, struct idset *from) | ||
| 125 | { | ||
| 126 | unsigned long i, len; | ||
| 127 | |||
| 128 | len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), | ||
| 129 | __BITOPS_WORDS(from->num_ssid * from->num_id)); | ||
| 130 | for (i = 0; i < len ; i++) | ||
| 131 | to->bitmap[i] |= from->bitmap[i]; | ||
| 132 | } | ||
diff --git a/drivers/s390/cio/idset.h b/drivers/s390/cio/idset.h index 528065cb5021..7543da4529f9 100644 --- a/drivers/s390/cio/idset.h +++ b/drivers/s390/cio/idset.h | |||
| @@ -21,5 +21,7 @@ void idset_sch_add(struct idset *set, struct subchannel_id id); | |||
| 21 | void idset_sch_del(struct idset *set, struct subchannel_id id); | 21 | void idset_sch_del(struct idset *set, struct subchannel_id id); |
| 22 | int idset_sch_contains(struct idset *set, struct subchannel_id id); | 22 | int idset_sch_contains(struct idset *set, struct subchannel_id id); |
| 23 | int idset_sch_get_first(struct idset *set, struct subchannel_id *id); | 23 | int idset_sch_get_first(struct idset *set, struct subchannel_id *id); |
| 24 | int idset_is_empty(struct idset *set); | ||
| 25 | void idset_add_set(struct idset *to, struct idset *from); | ||
| 24 | 26 | ||
| 25 | #endif /* S390_IDSET_H */ | 27 | #endif /* S390_IDSET_H */ |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 9aef402a5f1b..4be6e84b9599 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -401,7 +401,7 @@ static void announce_buffer_error(struct qdio_q *q, int count) | |||
| 401 | if ((!q->is_input_q && | 401 | if ((!q->is_input_q && |
| 402 | (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { | 402 | (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { |
| 403 | qdio_perf_stat_inc(&perf_stats.outbound_target_full); | 403 | qdio_perf_stat_inc(&perf_stats.outbound_target_full); |
| 404 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%3d", | 404 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", |
| 405 | q->first_to_check); | 405 | q->first_to_check); |
| 406 | return; | 406 | return; |
| 407 | } | 407 | } |
| @@ -418,7 +418,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
| 418 | { | 418 | { |
| 419 | int new; | 419 | int new; |
| 420 | 420 | ||
| 421 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %3d", count); | 421 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %02x", count); |
| 422 | 422 | ||
| 423 | /* for QEBSM the ACK was already set by EQBS */ | 423 | /* for QEBSM the ACK was already set by EQBS */ |
| 424 | if (is_qebsm(q)) { | 424 | if (is_qebsm(q)) { |
| @@ -455,6 +455,8 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
| 455 | count--; | 455 | count--; |
| 456 | if (!count) | 456 | if (!count) |
| 457 | return; | 457 | return; |
| 458 | /* need to change ALL buffers to get more interrupts */ | ||
| 459 | set_buf_states(q, q->first_to_check, SLSB_P_INPUT_NOT_INIT, count); | ||
| 458 | } | 460 | } |
| 459 | 461 | ||
| 460 | static int get_inbound_buffer_frontier(struct qdio_q *q) | 462 | static int get_inbound_buffer_frontier(struct qdio_q *q) |
| @@ -545,7 +547,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
| 545 | * has (probably) not moved (see qdio_inbound_processing). | 547 | * has (probably) not moved (see qdio_inbound_processing). |
| 546 | */ | 548 | */ |
| 547 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 549 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
| 548 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%3d", | 550 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", |
| 549 | q->first_to_check); | 551 | q->first_to_check); |
| 550 | return 1; | 552 | return 1; |
| 551 | } else | 553 | } else |
| @@ -565,11 +567,10 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
| 565 | 567 | ||
| 566 | if (q->is_input_q) { | 568 | if (q->is_input_q) { |
| 567 | qdio_perf_stat_inc(&perf_stats.inbound_handler); | 569 | qdio_perf_stat_inc(&perf_stats.inbound_handler); |
| 568 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); | 570 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); |
| 569 | } else { | 571 | } else |
| 570 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: nr:%1d", q->nr); | 572 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", |
| 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); | 573 | start, count); |
| 572 | } | ||
| 573 | 574 | ||
| 574 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, | 575 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, |
| 575 | q->irq_ptr->int_parm); | 576 | q->irq_ptr->int_parm); |
| @@ -633,7 +634,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
| 633 | switch (state) { | 634 | switch (state) { |
| 634 | case SLSB_P_OUTPUT_EMPTY: | 635 | case SLSB_P_OUTPUT_EMPTY: |
| 635 | /* the adapter got it */ | 636 | /* the adapter got it */ |
| 636 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %3d", q->nr, count); | 637 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %02x", q->nr, count); |
| 637 | 638 | ||
| 638 | atomic_sub(count, &q->nr_buf_used); | 639 | atomic_sub(count, &q->nr_buf_used); |
| 639 | q->first_to_check = add_buf(q->first_to_check, count); | 640 | q->first_to_check = add_buf(q->first_to_check, count); |
| @@ -1481,10 +1482,9 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
| 1481 | get_buf_state(q, prev_buf(bufnr), &state, 0); | 1482 | get_buf_state(q, prev_buf(bufnr), &state, 0); |
| 1482 | if (state != SLSB_CU_OUTPUT_PRIMED) | 1483 | if (state != SLSB_CU_OUTPUT_PRIMED) |
| 1483 | rc = qdio_kick_outbound_q(q); | 1484 | rc = qdio_kick_outbound_q(q); |
| 1484 | else { | 1485 | else |
| 1485 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); | ||
| 1486 | qdio_perf_stat_inc(&perf_stats.fast_requeue); | 1486 | qdio_perf_stat_inc(&perf_stats.fast_requeue); |
| 1487 | } | 1487 | |
| 1488 | out: | 1488 | out: |
| 1489 | tasklet_schedule(&q->tasklet); | 1489 | tasklet_schedule(&q->tasklet); |
| 1490 | return rc; | 1490 | return rc; |
| @@ -1510,12 +1510,8 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
| 1510 | if (!irq_ptr) | 1510 | if (!irq_ptr) |
| 1511 | return -ENODEV; | 1511 | return -ENODEV; |
| 1512 | 1512 | ||
| 1513 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1513 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, |
| 1514 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO input"); | 1514 | "do%02x b:%02x c:%02x", callflags, bufnr, count); |
| 1515 | else | ||
| 1516 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO output"); | ||
| 1517 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "q:%1d flag:%4x", q_nr, callflags); | ||
| 1518 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "buf:%2d cnt:%3d", bufnr, count); | ||
| 1519 | 1515 | ||
| 1520 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) | 1516 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) |
| 1521 | return -EBUSY; | 1517 | return -EBUSY; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 090b32a339c6..1294876bf7b4 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -60,6 +60,7 @@ static int ap_device_probe(struct device *dev); | |||
| 60 | static void ap_interrupt_handler(void *unused1, void *unused2); | 60 | static void ap_interrupt_handler(void *unused1, void *unused2); |
| 61 | static void ap_reset(struct ap_device *ap_dev); | 61 | static void ap_reset(struct ap_device *ap_dev); |
| 62 | static void ap_config_timeout(unsigned long ptr); | 62 | static void ap_config_timeout(unsigned long ptr); |
| 63 | static int ap_select_domain(void); | ||
| 63 | 64 | ||
| 64 | /* | 65 | /* |
| 65 | * Module description. | 66 | * Module description. |
| @@ -109,6 +110,10 @@ static unsigned long long poll_timeout = 250000; | |||
| 109 | 110 | ||
| 110 | /* Suspend flag */ | 111 | /* Suspend flag */ |
| 111 | static int ap_suspend_flag; | 112 | static int ap_suspend_flag; |
| 113 | /* Flag to check if domain was set through module parameter domain=. This is | ||
| 114 | * important when supsend and resume is done in a z/VM environment where the | ||
| 115 | * domain might change. */ | ||
| 116 | static int user_set_domain = 0; | ||
| 112 | static struct bus_type ap_bus_type; | 117 | static struct bus_type ap_bus_type; |
| 113 | 118 | ||
| 114 | /** | 119 | /** |
| @@ -643,6 +648,7 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state) | |||
| 643 | destroy_workqueue(ap_work_queue); | 648 | destroy_workqueue(ap_work_queue); |
| 644 | ap_work_queue = NULL; | 649 | ap_work_queue = NULL; |
| 645 | } | 650 | } |
| 651 | |||
| 646 | tasklet_disable(&ap_tasklet); | 652 | tasklet_disable(&ap_tasklet); |
| 647 | } | 653 | } |
| 648 | /* Poll on the device until all requests are finished. */ | 654 | /* Poll on the device until all requests are finished. */ |
| @@ -653,7 +659,10 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state) | |||
| 653 | spin_unlock_bh(&ap_dev->lock); | 659 | spin_unlock_bh(&ap_dev->lock); |
| 654 | } while ((flags & 1) || (flags & 2)); | 660 | } while ((flags & 1) || (flags & 2)); |
| 655 | 661 | ||
| 656 | ap_device_remove(dev); | 662 | spin_lock_bh(&ap_dev->lock); |
| 663 | ap_dev->unregistered = 1; | ||
| 664 | spin_unlock_bh(&ap_dev->lock); | ||
| 665 | |||
| 657 | return 0; | 666 | return 0; |
| 658 | } | 667 | } |
| 659 | 668 | ||
| @@ -666,11 +675,10 @@ static int ap_bus_resume(struct device *dev) | |||
| 666 | ap_suspend_flag = 0; | 675 | ap_suspend_flag = 0; |
| 667 | if (!ap_interrupts_available()) | 676 | if (!ap_interrupts_available()) |
| 668 | ap_interrupt_indicator = NULL; | 677 | ap_interrupt_indicator = NULL; |
| 669 | ap_device_probe(dev); | 678 | if (!user_set_domain) { |
| 670 | ap_reset(ap_dev); | 679 | ap_domain_index = -1; |
| 671 | setup_timer(&ap_dev->timeout, ap_request_timeout, | 680 | ap_select_domain(); |
| 672 | (unsigned long) ap_dev); | 681 | } |
| 673 | ap_scan_bus(NULL); | ||
| 674 | init_timer(&ap_config_timer); | 682 | init_timer(&ap_config_timer); |
| 675 | ap_config_timer.function = ap_config_timeout; | 683 | ap_config_timer.function = ap_config_timeout; |
| 676 | ap_config_timer.data = 0; | 684 | ap_config_timer.data = 0; |
| @@ -686,12 +694,14 @@ static int ap_bus_resume(struct device *dev) | |||
| 686 | tasklet_schedule(&ap_tasklet); | 694 | tasklet_schedule(&ap_tasklet); |
| 687 | if (ap_thread_flag) | 695 | if (ap_thread_flag) |
| 688 | rc = ap_poll_thread_start(); | 696 | rc = ap_poll_thread_start(); |
| 689 | } else { | ||
| 690 | ap_device_probe(dev); | ||
| 691 | ap_reset(ap_dev); | ||
| 692 | setup_timer(&ap_dev->timeout, ap_request_timeout, | ||
| 693 | (unsigned long) ap_dev); | ||
| 694 | } | 697 | } |
| 698 | if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) { | ||
| 699 | spin_lock_bh(&ap_dev->lock); | ||
| 700 | ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid), | ||
| 701 | ap_domain_index); | ||
| 702 | spin_unlock_bh(&ap_dev->lock); | ||
| 703 | } | ||
| 704 | queue_work(ap_work_queue, &ap_config_work); | ||
| 695 | 705 | ||
| 696 | return rc; | 706 | return rc; |
| 697 | } | 707 | } |
| @@ -1079,6 +1089,8 @@ static void ap_scan_bus(struct work_struct *unused) | |||
| 1079 | spin_lock_bh(&ap_dev->lock); | 1089 | spin_lock_bh(&ap_dev->lock); |
| 1080 | if (rc || ap_dev->unregistered) { | 1090 | if (rc || ap_dev->unregistered) { |
| 1081 | spin_unlock_bh(&ap_dev->lock); | 1091 | spin_unlock_bh(&ap_dev->lock); |
| 1092 | if (ap_dev->unregistered) | ||
| 1093 | i--; | ||
| 1082 | device_unregister(dev); | 1094 | device_unregister(dev); |
| 1083 | put_device(dev); | 1095 | put_device(dev); |
| 1084 | continue; | 1096 | continue; |
| @@ -1586,6 +1598,12 @@ int __init ap_module_init(void) | |||
| 1586 | ap_domain_index); | 1598 | ap_domain_index); |
| 1587 | return -EINVAL; | 1599 | return -EINVAL; |
| 1588 | } | 1600 | } |
| 1601 | /* In resume callback we need to know if the user had set the domain. | ||
| 1602 | * If so, we can not just reset it. | ||
| 1603 | */ | ||
| 1604 | if (ap_domain_index >= 0) | ||
| 1605 | user_set_domain = 1; | ||
| 1606 | |||
| 1589 | if (ap_instructions_available() != 0) { | 1607 | if (ap_instructions_available() != 0) { |
| 1590 | pr_warning("The hardware system does not support " | 1608 | pr_warning("The hardware system does not support " |
| 1591 | "AP instructions\n"); | 1609 | "AP instructions\n"); |
