Commit 21cdbc13 authored by Linus Torvalds's avatar Linus Torvalds

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: (81 commits)
  [S390] remove duplicated #includes
  [S390] cpumask: use mm_cpumask() wrapper
  [S390] cpumask: Use accessors code.
  [S390] cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits.
  [S390] cpumask: remove cpu_coregroup_map
  [S390] fix clock comparator save area usage
  [S390] Add hwcap flag for the etf3 enhancement facility
  [S390] Ensure that ipl panic notifier is called late.
  [S390] fix dfp elf hwcap/facility bit detection
  [S390] smp: perform initial cpu reset before starting a cpu
  [S390] smp: fix memory leak on __cpu_up
  [S390] ipl: Improve checking logic and remove switch defaults.
  [S390] s390dbf: Remove needless check for NULL pointer.
  [S390] s390dbf: Remove redundant initilizations.
  [S390] use kzfree()
  [S390] BUG to BUG_ON changes
  [S390] zfcpdump: Prevent zcore from beeing built as a kernel module.
  [S390] Use csum_partial in checksum.h
  [S390] cleanup lowcore.h
  [S390] eliminate ipl_device from lowcore
  ...
parents 86d9c070 ef3500b2
...@@ -830,6 +830,9 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -830,6 +830,9 @@ and is between 256 and 4096 characters. It is defined in the file
hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC) hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC)
terminal devices. Valid values: 0..8 terminal devices. Valid values: 0..8
hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs.
If specified, z/VM IUCV HVC accepts connections
from listed z/VM user IDs only.
i8042.debug [HW] Toggle i8042 debug mode i8042.debug [HW] Toggle i8042 debug mode
i8042.direct [HW] Put keyboard port into non-translated mode i8042.direct [HW] Put keyboard port into non-translated mode
......
...@@ -3745,6 +3745,15 @@ L: linux-s390@vger.kernel.org ...@@ -3745,6 +3745,15 @@ L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/ W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported S: Supported
S390 ZCRYPT DRIVER
P: Felix Beck
M: felix.beck@de.ibm.com
P: Ralph Wuerthner
M: ralph.wuerthner@de.ibm.com
M: linux390@de.ibm.com
L: linux-s390@vger.kernel.org
S: Supported
S390 ZFCP DRIVER S390 ZFCP DRIVER
P: Christof Schmitt P: Christof Schmitt
M: christof.schmitt@de.ibm.com M: christof.schmitt@de.ibm.com
......
...@@ -343,13 +343,6 @@ source "mm/Kconfig" ...@@ -343,13 +343,6 @@ source "mm/Kconfig"
comment "I/O subsystem configuration" comment "I/O subsystem configuration"
config MACHCHK_WARNING
bool "Process warning machine checks"
help
Select this option if you want the machine check handler on IBM S/390 or
zSeries to process warning machine checks (e.g. on power failures).
If unsure, say "Y".
config QDIO config QDIO
tristate "QDIO support" tristate "QDIO support"
---help--- ---help---
...@@ -521,7 +514,7 @@ config APPLDATA_OS ...@@ -521,7 +514,7 @@ config APPLDATA_OS
config APPLDATA_NET_SUM config APPLDATA_NET_SUM
tristate "Monitor overall network statistics" tristate "Monitor overall network statistics"
depends on APPLDATA_BASE depends on APPLDATA_BASE && NET
help help
This provides network related data to the Linux - VM Monitor Stream, This provides network related data to the Linux - VM Monitor Stream,
currently there is only a total sum of network I/O statistics, no currently there is only a total sum of network I/O statistics, no
...@@ -552,7 +545,7 @@ config KEXEC ...@@ -552,7 +545,7 @@ config KEXEC
but is independent of hardware/microcode support. but is independent of hardware/microcode support.
config ZFCPDUMP config ZFCPDUMP
tristate "zfcpdump support" bool "zfcpdump support"
select SMP select SMP
default n default n
help help
......
...@@ -201,8 +201,7 @@ static int __init prng_init(void) ...@@ -201,8 +201,7 @@ static int __init prng_init(void)
static void __exit prng_exit(void) static void __exit prng_exit(void)
{ {
/* wipe me */ /* wipe me */
memset(p->buf, 0, prng_chunk_size); kzfree(p->buf);
kfree(p->buf);
kfree(p); kfree(p);
misc_deregister(&prng_dev); misc_deregister(&prng_dev);
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
* with operation of the form "set_bit(bitnr, flags)". * with operation of the form "set_bit(bitnr, flags)".
*/ */
/* bitmap tables from arch/S390/kernel/bitmap.S */ /* bitmap tables from arch/s390/kernel/bitmap.c */
extern const char _oi_bitmap[]; extern const char _oi_bitmap[];
extern const char _ni_bitmap[]; extern const char _ni_bitmap[];
extern const char _zb_findmap[]; extern const char _zb_findmap[];
...@@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr, ...@@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr,
static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
{ {
#ifdef __s390x__ #ifdef __s390x__
if (likely((word & 0xffffffff) == 0xffffffff)) { if ((word & 0xffffffff) == 0xffffffff) {
word >>= 32; word >>= 32;
nr += 32; nr += 32;
} }
#endif #endif
if (likely((word & 0xffff) == 0xffff)) { if ((word & 0xffff) == 0xffff) {
word >>= 16; word >>= 16;
nr += 16; nr += 16;
} }
if (likely((word & 0xff) == 0xff)) { if ((word & 0xff) == 0xff) {
word >>= 8; word >>= 8;
nr += 8; nr += 8;
} }
...@@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) ...@@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
{ {
#ifdef __s390x__ #ifdef __s390x__
if (likely((word & 0xffffffff) == 0)) { if ((word & 0xffffffff) == 0) {
word >>= 32; word >>= 32;
nr += 32; nr += 32;
} }
#endif #endif
if (likely((word & 0xffff) == 0)) { if ((word & 0xffff) == 0) {
word >>= 16; word >>= 16;
nr += 16; nr += 16;
} }
if (likely((word & 0xff) == 0)) { if ((word & 0xff) == 0) {
word >>= 8; word >>= 8;
nr += 8; nr += 8;
} }
......
/*
* Data definitions for channel report processing
* Copyright IBM Corp. 2000,2009
* Author(s): Ingo Adlung <adlung@de.ibm.com>,
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Cornelia Huck <cornelia.huck@de.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>,
*/
#ifndef _ASM_S390_CRW_H
#define _ASM_S390_CRW_H
#include <linux/types.h>
/*
* Channel Report Word
*/
struct crw {
__u32 res1 : 1; /* reserved zero */
__u32 slct : 1; /* solicited */
__u32 oflw : 1; /* overflow */
__u32 chn : 1; /* chained */
__u32 rsc : 4; /* reporting source code */
__u32 anc : 1; /* ancillary report */
__u32 res2 : 1; /* reserved zero */
__u32 erc : 6; /* error-recovery code */
__u32 rsid : 16; /* reporting-source ID */
} __attribute__ ((packed));
typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
extern int crw_register_handler(int rsc, crw_handler_t handler);
extern void crw_unregister_handler(int rsc);
extern void crw_handle_channel_report(void);
#define NR_RSCS 16
#define CRW_RSC_MONITOR 0x2 /* monitoring facility */
#define CRW_RSC_SCH 0x3 /* subchannel */
#define CRW_RSC_CPATH 0x4 /* channel path */
#define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */
#define CRW_RSC_CSS 0xB /* channel subsystem */
#define CRW_ERC_EVENT 0x00 /* event information pending */
#define CRW_ERC_AVAIL 0x01 /* available */
#define CRW_ERC_INIT 0x02 /* initialized */
#define CRW_ERC_TERROR 0x03 /* temporary error */
#define CRW_ERC_IPARM 0x04 /* installed parm initialized */
#define CRW_ERC_TERM 0x05 /* terminal */
#define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */
#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */
#define CRW_ERC_PMOD 0x08 /* installed parameters modified */
static inline int stcrw(struct crw *pcrw)
{
int ccode;
asm volatile(
" stcrw 0(%2)\n"
" ipm %0\n"
" srl %0,28\n"
: "=d" (ccode), "=m" (*pcrw)
: "a" (pcrw)
: "cc" );
return ccode;
}
#endif /* _ASM_S390_CRW_H */
...@@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t { ...@@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t {
unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */ unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
} dasd_profile_info_t; } dasd_profile_info_t;
/* /*
* struct format_data_t * struct format_data_t
* represents all data necessary to format a dasd * represents all data necessary to format a dasd
*/ */
typedef struct format_data_t { typedef struct format_data_t {
int start_unit; /* from track */ unsigned int start_unit; /* from track */
int stop_unit; /* to track */ unsigned int stop_unit; /* to track */
int blksize; /* sectorsize */ unsigned int blksize; /* sectorsize */
int intensity; unsigned int intensity;
} format_data_t; } format_data_t;
/* /*
......
...@@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length) ...@@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length)
/* /*
* Return the number of idal words needed for an address/length pair. * Return the number of idal words needed for an address/length pair.
*/ */
static inline unsigned int static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
idal_nr_words(void *vaddr, unsigned int length)
{ {
#ifdef __s390x__ return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
if (idal_is_needed(vaddr, length)) (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
(IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
#endif
return 0;
} }
/* /*
* Create the list of idal words for an address/length pair. * Create the list of idal words for an address/length pair.
*/ */
static inline unsigned long * static inline unsigned long *idal_create_words(unsigned long *idaws,
idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) void *vaddr, unsigned int length)
{ {
#ifdef __s390x__
unsigned long paddr; unsigned long paddr;
unsigned int cidaw; unsigned int cidaw;
...@@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) ...@@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
paddr += IDA_BLOCK_SIZE; paddr += IDA_BLOCK_SIZE;
*idaws++ = paddr; *idaws++ = paddr;
} }
#endif
return idaws; return idaws;
} }
......
This diff is collapsed.
...@@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) ...@@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk) struct task_struct *tsk)
{ {
cpu_set(smp_processor_id(), next->cpu_vm_mask); cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
update_mm(next, tsk); update_mm(next, tsk);
} }
......
/*
* Machine check handler definitions
*
* Copyright IBM Corp. 2000,2009
* Author(s): Ingo Adlung <adlung@de.ibm.com>,
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Cornelia Huck <cornelia.huck@de.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>,
*/
#ifndef _ASM_S390_NMI_H
#define _ASM_S390_NMI_H
#include <linux/types.h>
struct mci {
__u32 sd : 1; /* 00 system damage */
__u32 pd : 1; /* 01 instruction-processing damage */
__u32 sr : 1; /* 02 system recovery */
__u32 : 1; /* 03 */
__u32 cd : 1; /* 04 timing-facility damage */
__u32 ed : 1; /* 05 external damage */
__u32 : 1; /* 06 */
__u32 dg : 1; /* 07 degradation */
__u32 w : 1; /* 08 warning pending */
__u32 cp : 1; /* 09 channel-report pending */
__u32 sp : 1; /* 10 service-processor damage */
__u32 ck : 1; /* 11 channel-subsystem damage */
__u32 : 2; /* 12-13 */
__u32 b : 1; /* 14 backed up */
__u32 : 1; /* 15 */
__u32 se : 1; /* 16 storage error uncorrected */
__u32 sc : 1; /* 17 storage error corrected */
__u32 ke : 1; /* 18 storage-key error uncorrected */
__u32 ds : 1; /* 19 storage degradation */
__u32 wp : 1; /* 20 psw mwp validity */
__u32 ms : 1; /* 21 psw mask and key validity */
__u32 pm : 1; /* 22 psw program mask and cc validity */
__u32 ia : 1; /* 23 psw instruction address validity */
__u32 fa : 1; /* 24 failing storage address validity */
__u32 : 1; /* 25 */
__u32 ec : 1; /* 26 external damage code validity */
__u32 fp : 1; /* 27 floating point register validity */
__u32 gr : 1; /* 28 general register validity */
__u32 cr : 1; /* 29 control register validity */
__u32 : 1; /* 30 */
__u32 st : 1; /* 31 storage logical validity */
__u32 ie : 1; /* 32 indirect storage error */
__u32 ar : 1; /* 33 access register validity */
__u32 da : 1; /* 34 delayed access exception */
__u32 : 7; /* 35-41 */
__u32 pr : 1; /* 42 tod programmable register validity */
__u32 fc : 1; /* 43 fp control register validity */
__u32 ap : 1; /* 44 ancillary report */
__u32 : 1; /* 45 */
__u32 ct : 1; /* 46 cpu timer validity */
__u32 cc : 1; /* 47 clock comparator validity */
__u32 : 16; /* 47-63 */
};
struct pt_regs;
extern void s390_handle_mcck(void);
extern void s390_do_machine_check(struct pt_regs *regs);
#endif /* _ASM_S390_NMI_H */
...@@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr) ...@@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr)
asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
} }
struct cpuinfo_S390
{
cpuid_t cpu_id;
__u16 cpu_addr;
__u16 cpu_nr;
unsigned long loops_per_jiffy;
unsigned long *pgd_quick;
#ifdef __s390x__
unsigned long *pmd_quick;
#endif /* __s390x__ */
unsigned long *pte_quick;
unsigned long pgtable_cache_sz;
};
extern void s390_adjust_jiffies(void); extern void s390_adjust_jiffies(void);
extern void print_cpu_info(struct cpuinfo_S390 *); extern void print_cpu_info(void);
extern int get_cpu_capability(unsigned int *); extern int get_cpu_capability(unsigned int *);
/* /*
......
...@@ -172,6 +172,8 @@ ...@@ -172,6 +172,8 @@
#define NUM_CRS 16 #define NUM_CRS 16
#define NUM_ACRS 16 #define NUM_ACRS 16
#define NUM_CR_WORDS 3
#define FPR_SIZE 8 #define FPR_SIZE 8
#define FPC_SIZE 4 #define FPC_SIZE 4
#define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */ #define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */
...@@ -334,7 +336,7 @@ struct pt_regs ...@@ -334,7 +336,7 @@ struct pt_regs
*/ */
typedef struct typedef struct
{ {
unsigned long cr[3]; unsigned long cr[NUM_CR_WORDS];
} per_cr_words; } per_cr_words;
#define PER_EM_MASK 0xE8000000UL #define PER_EM_MASK 0xE8000000UL
......
...@@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, ...@@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
int, int, unsigned long); int, int, unsigned long);
/* qdio errors reported to the upper-layer program */ /* qdio errors reported to the upper-layer program */
#define QDIO_ERROR_SIGA_TARGET 0x02
#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 #define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10
#define QDIO_ERROR_SIGA_BUSY 0x20 #define QDIO_ERROR_SIGA_BUSY 0x20
#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40
......
...@@ -50,12 +50,7 @@ extern void machine_power_off_smp(void); ...@@ -50,12 +50,7 @@ extern void machine_power_off_smp(void);
#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ #define PROC_CHANGE_PENALTY 20 /* Schedule penalty */
#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr) #define raw_smp_processor_id() (S390_lowcore.cpu_nr)
static inline __u16 hard_smp_processor_id(void)
{
return stap();
}
/* /*
* returns 1 if cpu is in stopped/check stopped state or not operational * returns 1 if cpu is in stopped/check stopped state or not operational
......
...@@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src) ...@@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src)
static inline char *strcpy(char *dst, const char *src) static inline char *strcpy(char *dst, const char *src)
{ {
#if __GNUC__ < 4
register int r0 asm("0") = 0; register int r0 asm("0") = 0;
char *ret = dst; char *ret = dst;
...@@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src) ...@@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src)
: "+&a" (dst), "+&a" (src) : "d" (r0) : "+&a" (dst), "+&a" (src) : "d" (r0)
: "cc", "memory"); : "cc", "memory");
return ret; return ret;
#else
return __builtin_strcpy(dst, src);
#endif
} }
static inline size_t strlen(const char *s) static inline size_t strlen(const char *s)
{ {
#if __GNUC__ < 4
register unsigned long r0 asm("0") = 0; register unsigned long r0 asm("0") = 0;
const char *tmp = s; const char *tmp = s;
...@@ -121,6 +126,9 @@ static inline size_t strlen(const char *s) ...@@ -121,6 +126,9 @@ static inline size_t strlen(const char *s)
" jo 0b" " jo 0b"
: "+d" (r0), "+a" (tmp) : : "cc"); : "+d" (r0), "+a" (tmp) : : "cc");
return r0 - (unsigned long) s; return r0 - (unsigned long) s;
#else
return __builtin_strlen(s);
#endif
} }
static inline size_t strnlen(const char * s, size_t n) static inline size_t strnlen(const char * s, size_t n)
...@@ -135,7 +143,13 @@ static inline size_t strnlen(const char * s, size_t n) ...@@ -135,7 +143,13 @@ static inline size_t strnlen(const char * s, size_t n)
: "+a" (end), "+a" (tmp) : "d" (r0) : "cc"); : "+a" (end), "+a" (tmp) : "d" (r0) : "cc");
return end - s; return end - s;
} }
#else /* IN_ARCH_STRING_C */
void *memchr(const void * s, int c, size_t n);
void *memscan(void *s, int c, size_t n);
char *strcat(char *dst, const char *src);
char *strcpy(char *dst, const char *src);
size_t strlen(const char *s);
size_t strnlen(const char * s, size_t n);
#endif /* !IN_ARCH_STRING_C */ #endif /* !IN_ARCH_STRING_C */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -100,6 +100,7 @@ struct sysinfo_3_2_2 { ...@@ -100,6 +100,7 @@ struct sysinfo_3_2_2 {
char reserved_1[24]; char reserved_1[24];
} vm[8]; } vm[8];
char reserved_544[3552];
}; };
static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
......
...@@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm) ...@@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm)
* If the process only ran on the local cpu, do a local flush. * If the process only ran on the local cpu, do a local flush.
*/ */
local_cpumask = cpumask_of_cpu(smp_processor_id()); local_cpumask = cpumask_of_cpu(smp_processor_id());
if (cpus_equal(mm->cpu_vm_mask, local_cpumask)) if (cpumask_equal(mm_cpumask(mm), &local_cpumask))
__tlb_flush_local(); __tlb_flush_local();
else else
__tlb_flush_global(); __tlb_flush_global();
...@@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce) ...@@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce)
static inline void __tlb_flush_mm(struct mm_struct * mm) static inline void __tlb_flush_mm(struct mm_struct * mm)
{ {
if (unlikely(cpus_empty(mm->cpu_vm_mask))) if (unlikely(cpumask_empty(mm_cpumask(mm))))
return; return;
/* /*
* If the machine has IDTE we prefer to do a per mm flush * If the machine has IDTE we prefer to do a per mm flush
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#define mc_capable() (1) #define mc_capable() (1)
cpumask_t cpu_coregroup_map(unsigned int cpu);
const struct cpumask *cpu_coregroup_mask(unsigned int cpu); const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
extern cpumask_t cpu_core_map[NR_CPUS]; extern cpumask_t cpu_core_map[NR_CPUS];
......
...@@ -39,7 +39,7 @@ struct vtoc_labeldate ...@@ -39,7 +39,7 @@ struct vtoc_labeldate
__u16 day; __u16 day;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct vtoc_volume_label struct vtoc_volume_label_cdl
{ {
char volkey[4]; /* volume key = volume label */ char volkey[4]; /* volume key = volume label */
char vollbl[4]; /* volume label */ char vollbl[4]; /* volume label */
...@@ -56,6 +56,14 @@ struct vtoc_volume_label ...@@ -56,6 +56,14 @@ struct vtoc_volume_label
char res3[29]; /* reserved */ char res3[29]; /* reserved */
} __attribute__ ((packed)); } __attribute__ ((packed));
struct vtoc_volume_label_ldl {
char vollbl[4]; /* volume label */
char volid[6]; /* volume identifier */
char res3[69]; /* reserved */
char ldl_version; /* version number, valid for ldl format */
__u64 formatted_blocks; /* valid when ldl_version >= f2 */
} __attribute__ ((packed));
struct vtoc_extent struct vtoc_extent
{ {
__u8 typeind; /* extent type indicator */ __u8 typeind; /* extent type indicator */
...@@ -140,7 +148,11 @@ struct vtoc_format4_label ...@@ -140,7 +148,11 @@ struct vtoc_format4_label
char res2[10]; /* reserved */ char res2[10]; /* reserved */
__u8 DS4EFLVL; /* extended free-space management level */ __u8 DS4EFLVL; /* extended free-space management level */
struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */
char res3[9]; /* reserved */ char res3; /* reserved */
__u32 DS4DCYL; /* number of logical cyls */
char res4[2]; /* reserved */
__u8 DS4DEVF2; /* device flags */
char res5; /* reserved */
} __attribute__ ((packed)); } __attribute__ ((packed));
struct vtoc_ds5ext struct vtoc_ds5ext
......
...@@ -17,10 +17,12 @@ CFLAGS_smp.o := -Wno-nonnull ...@@ -17,10 +17,12 @@ CFLAGS_smp.o := -Wno-nonnull
# #
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
vdso.o vtime.o vdso.o vtime.o sysinfo.o nmi.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
......
/*
* arch/s390/kernel/bitmap.S
* Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
* See include/asm-s390/{bitops.h|posix_types.h} for details
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
*/
.globl _oi_bitmap
_oi_bitmap:
.byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
.globl _ni_bitmap
_ni_bitmap:
.byte 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
.globl _zb_findmap
_zb_findmap:
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8
.globl _sb_findmap
_sb_findmap:
.byte 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
/*
* Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
* See include/asm/{bitops.h|posix_types.h} for details
*
* Copyright IBM Corp. 1999,2009
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
*/
#include <linux/bitops.h>
#include <linux/module.h>
const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
EXPORT_SYMBOL(_oi_bitmap);
const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
EXPORT_SYMBOL(_ni_bitmap);
const char _zb_findmap[] = {
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 };
EXPORT_SYMBOL(_zb_findmap);
const char _sb_findmap[] = {
8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
EXPORT_SYMBOL(_sb_findmap);
#ifndef _PTRACE32_H #ifndef _PTRACE32_H
#define _PTRACE32_H #define _PTRACE32_H
#include <asm/ptrace.h> /* needed for NUM_CR_WORDS */
#include "compat_linux.h" /* needed for psw_compat_t */ #include "compat_linux.h" /* needed for psw_compat_t */
typedef struct { typedef struct {
__u32 cr[3]; __u32 cr[NUM_CR_WORDS];
} per_cr_words32; } per_cr_words32;
typedef struct { typedef struct {
......
...@@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length, ...@@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
static int static int
debug_open(struct inode *inode, struct file *file) debug_open(struct inode *inode, struct file *file)
{ {
int i = 0, rc = 0; int i, rc = 0;
file_private_info_t *p_info; file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot; debug_info_t *debug_info, *debug_info_snapshot;
...@@ -642,8 +642,7 @@ debug_open(struct inode *inode, struct file *file) ...@@ -642,8 +642,7 @@ debug_open(struct inode *inode, struct file *file)
p_info = kmalloc(sizeof(file_private_info_t), p_info = kmalloc(sizeof(file_private_info_t),
GFP_KERNEL); GFP_KERNEL);
if(!p_info){ if(!p_info){
if(debug_info_snapshot) debug_info_free(debug_info_snapshot);
debug_info_free(debug_info_snapshot);
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
...@@ -698,8 +697,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area, ...@@ -698,8 +697,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area,
if ((uid != 0) || (gid != 0)) if ((uid != 0) || (gid != 0))
pr_warning("Root becomes the owner of all s390dbf files " pr_warning("Root becomes the owner of all s390dbf files "
"in sysfs\n"); "in sysfs\n");
if (!initialized) BUG_ON(!initialized);
BUG();
mutex_lock(&debug_mutex); mutex_lock(&debug_mutex);
/* create new debug_info */ /* create new debug_info */
...@@ -1156,7 +1154,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view) ...@@ -1156,7 +1154,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
else { else {
debugfs_remove(id->debugfs_entries[i]); debugfs_remove(id->debugfs_entries[i]);
id->views[i] = NULL; id->views[i] = NULL;
rc = 0;
} }
spin_unlock_irqrestore(&id->lock, flags); spin_unlock_irqrestore(&id->lock, flags);
out: out:
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Heiko Carstens <heiko.carstens@de.ibm.com> * Heiko Carstens <heiko.carstens@de.ibm.com>
*/ */
#include <linux/compiler.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/sysinfo.h>
#include <asm/cpcmd.h> #include <asm/cpcmd.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include "entry.h" #include "entry.h"
...@@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void) ...@@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void)
page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
} }
static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
static noinline __init void detect_machine_type(void) static noinline __init void detect_machine_type(void)
{ {
struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; /* No VM information? Looks like LPAR */
if (stsi(&vmms, 3, 2, 2) == -ENOSYS)
get_cpu_id(&S390_lowcore.cpu_data.cpu_id); return;
if (!vmms.count)
/* Running under z/VM ? */ return;
if (cpuinfo->cpu_id.version == 0xff)
machine_flags |= MACHINE_FLAG_VM;
/* Running under KVM ? */ /* Running under KVM? If not we assume z/VM */
if (cpuinfo->cpu_id.version == 0xfe) if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3))
machine_flags |= MACHINE_FLAG_KVM; machine_flags |= MACHINE_FLAG_KVM;
else
machine_flags |= MACHINE_FLAG_VM;
} }
static __init void early_pgm_check_handler(void) static __init void early_pgm_check_handler(void)
...@@ -348,7 +352,6 @@ static void __init setup_boot_command_line(void) ...@@ -348,7 +352,6 @@ static void __init setup_boot_command_line(void)
/* copy arch command line */ /* copy arch command line */
strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
/* append IPL PARM data to the boot command line */ /* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM) { if (MACHINE_IS_VM) {
......
...@@ -469,6 +469,8 @@ start: ...@@ -469,6 +469,8 @@ start:
.org 0x10000 .org 0x10000
startup:basr %r13,0 # get base startup:basr %r13,0 # get base
.LPG0: .LPG0:
xc 0x200(256),0x200 # partially clear lowcore
xc 0x300(256),0x300
#ifndef CONFIG_MARCH_G5 #ifndef CONFIG_MARCH_G5
# check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
......
...@@ -20,7 +20,6 @@ startup_continue: ...@@ -20,7 +20,6 @@ startup_continue:
lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore # move IPL device to lowcore
mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
# #
# Setup stack # Setup stack
# #
......
...@@ -86,7 +86,6 @@ startup_continue: ...@@ -86,7 +86,6 @@ startup_continue:
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore # move IPL device to lowcore
mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
lghi %r0,__LC_PASTE lghi %r0,__LC_PASTE
stg %r0,__LC_VDSO_PER_CPU stg %r0,__LC_VDSO_PER_CPU
# #
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/reset.h> #include <asm/reset.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include <asm/setup.h> #include <asm/checksum.h>
#define IPL_PARM_BLOCK_VERSION 0 #define IPL_PARM_BLOCK_VERSION 0
...@@ -56,13 +56,14 @@ struct shutdown_trigger { ...@@ -56,13 +56,14 @@ struct shutdown_trigger {
}; };
/* /*
* Five shutdown action types are supported: * The following shutdown action types are supported:
*/ */
#define SHUTDOWN_ACTION_IPL_STR "ipl" #define SHUTDOWN_ACTION_IPL_STR "ipl"
#define SHUTDOWN_ACTION_REIPL_STR "reipl" #define SHUTDOWN_ACTION_REIPL_STR "reipl"
#define SHUTDOWN_ACTION_DUMP_STR "dump" #define SHUTDOWN_ACTION_DUMP_STR "dump"
#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
#define SHUTDOWN_ACTION_STOP_STR "stop" #define SHUTDOWN_ACTION_STOP_STR "stop"
#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
struct shutdown_action { struct shutdown_action {
char *name; char *name;
...@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; ...@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
static struct ipl_parameter_block *reipl_block_fcp; static struct ipl_parameter_block *reipl_block_fcp;
static struct ipl_parameter_block *reipl_block_ccw; static struct ipl_parameter_block *reipl_block_ccw;
static struct ipl_parameter_block *reipl_block_nss; static struct ipl_parameter_block *reipl_block_nss;
static struct ipl_parameter_block *reipl_block_actual;
static int dump_capabilities = DUMP_TYPE_NONE; static int dump_capabilities = DUMP_TYPE_NONE;
static enum dump_type dump_type = DUMP_TYPE_NONE; static enum dump_type dump_type = DUMP_TYPE_NONE;
...@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type) ...@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_CCW_VM; reipl_method = REIPL_METHOD_CCW_VM;
else else
reipl_method = REIPL_METHOD_CCW_CIO; reipl_method = REIPL_METHOD_CCW_CIO;
reipl_block_actual = reipl_block_ccw;
break; break;
case IPL_TYPE_FCP: case IPL_TYPE_FCP:
if (diag308_set_works) if (diag308_set_works)
...@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type) ...@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_FCP_RO_VM; reipl_method = REIPL_METHOD_FCP_RO_VM;
else else
reipl_method = REIPL_METHOD_FCP_RO_DIAG; reipl_method = REIPL_METHOD_FCP_RO_DIAG;
reipl_block_actual = reipl_block_fcp;
break; break;
case IPL_TYPE_FCP_DUMP: case IPL_TYPE_FCP_DUMP:
reipl_method = REIPL_METHOD_FCP_DUMP; reipl_method = REIPL_METHOD_FCP_DUMP;
...@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type) ...@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_NSS_DIAG; reipl_method = REIPL_METHOD_NSS_DIAG;
else else
reipl_method = REIPL_METHOD_NSS; reipl_method = REIPL_METHOD_NSS;
reipl_block_actual = reipl_block_nss;
break; break;
case IPL_TYPE_UNKNOWN: case IPL_TYPE_UNKNOWN:
reipl_method = REIPL_METHOD_DEFAULT; reipl_method = REIPL_METHOD_DEFAULT;
...@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger) ...@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger)
diag308(DIAG308_IPL, NULL); diag308(DIAG308_IPL, NULL);
break; break;
case REIPL_METHOD_FCP_DUMP: case REIPL_METHOD_FCP_DUMP:
default:
break; break;
} }
disabled_wait((unsigned long) __builtin_return_address(0)); disabled_wait((unsigned long) __builtin_return_address(0));
...@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void) ...@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void)
{ {
int rc; int rc;
if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP)) if (!diag308_set_works) {
return 0; if (ipl_info.type == IPL_TYPE_FCP)
if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP)) make_attrs_ro(reipl_fcp_attrs);
make_attrs_ro(reipl_fcp_attrs); else
return 0;
}
reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
if (!reipl_block_fcp) if (!reipl_block_fcp)
...@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger) ...@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger)
diag308(DIAG308_DUMP, NULL); diag308(DIAG308_DUMP, NULL);
break; break;
case DUMP_METHOD_NONE: case DUMP_METHOD_NONE:
default:
return; return;
} }
printk(KERN_EMERG "Dump failed!\n"); printk(KERN_EMERG "Dump failed!\n");
...@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = { ...@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = {
.init = dump_init, .init = dump_init,
}; };
static void dump_reipl_run(struct shutdown_trigger *trigger)
{
preempt_disable();
/*
* Bypass dynamic address translation (DAT) when storing IPL parameter
* information block address and checksum into the prefix area
* (corresponding to absolute addresses 0-8191).
* When enhanced DAT applies and the STE format control in one,
* the absolute address is formed without prefixing. In this case a
* normal store (stg/st) into the prefix area would no more match to
* absolute addresses 0-8191.
*/
#ifdef CONFIG_64BIT
asm volatile("sturg %0,%1"
:: "a" ((unsigned long) reipl_block_actual),
"a" (&lowcore_ptr[smp_processor_id()]->ipib));
#else
asm volatile("stura %0,%1"
:: "a" ((unsigned long) reipl_block_actual),
"a" (&lowcore_ptr[smp_processor_id()]->ipib));
#endif
asm volatile("stura %0,%1"
:: "a" (csum_partial(reipl_block_actual,
reipl_block_actual->hdr.len, 0)),
"a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
preempt_enable();
dump_run(trigger);
}
static int __init dump_reipl_init(void)
{
if (!diag308_set_works)
return -EOPNOTSUPP;
else
return 0;
}
static struct shutdown_action __refdata dump_reipl_action = {
.name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
.fn = dump_reipl_run,
.init = dump_reipl_init,
};
/* /*
* vmcmd shutdown action: Trigger vm command on shutdown. * vmcmd shutdown action: Trigger vm command on shutdown.
*/ */
...@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, ...@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
/* action list */ /* action list */
static struct shutdown_action *shutdown_actions_list[] = { static struct shutdown_action *shutdown_actions_list[] = {
&ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
&vmcmd_action, &stop_action};
#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
/* /*
...@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, ...@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
size_t len) size_t len)
{ {
int i; int i;
for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
if (!shutdown_actions_list[i]) if (!shutdown_actions_list[i])
continue; continue;
if (strncmp(buf, shutdown_actions_list[i]->name, if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
strlen(shutdown_actions_list[i]->name)) == 0) {
trigger->action = shutdown_actions_list[i]; trigger->action = shutdown_actions_list[i];
return len; return len;
} }
...@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self, ...@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self,
static struct notifier_block on_panic_nb = { static struct notifier_block on_panic_nb = {
.notifier_call = on_panic_notify, .notifier_call = on_panic_notify,
.priority = 0, .priority = INT_MIN,
}; };
void __init setup_ipl(void) void __init setup_ipl(void)
...@@ -1696,7 +1745,6 @@ void __init setup_ipl(void) ...@@ -1696,7 +1745,6 @@ void __init setup_ipl(void)
sizeof(ipl_info.data.nss.name)); sizeof(ipl_info.data.nss.name));
break; break;
case IPL_TYPE_UNKNOWN: case IPL_TYPE_UNKNOWN:
default:
/* We have no info to copy */ /* We have no info to copy */
break; break;
} }
......
...@@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, ...@@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
info->plt_initialized = 1; info->plt_initialized = 1;
} }
if (r_type == R_390_PLTOFF16 || if (r_type == R_390_PLTOFF16 ||
r_type == R_390_PLTOFF32 r_type == R_390_PLTOFF32 ||
|| r_type == R_390_PLTOFF64 r_type == R_390_PLTOFF64)
)
val = me->arch.plt_offset - me->arch.got_offset + val = me->arch.plt_offset - me->arch.got_offset +
info->plt_offset + rela->r_addend; info->plt_offset + rela->r_addend;
else else {
val = (Elf_Addr) me->module_core + if (!((r_type == R_390_PLT16DBL &&
me->arch.plt_offset + info->plt_offset + val - loc + 0xffffUL < 0x1ffffeUL) ||
rela->r_addend - loc; (r_type == R_390_PLT32DBL &&
val - loc + 0xffffffffULL < 0x1fffffffeULL)))
val = (Elf_Addr) me->module_core +
me->arch.plt_offset +
info->plt_offset;
val += rela->r_addend - loc;
}
if (r_type == R_390_PLT16DBL) if (r_type == R_390_PLT16DBL)
*(unsigned short *) loc = val >> 1; *(unsigned short *) loc = val >> 1;
else if (r_type == R_390_PLTOFF16) else if (r_type == R_390_PLTOFF16)
......
/* /*
* arch/s390/kernel/process.c * This file handles the architecture dependent parts of process handling.
* *
* S390 version * Copyright IBM Corp. 1999,2009
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Hartmut Penner <hp@de.ibm.com>,
* Hartmut Penner (hp@de.ibm.com), * Denis Joseph Barrow,
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
*
* Derived from "arch/i386/kernel/process.c"
* Copyright (C) 1995, Linus Torvalds
*/
/*
* This file handles the architecture-dependent parts of process handling..
*/ */
#include <linux/compiler.h> #include <linux/compiler.h>
...@@ -47,6 +39,7 @@ ...@@ -47,6 +39,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/nmi.h>
#include "entry.h" #include "entry.h"
asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
...@@ -76,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) ...@@ -76,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return sf->gprs[8]; return sf->gprs[8];
} }
extern void s390_handle_mcck(void);
/* /*
* The idle loop on a S390... * The idle loop on a S390...
*/ */
...@@ -149,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -149,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
0, &regs, 0, NULL, NULL); 0, &regs, 0, NULL, NULL);
} }
EXPORT_SYMBOL(kernel_thread);
/* /*
* Free current thread data structures etc.. * Free current thread data structures etc..
...@@ -168,34 +161,35 @@ void release_thread(struct task_struct *dead_task) ...@@ -168,34 +161,35 @@ void release_thread(struct task_struct *dead_task)
} }
int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
unsigned long unused, unsigned long unused,
struct task_struct * p, struct pt_regs * regs) struct task_struct *p, struct pt_regs *regs)
{ {
struct fake_frame struct thread_info *ti;
{ struct fake_frame
struct stack_frame sf; {
struct pt_regs childregs; struct stack_frame sf;
} *frame; struct pt_regs childregs;
} *frame;
frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
p->thread.ksp = (unsigned long) frame; frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
p->thread.ksp = (unsigned long) frame;
/* Store access registers to kernel stack of new process. */ /* Store access registers to kernel stack of new process. */
frame->childregs = *regs; frame->childregs = *regs;
frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */
frame->childregs.gprs[15] = new_stackp; frame->childregs.gprs[15] = new_stackp;
frame->sf.back_chain = 0; frame->sf.back_chain = 0;
/* new return point is ret_from_fork */ /* new return point is ret_from_fork */
frame->sf.gprs[8] = (unsigned long) ret_from_fork; frame->sf.gprs[8] = (unsigned long) ret_from_fork;
/* fake return stack for resume(), don't go back to schedule */ /* fake return stack for resume(), don't go back to schedule */
frame->sf.gprs[9] = (unsigned long) frame; frame->sf.gprs[9] = (unsigned long) frame;
/* Save access registers to new thread structure. */ /* Save access registers to new thread structure. */
save_access_regs(&p->thread.acrs[0]); save_access_regs(&p->thread.acrs[0]);
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
/* /*
* save fprs to current->thread.fp_regs to merge them with * save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the child. * the emulated registers and then copy the result to the child.
*/ */
...@@ -220,10 +214,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -220,10 +214,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
/* start new process with ar4 pointing to the correct address space */ /* start new process with ar4 pointing to the correct address space */
p->thread.mm_segment = get_fs(); p->thread.mm_segment = get_fs();
/* Don't copy debug registers */ /* Don't copy debug registers */
memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));
/* Initialize per thread user and system timer values */
return 0; ti = task_thread_info(p);
ti->user_timer = 0;
ti->system_timer = 0;
return 0;
} }
SYSCALL_DEFINE0(fork) SYSCALL_DEFINE0(fork)
...@@ -311,7 +308,7 @@ SYSCALL_DEFINE0(execve) ...@@ -311,7 +308,7 @@ SYSCALL_DEFINE0(execve)
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{ {
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
/* /*
* save fprs to current->thread.fp_regs to merge them with * save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the dump. * the emulated registers and then copy the result to the dump.
*/ */
...@@ -322,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) ...@@ -322,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
return 1; return 1;
} }
EXPORT_SYMBOL(dump_fpu);
unsigned long get_wchan(struct task_struct *p) unsigned long get_wchan(struct task_struct *p)
{ {
...@@ -346,4 +344,3 @@ unsigned long get_wchan(struct task_struct *p) ...@@ -346,4 +344,3 @@ unsigned long get_wchan(struct task_struct *p)
} }
return 0; return 0;
} }
...@@ -18,10 +18,11 @@ ...@@ -18,10 +18,11 @@
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/param.h> #include <asm/param.h>
void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) void __cpuinit print_cpu_info(void)
{ {
pr_info("Processor %d started, address %d, identification %06X\n", pr_info("Processor %d started, address %d, identification %06X\n",
cpuinfo->cpu_nr, cpuinfo->cpu_addr, cpuinfo->cpu_id.ident); S390_lowcore.cpu_nr, S390_lowcore.cpu_addr,
S390_lowcore.cpu_id.ident);
} }
/* /*
...@@ -30,48 +31,46 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) ...@@ -30,48 +31,46 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v) static int show_cpuinfo(struct seq_file *m, void *v)
{ {
static const char *hwcap_str[8] = { static const char *hwcap_str[9] = {
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
"edat" "edat", "etf3eh"
}; };
struct cpuinfo_S390 *cpuinfo; struct _lowcore *lc;
unsigned long n = (unsigned long) v - 1; unsigned long n = (unsigned long) v - 1;
int i; int i;
s390_adjust_jiffies(); s390_adjust_jiffies();
preempt_disable(); preempt_disable();
if (!n) { if (!n) {
seq_printf(m, "vendor_id : IBM/S390\n" seq_printf(m, "vendor_id : IBM/S390\n"
"# processors : %i\n" "# processors : %i\n"
"bogomips per cpu: %lu.%02lu\n", "bogomips per cpu: %lu.%02lu\n",
num_online_cpus(), loops_per_jiffy/(500000/HZ), num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100); (loops_per_jiffy/(5000/HZ))%100);
seq_puts(m, "features\t: "); seq_puts(m, "features\t: ");
for (i = 0; i < 8; i++) for (i = 0; i < 9; i++)
if (hwcap_str[i] && (elf_hwcap & (1UL << i))) if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
seq_printf(m, "%s ", hwcap_str[i]); seq_printf(m, "%s ", hwcap_str[i]);
seq_puts(m, "\n"); seq_puts(m, "\n");
} }
if (cpu_online(n)) { if (cpu_online(n)) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (smp_processor_id() == n) lc = (smp_processor_id() == n) ?
cpuinfo = &S390_lowcore.cpu_data; &S390_lowcore : lowcore_ptr[n];
else
cpuinfo = &lowcore_ptr[n]->cpu_data;
#else #else
cpuinfo = &S390_lowcore.cpu_data; lc = &S390_lowcore;
#endif #endif
seq_printf(m, "processor %li: " seq_printf(m, "processor %li: "
"version = %02X, " "version = %02X, "
"identification = %06X, " "identification = %06X, "
"machine = %04X\n", "machine = %04X\n",
n, cpuinfo->cpu_id.version, n, lc->cpu_id.version,
cpuinfo->cpu_id.ident, lc->cpu_id.ident,
cpuinfo->cpu_id.machine); lc->cpu_id.machine);
} }
preempt_enable(); preempt_enable();
return 0; return 0;
} }
static void *c_start(struct seq_file *m, loff_t *pos) static void *c_start(struct seq_file *m, loff_t *pos)
......
/* /*
* arch/s390/kernel/reipl.S * Copyright IBM Corp 2000,2009
* * Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
* S390 version * Denis Joseph Barrow,
* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*/ */
#include <asm/lowcore.h> #include <asm/lowcore.h>
...@@ -30,7 +27,7 @@ do_reipl_asm: basr %r13,0 ...@@ -30,7 +27,7 @@ do_reipl_asm: basr %r13,0
mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10) mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
stckc .Lclkcmp-.Lpg0(%r13) stckc .Lclkcmp-.Lpg0(%r13)
mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13)
stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
......
/*
* arch/s390/kernel/s390_ksyms.c
*
* S390 version
*/
#include <linux/highuid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/syscalls.h>
#include <linux/interrupt.h>
#include <asm/checksum.h>
#include <asm/cpcmd.h>
#include <asm/delay.h>
#include <asm/pgalloc.h>
#include <asm/setup.h>
#include <asm/ftrace.h> #include <asm/ftrace.h>
#ifdef CONFIG_IP_MULTICAST
#include <net/arp.h>
#endif
/*
* memory management
*/
EXPORT_SYMBOL(_oi_bitmap);
EXPORT_SYMBOL(_ni_bitmap);
EXPORT_SYMBOL(_zb_findmap);
EXPORT_SYMBOL(_sb_findmap);
/*
* binfmt_elf loader
*/
extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(empty_zero_page);
/*
* misc.
*/
EXPORT_SYMBOL(machine_flags);
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(csum_fold);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_devno);
EXPORT_SYMBOL(console_irq);
#ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_FUNCTION_TRACER
EXPORT_SYMBOL(_mcount); EXPORT_SYMBOL(_mcount);
......
...@@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess); ...@@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess);
* Machine setup.. * Machine setup..
*/ */
unsigned int console_mode = 0; unsigned int console_mode = 0;
EXPORT_SYMBOL(console_mode);
unsigned int console_devno = -1; unsigned int console_devno = -1;
EXPORT_SYMBOL(console_devno);
unsigned int console_irq = -1; unsigned int console_irq = -1;
EXPORT_SYMBOL(console_irq);
unsigned long machine_flags; unsigned long machine_flags;
EXPORT_SYMBOL(machine_flags);
unsigned long elf_hwcap = 0; unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE]; char elf_platform[ELF_PLATFORM_SIZE];
...@@ -86,6 +94,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ ...@@ -86,6 +94,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
int __initdata memory_end_set; int __initdata memory_end_set;
unsigned long __initdata memory_end; unsigned long __initdata memory_end;
/* An array with a pointer to the lowcore of every CPU. */
struct _lowcore *lowcore_ptr[NR_CPUS];
EXPORT_SYMBOL(lowcore_ptr);
/* /*
* This is set up by the setup-routine at boot-time * This is set up by the setup-routine at boot-time
* for S390 need to find out, what we have to setup * for S390 need to find out, what we have to setup
...@@ -109,13 +121,10 @@ static struct resource data_resource = { ...@@ -109,13 +121,10 @@ static struct resource data_resource = {
*/ */
void __cpuinit cpu_init(void) void __cpuinit cpu_init(void)
{ {
int addr = hard_smp_processor_id();
/* /*
* Store processor id in lowcore (used e.g. in timer_interrupt) * Store processor id in lowcore (used e.g. in timer_interrupt)
*/ */
get_cpu_id(&S390_lowcore.cpu_data.cpu_id); get_cpu_id(&S390_lowcore.cpu_id);
S390_lowcore.cpu_data.cpu_addr = addr;
/* /*
* Force FPU initialization: * Force FPU initialization:
...@@ -125,8 +134,7 @@ void __cpuinit cpu_init(void) ...@@ -125,8 +134,7 @@ void __cpuinit cpu_init(void)
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
if (current->mm) BUG_ON(current->mm);
BUG();
enter_lazy_tlb(&init_mm, current); enter_lazy_tlb(&init_mm, current);
} }
...@@ -217,7 +225,7 @@ static void __init conmode_default(void) ...@@ -217,7 +225,7 @@ static void __init conmode_default(void)
} }
} }
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) #ifdef CONFIG_ZFCPDUMP
static void __init setup_zfcpdump(unsigned int console_devno) static void __init setup_zfcpdump(unsigned int console_devno)
{ {
static char str[41]; static char str[41];
...@@ -289,11 +297,7 @@ static int __init early_parse_mem(char *p) ...@@ -289,11 +297,7 @@ static int __init early_parse_mem(char *p)
early_param("mem", early_parse_mem); early_param("mem", early_parse_mem);
#ifdef CONFIG_S390_SWITCH_AMODE #ifdef CONFIG_S390_SWITCH_AMODE
#ifdef CONFIG_PGSTE
unsigned int switch_amode = 1;
#else
unsigned int switch_amode = 0; unsigned int switch_amode = 0;
#endif
EXPORT_SYMBOL_GPL(switch_amode); EXPORT_SYMBOL_GPL(switch_amode);
static int set_amode_and_uaccess(unsigned long user_amode, static int set_amode_and_uaccess(unsigned long user_amode,
...@@ -414,7 +418,6 @@ setup_lowcore(void) ...@@ -414,7 +418,6 @@ setup_lowcore(void)
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
lc->clock_comparator = -1ULL; lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long) lc->async_stack = (unsigned long)
...@@ -434,6 +437,7 @@ setup_lowcore(void) ...@@ -434,6 +437,7 @@ setup_lowcore(void)
lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
#endif #endif
set_prefix((u32)(unsigned long) lc); set_prefix((u32)(unsigned long) lc);
lowcore_ptr[0] = lc;
} }
static void __init static void __init
...@@ -510,7 +514,7 @@ static void __init setup_memory_end(void) ...@@ -510,7 +514,7 @@ static void __init setup_memory_end(void)
unsigned long max_mem; unsigned long max_mem;
int i; int i;
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) #ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP) { if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
memory_end = ZFCPDUMP_HSA_SIZE; memory_end = ZFCPDUMP_HSA_SIZE;
memory_end_set = 1; memory_end_set = 1;
...@@ -677,7 +681,6 @@ setup_memory(void) ...@@ -677,7 +681,6 @@ setup_memory(void)
static void __init setup_hwcaps(void) static void __init setup_hwcaps(void)
{ {
static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
unsigned long long facility_list_extended; unsigned long long facility_list_extended;
unsigned int facility_list; unsigned int facility_list;
int i; int i;
...@@ -693,15 +696,22 @@ static void __init setup_hwcaps(void) ...@@ -693,15 +696,22 @@ static void __init setup_hwcaps(void)
* Bit 17: the message-security assist is installed * Bit 17: the message-security assist is installed
* Bit 19: the long-displacement facility is installed * Bit 19: the long-displacement facility is installed
* Bit 21: the extended-immediate facility is installed * Bit 21: the extended-immediate facility is installed
* Bit 22: extended-translation facility 3 is installed
* Bit 30: extended-translation facility 3 enhancement facility
* These get translated to: * These get translated to:
* HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
* HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
* HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5. * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and
* HWCAP_S390_ETF3EH bit 8 (22 && 30).
*/ */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
if (facility_list & (1UL << (31 - stfl_bits[i]))) if (facility_list & (1UL << (31 - stfl_bits[i])))
elf_hwcap |= 1UL << i; elf_hwcap |= 1UL << i;
if ((facility_list & (1UL << (31 - 22)))
&& (facility_list & (1UL << (31 - 30))))
elf_hwcap |= 1UL << 8;
/* /*
* Check for additional facilities with store-facility-list-extended. * Check for additional facilities with store-facility-list-extended.
* stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
...@@ -710,20 +720,22 @@ static void __init setup_hwcaps(void) ...@@ -710,20 +720,22 @@ static void __init setup_hwcaps(void)
* How many facility words are stored depends on the number of * How many facility words are stored depends on the number of
* doublewords passed to the instruction. The additional facilites * doublewords passed to the instruction. The additional facilites
* are: * are:
* Bit 43: decimal floating point facility is installed * Bit 42: decimal floating point facility is installed
* Bit 44: perform floating point operation facility is installed
* translated to: * translated to:
* HWCAP_S390_DFP bit 6. * HWCAP_S390_DFP bit 6 (42 && 44).
*/ */
if ((elf_hwcap & (1UL << 2)) && if ((elf_hwcap & (1UL << 2)) &&
__stfle(&facility_list_extended, 1) > 0) { __stfle(&facility_list_extended, 1) > 0) {
if (facility_list_extended & (1ULL << (64 - 43))) if ((facility_list_extended & (1ULL << (63 - 42)))
&& (facility_list_extended & (1ULL << (63 - 44))))
elf_hwcap |= 1UL << 6; elf_hwcap |= 1UL << 6;
} }
if (MACHINE_HAS_HPAGE) if (MACHINE_HAS_HPAGE)
elf_hwcap |= 1UL << 7; elf_hwcap |= 1UL << 7;
switch (cpuinfo->cpu_id.machine) { switch (S390_lowcore.cpu_id.machine) {
case 0x9672: case 0x9672:
#if !defined(CONFIG_64BIT) #if !defined(CONFIG_64BIT)
default: /* Use "g5" as default for 31 bit kernels. */ default: /* Use "g5" as default for 31 bit kernels. */
...@@ -816,7 +828,7 @@ setup_arch(char **cmdline_p) ...@@ -816,7 +828,7 @@ setup_arch(char **cmdline_p)
setup_lowcore(); setup_lowcore();
cpu_init(); cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; __cpu_logical_map[0] = stap();
s390_init_cpu_topology(); s390_init_cpu_topology();
/* /*
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irqflags.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
...@@ -50,12 +51,6 @@ ...@@ -50,12 +51,6 @@
#include <asm/vdso.h> #include <asm/vdso.h>
#include "entry.h" #include "entry.h"
/*
* An array with a pointer the lowcore of every CPU.
*/
struct _lowcore *lowcore_ptr[NR_CPUS];
EXPORT_SYMBOL(lowcore_ptr);
static struct task_struct *current_set[NR_CPUS]; static struct task_struct *current_set[NR_CPUS];
static u8 smp_cpu_type; static u8 smp_cpu_type;
...@@ -81,9 +76,7 @@ void smp_send_stop(void) ...@@ -81,9 +76,7 @@ void smp_send_stop(void)
/* Disable all interrupts/machine checks */ /* Disable all interrupts/machine checks */
__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
trace_hardirqs_off();
/* write magic number to zero page (absolute 0) */
lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
/* stop all processors */ /* stop all processors */
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
...@@ -233,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); ...@@ -233,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
*/ */
#define CPU_INIT_NO 1 #define CPU_INIT_NO 1
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) #ifdef CONFIG_ZFCPDUMP
/* /*
* zfcpdump_prefix_array holds prefix registers for the following scenario: * zfcpdump_prefix_array holds prefix registers for the following scenario:
...@@ -274,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas); ...@@ -274,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ #endif /* CONFIG_ZFCPDUMP */
static int cpu_stopped(int cpu) static int cpu_stopped(int cpu)
{ {
...@@ -304,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) ...@@ -304,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
{ {
int cpu_id, logical_cpu; int cpu_id, logical_cpu;
logical_cpu = first_cpu(avail); logical_cpu = cpumask_first(&avail);
if (logical_cpu == NR_CPUS) if (logical_cpu >= nr_cpu_ids)
return 0; return 0;
for (cpu_id = 0; cpu_id <= 65535; cpu_id++) { for (cpu_id = 0; cpu_id <= 65535; cpu_id++) {
if (cpu_known(cpu_id)) if (cpu_known(cpu_id))
...@@ -316,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) ...@@ -316,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
continue; continue;
cpu_set(logical_cpu, cpu_present_map); cpu_set(logical_cpu, cpu_present_map);
smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
logical_cpu = next_cpu(logical_cpu, avail); logical_cpu = cpumask_next(logical_cpu, &avail);
if (logical_cpu == NR_CPUS) if (logical_cpu >= nr_cpu_ids)
break; break;
} }
return 0; return 0;
...@@ -329,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) ...@@ -329,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
int cpu_id, logical_cpu, cpu; int cpu_id, logical_cpu, cpu;
int rc; int rc;
logical_cpu = first_cpu(avail); logical_cpu = cpumask_first(&avail);
if (logical_cpu == NR_CPUS) if (logical_cpu >= nr_cpu_ids)
return 0; return 0;
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
...@@ -351,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) ...@@ -351,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
else else
smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
logical_cpu = next_cpu(logical_cpu, avail); logical_cpu = cpumask_next(logical_cpu, &avail);
if (logical_cpu == NR_CPUS) if (logical_cpu >= nr_cpu_ids)
break; break;
} }
out: out:
...@@ -379,7 +372,7 @@ static void __init smp_detect_cpus(void) ...@@ -379,7 +372,7 @@ static void __init smp_detect_cpus(void)
c_cpus = 1; c_cpus = 1;
s_cpus = 0; s_cpus = 0;
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; boot_cpu_addr = __cpu_logical_map[0];
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
panic("smp_detect_cpus failed to allocate memory\n"); panic("smp_detect_cpus failed to allocate memory\n");
...@@ -453,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid) ...@@ -453,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid)
/* Switch on interrupts */ /* Switch on interrupts */
local_irq_enable(); local_irq_enable();
/* Print info about this processor */ /* Print info about this processor */
print_cpu_info(&S390_lowcore.cpu_data); print_cpu_info();
/* cpu_idle will call schedule for us */ /* cpu_idle will call schedule for us */
cpu_idle(); cpu_idle();
return 0; return 0;
...@@ -515,7 +508,6 @@ static int __cpuinit smp_alloc_lowcore(int cpu) ...@@ -515,7 +508,6 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_HOTPLUG_CPU
static void smp_free_lowcore(int cpu) static void smp_free_lowcore(int cpu)
{ {
struct _lowcore *lowcore; struct _lowcore *lowcore;
...@@ -534,7 +526,6 @@ static void smp_free_lowcore(int cpu) ...@@ -534,7 +526,6 @@ static void smp_free_lowcore(int cpu)
free_pages((unsigned long) lowcore, lc_order); free_pages((unsigned long) lowcore, lc_order);
lowcore_ptr[cpu] = NULL; lowcore_ptr[cpu] = NULL;
} }
#endif /* CONFIG_HOTPLUG_CPU */
/* Upping and downing of CPUs */ /* Upping and downing of CPUs */
int __cpuinit __cpu_up(unsigned int cpu) int __cpuinit __cpu_up(unsigned int cpu)
...@@ -543,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -543,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu)
struct _lowcore *cpu_lowcore; struct _lowcore *cpu_lowcore;
struct stack_frame *sf; struct stack_frame *sf;
sigp_ccode ccode; sigp_ccode ccode;
u32 lowcore;
if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
return -EIO; return -EIO;
if (smp_alloc_lowcore(cpu)) if (smp_alloc_lowcore(cpu))
return -ENOMEM; return -ENOMEM;
do {
ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), ccode = signal_processor(cpu, sigp_initial_cpu_reset);
cpu, sigp_set_prefix); if (ccode == sigp_busy)
if (ccode) udelay(10);
return -EIO; if (ccode == sigp_not_operational)
goto err_out;
} while (ccode == sigp_busy);
lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
udelay(10);
idle = current_set[cpu]; idle = current_set[cpu];
cpu_lowcore = lowcore_ptr[cpu]; cpu_lowcore = lowcore_ptr[cpu];
...@@ -571,9 +569,8 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -571,9 +569,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
: : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); : : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
cpu_lowcore->current_task = (unsigned long) idle; cpu_lowcore->current_task = (unsigned long) idle;
cpu_lowcore->cpu_data.cpu_nr = cpu; cpu_lowcore->cpu_nr = cpu;
cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
eieio(); eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy) while (signal_processor(cpu, sigp_restart) == sigp_busy)
...@@ -582,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -582,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
while (!cpu_online(cpu)) while (!cpu_online(cpu))
cpu_relax(); cpu_relax();
return 0; return 0;
err_out:
smp_free_lowcore(cpu);
return -EIO;
} }
static int __init setup_possible_cpus(char *s) static int __init setup_possible_cpus(char *s)
...@@ -589,9 +590,8 @@ static int __init setup_possible_cpus(char *s) ...@@ -589,9 +590,8 @@ static int __init setup_possible_cpus(char *s)
int pcpus, cpu; int pcpus, cpu;
pcpus = simple_strtoul(s, NULL, 0); pcpus = simple_strtoul(s, NULL, 0);
cpu_possible_map = cpumask_of_cpu(0); for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++) set_cpu_possible(cpu, true);
cpu_set(cpu, cpu_possible_map);
return 0; return 0;
} }
early_param("possible_cpus", setup_possible_cpus); early_param("possible_cpus", setup_possible_cpus);
...@@ -663,7 +663,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -663,7 +663,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* request the 0x1201 emergency signal external interrupt */ /* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201"); panic("Couldn't request external interrupt 0x1201");
print_cpu_info(&S390_lowcore.cpu_data); print_cpu_info();
/* Reallocate current lowcore, but keep its contents. */ /* Reallocate current lowcore, but keep its contents. */
lc_order = sizeof(long) == 8 ? 1 : 0; lc_order = sizeof(long) == 8 ? 1 : 0;
......
/* /*
* drivers/s390/sysinfo.c * Copyright IBM Corp. 2001, 2009
* * Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
* Copyright IBM Corp. 2001, 2008 * Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com)
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -24,7 +22,7 @@ ...@@ -24,7 +22,7 @@
static inline int stsi_0(void) static inline int stsi_0(void)
{ {
int rc = stsi (NULL, 0, 0, 0); int rc = stsi(NULL, 0, 0, 0);
return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
} }
...@@ -78,23 +76,6 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) ...@@ -78,23 +76,6 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
return len; return len;
} }
#if 0 /* Currently unused */
static int stsi_1_2_1(struct sysinfo_1_2_1 *info, char *page, int len)
{
if (stsi(info, 1, 2, 1) == -ENOSYS)
return len;
len += sprintf(page + len, "\n");
EBCASC(info->sequence, sizeof(info->sequence));
EBCASC(info->plant, sizeof(info->plant));
len += sprintf(page + len, "Sequence Code of CPU: %-16.16s\n",
info->sequence);
len += sprintf(page + len, "Plant of CPU: %-16.16s\n",
info->plant);
return len;
}
#endif
static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
{ {
struct sysinfo_1_2_2_extension *ext; struct sysinfo_1_2_2_extension *ext;
...@@ -145,33 +126,15 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) ...@@ -145,33 +126,15 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
if (info->secondary_capability != 0) if (info->secondary_capability != 0)
len += sprintf(page + len, "Secondary Capability: %d\n", len += sprintf(page + len, "Secondary Capability: %d\n",
info->secondary_capability); info->secondary_capability);
return len; return len;
} }
#if 0 /* Currently unused */
static int stsi_2_2_1(struct sysinfo_2_2_1 *info, char *page, int len)
{
if (stsi(info, 2, 2, 1) == -ENOSYS)
return len;
len += sprintf(page + len, "\n");
EBCASC (info->sequence, sizeof(info->sequence));
EBCASC (info->plant, sizeof(info->plant));
len += sprintf(page + len, "Sequence Code of logical CPU: %-16.16s\n",
info->sequence);
len += sprintf(page + len, "Plant of logical CPU: %-16.16s\n",
info->plant);
return len;
}
#endif
static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len)
{ {
if (stsi(info, 2, 2, 2) == -ENOSYS) if (stsi(info, 2, 2, 2) == -ENOSYS)
return len; return len;
EBCASC (info->name, sizeof(info->name)); EBCASC(info->name, sizeof(info->name));
len += sprintf(page + len, "\n"); len += sprintf(page + len, "\n");
len += sprintf(page + len, "LPAR Number: %d\n", len += sprintf(page + len, "LPAR Number: %d\n",
...@@ -214,8 +177,8 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) ...@@ -214,8 +177,8 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
if (stsi(info, 3, 2, 2) == -ENOSYS) if (stsi(info, 3, 2, 2) == -ENOSYS)
return len; return len;
for (i = 0; i < info->count; i++) { for (i = 0; i < info->count; i++) {
EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
len += sprintf(page + len, "\n"); len += sprintf(page + len, "\n");
len += sprintf(page + len, "VM%02d Name: %-8.8s\n", len += sprintf(page + len, "VM%02d Name: %-8.8s\n",
i, info->vm[i].name); i, info->vm[i].name);
...@@ -237,14 +200,13 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) ...@@ -237,14 +200,13 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
return len; return len;
} }
static int proc_read_sysinfo(char *page, char **start, static int proc_read_sysinfo(char *page, char **start,
off_t off, int count, off_t off, int count,
int *eof, void *data) int *eof, void *data)
{ {
unsigned long info = get_zeroed_page (GFP_KERNEL); unsigned long info = get_zeroed_page(GFP_KERNEL);
int level, len; int level, len;
if (!info) if (!info)
return 0; return 0;
...@@ -262,8 +224,8 @@ static int proc_read_sysinfo(char *page, char **start, ...@@ -262,8 +224,8 @@ static int proc_read_sysinfo(char *page, char **start,
if (level >= 3) if (level >= 3)
len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len);
free_page (info); free_page(info);
return len; return len;
} }
static __init int create_proc_sysinfo(void) static __init int create_proc_sysinfo(void)
...@@ -272,8 +234,7 @@ static __init int create_proc_sysinfo(void) ...@@ -272,8 +234,7 @@ static __init int create_proc_sysinfo(void)
proc_read_sysinfo, NULL); proc_read_sysinfo, NULL);
return 0; return 0;
} }
device_initcall(create_proc_sysinfo);
__initcall(create_proc_sysinfo);
/* /*
* Service levels interface. * Service levels interface.
...@@ -387,13 +348,11 @@ static __init int create_proc_service_level(void) ...@@ -387,13 +348,11 @@ static __init int create_proc_service_level(void)
register_service_level(&service_level_vm); register_service_level(&service_level_vm);
return 0; return 0;
} }
subsys_initcall(create_proc_service_level); subsys_initcall(create_proc_service_level);
/* /*
* Bogomips calculation based on cpu capability. * Bogomips calculation based on cpu capability.
*/ */
int get_cpu_capability(unsigned int *capability) int get_cpu_capability(unsigned int *capability)
{ {
struct sysinfo_1_2_2 *info; struct sysinfo_1_2_2 *info;
......
...@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old, ...@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old,
} }
static DEFINE_PER_CPU(atomic_t, clock_sync_word); static DEFINE_PER_CPU(atomic_t, clock_sync_word);
static DEFINE_MUTEX(clock_sync_mutex);
static unsigned long clock_sync_flags; static unsigned long clock_sync_flags;
#define CLOCK_SYNC_HAS_ETR 0 #define CLOCK_SYNC_HAS_ETR 0
...@@ -394,6 +395,20 @@ static void enable_sync_clock(void) ...@@ -394,6 +395,20 @@ static void enable_sync_clock(void)
atomic_set_mask(0x80000000, sw_ptr); atomic_set_mask(0x80000000, sw_ptr);
} }
/*
* Function to check if the clock is in sync.
*/
static inline int check_sync_clock(void)
{
atomic_t *sw_ptr;
int rc;
sw_ptr = &get_cpu_var(clock_sync_word);
rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
put_cpu_var(clock_sync_sync);
return rc;
}
/* Single threaded workqueue used for etr and stp sync events */ /* Single threaded workqueue used for etr and stp sync events */
static struct workqueue_struct *time_sync_wq; static struct workqueue_struct *time_sync_wq;
...@@ -485,6 +500,8 @@ static void etr_reset(void) ...@@ -485,6 +500,8 @@ static void etr_reset(void)
if (etr_setr(&etr_eacr) == 0) { if (etr_setr(&etr_eacr) == 0) {
etr_tolec = get_clock(); etr_tolec = get_clock();
set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags); set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
if (etr_port0_online && etr_port1_online)
set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
} else if (etr_port0_online || etr_port1_online) { } else if (etr_port0_online || etr_port1_online) {
pr_warning("The real or virtual hardware system does " pr_warning("The real or virtual hardware system does "
"not provide an ETR interface\n"); "not provide an ETR interface\n");
...@@ -533,8 +550,7 @@ void etr_switch_to_local(void) ...@@ -533,8 +550,7 @@ void etr_switch_to_local(void)
{ {
if (!etr_eacr.sl) if (!etr_eacr.sl)
return; return;
if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) disable_sync_clock(NULL);
disable_sync_clock(NULL);
set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
queue_work(time_sync_wq, &etr_work); queue_work(time_sync_wq, &etr_work);
} }
...@@ -549,8 +565,7 @@ void etr_sync_check(void) ...@@ -549,8 +565,7 @@ void etr_sync_check(void)
{ {
if (!etr_eacr.es) if (!etr_eacr.es)
return; return;
if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) disable_sync_clock(NULL);
disable_sync_clock(NULL);
set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
queue_work(time_sync_wq, &etr_work); queue_work(time_sync_wq, &etr_work);
} }
...@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib, ...@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
* Do not try to get the alternate port aib if the clock * Do not try to get the alternate port aib if the clock
* is not in sync yet. * is not in sync yet.
*/ */
if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es) if (!check_sync_clock())
return eacr; return eacr;
/* /*
...@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work) ...@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work)
on_each_cpu(disable_sync_clock, NULL, 1); on_each_cpu(disable_sync_clock, NULL, 1);
del_timer_sync(&etr_timer); del_timer_sync(&etr_timer);
etr_update_eacr(eacr); etr_update_eacr(eacr);
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
goto out_unlock; goto out_unlock;
} }
...@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work) ...@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work)
/* Both ports not usable. */ /* Both ports not usable. */
eacr.es = eacr.sl = 0; eacr.es = eacr.sl = 0;
sync_port = -1; sync_port = -1;
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
} }
if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
eacr.es = 0;
/* /*
* If the clock is in sync just update the eacr and return. * If the clock is in sync just update the eacr and return.
* If there is no valid sync port wait for a port update. * If there is no valid sync port wait for a port update.
*/ */
if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) || if (check_sync_clock() || sync_port < 0) {
eacr.es || sync_port < 0) {
etr_update_eacr(eacr); etr_update_eacr(eacr);
etr_set_tolec_timeout(now); etr_set_tolec_timeout(now);
goto out_unlock; goto out_unlock;
...@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work) ...@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work)
* and set up a timer to try again after 0.5 seconds * and set up a timer to try again after 0.5 seconds
*/ */
etr_update_eacr(eacr); etr_update_eacr(eacr);
set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
if (now < etr_tolec + (1600000 << 12) || if (now < etr_tolec + (1600000 << 12) ||
etr_sync_clock_stop(&aib, sync_port) != 0) { etr_sync_clock_stop(&aib, sync_port) != 0) {
/* Sync failed. Try again in 1/2 second. */ /* Sync failed. Try again in 1/2 second. */
eacr.es = 0; eacr.es = 0;
etr_update_eacr(eacr); etr_update_eacr(eacr);
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
etr_set_sync_timeout(); etr_set_sync_timeout();
} else } else
etr_set_tolec_timeout(now); etr_set_tolec_timeout(now);
...@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev, ...@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev,
return -EINVAL; return -EINVAL;
if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags)) if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&clock_sync_mutex);
if (dev == &etr_port0_dev) { if (dev == &etr_port0_dev) {
if (etr_port0_online == value) if (etr_port0_online == value)
return count; /* Nothing to do. */ goto out; /* Nothing to do. */
etr_port0_online = value; etr_port0_online = value;
if (etr_port0_online && etr_port1_online)
set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
else
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
queue_work(time_sync_wq, &etr_work); queue_work(time_sync_wq, &etr_work);
} else { } else {
if (etr_port1_online == value) if (etr_port1_online == value)
return count; /* Nothing to do. */ goto out; /* Nothing to do. */
etr_port1_online = value; etr_port1_online = value;
if (etr_port0_online && etr_port1_online)
set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
else
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
queue_work(time_sync_wq, &etr_work); queue_work(time_sync_wq, &etr_work);
} }
out:
mutex_unlock(&clock_sync_mutex);
return count; return count;
} }
...@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm) ...@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm)
*/ */
void stp_sync_check(void) void stp_sync_check(void)
{ {
if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
return;
disable_sync_clock(NULL); disable_sync_clock(NULL);
queue_work(time_sync_wq, &stp_work); queue_work(time_sync_wq, &stp_work);
} }
...@@ -1485,8 +1501,6 @@ void stp_sync_check(void) ...@@ -1485,8 +1501,6 @@ void stp_sync_check(void)
*/ */
void stp_island_check(void) void stp_island_check(void)
{ {
if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
return;
disable_sync_clock(NULL); disable_sync_clock(NULL);
queue_work(time_sync_wq, &stp_work); queue_work(time_sync_wq, &stp_work);
} }
...@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data) ...@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data)
enable_sync_clock(); enable_sync_clock();
set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
queue_work(time_sync_wq, &etr_work);
rc = 0; rc = 0;
if (stp_info.todoff[0] || stp_info.todoff[1] || if (stp_info.todoff[0] || stp_info.todoff[1] ||
stp_info.todoff[2] || stp_info.todoff[3] || stp_info.todoff[2] || stp_info.todoff[3] ||
...@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data) ...@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data)
if (rc) { if (rc) {
disable_sync_clock(NULL); disable_sync_clock(NULL);
stp_sync->in_sync = -EAGAIN; stp_sync->in_sync = -EAGAIN;
clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
if (etr_port0_online || etr_port1_online)
queue_work(time_sync_wq, &etr_work);
} else } else
stp_sync->in_sync = 1; stp_sync->in_sync = 1;
xchg(&first, 0); xchg(&first, 0);
...@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work) ...@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work)
if (rc || stp_info.c == 0) if (rc || stp_info.c == 0)
goto out_unlock; goto out_unlock;
/* Skip synchronization if the clock is already in sync. */
if (check_sync_clock())
goto out_unlock;
memset(&stp_sync, 0, sizeof(stp_sync)); memset(&stp_sync, 0, sizeof(stp_sync));
get_online_cpus(); get_online_cpus();
atomic_set(&stp_sync.cpus, num_online_cpus() - 1); atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
...@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class, ...@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class,
return -EINVAL; return -EINVAL;
if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&clock_sync_mutex);
stp_online = value; stp_online = value;
if (stp_online)
set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
else
clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
queue_work(time_sync_wq, &stp_work); queue_work(time_sync_wq, &stp_work);
mutex_unlock(&clock_sync_mutex);
return count; return count;
} }
......
...@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock); ...@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock);
cpumask_t cpu_core_map[NR_CPUS]; cpumask_t cpu_core_map[NR_CPUS];
cpumask_t cpu_coregroup_map(unsigned int cpu) static cpumask_t cpu_coregroup_map(unsigned int cpu)
{ {
struct core_info *core = &core_info; struct core_info *core = &core_info;
unsigned long flags; unsigned long flags;
......
...@@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception; ...@@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception;
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
#define LONG "%08lx "
#define FOURLONG "%08lx %08lx %08lx %08lx\n" #define FOURLONG "%08lx %08lx %08lx %08lx\n"
static int kstack_depth_to_print = 12; static int kstack_depth_to_print = 12;
#else /* CONFIG_64BIT */ #else /* CONFIG_64BIT */
#define LONG "%016lx "
#define FOURLONG "%016lx %016lx %016lx %016lx\n" #define FOURLONG "%016lx %016lx %016lx %016lx\n"
static int kstack_depth_to_print = 20; static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
...@@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) ...@@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
break; break;
if (i && ((i * sizeof (long) % 32) == 0)) if (i && ((i * sizeof (long) % 32) == 0))
printk("\n "); printk("\n ");
printk("%p ", (void *)*stack++); printk(LONG, *stack++);
} }
printk("\n"); printk("\n");
show_trace(task, sp); show_trace(task, sp);
......
...@@ -144,7 +144,6 @@ int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore) ...@@ -144,7 +144,6 @@ int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_HOTPLUG_CPU
void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
{ {
unsigned long segment_table, page_table, page_frame; unsigned long segment_table, page_table, page_frame;
...@@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) ...@@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
free_page(page_table); free_page(page_table);
free_pages(segment_table, SEGMENT_ORDER); free_pages(segment_table, SEGMENT_ORDER);
} }
#endif /* CONFIG_HOTPLUG_CPU */
static void __vdso_init_cr5(void *dummy) static void __vdso_init_cr5(void *dummy)
{ {
......
...@@ -108,6 +108,8 @@ SECTIONS ...@@ -108,6 +108,8 @@ SECTIONS
EXIT_TEXT EXIT_TEXT
} }
/* early.c uses stsi, which requires page aligned data. */
. = ALIGN(PAGE_SIZE);
.init.data : { .init.data : {
INIT_DATA INIT_DATA
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/nmi.h>
#include "kvm-s390.h" #include "kvm-s390.h"
#include "gaccess.h" #include "gaccess.h"
...@@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) ...@@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup, setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
(unsigned long) vcpu); (unsigned long) vcpu);
get_cpu_id(&vcpu->arch.cpu_id); get_cpu_id(&vcpu->arch.cpu_id);
vcpu->arch.cpu_id.version = 0xfe; vcpu->arch.cpu_id.version = 0xff;
return 0; return 0;
} }
...@@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, ...@@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
return -EINVAL; /* not implemented yet */ return -EINVAL; /* not implemented yet */
} }
extern void s390_handle_mcck(void);
static void __vcpu_run(struct kvm_vcpu *vcpu) static void __vcpu_run(struct kvm_vcpu *vcpu)
{ {
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/module.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -92,6 +93,7 @@ void __udelay(unsigned long usecs) ...@@ -92,6 +93,7 @@ void __udelay(unsigned long usecs)
local_irq_restore(flags); local_irq_restore(flags);
preempt_enable(); preempt_enable();
} }
EXPORT_SYMBOL(__udelay);
/* /*
* Simple udelay variant. To be used on startup and reboot * Simple udelay variant. To be used on startup and reboot
......
...@@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n) ...@@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n)
*/ */
size_t strlen(const char *s) size_t strlen(const char *s)
{ {
#if __GNUC__ < 4
return __strend(s) - s; return __strend(s) - s;
#else
return __builtin_strlen(s);
#endif
} }
EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strlen);
...@@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen); ...@@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen);
*/ */
char *strcpy(char *dest, const char *src) char *strcpy(char *dest, const char *src)
{ {
#if __GNUC__ < 4
register int r0 asm("0") = 0; register int r0 asm("0") = 0;
char *ret = dest; char *ret = dest;
...@@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src) ...@@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src)
: "+&a" (dest), "+&a" (src) : "d" (r0) : "+&a" (dest), "+&a" (src) : "d" (r0)
: "cc", "memory" ); : "cc", "memory" );
return ret; return ret;
#else
return __builtin_strcpy(dest, src);
#endif
} }
EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strcpy);
......
...@@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code) ...@@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code)
do_no_context(regs, error_code, 0); do_no_context(regs, error_code, 0);
} }
/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
*/
static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code,
unsigned long address)
{
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
up_read(&mm->mmap_sem);
if (is_global_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
return 1;
}
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_MASK_PSTATE)
do_group_exit(SIGKILL);
do_no_context(regs, error_code, address);
return 0;
}
static void do_sigbus(struct pt_regs *regs, unsigned long error_code, static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
unsigned long address) unsigned long address)
{ {
...@@ -367,7 +344,6 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write) ...@@ -367,7 +344,6 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
goto bad_area; goto bad_area;
} }
survive:
if (is_vm_hugetlb_page(vma)) if (is_vm_hugetlb_page(vma))
address &= HPAGE_MASK; address &= HPAGE_MASK;
/* /*
...@@ -378,8 +354,8 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write) ...@@ -378,8 +354,8 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
fault = handle_mm_fault(mm, vma, address, write); fault = handle_mm_fault(mm, vma, address, write);
if (unlikely(fault & VM_FAULT_ERROR)) { if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM) { if (fault & VM_FAULT_OOM) {
if (do_out_of_memory(regs, error_code, address)) up_read(&mm->mmap_sem);
goto survive; pagefault_out_of_memory();
return; return;
} else if (fault & VM_FAULT_SIGBUS) { } else if (fault & VM_FAULT_SIGBUS) {
do_sigbus(regs, error_code, address); do_sigbus(regs, error_code, address);
......
...@@ -40,7 +40,9 @@ ...@@ -40,7 +40,9 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
EXPORT_SYMBOL(empty_zero_page);
/* /*
* paging_init() sets up the page tables * paging_init() sets up the page tables
......
...@@ -258,6 +258,10 @@ int s390_enable_sie(void) ...@@ -258,6 +258,10 @@ int s390_enable_sie(void)
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct mm_struct *mm, *old_mm; struct mm_struct *mm, *old_mm;
/* Do we have switched amode? If no, we cannot do sie */
if (!switch_amode)
return -EINVAL;
/* Do we have pgstes? if yes, we are done */ /* Do we have pgstes? if yes, we are done */
if (tsk->mm->context.has_pgste) if (tsk->mm->context.has_pgste)
return 0; return 0;
...@@ -292,7 +296,7 @@ int s390_enable_sie(void) ...@@ -292,7 +296,7 @@ int s390_enable_sie(void)
tsk->mm = tsk->active_mm = mm; tsk->mm = tsk->active_mm = mm;
preempt_disable(); preempt_disable();
update_mm(mm, tsk); update_mm(mm, tsk);
cpu_set(smp_processor_id(), mm->cpu_vm_mask); cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
preempt_enable(); preempt_enable();
task_unlock(tsk); task_unlock(tsk);
mmput(old_mm); mmput(old_mm);
......
...@@ -13,10 +13,11 @@ ...@@ -13,10 +13,11 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <linux/ctype.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mempool.h> #include <linux/mempool.h>
#include <linux/module.h> #include <linux/moduleparam.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <net/iucv/iucv.h> #include <net/iucv/iucv.h>
...@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1; ...@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1;
/* Array of allocated hvc iucv tty lines... */ /* Array of allocated hvc iucv tty lines... */
static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
#define IUCV_HVC_CON_IDX (0) #define IUCV_HVC_CON_IDX (0)
/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
#define MAX_VMID_FILTER (500)
static size_t hvc_iucv_filter_size;
static void *hvc_iucv_filter;
static const char *hvc_iucv_filter_string;
static DEFINE_RWLOCK(hvc_iucv_filter_lock);
/* Kmem cache and mempool for iucv_tty_buffer elements */ /* Kmem cache and mempool for iucv_tty_buffer elements */
static struct kmem_cache *hvc_iucv_buffer_cache; static struct kmem_cache *hvc_iucv_buffer_cache;
...@@ -617,6 +624,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) ...@@ -617,6 +624,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
} }
} }
/**
* hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
* @ipvmid: Originating z/VM user ID (right padded with blanks)
*
* Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise
* non-zero.
*/
static int hvc_iucv_filter_connreq(u8 ipvmid[8])
{
size_t i;
/* Note: default policy is ACCEPT if no filter is set */
if (!hvc_iucv_filter_size)
return 0;
for (i = 0; i < hvc_iucv_filter_size; i++)
if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8))
return 0;
return 1;
}
/** /**
* hvc_iucv_path_pending() - IUCV handler to process a connection request. * hvc_iucv_path_pending() - IUCV handler to process a connection request.
* @path: Pending path (struct iucv_path) * @path: Pending path (struct iucv_path)
...@@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path, ...@@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
{ {
struct hvc_iucv_private *priv; struct hvc_iucv_private *priv;
u8 nuser_data[16]; u8 nuser_data[16];
u8 vm_user_id[9];
int i, rc; int i, rc;
priv = NULL; priv = NULL;
...@@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path, ...@@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
if (!priv) if (!priv)
return -ENODEV; return -ENODEV;
/* Enforce that ipvmid is allowed to connect to us */
read_lock(&hvc_iucv_filter_lock);
rc = hvc_iucv_filter_connreq(ipvmid);
read_unlock(&hvc_iucv_filter_lock);
if (rc) {
iucv_path_sever(path, ipuser);
iucv_path_free(path);
memcpy(vm_user_id, ipvmid, 8);
vm_user_id[8] = 0;
pr_info("A connection request from z/VM user ID %s "
"was refused\n", vm_user_id);
return 0;
}
spin_lock(&priv->lock); spin_lock(&priv->lock);
/* If the terminal is already connected or being severed, then sever /* If the terminal is already connected or being severed, then sever
...@@ -876,6 +919,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) ...@@ -876,6 +919,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
return 0; return 0;
} }
/**
* hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
* @filter: String containing a comma-separated list of z/VM user IDs
*/
static const char *hvc_iucv_parse_filter(const char *filter, char *dest)
{
const char *nextdelim, *residual;
size_t len;
nextdelim = strchr(filter, ',');
if (nextdelim) {
len = nextdelim - filter;
residual = nextdelim + 1;
} else {
len = strlen(filter);
residual = filter + len;
}
if (len == 0)
return ERR_PTR(-EINVAL);
/* check for '\n' (if called from sysfs) */
if (filter[len - 1] == '\n')
len--;
if (len > 8)
return ERR_PTR(-EINVAL);
/* pad with blanks and save upper case version of user ID */
memset(dest, ' ', 8);
while (len--)
dest[len] = toupper(filter[len]);
return residual;
}
/**
* hvc_iucv_setup_filter() - Set up z/VM user ID filter
* @filter: String consisting of a comma-separated list of z/VM user IDs
*
* The function parses the @filter string and creates an array containing
* the list of z/VM user ID filter entries.
* Return code 0 means success, -EINVAL if the filter is syntactically
* incorrect, -ENOMEM if there was not enough memory to allocate the
* filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
*/
static int hvc_iucv_setup_filter(const char *val)
{
const char *residual;
int err;
size_t size, count;
void *array, *old_filter;
count = strlen(val);
if (count == 0 || (count == 1 && val[0] == '\n')) {
size = 0;
array = NULL;
goto out_replace_filter; /* clear filter */
}
/* count user IDs in order to allocate sufficient memory */
size = 1;
residual = val;
while ((residual = strchr(residual, ',')) != NULL) {
residual++;
size++;
}
/* check if the specified list exceeds the filter limit */
if (size > MAX_VMID_FILTER)
return -ENOSPC;
array = kzalloc(size * 8, GFP_KERNEL);
if (!array)
return -ENOMEM;
count = size;
residual = val;
while (*residual && count) {
residual = hvc_iucv_parse_filter(residual,
array + ((size - count) * 8));
if (IS_ERR(residual)) {
err = PTR_ERR(residual);
kfree(array);
goto out_err;
}
count--;
}
out_replace_filter:
write_lock_bh(&hvc_iucv_filter_lock);
old_filter = hvc_iucv_filter;
hvc_iucv_filter_size = size;
hvc_iucv_filter = array;
write_unlock_bh(&hvc_iucv_filter_lock);
kfree(old_filter);
err = 0;
out_err:
return err;
}
/**
* param_set_vmidfilter() - Set z/VM user ID filter parameter
* @val: String consisting of a comma-separated list of z/VM user IDs
* @kp: Kernel parameter pointing to hvc_iucv_filter array
*
* The function sets up the z/VM user ID filter specified as comma-separated
* list of user IDs in @val.
* Note: If it is called early in the boot process, @val is stored and
* parsed later in hvc_iucv_init().
*/
static int param_set_vmidfilter(const char *val, struct kernel_param *kp)
{
int rc;
if (!MACHINE_IS_VM || !hvc_iucv_devices)
return -ENODEV;
if (!val)
return -EINVAL;
rc = 0;
if (slab_is_available())
rc = hvc_iucv_setup_filter(val);
else
hvc_iucv_filter_string = val; /* defer... */
return rc;
}
/**
* param_get_vmidfilter() - Get z/VM user ID filter
* @buffer: Buffer to store z/VM user ID filter,
* (buffer size assumption PAGE_SIZE)
* @kp: Kernel parameter pointing to the hvc_iucv_filter array
*
* The function stores the filter as a comma-separated list of z/VM user IDs
* in @buffer. Typically, sysfs routines call this function for attr show.
*/
static int param_get_vmidfilter(char *buffer, struct kernel_param *kp)
{
int rc;
size_t index, len;
void *start, *end;
if (!MACHINE_IS_VM || !hvc_iucv_devices)
return -ENODEV;
rc = 0;
read_lock_bh(&hvc_iucv_filter_lock);
for (index = 0; index < hvc_iucv_filter_size; index++) {
start = hvc_iucv_filter + (8 * index);
end = memchr(start, ' ', 8);
len = (end) ? end - start : 8;
memcpy(buffer + rc, start, len);
rc += len;
buffer[rc++] = ',';
}
read_unlock_bh(&hvc_iucv_filter_lock);
if (rc)
buffer[--rc] = '\0'; /* replace last comma and update rc */
return rc;
}
#define param_check_vmidfilter(name, p) __param_check(name, p, void)
/** /**
* hvc_iucv_init() - z/VM IUCV HVC device driver initialization * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
*/ */
...@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void) ...@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void)
int rc; int rc;
unsigned int i; unsigned int i;
if (!hvc_iucv_devices)
return -ENODEV;
if (!MACHINE_IS_VM) { if (!MACHINE_IS_VM) {
pr_info("The z/VM IUCV HVC device driver cannot " pr_notice("The z/VM IUCV HVC device driver cannot "
"be used without z/VM\n"); "be used without z/VM\n");
return -ENODEV; rc = -ENODEV;
goto out_error;
} }
if (!hvc_iucv_devices) if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) {
return -ENODEV; pr_err("%lu is not a valid value for the hvc_iucv= "
"kernel parameter\n", hvc_iucv_devices);
rc = -EINVAL;
goto out_error;
}
if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) /* parse hvc_iucv_allow string and create z/VM user ID filter list */
return -EINVAL; if (hvc_iucv_filter_string) {
rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
switch (rc) {
case 0:
break;
case -ENOMEM:
pr_err("Allocating memory failed with "
"reason code=%d\n", 3);
goto out_error;
case -EINVAL:
pr_err("hvc_iucv_allow= does not specify a valid "
"z/VM user ID list\n");
goto out_error;
case -ENOSPC:
pr_err("hvc_iucv_allow= specifies too many "
"z/VM user IDs\n");
goto out_error;
default:
goto out_error;
}
}
hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
sizeof(struct iucv_tty_buffer), sizeof(struct iucv_tty_buffer),
0, 0, NULL); 0, 0, NULL);
if (!hvc_iucv_buffer_cache) { if (!hvc_iucv_buffer_cache) {
pr_err("Allocating memory failed with reason code=%d\n", 1); pr_err("Allocating memory failed with reason code=%d\n", 1);
return -ENOMEM; rc = -ENOMEM;
goto out_error;
} }
hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
...@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void) ...@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void)
if (!hvc_iucv_mempool) { if (!hvc_iucv_mempool) {
pr_err("Allocating memory failed with reason code=%d\n", 2); pr_err("Allocating memory failed with reason code=%d\n", 2);
kmem_cache_destroy(hvc_iucv_buffer_cache); kmem_cache_destroy(hvc_iucv_buffer_cache);
return -ENOMEM; rc = -ENOMEM;
goto out_error;
} }
/* register the first terminal device as console /* register the first terminal device as console
...@@ -953,6 +1191,8 @@ static int __init hvc_iucv_init(void) ...@@ -953,6 +1191,8 @@ static int __init hvc_iucv_init(void)
out_error_memory: out_error_memory:
mempool_destroy(hvc_iucv_mempool); mempool_destroy(hvc_iucv_mempool);
kmem_cache_destroy(hvc_iucv_buffer_cache); kmem_cache_destroy(hvc_iucv_buffer_cache);
out_error:
hvc_iucv_devices = 0; /* ensure that we do not provide any device */
return rc; return rc;
} }
...@@ -968,3 +1208,4 @@ static int __init hvc_iucv_config(char *val) ...@@ -968,3 +1208,4 @@ static int __init hvc_iucv_config(char *val)
device_initcall(hvc_iucv_init); device_initcall(hvc_iucv_init);
__setup("hvc_iucv=", hvc_iucv_config); __setup("hvc_iucv=", hvc_iucv_config);
core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640);
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
# Makefile for the S/390 specific device drivers # Makefile for the S/390 specific device drivers
# #
CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
obj-y += s390mach.o sysinfo.o
obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
drivers-y += drivers/s390/built-in.o drivers-y += drivers/s390/built-in.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* Author(s): Stefan Weinhuber <wein@de.ibm.com> * Author(s): Stefan Weinhuber <wein@de.ibm.com>
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/list.h> #include <linux/list.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include "dasd_int.h" #include "dasd_int.h"
...@@ -503,7 +505,7 @@ static void lcu_update_work(struct work_struct *work) ...@@ -503,7 +505,7 @@ static void lcu_update_work(struct work_struct *work)
*/ */
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
if (rc || (lcu->flags & NEED_UAC_UPDATE)) { if (rc || (lcu->flags & NEED_UAC_UPDATE)) {
DEV_MESSAGE(KERN_WARNING, device, "could not update" DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
" alias data in lcu (rc = %d), retry later", rc); " alias data in lcu (rc = %d), retry later", rc);
schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
} else { } else {
...@@ -646,14 +648,16 @@ static int reset_summary_unit_check(struct alias_lcu *lcu, ...@@ -646,14 +648,16 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
{ {
struct dasd_ccw_req *cqr; struct dasd_ccw_req *cqr;
int rc = 0; int rc = 0;
struct ccw1 *ccw;
cqr = lcu->rsu_cqr; cqr = lcu->rsu_cqr;
strncpy((char *) &cqr->magic, "ECKD", 4); strncpy((char *) &cqr->magic, "ECKD", 4);
ASCEBC((char *) &cqr->magic, 4); ASCEBC((char *) &cqr->magic, 4);
cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RSCK; ccw = cqr->cpaddr;
cqr->cpaddr->flags = 0 ; ccw->cmd_code = DASD_ECKD_CCW_RSCK;
cqr->cpaddr->count = 16; ccw->flags = 0 ;
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; ccw->count = 16;
ccw->cda = (__u32)(addr_t) cqr->data;
((char *)cqr->data)[0] = reason; ((char *)cqr->data)[0] = reason;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
...@@ -855,16 +859,25 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, ...@@ -855,16 +859,25 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
struct alias_lcu *lcu; struct alias_lcu *lcu;
char reason; char reason;
struct dasd_eckd_private *private; struct dasd_eckd_private *private;
char *sense;
private = (struct dasd_eckd_private *) device->private; private = (struct dasd_eckd_private *) device->private;
reason = irb->ecw[8]; sense = dasd_get_sense(irb);
DEV_MESSAGE(KERN_WARNING, device, "%s %x", if (sense) {
"eckd handle summary unit check: reason", reason); reason = sense[8];
DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x",
"eckd handle summary unit check: reason", reason);
} else {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"eckd handle summary unit check:"
" no reason code available");
return;
}
lcu = private->lcu; lcu = private->lcu;
if (!lcu) { if (!lcu) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"device not ready to handle summary" "device not ready to handle summary"
" unit check (no lcu structure)"); " unit check (no lcu structure)");
return; return;
...@@ -877,7 +890,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, ...@@ -877,7 +890,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
* the next interrupt on a different device * the next interrupt on a different device
*/ */
if (list_empty(&device->alias_list)) { if (list_empty(&device->alias_list)) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"device is in offline processing," "device is in offline processing,"
" don't do summary unit check handling"); " don't do summary unit check handling");
spin_unlock(&lcu->lock); spin_unlock(&lcu->lock);
...@@ -885,7 +898,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, ...@@ -885,7 +898,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
} }
if (lcu->suc_data.device) { if (lcu->suc_data.device) {
/* already scheduled or running */ /* already scheduled or running */
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"previous instance of summary unit check worker" "previous instance of summary unit check worker"
" still pending"); " still pending");
spin_unlock(&lcu->lock); spin_unlock(&lcu->lock);
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* *
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -67,6 +69,8 @@ int dasd_probeonly = 0; /* is true, when probeonly mode is active */ ...@@ -67,6 +69,8 @@ int dasd_probeonly = 0; /* is true, when probeonly mode is active */
int dasd_autodetect = 0; /* is true, when autodetection is active */ int dasd_autodetect = 0; /* is true, when autodetection is active */
int dasd_nopav = 0; /* is true, when PAV is disabled */ int dasd_nopav = 0; /* is true, when PAV is disabled */
EXPORT_SYMBOL_GPL(dasd_nopav); EXPORT_SYMBOL_GPL(dasd_nopav);
int dasd_nofcx; /* disable High Performance Ficon */
EXPORT_SYMBOL_GPL(dasd_nofcx);
/* /*
* char *dasd[] is intended to hold the ranges supplied by the dasd= statement * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
...@@ -125,6 +129,7 @@ __setup ("dasd=", dasd_call_setup); ...@@ -125,6 +129,7 @@ __setup ("dasd=", dasd_call_setup);
* Read a device busid/devno from a string. * Read a device busid/devno from a string.
*/ */
static int static int
dasd_busid(char **str, int *id0, int *id1, int *devno) dasd_busid(char **str, int *id0, int *id1, int *devno)
{ {
int val, old_style; int val, old_style;
...@@ -132,8 +137,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) ...@@ -132,8 +137,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno)
/* Interpret ipldev busid */ /* Interpret ipldev busid */
if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) { if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
if (ipl_info.type != IPL_TYPE_CCW) { if (ipl_info.type != IPL_TYPE_CCW) {
MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw " pr_err("The IPL device is not a CCW device\n");
"device");
return -EINVAL; return -EINVAL;
} }
*id0 = 0; *id0 = 0;
...@@ -209,9 +213,8 @@ dasd_feature_list(char *str, char **endp) ...@@ -209,9 +213,8 @@ dasd_feature_list(char *str, char **endp)
else if (len == 8 && !strncmp(str, "failfast", 8)) else if (len == 8 && !strncmp(str, "failfast", 8))
features |= DASD_FEATURE_FAILFAST; features |= DASD_FEATURE_FAILFAST;
else { else {
MESSAGE(KERN_WARNING, pr_warning("%*s is not a supported device option\n",
"unsupported feature: %*s, " len, str);
"ignoring setting", len, str);
rc = -EINVAL; rc = -EINVAL;
} }
str += len; str += len;
...@@ -220,8 +223,8 @@ dasd_feature_list(char *str, char **endp) ...@@ -220,8 +223,8 @@ dasd_feature_list(char *str, char **endp)
str++; str++;
} }
if (*str != ')') { if (*str != ')') {
MESSAGE(KERN_WARNING, "%s", pr_warning("A closing parenthesis ')' is missing in the "
"missing ')' in dasd parameter string\n"); "dasd= parameter\n");
rc = -EINVAL; rc = -EINVAL;
} else } else
str++; str++;
...@@ -253,25 +256,29 @@ dasd_parse_keyword( char *parsestring ) { ...@@ -253,25 +256,29 @@ dasd_parse_keyword( char *parsestring ) {
} }
if (strncmp("autodetect", parsestring, length) == 0) { if (strncmp("autodetect", parsestring, length) == 0) {
dasd_autodetect = 1; dasd_autodetect = 1;
MESSAGE (KERN_INFO, "%s", pr_info("The autodetection mode has been activated\n");
"turning to autodetection mode");
return residual_str; return residual_str;
} }
if (strncmp("probeonly", parsestring, length) == 0) { if (strncmp("probeonly", parsestring, length) == 0) {
dasd_probeonly = 1; dasd_probeonly = 1;
MESSAGE(KERN_INFO, "%s", pr_info("The probeonly mode has been activated\n");
"turning to probeonly mode");
return residual_str; return residual_str;
} }
if (strncmp("nopav", parsestring, length) == 0) { if (strncmp("nopav", parsestring, length) == 0) {
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM"); pr_info("'nopav' is not supported on z/VM\n");
else { else {
dasd_nopav = 1; dasd_nopav = 1;
MESSAGE(KERN_INFO, "%s", "disable PAV mode"); pr_info("PAV support has be deactivated\n");
} }
return residual_str; return residual_str;
} }
if (strncmp("nofcx", parsestring, length) == 0) {
dasd_nofcx = 1;
pr_info("High Performance FICON support has been "
"deactivated\n");
return residual_str;
}
if (strncmp("fixedbuffers", parsestring, length) == 0) { if (strncmp("fixedbuffers", parsestring, length) == 0) {
if (dasd_page_cache) if (dasd_page_cache)
return residual_str; return residual_str;
...@@ -280,10 +287,10 @@ dasd_parse_keyword( char *parsestring ) { ...@@ -280,10 +287,10 @@ dasd_parse_keyword( char *parsestring ) {
PAGE_SIZE, SLAB_CACHE_DMA, PAGE_SIZE, SLAB_CACHE_DMA,
NULL); NULL);
if (!dasd_page_cache) if (!dasd_page_cache)
MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, "
"fixed buffer mode disabled."); "fixed buffer mode disabled.");
else else
MESSAGE (KERN_INFO, "%s", DBF_EVENT(DBF_INFO, "%s",
"turning on fixed buffer mode"); "turning on fixed buffer mode");
return residual_str; return residual_str;
} }
...@@ -321,7 +328,7 @@ dasd_parse_range( char *parsestring ) { ...@@ -321,7 +328,7 @@ dasd_parse_range( char *parsestring ) {
(from_id0 != to_id0 || from_id1 != to_id1 || from > to)) (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
rc = -EINVAL; rc = -EINVAL;
if (rc) { if (rc) {
MESSAGE(KERN_ERR, "Invalid device range %s", parsestring); pr_err("%s is not a valid device range\n", parsestring);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
features = dasd_feature_list(str, &str); features = dasd_feature_list(str, &str);
...@@ -340,8 +347,8 @@ dasd_parse_range( char *parsestring ) { ...@@ -340,8 +347,8 @@ dasd_parse_range( char *parsestring ) {
return str + 1; return str + 1;
if (*str == '\0') if (*str == '\0')
return str; return str;
MESSAGE(KERN_WARNING, pr_warning("The dasd= parameter value %s has an invalid ending\n",
"junk at end of dasd parameter string: %s\n", str); str);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* *
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -144,8 +146,8 @@ dasd_diag_erp(struct dasd_device *device) ...@@ -144,8 +146,8 @@ dasd_diag_erp(struct dasd_device *device)
mdsk_term_io(device); mdsk_term_io(device);
rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
if (rc) if (rc)
DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " dev_warn(&device->cdev->dev, "DIAG ERP failed with "
"rc=%d", rc); "rc=%d\n", rc);
} }
/* Start a given request at the device. Return zero on success, non-zero /* Start a given request at the device. Return zero on success, non-zero
...@@ -160,7 +162,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) ...@@ -160,7 +162,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
device = cqr->startdev; device = cqr->startdev;
if (cqr->retries < 0) { if (cqr->retries < 0) {
DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " DBF_DEV_EVENT(DBF_ERR, device, "DIAG start_IO: request %p "
"- no retry left)", cqr); "- no retry left)", cqr);
cqr->status = DASD_CQR_ERROR; cqr->status = DASD_CQR_ERROR;
return -EIO; return -EIO;
...@@ -195,7 +197,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) ...@@ -195,7 +197,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
break; break;
default: /* Error condition */ default: /* Error condition */
cqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_QUEUED;
DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc); DBF_DEV_EVENT(DBF_WARNING, device, "dia250 returned rc=%d", rc);
dasd_diag_erp(device); dasd_diag_erp(device);
rc = -EIO; rc = -EIO;
break; break;
...@@ -243,13 +245,14 @@ dasd_ext_handler(__u16 code) ...@@ -243,13 +245,14 @@ dasd_ext_handler(__u16 code)
return; return;
} }
if (!ip) { /* no intparm: unsolicited interrupt */ if (!ip) { /* no intparm: unsolicited interrupt */
MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
"interrupt");
return; return;
} }
cqr = (struct dasd_ccw_req *) ip; cqr = (struct dasd_ccw_req *) ip;
device = (struct dasd_device *) cqr->startdev; device = (struct dasd_device *) cqr->startdev;
if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
DEV_MESSAGE(KERN_WARNING, device, DBF_DEV_EVENT(DBF_WARNING, device,
" magic number of dasd_ccw_req 0x%08X doesn't" " magic number of dasd_ccw_req 0x%08X doesn't"
" match discipline 0x%08X", " match discipline 0x%08X",
cqr->magic, *(int *) (&device->discipline->name)); cqr->magic, *(int *) (&device->discipline->name));
...@@ -281,15 +284,11 @@ dasd_ext_handler(__u16 code) ...@@ -281,15 +284,11 @@ dasd_ext_handler(__u16 code)
rc = dasd_start_diag(next); rc = dasd_start_diag(next);
if (rc == 0) if (rc == 0)
expires = next->expires; expires = next->expires;
else if (rc != -EACCES)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"Interrupt fastpath "
"failed!");
} }
} }
} else { } else {
cqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_QUEUED;
DEV_MESSAGE(KERN_WARNING, device, "interrupt status for " DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
"request %p was %d (%d retries left)", cqr, status, "request %p was %d (%d retries left)", cqr, status,
cqr->retries); cqr->retries);
dasd_diag_erp(device); dasd_diag_erp(device);
...@@ -322,8 +321,9 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -322,8 +321,9 @@ dasd_diag_check_device(struct dasd_device *device)
if (private == NULL) { if (private == NULL) {
private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);
if (private == NULL) { if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"memory allocation failed for private data"); "Allocating memory for private DASD data "
"failed\n");
return -ENOMEM; return -ENOMEM;
} }
ccw_device_get_id(device->cdev, &private->dev_id); ccw_device_get_id(device->cdev, &private->dev_id);
...@@ -331,7 +331,7 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -331,7 +331,7 @@ dasd_diag_check_device(struct dasd_device *device)
} }
block = dasd_alloc_block(); block = dasd_alloc_block();
if (IS_ERR(block)) { if (IS_ERR(block)) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"could not allocate dasd block structure"); "could not allocate dasd block structure");
device->private = NULL; device->private = NULL;
kfree(private); kfree(private);
...@@ -347,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -347,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device)
rc = diag210((struct diag210 *) rdc_data); rc = diag210((struct diag210 *) rdc_data);
if (rc) { if (rc) {
DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device " DBF_DEV_EVENT(DBF_WARNING, device, "failed to retrieve device "
"information (rc=%d)", rc); "information (rc=%d)", rc);
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out; goto out;
...@@ -362,8 +362,8 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -362,8 +362,8 @@ dasd_diag_check_device(struct dasd_device *device)
private->pt_block = 2; private->pt_block = 2;
break; break;
default: default:
DEV_MESSAGE(KERN_WARNING, device, "unsupported device class " dev_warn(&device->cdev->dev, "Device type %d is not supported "
"(class=%d)", private->rdc_data.vdev_class); "in DIAG mode\n", private->rdc_data.vdev_class);
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out; goto out;
} }
...@@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device)
/* figure out blocksize of device */ /* figure out blocksize of device */
label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
if (label == NULL) { if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"No memory to allocate initialization request"); "No memory to allocate initialization request");
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
...@@ -404,8 +404,8 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -404,8 +404,8 @@ dasd_diag_check_device(struct dasd_device *device)
private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
rc = dia250(&private->iob, RW_BIO); rc = dia250(&private->iob, RW_BIO);
if (rc == 3) { if (rc == 3) {
DEV_MESSAGE(KERN_WARNING, device, "%s", dev_warn(&device->cdev->dev,
"DIAG call failed"); "A 64-bit DIAG call failed\n");
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out_label; goto out_label;
} }
...@@ -414,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -414,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device)
break; break;
} }
if (bsize > PAGE_SIZE) { if (bsize > PAGE_SIZE) {
DEV_MESSAGE(KERN_WARNING, device, "device access failed " dev_warn(&device->cdev->dev, "Accessing the DASD failed because"
"(rc=%d)", rc); " of an incorrect format (rc=%d)\n", rc);
rc = -EIO; rc = -EIO;
goto out_label; goto out_label;
} }
...@@ -433,15 +433,15 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -433,15 +433,15 @@ dasd_diag_check_device(struct dasd_device *device)
block->s2b_shift++; block->s2b_shift++;
rc = mdsk_init_io(device, block->bp_block, 0, NULL); rc = mdsk_init_io(device, block->bp_block, 0, NULL);
if (rc) { if (rc) {
DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " dev_warn(&device->cdev->dev, "DIAG initialization "
"failed (rc=%d)", rc); "failed with rc=%d\n", rc);
rc = -EIO; rc = -EIO;
} else { } else {
DEV_MESSAGE(KERN_INFO, device, dev_info(&device->cdev->dev,
"(%ld B/blk): %ldkB", "New DASD with %ld byte/block, total size %ld KB\n",
(unsigned long) block->bp_block, (unsigned long) block->bp_block,
(unsigned long) (block->blocks << (unsigned long) (block->blocks <<
block->s2b_shift) >> 1); block->s2b_shift) >> 1);
} }
out_label: out_label:
free_page((long) label); free_page((long) label);
...@@ -595,7 +595,7 @@ static void ...@@ -595,7 +595,7 @@ static void
dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
struct irb *stat) struct irb *stat)
{ {
DEV_MESSAGE(KERN_ERR, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"dump sense not available for DIAG data"); "dump sense not available for DIAG data");
} }
...@@ -621,10 +621,8 @@ static int __init ...@@ -621,10 +621,8 @@ static int __init
dasd_diag_init(void) dasd_diag_init(void)
{ {
if (!MACHINE_IS_VM) { if (!MACHINE_IS_VM) {
MESSAGE_LOG(KERN_INFO, pr_info("Discipline %s cannot be used without z/VM\n",
"Machine is not VM: %s " dasd_diag_discipline.name);
"discipline not initializing",
dasd_diag_discipline.name);
return -ENODEV; return -ENODEV;
} }
ASCEBC(dasd_diag_discipline.ebcname, 4); ASCEBC(dasd_diag_discipline.ebcname, 4);
......
This diff is collapsed.
...@@ -38,8 +38,11 @@ ...@@ -38,8 +38,11 @@
#define DASD_ECKD_CCW_RELEASE 0x94 #define DASD_ECKD_CCW_RELEASE 0x94
#define DASD_ECKD_CCW_READ_CKD_MT 0x9e #define DASD_ECKD_CCW_READ_CKD_MT 0x9e
#define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d #define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d
#define DASD_ECKD_CCW_WRITE_TRACK_DATA 0xA5
#define DASD_ECKD_CCW_READ_TRACK_DATA 0xA6
#define DASD_ECKD_CCW_RESERVE 0xB4 #define DASD_ECKD_CCW_RESERVE 0xB4
#define DASD_ECKD_CCW_PFX 0xE7 #define DASD_ECKD_CCW_PFX 0xE7
#define DASD_ECKD_CCW_PFX_READ 0xEA
#define DASD_ECKD_CCW_RSCK 0xF9 #define DASD_ECKD_CCW_RSCK 0xF9
/* /*
...@@ -48,6 +51,11 @@ ...@@ -48,6 +51,11 @@
#define PSF_ORDER_PRSSD 0x18 #define PSF_ORDER_PRSSD 0x18
#define PSF_ORDER_SSC 0x1D #define PSF_ORDER_SSC 0x1D
/*
* Size that is reportet for large volumes in the old 16-bit no_cyl field
*/
#define LV_COMPAT_CYL 0xFFFE
/***************************************************************************** /*****************************************************************************
* SECTION: Type Definitions * SECTION: Type Definitions
****************************************************************************/ ****************************************************************************/
...@@ -118,7 +126,9 @@ struct DE_eckd_data { ...@@ -118,7 +126,9 @@ struct DE_eckd_data {
unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */ unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */
__u8 ep_format; /* Extended Parameter format byte */ __u8 ep_format; /* Extended Parameter format byte */
__u8 ep_prio; /* Extended Parameter priority I/O byte */ __u8 ep_prio; /* Extended Parameter priority I/O byte */
__u8 ep_reserved[6]; /* Extended Parameter Reserved */ __u8 ep_reserved1; /* Extended Parameter Reserved */
__u8 ep_rec_per_track; /* Number of records on a track */
__u8 ep_reserved[4]; /* Extended Parameter Reserved */
} __attribute__ ((packed)); } __attribute__ ((packed));
struct LO_eckd_data { struct LO_eckd_data {
...@@ -139,11 +149,37 @@ struct LO_eckd_data { ...@@ -139,11 +149,37 @@ struct LO_eckd_data {
__u16 length; __u16 length;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct LRE_eckd_data {
struct {
unsigned char orientation:2;
unsigned char operation:6;
} __attribute__ ((packed)) operation;
struct {
unsigned char length_valid:1;
unsigned char length_scope:1;
unsigned char imbedded_ccw_valid:1;
unsigned char check_bytes:2;
unsigned char imbedded_count_valid:1;
unsigned char reserved:1;
unsigned char read_count_suffix:1;
} __attribute__ ((packed)) auxiliary;
__u8 imbedded_ccw;
__u8 count;
struct ch_t seek_addr;
struct chr_t search_arg;
__u8 sector;
__u16 length;
__u8 imbedded_count;
__u8 extended_operation;
__u16 extended_parameter_length;
__u8 extended_parameter[0];
} __attribute__ ((packed));
/* Prefix data for format 0x00 and 0x01 */ /* Prefix data for format 0x00 and 0x01 */
struct PFX_eckd_data { struct PFX_eckd_data {
unsigned char format; unsigned char format;
struct { struct {
unsigned char define_extend:1; unsigned char define_extent:1;
unsigned char time_stamp:1; unsigned char time_stamp:1;
unsigned char verify_base:1; unsigned char verify_base:1;
unsigned char hyper_pav:1; unsigned char hyper_pav:1;
...@@ -153,9 +189,8 @@ struct PFX_eckd_data { ...@@ -153,9 +189,8 @@ struct PFX_eckd_data {
__u8 aux; __u8 aux;
__u8 base_lss; __u8 base_lss;
__u8 reserved[7]; __u8 reserved[7];
struct DE_eckd_data define_extend; struct DE_eckd_data define_extent;
struct LO_eckd_data locate_record; struct LRE_eckd_data locate_record;
__u8 LO_extended_data[4];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct dasd_eckd_characteristics { struct dasd_eckd_characteristics {
...@@ -228,7 +263,8 @@ struct dasd_eckd_characteristics { ...@@ -228,7 +263,8 @@ struct dasd_eckd_characteristics {
__u8 factor7; __u8 factor7;
__u8 factor8; __u8 factor8;
__u8 reserved2[3]; __u8 reserved2[3];
__u8 reserved3[10]; __u8 reserved3[6];
__u32 long_no_cyl;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* elements of the configuration data */ /* elements of the configuration data */
...@@ -406,6 +442,7 @@ struct dasd_eckd_private { ...@@ -406,6 +442,7 @@ struct dasd_eckd_private {
int uses_cdl; int uses_cdl;
struct attrib_data_t attrib; /* e.g. cache operations */ struct attrib_data_t attrib; /* e.g. cache operations */
struct dasd_rssd_features features; struct dasd_rssd_features features;
u32 real_cyl;
/* alias managemnet */ /* alias managemnet */
struct dasd_uid uid; struct dasd_uid uid;
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
* Author(s): Stefan Weinhuber <wein@de.ibm.com> * Author(s): Stefan Weinhuber <wein@de.ibm.com>
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -297,11 +299,12 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, ...@@ -297,11 +299,12 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
struct dasd_eer_header header; struct dasd_eer_header header;
unsigned long flags; unsigned long flags;
struct eerbuffer *eerb; struct eerbuffer *eerb;
char *sense;
/* go through cqr chain and count the valid sense data sets */ /* go through cqr chain and count the valid sense data sets */
data_size = 0; data_size = 0;
for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers)
if (temp_cqr->irb.esw.esw0.erw.cons) if (dasd_get_sense(&temp_cqr->irb))
data_size += 32; data_size += 32;
header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
...@@ -316,9 +319,11 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, ...@@ -316,9 +319,11 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
list_for_each_entry(eerb, &bufferlist, list) { list_for_each_entry(eerb, &bufferlist, list) {
dasd_eer_start_record(eerb, header.total_size); dasd_eer_start_record(eerb, header.total_size);
dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header)); dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header));
for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) {
if (temp_cqr->irb.esw.esw0.erw.cons) sense = dasd_get_sense(&temp_cqr->irb);
dasd_eer_write_buffer(eerb, cqr->irb.ecw, 32); if (sense)
dasd_eer_write_buffer(eerb, sense, 32);
}
dasd_eer_write_buffer(eerb, "EOR", 4); dasd_eer_write_buffer(eerb, "EOR", 4);
} }
spin_unlock_irqrestore(&bufferlock, flags); spin_unlock_irqrestore(&bufferlock, flags);
...@@ -451,6 +456,7 @@ int dasd_eer_enable(struct dasd_device *device) ...@@ -451,6 +456,7 @@ int dasd_eer_enable(struct dasd_device *device)
{ {
struct dasd_ccw_req *cqr; struct dasd_ccw_req *cqr;
unsigned long flags; unsigned long flags;
struct ccw1 *ccw;
if (device->eer_cqr) if (device->eer_cqr)
return 0; return 0;
...@@ -468,10 +474,11 @@ int dasd_eer_enable(struct dasd_device *device) ...@@ -468,10 +474,11 @@ int dasd_eer_enable(struct dasd_device *device)
cqr->expires = 10 * HZ; cqr->expires = 10 * HZ;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; ccw = cqr->cpaddr;
cqr->cpaddr->count = SNSS_DATA_SIZE; ccw->cmd_code = DASD_ECKD_CCW_SNSS;
cqr->cpaddr->flags = 0; ccw->count = SNSS_DATA_SIZE;
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; ccw->flags = 0;
ccw->cda = (__u32)(addr_t) cqr->data;
cqr->buildclk = get_clock(); cqr->buildclk = get_clock();
cqr->status = DASD_CQR_FILLED; cqr->status = DASD_CQR_FILLED;
...@@ -534,7 +541,7 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) ...@@ -534,7 +541,7 @@ static int dasd_eer_open(struct inode *inp, struct file *filp)
if (eerb->buffer_page_count < 1 || if (eerb->buffer_page_count < 1 ||
eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { eerb->buffer_page_count > INT_MAX / PAGE_SIZE) {
kfree(eerb); kfree(eerb);
MESSAGE(KERN_WARNING, "can't open device since module " DBF_EVENT(DBF_WARNING, "can't open device since module "
"parameter eer_pages is smaller than 1 or" "parameter eer_pages is smaller than 1 or"
" bigger than %d", (int)(INT_MAX / PAGE_SIZE)); " bigger than %d", (int)(INT_MAX / PAGE_SIZE));
unlock_kernel(); unlock_kernel();
...@@ -687,7 +694,7 @@ int __init dasd_eer_init(void) ...@@ -687,7 +694,7 @@ int __init dasd_eer_init(void)
if (rc) { if (rc) {
kfree(dasd_eer_dev); kfree(dasd_eer_dev);
dasd_eer_dev = NULL; dasd_eer_dev = NULL;
MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not "
"register misc device"); "register misc device");
return rc; return rc;
} }
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* *
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -91,14 +93,14 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr) ...@@ -91,14 +93,14 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr)
/* just retry - there is nothing to save ... I got no sense data.... */ /* just retry - there is nothing to save ... I got no sense data.... */
if (cqr->retries > 0) { if (cqr->retries > 0) {
DEV_MESSAGE (KERN_DEBUG, device, DBF_DEV_EVENT(DBF_DEBUG, device,
"default ERP called (%i retries left)", "default ERP called (%i retries left)",
cqr->retries); cqr->retries);
cqr->lpm = LPM_ANYPATH; cqr->lpm = LPM_ANYPATH;
cqr->status = DASD_CQR_FILLED; cqr->status = DASD_CQR_FILLED;
} else { } else {
DEV_MESSAGE (KERN_WARNING, device, "%s", dev_err(&device->cdev->dev,
"default ERP called (NO retry left)"); "default ERP has run out of retries and failed\n");
cqr->status = DASD_CQR_FAILED; cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
} }
...@@ -162,8 +164,21 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) ...@@ -162,8 +164,21 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
device->discipline->dump_sense(device, cqr, irb); device->discipline->dump_sense(device, cqr, irb);
} }
void
dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb)
{
struct dasd_device *device;
device = cqr->startdev;
/* dump sense data to s390 debugfeature*/
if (device->discipline && device->discipline->dump_sense_dbf)
device->discipline->dump_sense_dbf(device, cqr, irb, "log");
}
EXPORT_SYMBOL(dasd_log_sense_dbf);
EXPORT_SYMBOL(dasd_default_erp_action); EXPORT_SYMBOL(dasd_default_erp_action);
EXPORT_SYMBOL(dasd_default_erp_postaction); EXPORT_SYMBOL(dasd_default_erp_postaction);
EXPORT_SYMBOL(dasd_alloc_erp_request); EXPORT_SYMBOL(dasd_alloc_erp_request);
EXPORT_SYMBOL(dasd_free_erp_request); EXPORT_SYMBOL(dasd_free_erp_request);
EXPORT_SYMBOL(dasd_log_sense); EXPORT_SYMBOL(dasd_log_sense);
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
* *
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/debug.h> #include <asm/debug.h>
...@@ -128,17 +130,18 @@ dasd_fba_check_characteristics(struct dasd_device *device) ...@@ -128,17 +130,18 @@ dasd_fba_check_characteristics(struct dasd_device *device)
private = kzalloc(sizeof(struct dasd_fba_private), private = kzalloc(sizeof(struct dasd_fba_private),
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
if (private == NULL) { if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s", dev_warn(&device->cdev->dev,
"memory allocation failed for private " "Allocating memory for private DASD "
"data"); "data failed\n");
return -ENOMEM; return -ENOMEM;
} }
device->private = (void *) private; device->private = (void *) private;
} }
block = dasd_alloc_block(); block = dasd_alloc_block();
if (IS_ERR(block)) { if (IS_ERR(block)) {
DEV_MESSAGE(KERN_WARNING, device, "%s", DBF_EVENT(DBF_WARNING, "could not allocate dasd block "
"could not allocate dasd block structure"); "structure for device: %s",
dev_name(&device->cdev->dev));
device->private = NULL; device->private = NULL;
kfree(private); kfree(private);
return PTR_ERR(block); return PTR_ERR(block);
...@@ -150,9 +153,9 @@ dasd_fba_check_characteristics(struct dasd_device *device) ...@@ -150,9 +153,9 @@ dasd_fba_check_characteristics(struct dasd_device *device)
rdc_data = (void *) &(private->rdc_data); rdc_data = (void *) &(private->rdc_data);
rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32); rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
if (rc) { if (rc) {
DEV_MESSAGE(KERN_WARNING, device, DBF_EVENT(DBF_WARNING, "Read device characteristics returned "
"Read device characteristics returned error %d", "error %d for device: %s",
rc); rc, dev_name(&device->cdev->dev));
device->block = NULL; device->block = NULL;
dasd_free_block(block); dasd_free_block(block);
device->private = NULL; device->private = NULL;
...@@ -160,15 +163,16 @@ dasd_fba_check_characteristics(struct dasd_device *device) ...@@ -160,15 +163,16 @@ dasd_fba_check_characteristics(struct dasd_device *device)
return rc; return rc;
} }
DEV_MESSAGE(KERN_INFO, device, dev_info(&device->cdev->dev,
"%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)", "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
cdev->id.dev_type, "and %d B/blk\n",
cdev->id.dev_model, cdev->id.dev_type,
cdev->id.cu_type, cdev->id.dev_model,
cdev->id.cu_model, cdev->id.cu_type,
((private->rdc_data.blk_bdsa * cdev->id.cu_model,
(private->rdc_data.blk_size >> 9)) >> 11), ((private->rdc_data.blk_bdsa *
private->rdc_data.blk_size); (private->rdc_data.blk_size >> 9)) >> 11),
private->rdc_data.blk_size);
return 0; return 0;
} }
...@@ -180,7 +184,7 @@ static int dasd_fba_do_analysis(struct dasd_block *block) ...@@ -180,7 +184,7 @@ static int dasd_fba_do_analysis(struct dasd_block *block)
private = (struct dasd_fba_private *) block->base->private; private = (struct dasd_fba_private *) block->base->private;
rc = dasd_check_blocksize(private->rdc_data.blk_size); rc = dasd_check_blocksize(private->rdc_data.blk_size);
if (rc) { if (rc) {
DEV_MESSAGE(KERN_INFO, block->base, "unknown blocksize %d", DBF_DEV_EVENT(DBF_WARNING, block->base, "unknown blocksize %d",
private->rdc_data.blk_size); private->rdc_data.blk_size);
return rc; return rc;
} }
...@@ -215,7 +219,7 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr) ...@@ -215,7 +219,7 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr)
if (cqr->function == dasd_default_erp_action) if (cqr->function == dasd_default_erp_action)
return dasd_default_erp_postaction; return dasd_default_erp_postaction;
DEV_MESSAGE(KERN_WARNING, cqr->startdev, "unknown ERP action %p", DBF_DEV_EVENT(DBF_WARNING, cqr->startdev, "unknown ERP action %p",
cqr->function); cqr->function);
return NULL; return NULL;
} }
...@@ -233,9 +237,9 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, ...@@ -233,9 +237,9 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device,
} }
/* check for unsolicited interrupts */ /* check for unsolicited interrupts */
DEV_MESSAGE(KERN_DEBUG, device, "%s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"unsolicited interrupt received"); "unsolicited interrupt received");
device->discipline->dump_sense(device, NULL, irb); device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited");
dasd_schedule_device_bh(device); dasd_schedule_device_bh(device);
return; return;
}; };
...@@ -436,6 +440,25 @@ dasd_fba_fill_info(struct dasd_device * device, ...@@ -436,6 +440,25 @@ dasd_fba_fill_info(struct dasd_device * device,
return 0; return 0;
} }
static void
dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req,
struct irb *irb, char *reason)
{
int sl;
if (irb->esw.esw0.erw.cons) {
for (sl = 0; sl < 4; sl++) {
DBF_DEV_EVENT(DBF_EMERG, device,
"%s: %08x %08x %08x %08x",
reason, irb->ecw[8 * 0], irb->ecw[8 * 1],
irb->ecw[8 * 2], irb->ecw[8 * 3]);
}
} else {
DBF_DEV_EVENT(DBF_EMERG, device, "%s",
"SORRY - NO VALID SENSE AVAILABLE\n");
}
}
static void static void
dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
struct irb *irb) struct irb *irb)
...@@ -446,7 +469,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -446,7 +469,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
page = (char *) get_zeroed_page(GFP_ATOMIC); page = (char *) get_zeroed_page(GFP_ATOMIC);
if (page == NULL) { if (page == NULL) {
DEV_MESSAGE(KERN_ERR, device, " %s", DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"No memory to dump sense data"); "No memory to dump sense data");
return; return;
} }
...@@ -476,8 +499,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -476,8 +499,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
len += sprintf(page + len, KERN_ERR PRINTK_HEADER len += sprintf(page + len, KERN_ERR PRINTK_HEADER
" SORRY - NO VALID SENSE AVAILABLE\n"); " SORRY - NO VALID SENSE AVAILABLE\n");
} }
MESSAGE_LOG(KERN_ERR, "%s", printk(KERN_ERR "%s", page);
page + sizeof(KERN_ERR PRINTK_HEADER));
/* dump the Channel Program */ /* dump the Channel Program */
/* print first CCWs (maximum 8) */ /* print first CCWs (maximum 8) */
...@@ -498,8 +520,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -498,8 +520,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
len += sprintf(page + len, "\n"); len += sprintf(page + len, "\n");
act++; act++;
} }
MESSAGE_LOG(KERN_ERR, "%s", printk(KERN_ERR "%s", page);
page + sizeof(KERN_ERR PRINTK_HEADER));
/* print failing CCW area */ /* print failing CCW area */
...@@ -540,8 +561,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -540,8 +561,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
act++; act++;
} }
if (len > 0) if (len > 0)
MESSAGE_LOG(KERN_ERR, "%s", printk(KERN_ERR "%s", page);
page + sizeof(KERN_ERR PRINTK_HEADER));
free_page((unsigned long) page); free_page((unsigned long) page);
} }
...@@ -576,6 +596,7 @@ static struct dasd_discipline dasd_fba_discipline = { ...@@ -576,6 +596,7 @@ static struct dasd_discipline dasd_fba_discipline = {
.build_cp = dasd_fba_build_cp, .build_cp = dasd_fba_build_cp,
.free_cp = dasd_fba_free_cp, .free_cp = dasd_fba_free_cp,
.dump_sense = dasd_fba_dump_sense, .dump_sense = dasd_fba_dump_sense,
.dump_sense_dbf = dasd_fba_dump_sense_dbf,
.fill_info = dasd_fba_fill_info, .fill_info = dasd_fba_fill_info,
}; };
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* *
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
...@@ -163,9 +165,8 @@ int dasd_gendisk_init(void) ...@@ -163,9 +165,8 @@ int dasd_gendisk_init(void)
/* Register to static dasd major 94 */ /* Register to static dasd major 94 */
rc = register_blkdev(DASD_MAJOR, "dasd"); rc = register_blkdev(DASD_MAJOR, "dasd");
if (rc != 0) { if (rc != 0) {
MESSAGE(KERN_WARNING, pr_warning("Registering the device driver with major number "
"Couldn't register successfully to " "%d failed\n", DASD_MAJOR);
"major no %d", DASD_MAJOR);
return rc; return rc;
} }
return 0; return 0;
......
...@@ -112,6 +112,9 @@ do { \ ...@@ -112,6 +112,9 @@ do { \
d_data); \ d_data); \
} while(0) } while(0)
/* limit size for an errorstring */
#define ERRORLENGTH 30
/* definition of dbf debug levels */ /* definition of dbf debug levels */
#define DBF_EMERG 0 /* system is unusable */ #define DBF_EMERG 0 /* system is unusable */
#define DBF_ALERT 1 /* action must be taken immediately */ #define DBF_ALERT 1 /* action must be taken immediately */
...@@ -157,7 +160,8 @@ struct dasd_ccw_req { ...@@ -157,7 +160,8 @@ struct dasd_ccw_req {
struct dasd_block *block; /* the originating block device */ struct dasd_block *block; /* the originating block device */
struct dasd_device *memdev; /* the device used to allocate this */ struct dasd_device *memdev; /* the device used to allocate this */
struct dasd_device *startdev; /* device the request is started on */ struct dasd_device *startdev; /* device the request is started on */
struct ccw1 *cpaddr; /* address of channel program */ void *cpaddr; /* address of ccw or tcw */
unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */
char status; /* status of this request */ char status; /* status of this request */
short retries; /* A retry counter */ short retries; /* A retry counter */
unsigned long flags; /* flags of this request */ unsigned long flags; /* flags of this request */
...@@ -280,6 +284,8 @@ struct dasd_discipline { ...@@ -280,6 +284,8 @@ struct dasd_discipline {
dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *);
void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
struct irb *); struct irb *);
void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *,
struct irb *, char *);
void (*handle_unsolicited_interrupt) (struct dasd_device *, void (*handle_unsolicited_interrupt) (struct dasd_device *,
struct irb *); struct irb *);
...@@ -378,7 +384,7 @@ struct dasd_block { ...@@ -378,7 +384,7 @@ struct dasd_block {
struct block_device *bdev; struct block_device *bdev;
atomic_t open_count; atomic_t open_count;
unsigned long blocks; /* size of volume in blocks */ unsigned long long blocks; /* size of volume in blocks */
unsigned int bp_block; /* bytes per block */ unsigned int bp_block; /* bytes per block */
unsigned int s2b_shift; /* log2 (bp_block/512) */ unsigned int s2b_shift; /* log2 (bp_block/512) */
...@@ -573,12 +579,14 @@ int dasd_generic_notify(struct ccw_device *, int); ...@@ -573,12 +579,14 @@ int dasd_generic_notify(struct ccw_device *, int);
void dasd_generic_handle_state_change(struct dasd_device *); void dasd_generic_handle_state_change(struct dasd_device *);
int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int); int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
char *dasd_get_sense(struct irb *);
/* externals in dasd_devmap.c */ /* externals in dasd_devmap.c */
extern int dasd_max_devindex; extern int dasd_max_devindex;
extern int dasd_probeonly; extern int dasd_probeonly;
extern int dasd_autodetect; extern int dasd_autodetect;
extern int dasd_nopav; extern int dasd_nopav;
extern int dasd_nofcx;
int dasd_devmap_init(void); int dasd_devmap_init(void);
void dasd_devmap_exit(void); void dasd_devmap_exit(void);
...@@ -623,6 +631,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int, ...@@ -623,6 +631,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int,
struct dasd_device *); struct dasd_device *);
void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_log_sense(struct dasd_ccw_req *, struct irb *); void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
void dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb);
/* externals in dasd_3990_erp.c */ /* externals in dasd_3990_erp.c */
struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *); struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
* *
* i/o controls for the dasd driver. * i/o controls for the dasd driver.
*/ */
#define KMSG_COMPONENT "dasd"
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -94,7 +97,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) ...@@ -94,7 +97,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block)
if (!capable (CAP_SYS_ADMIN)) if (!capable (CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
DEV_MESSAGE(KERN_DEBUG, base, "%s", "Quiesce IO on device"); dev_info(&base->cdev->dev, "The DASD has been put in the quiesce "
"state\n");
spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
base->stopped |= DASD_STOPPED_QUIESCE; base->stopped |= DASD_STOPPED_QUIESCE;
spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
...@@ -103,7 +107,7 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) ...@@ -103,7 +107,7 @@ static int dasd_ioctl_quiesce(struct dasd_block *block)
/* /*
* Quiesce device. * Resume device.
*/ */
static int dasd_ioctl_resume(struct dasd_block *block) static int dasd_ioctl_resume(struct dasd_block *block)
{ {
...@@ -114,7 +118,8 @@ static int dasd_ioctl_resume(struct dasd_block *block) ...@@ -114,7 +118,8 @@ static int dasd_ioctl_resume(struct dasd_block *block)
if (!capable (CAP_SYS_ADMIN)) if (!capable (CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
DEV_MESSAGE(KERN_DEBUG, base, "%s", "resume IO on device"); dev_info(&base->cdev->dev, "I/O operations have been resumed "
"on the DASD\n");
spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
base->stopped &= ~DASD_STOPPED_QUIESCE; base->stopped &= ~DASD_STOPPED_QUIESCE;
spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
...@@ -140,13 +145,13 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) ...@@ -140,13 +145,13 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
return -EPERM; return -EPERM;
if (base->state != DASD_STATE_BASIC) { if (base->state != DASD_STATE_BASIC) {
DEV_MESSAGE(KERN_WARNING, base, "%s", dev_warn(&base->cdev->dev,
"dasd_format: device is not disabled! "); "The DASD cannot be formatted while it is enabled\n");
return -EBUSY; return -EBUSY;
} }
DBF_DEV_EVENT(DBF_NOTICE, base, DBF_DEV_EVENT(DBF_NOTICE, base,
"formatting units %d to %d (%d B blocks) flags %d", "formatting units %u to %u (%u B blocks) flags %u",
fdata->start_unit, fdata->start_unit,
fdata->stop_unit, fdata->blksize, fdata->intensity); fdata->stop_unit, fdata->blksize, fdata->intensity);
...@@ -169,10 +174,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) ...@@ -169,10 +174,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
dasd_sfree_request(cqr, cqr->memdev); dasd_sfree_request(cqr, cqr->memdev);
if (rc) { if (rc) {
if (rc != -ERESTARTSYS) if (rc != -ERESTARTSYS)
DEV_MESSAGE(KERN_ERR, base, dev_err(&base->cdev->dev,
" Formatting of unit %d failed " "Formatting unit %d failed with "
"with rc = %d", "rc=%d\n", fdata->start_unit, rc);
fdata->start_unit, rc);
return rc; return rc;
} }
fdata->start_unit++; fdata->start_unit++;
...@@ -199,8 +203,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) ...@@ -199,8 +203,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
return -EFAULT; return -EFAULT;
if (bdev != bdev->bd_contains) { if (bdev != bdev->bd_contains) {
DEV_MESSAGE(KERN_WARNING, block->base, "%s", dev_warn(&block->base->cdev->dev,
"Cannot low-level format a partition"); "The specified DASD is a partition and cannot be "
"formatted\n");
return -EINVAL; return -EINVAL;
} }
return dasd_format(block, &fdata); return dasd_format(block, &fdata);
...@@ -365,9 +370,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, ...@@ -365,9 +370,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
return ret; return ret;
} }
int static int
dasd_ioctl(struct block_device *bdev, fmode_t mode, dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct dasd_block *block = bdev->bd_disk->private_data; struct dasd_block *block = bdev->bd_disk->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -420,3 +425,14 @@ dasd_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -420,3 +425,14 @@ dasd_ioctl(struct block_device *bdev, fmode_t mode,
return -EINVAL; return -EINVAL;
} }
} }
int dasd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
int rc;
lock_kernel();
rc = dasd_do_ioctl(bdev, mode, cmd, arg);
unlock_kernel();
return rc;
}
This diff is collapsed.
...@@ -324,8 +324,6 @@ static inline void tape_proc_cleanup (void) {;} ...@@ -324,8 +324,6 @@ static inline void tape_proc_cleanup (void) {;}
#endif #endif
/* a function for dumping device sense info */ /* a function for dumping device sense info */
extern void tape_dump_sense(struct tape_device *, struct tape_request *,
struct irb *);
extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *, extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *,
struct irb *); struct irb *);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment