diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 14:46:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 14:46:09 -0700 |
commit | 9f9d76321659b5ebc9939101481f7c3ce228ea6e (patch) | |
tree | 7abd21796ad85ba6c606cd2a93e787fb90b3abe6 | |
parent | 1b21f458ddbc8fb6fceeb68158e9e04b2571dabd (diff) | |
parent | f60d89108f3481ca11672b82cf7e67171e050ce4 (diff) |
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] vmlogrdr function annotation.
[S390] s390: rename CPU_IDLE to S390_CPU_IDLE
[S390] cio: Remove prototype for non-existing function cmf_reset().
[S390] zcrypt: fix request timeout handling
[S390] system call optimization.
[S390] dasd: Avoid compile warnings on !CONFIG_DASD_PROFILE
[S390] Remove volatile from atomic_t
[S390] Program check in diag 210 under 31 bit
[S390] Bogomips calculation for 64 bit.
[S390] smp: Merge smp_count_cpus() and smp_get_save_areas().
[S390] zcore: Fix __user annotation.
[S390] fixed cdl-format detection.
[S390] sclp: Test facility list before executing a service call.
[S390] sclp: introduce some new interfaces.
[S390] Fixed comment typo.
[S390] vmcp cleanup
31 files changed, 459 insertions, 348 deletions
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 2775d261833..95f5160df27 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -24,7 +24,7 @@ #define CRYPT_S390_PRIORITY 300 #define CRYPT_S390_COMPOSITE_PRIORITY 400 -/* s930 cryptographic operations */ +/* s390 cryptographic operations */ enum crypt_s390_operations { CRYPT_S390_KM = 0x0100, CRYPT_S390_KMC = 0x0200, diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 50538e54561..e6289ee74ec 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -171,37 +171,6 @@ static inline int memory_fast_detect(void) } #endif -#define ADDR2G (1UL << 31) - -static noinline __init unsigned long sclp_memory_detect(void) -{ - struct sclp_readinfo_sccb *sccb; - unsigned long long memsize; - - sccb = &s390_readinfo_sccb; - - if (sccb->header.response_code != 0x10) - return 0; - - if (sccb->rnsize) - memsize = sccb->rnsize << 20; - else - memsize = sccb->rnsize2 << 20; - if (sccb->rnmax) - memsize *= sccb->rnmax; - else - memsize *= sccb->rnmax2; -#ifndef CONFIG_64BIT - /* - * Can't deal with more than 2G in 31 bit addressing mode, so - * limit the value in order to avoid strange side effects. - */ - if (memsize > ADDR2G) - memsize = ADDR2G; -#endif - return (unsigned long) memsize; -} - static inline __init unsigned long __tprot(unsigned long addr) { int cc = -1; @@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr) /* Checking memory in 128KB increments. */ #define CHUNK_INCR (1UL << 17) +#define ADDR2G (1UL << 31) static noinline __init void find_memory_chunks(unsigned long memsize) { @@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void) */ void __init startup_init(void) { - unsigned long memsize; + unsigned long long memsize; ipl_save_parameters(); clear_bss_section(); @@ -305,8 +275,17 @@ void __init startup_init(void) sort_main_extable(); setup_lowcore_early(); sclp_readinfo_early(); + sclp_facilities_detect(); memsize = sclp_memory_detect(); +#ifndef CONFIG_64BIT + /* + * Can't deal with more than 2G in 31 bit addressing mode, so + * limit the value in order to avoid strange side effects. + */ + if (memsize > ADDR2G) + memsize = ADDR2G; +#endif if (memory_fast_detect() < 0) - find_memory_chunks(memsize); + find_memory_chunks((unsigned long) memsize); lockdep_on(); } diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 6234c6978a1..bc7ff3658c3 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -107,6 +107,11 @@ STACK_SIZE = 1 << STACK_SHIFT l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 .endm + .macro SAVE_ALL_SVC psworg,savearea + la %r12,\psworg + l %r15,__LC_KERNEL_STACK # problem state -> load ksp + .endm + .macro SAVE_ALL_SYNC psworg,savearea la %r12,\psworg tm \psworg+1,0x01 # test problem state bit @@ -218,7 +223,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA lh %r7,0x8a # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 685f11faa4b..2a7b1304418 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -99,6 +99,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ larl %r13,system_call .endm + .macro SAVE_ALL_SVC psworg,savearea + la %r12,\psworg + lg %r15,__LC_KERNEL_STACK # problem state -> load ksp + .endm + .macro SAVE_ALL_SYNC psworg,savearea la %r12,\psworg tm \psworg+1,0x01 # test problem state bit @@ -207,7 +212,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 367caf92ea7..82b131ddd7f 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -25,10 +25,6 @@ #define IPL_PARM_BLOCK_VERSION 0 -#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10) -#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) -#define SCCB_FLAG (s390_readinfo_sccb.flags) - #define IPL_UNKNOWN_STR "unknown" #define IPL_CCW_STR "ccw" #define IPL_FCP_STR "fcp" @@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw; static enum shutdown_action on_panic_action = SHUTDOWN_STOP; +static struct sclp_ipl_info sclp_ipl_info; + int diag308(unsigned long subcode, void *addr) { register unsigned long _addr asm("0") = (unsigned long) addr; @@ -375,9 +373,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) { char loadparm[LOADPARM_LEN + 1] = {}; - if (!SCCB_VALID) + if (!sclp_ipl_info.is_valid) return sprintf(page, "#unknown#\n"); - memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); + memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); EBCASC(loadparm, LOADPARM_LEN); strstrip(loadparm); return sprintf(page, "%s\n", loadparm); @@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void) reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; /* check if read scp info worked and set loadparm */ - if (SCCB_VALID) + if (sclp_ipl_info.is_valid) memcpy(reipl_block_ccw->ipl_info.ccw.load_param, - SCCB_LOADPARM, LOADPARM_LEN); + &sclp_ipl_info.loadparm, LOADPARM_LEN); else /* read scp info failed: set empty loadparm (EBCDIC blanks) */ memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, @@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void) { int rc; - if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) + if (!sclp_ipl_info.has_dump) return 0; /* LDIPL DUMP is not installed */ if (!diag308_set_works) return 0; @@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void) { int rc; + sclp_get_ipl_info(&sclp_ipl_info); reipl_probe(); rc = ipl_init(); if (rc) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index eb43c3b3126..441975b796f 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -93,8 +93,8 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code) /* disable monitor call class 0 */ __ctl_clear_bit(8, 15); - atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE, - (void *)(long) smp_processor_id()); + atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE, + (void *)(long) smp_processor_id()); } extern void s390_handle_mcck(void); @@ -115,7 +115,7 @@ static void default_idle(void) } rc = atomic_notifier_call_chain(&idle_chain, - CPU_IDLE, (void *)(long) cpu); + S390_CPU_IDLE, (void *)(long) cpu); if (rc != NOTIFY_OK && rc != NOTIFY_DONE) BUG(); if (rc != NOTIFY_OK) { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8ff2feaf9b0..182c085ae4d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -410,58 +410,40 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ __attribute__((__section__(".data"))); -static void __init smp_get_save_areas(void) +static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { - unsigned int cpu, cpu_num, rc; - __u16 boot_cpu_addr; - if (ipl_info.type != IPL_TYPE_FCP_DUMP) return; - boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; - cpu_num = 1; - for (cpu = 0; cpu <= 65535; cpu++) { - if ((u16) cpu == boot_cpu_addr) - continue; - __cpu_logical_map[1] = (__u16) cpu; - if (signal_processor(1, sigp_sense) == sigp_not_operational) - continue; - if (cpu_num >= NR_CPUS) { - printk("WARNING: Registers for cpu %i are not " - "saved, since dump kernel was compiled with" - "NR_CPUS=%i!\n", cpu_num, NR_CPUS); - continue; - } - zfcpdump_save_areas[cpu_num] = - alloc_bootmem(sizeof(union save_area)); - while (1) { - rc = signal_processor(1, sigp_stop_and_store_status); - if (rc != sigp_busy) - break; - cpu_relax(); - } - memcpy(zfcpdump_save_areas[cpu_num], - (void *)(unsigned long) store_prefix() + - SAVE_AREA_BASE, SAVE_AREA_SIZE); -#ifdef __s390x__ - /* copy original prefix register */ - zfcpdump_save_areas[cpu_num]->s390x.pref_reg = - zfcpdump_prefix_array[cpu_num]; -#endif - cpu_num++; + if (cpu >= NR_CPUS) { + printk(KERN_WARNING "Registers for cpu %i not saved since dump " + "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS); + return; } + zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area)); + __cpu_logical_map[1] = (__u16) phy_cpu; + while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy) + cpu_relax(); + memcpy(zfcpdump_save_areas[cpu], + (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE, + SAVE_AREA_SIZE); +#ifdef CONFIG_64BIT + /* copy original prefix register */ + zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu]; +#endif } union save_area *zfcpdump_save_areas[NR_CPUS + 1]; EXPORT_SYMBOL_GPL(zfcpdump_save_areas); #else -#define smp_get_save_areas() do { } while (0) -#endif + +static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } + +#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ /* * Lets check how many CPUs we have. */ - static unsigned int __init smp_count_cpus(void) { unsigned int cpu, num_cpus; @@ -470,7 +452,6 @@ static unsigned int __init smp_count_cpus(void) /* * cpu 0 is the boot cpu. See smp_prepare_boot_cpu. */ - boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; current_thread_info()->cpu = 0; num_cpus = 1; @@ -480,12 +461,11 @@ static unsigned int __init smp_count_cpus(void) __cpu_logical_map[1] = (__u16) cpu; if (signal_processor(1, sigp_sense) == sigp_not_operational) continue; + smp_get_save_area(num_cpus, cpu); num_cpus++; } - printk("Detected %d CPU's\n", (int) num_cpus); printk("Boot cpu address %2X\n", boot_cpu_addr); - return num_cpus; } @@ -606,7 +586,6 @@ void __init smp_setup_cpu_possible_map(void) { unsigned int phy_cpus, pos_cpus, cpu; - smp_get_save_areas(); phy_cpus = smp_count_cpus(); pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 9c2872a7cca..48dae49bc1e 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -226,10 +226,10 @@ static int nohz_idle_notify(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action) { - case CPU_IDLE: + case S390_CPU_IDLE: stop_hz_timer(); break; - case CPU_NOT_IDLE: + case S390_CPU_NOT_IDLE: start_hz_timer(); break; } diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 1e1a6ee2cac..b6ed143e859 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -545,10 +545,10 @@ static int vtimer_idle_notify(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action) { - case CPU_IDLE: + case S390_CPU_IDLE: stop_cpu_timer(); break; - case CPU_NOT_IDLE: + case S390_CPU_NOT_IDLE: start_cpu_timer(); break; } diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index 59aea65ce99..52084436ab6 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -4,7 +4,7 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o -obj-$(CONFIG_32BIT) += div64.o +lib-y += delay.o string.o uaccess_std.o uaccess_pt.o +obj-$(CONFIG_32BIT) += div64.o qrnnd.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 8b3b0f4a157..ac7e8ef504c 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -28,6 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL; static struct proc_dir_entry *dasd_devices_entry = NULL; static struct proc_dir_entry *dasd_statistics_entry = NULL; +#ifdef CONFIG_DASD_PROFILE static char * dasd_get_user_string(const char __user *user_buf, size_t user_len) { @@ -47,6 +48,7 @@ dasd_get_user_string(const char __user *user_buf, size_t user_len) buffer[user_len] = 0; return buffer; } +#endif /* CONFIG_DASD_PROFILE */ static int dasd_devices_show(struct seq_file *m, void *v) @@ -167,6 +169,7 @@ dasd_calc_metrics(char *page, char **start, off_t off, return len; } +#ifdef CONFIG_DASD_PROFILE static char * dasd_statistics_array(char *str, unsigned int *array, int shift) { @@ -180,6 +183,7 @@ dasd_statistics_array(char *str, unsigned int *array, int shift) str += sprintf(str,"\n"); return str; } +#endif /* CONFIG_DASD_PROFILE */ static int dasd_statistics_read(char *page, char **start, off_t off, diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index dbb99d1b6f5..c7318a12585 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t; typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ +struct sccb_header { + u16 length; + u8 function_code; + u8 control_mask[3]; + u16 response_code; +} __attribute__((packed)); + +extern u64 sclp_facilities; + +#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) +#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) + struct gds_subvector { u8 length; u8 key; diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c index a66b914519b..c68f5e7e63a 100644 --- a/drivers/s390/char/sclp_chp.c +++ b/drivers/s390/char/sclp_chp.c @@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd) struct chp_cfg_data *data; int rc; + if (!SCLP_HAS_CHP_RECONFIG) + return -EOPNOTSUPP; /* Prepare sccb. */ data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!data) @@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info) struct chp_info_data *data; int rc; + if (!SCLP_HAS_CHP_INFO) + return -EOPNOTSUPP; /* Prepare sccb. */ data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!data) diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c index 7bcbe643b08..a1136e05275 100644 --- a/drivers/s390/char/sclp_info.c +++ b/drivers/s390/char/sclp_info.c @@ -11,47 +11,106 @@ #include <asm/sclp.h> #include "sclp.h" -struct sclp_readinfo_sccb s390_readinfo_sccb; +struct sclp_readinfo_sccb { + struct sccb_header header; /* 0-7 */ + u16 rnmax; /* 8-9 */ + u8 rnsize; /* 10 */ + u8 _reserved0[24 - 11]; /* 11-23 */ + u8 loadparm[8]; /* 24-31 */ + u8 _reserved1[48 - 32]; /* 32-47 */ + u64 facilities; /* 48-55 */ + u8 _reserved2[91 - 56]; /* 56-90 */ + u8 flags; /* 91 */ + u8 _reserved3[100 - 92]; /* 92-99 */ + u32 rnsize2; /* 100-103 */ + u64 rnmax2; /* 104-111 */ + u8 _reserved4[4096 - 112]; /* 112-4095 */ +} __attribute__((packed, aligned(4096))); + +static struct sclp_readinfo_sccb __initdata early_readinfo_sccb; +static int __initdata early_readinfo_sccb_valid; + +u64 sclp_facilities; void __init sclp_readinfo_early(void) { - sclp_cmdw_t command; - struct sccb_header *sccb; int ret; + int i; + struct sclp_readinfo_sccb *sccb; + sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, + SCLP_CMDW_READ_SCP_INFO}; - __ctl_set_bit(0, 9); /* enable service signal subclass mask */ - - sccb = &s390_readinfo_sccb.header; - command = SCLP_CMDW_READ_SCP_INFO_FORCED; - while (1) { - u16 response; - - memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); - sccb->length = sizeof(s390_readinfo_sccb); - sccb->control_mask[2] = 0x80; - - ret = sclp_service_call(command, &s390_readinfo_sccb); - - if (ret == -EIO) - goto out; - if (ret == -EBUSY) - continue; + /* Enable service signal subclass mask. */ + __ctl_set_bit(0, 9); + sccb = &early_readinfo_sccb; + for (i = 0; i < ARRAY_SIZE(commands); i++) { + do { + memset(sccb, 0, sizeof(*sccb)); + sccb->header.length = sizeof(*sccb); + sccb->header.control_mask[2] = 0x80; + ret = sclp_service_call(commands[i], sccb); + } while (ret == -EBUSY); + if (ret) + break; __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | PSW_MASK_WAIT | PSW_DEFAULT_KEY); local_irq_disable(); + /* + * Contents of the sccb might have changed + * therefore a barrier is needed. + */ barrier(); + if (sccb->header.response_code == 0x10) { + early_readinfo_sccb_valid = 1; + break; + } + if (sccb->header.response_code != 0x1f0) + break; + } + /* Disable service signal subclass mask again. */ + __ctl_clear_bit(0, 9); +} - response = sccb->response_code; +void __init sclp_facilities_detect(void) +{ + if (!early_readinfo_sccb_valid) + return; + sclp_facilities = early_readinfo_sccb.facilities; +} - if (response == 0x10) - break; +unsigned long long __init sclp_memory_detect(void) +{ + unsigned long long memsize; + struct sclp_readinfo_sccb *sccb; - if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) - break; + if (!early_readinfo_sccb_valid) + return 0; + sccb = &early_readinfo_sccb; + if (sccb->rnsize) + memsize = sccb->rnsize << 20; + else + memsize = sccb->rnsize2 << 20; + if (sccb->rnmax) + memsize *= sccb->rnmax; + else + memsize *= sccb->rnmax2; + return memsize; +} - command = SCLP_CMDW_READ_SCP_INFO; - } -out: - __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ +/* + * This function will be called after sclp_memory_detect(), which gets called + * early from early.c code. Therefore the sccb should have valid contents. + */ +void __init sclp_get_ipl_info(struct sclp_ipl_info *info) +{ + struct sclp_readinfo_sccb *sccb; + + if (!early_readinfo_sccb_valid) + return; + sccb = &early_readinfo_sccb; + info->is_valid = 1; + if (sccb->flags & 0x2) + info->has_dump = 1; + memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); } diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index fce3dac5cb3..82e6a6b253e 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -175,13 +175,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static const struct file_operations vmcp_fops = { .owner = THIS_MODULE, - .open = &vmcp_open, - .release = &vmcp_release, - .read = &vmcp_read, - .llseek = &no_llseek, - .write = &vmcp_write, - .unlocked_ioctl = &vmcp_ioctl, - .compat_ioctl = &vmcp_ioctl + .open = vmcp_open, + .release = vmcp_release, + .read = vmcp_read, + .write = vmcp_write, + .unlocked_ioctl = vmcp_ioctl, + .compat_ioctl = vmcp_ioctl }; static struct miscdevice vmcp_dev = { diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index a5a00e9ae4d..12f7a4ce82c 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void) } -static int vmlogrdr_init(void) +static int __init vmlogrdr_init(void) { int rc; int i; @@ -885,7 +885,7 @@ cleanup: } -static void vmlogrdr_exit(void) +static void __exit vmlogrdr_exit(void) { vmlogrdr_cleanup(); printk (KERN_INFO "vmlogrdr: driver unloaded\n"); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 4e711a985d5..3712ede1672 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count) return rc; } -static int memcpy_real_user(__user void *dest, unsigned long src, size_t count) +static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) { static char buf[4096]; int offs = 0, size; diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 997f4687453..60b9347f7c9 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -27,7 +27,6 @@ /* * diag210 is used under VM to get information about a virtual device */ -#ifdef CONFIG_64BIT int diag210(struct diag210 * addr) { @@ -43,6 +42,7 @@ diag210(struct diag210 * addr) spin_lock_irqsave(&diag210_lock, flags); diag210_tmp = *addr; +#ifdef CONFIG_64BIT asm volatile( " lhi %0,-1\n" " sam31\n" @@ -51,19 +51,8 @@ diag210(struct diag210 * addr) " srl %0,28\n" "1: sam64\n" EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory"); - - *addr = diag210_tmp; - spin_unlock_irqrestore(&diag210_lock, flags); - - return ccode; -} + : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); #else -int -diag210(struct diag210 * addr) -{ - int ccode; - asm volatile( " lhi %0,-1\n" " diag %1,0,0x210\n" @@ -71,11 +60,14 @@ diag210(struct diag210 * addr) " srl %0,28\n" "1:\n" EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory"); + : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); +#endif + + *addr = diag210_tmp; + spin_unlock_irqrestore(&diag210_lock, flags); return ccode; } -#endif /* * Input : diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 5aac0ec3636..90bd2201451 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long); static void ap_poll_timeout(unsigned long); static int ap_poll_thread_start(void); static void ap_poll_thread_stop(void); +static void ap_request_timeout(unsigned long); /** * Module description. @@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) case AP_RESPONSE_NORMAL: return 0; case AP_RESPONSE_Q_FULL: + case AP_RESPONSE_RESET_IN_PROGRESS: return -EBUSY; default: /* Device is gone. */ return -ENODEV; @@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) if (status.queue_empty) return -ENOENT; return -EBUSY; + case AP_RESPONSE_RESET_IN_PROGRESS: + return -EBUSY; default: return -ENODEV; } @@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid) i = AP_MAX_RESET; /* return with -ENODEV */ break; case AP_RESPONSE_RESET_IN_PROGRESS: + rc = -EBUSY; case AP_RESPONSE_BUSY: default: break; } - if (rc != -ENODEV) + if (rc != -ENODEV && rc != -EBUSY) break; if (i < AP_MAX_RESET - 1) { udelay(5); @@ -341,6 +346,40 @@ static int ap_init_queue(ap_qid_t qid) } /** + * Arm request timeout if a AP device was idle and a new request is submitted. + */ +static void ap_increase_queue_count(struct ap_device *ap_dev) +{ + int timeout = ap_dev->drv->request_timeout; + + ap_dev->queue_count++; + if (ap_dev->queue_count == 1) { + mod_timer(&ap_dev->timeout, jiffies + timeout); + ap_dev->reset = AP_RESET_ARMED; + } +} + +/** + * AP device is still alive, re-schedule request timeout if there are still + * pending requests. + */ +static void ap_decrease_queue_count(struct ap_device *ap_dev) +{ + int timeout = ap_dev->drv->request_timeout; + + ap_dev->queue_count--; + if (ap_dev->queue_count > 0) + mod_timer(&ap_dev->timeout, jiffies + timeout); + else + /** + * The timeout timer should to be disabled now - since + * del_timer_sync() is very expensive, we just tell via the + * reset flag to ignore the pending timeout timer. + */ + ap_dev->reset = AP_RESET_IGNORE; +} + +/** * AP device related attributes. */ static ssize_t ap_hwtype_show(struct device *dev, @@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev) struct ap_driver *ap_drv = ap_dev->drv; ap_flush_queue(ap_dev); |