mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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: (21 commits) [S390] dasd: fix race condition in resume code [S390] Add EX_TABLE for addressing exception in usercopy functions. [S390] 64-bit register support for 31-bit processes [S390] hibernate: Use correct place for CPU address in lowcore [S390] pm: ignore time spend in suspended state [S390] zcrypt: Improve some comments [S390] zcrypt: Fix sparse warning. [S390] perf_counter: fix vdso detection [S390] ftrace: drop nmi protection [S390] compat: fix truncate system call wrapper [S390] Provide arch specific mdelay implementation. [S390] Fix enabled udelay for short delays. [S390] cio: allow setting boxed devices offline [S390] cio: make not operational handling consistent [S390] cio: make disconnected handling consistent [S390] Fix memory leak in /proc/cio_ignore [S390] cio: channel path memory leak [S390] module: fix memory leak in s390 module loader [S390] Enable kmemleak on s390. [S390] 3270 console build fix ...
This commit is contained in:
commit
f144c78e52
28 changed files with 282 additions and 82 deletions
|
@ -14,10 +14,11 @@
|
||||||
#ifndef _S390_DELAY_H
|
#ifndef _S390_DELAY_H
|
||||||
#define _S390_DELAY_H
|
#define _S390_DELAY_H
|
||||||
|
|
||||||
extern void __udelay(unsigned long usecs);
|
extern void __udelay(unsigned long long usecs);
|
||||||
extern void udelay_simple(unsigned long usecs);
|
extern void udelay_simple(unsigned long long usecs);
|
||||||
extern void __delay(unsigned long loops);
|
extern void __delay(unsigned long loops);
|
||||||
|
|
||||||
#define udelay(n) __udelay(n)
|
#define udelay(n) __udelay((unsigned long long) (n))
|
||||||
|
#define mdelay(n) __udelay((unsigned long long) (n) * 1000)
|
||||||
|
|
||||||
#endif /* defined(_S390_DELAY_H) */
|
#endif /* defined(_S390_DELAY_H) */
|
||||||
|
|
|
@ -92,6 +92,18 @@
|
||||||
/* Keep this the last entry. */
|
/* Keep this the last entry. */
|
||||||
#define R_390_NUM 61
|
#define R_390_NUM 61
|
||||||
|
|
||||||
|
/* Bits present in AT_HWCAP. */
|
||||||
|
#define HWCAP_S390_ESAN3 1
|
||||||
|
#define HWCAP_S390_ZARCH 2
|
||||||
|
#define HWCAP_S390_STFLE 4
|
||||||
|
#define HWCAP_S390_MSA 8
|
||||||
|
#define HWCAP_S390_LDISP 16
|
||||||
|
#define HWCAP_S390_EIMM 32
|
||||||
|
#define HWCAP_S390_DFP 64
|
||||||
|
#define HWCAP_S390_HPAGE 128
|
||||||
|
#define HWCAP_S390_ETF3EH 256
|
||||||
|
#define HWCAP_S390_HIGH_GPRS 512
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are used to set parameters in the core dumps.
|
* These are used to set parameters in the core dumps.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -311,6 +311,10 @@ typedef struct
|
||||||
__u32 orig_gpr2;
|
__u32 orig_gpr2;
|
||||||
} s390_compat_regs;
|
} s390_compat_regs;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
__u32 gprs_high[NUM_GPRS];
|
||||||
|
} s390_compat_regs_high;
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,21 @@
|
||||||
#ifndef _ASM_S390_UCONTEXT_H
|
#ifndef _ASM_S390_UCONTEXT_H
|
||||||
#define _ASM_S390_UCONTEXT_H
|
#define _ASM_S390_UCONTEXT_H
|
||||||
|
|
||||||
|
#define UC_EXTENDED 0x00000001
|
||||||
|
|
||||||
|
#ifndef __s390x__
|
||||||
|
|
||||||
|
struct ucontext_extended {
|
||||||
|
unsigned long uc_flags;
|
||||||
|
struct ucontext *uc_link;
|
||||||
|
stack_t uc_stack;
|
||||||
|
_sigregs uc_mcontext;
|
||||||
|
unsigned long uc_sigmask[2];
|
||||||
|
unsigned long uc_gprs_high[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ucontext {
|
struct ucontext {
|
||||||
unsigned long uc_flags;
|
unsigned long uc_flags;
|
||||||
struct ucontext *uc_link;
|
struct ucontext *uc_link;
|
||||||
|
|
|
@ -39,6 +39,7 @@ typedef struct
|
||||||
struct sigcontext32 sc;
|
struct sigcontext32 sc;
|
||||||
_sigregs32 sregs;
|
_sigregs32 sregs;
|
||||||
int signo;
|
int signo;
|
||||||
|
__u32 gprs_high[NUM_GPRS];
|
||||||
__u8 retcode[S390_SYSCALL_SIZE];
|
__u8 retcode[S390_SYSCALL_SIZE];
|
||||||
} sigframe32;
|
} sigframe32;
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ typedef struct
|
||||||
__u8 retcode[S390_SYSCALL_SIZE];
|
__u8 retcode[S390_SYSCALL_SIZE];
|
||||||
compat_siginfo_t info;
|
compat_siginfo_t info;
|
||||||
struct ucontext32 uc;
|
struct ucontext32 uc;
|
||||||
|
__u32 gprs_high[NUM_GPRS];
|
||||||
} rt_sigframe32;
|
} rt_sigframe32;
|
||||||
|
|
||||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||||
|
@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
|
||||||
|
{
|
||||||
|
__u32 gprs_high[NUM_GPRS];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_GPRS; i++)
|
||||||
|
gprs_high[i] = regs->gprs[i] >> 32;
|
||||||
|
|
||||||
|
return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
|
||||||
|
{
|
||||||
|
__u32 gprs_high[NUM_GPRS];
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
for (i = 0; i < NUM_GPRS; i++)
|
||||||
|
*(__u32 *)®s->gprs[i] = gprs_high[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
asmlinkage long sys32_sigreturn(void)
|
asmlinkage long sys32_sigreturn(void)
|
||||||
{
|
{
|
||||||
struct pt_regs *regs = task_pt_regs(current);
|
struct pt_regs *regs = task_pt_regs(current);
|
||||||
|
@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void)
|
||||||
|
|
||||||
if (restore_sigregs32(regs, &frame->sregs))
|
if (restore_sigregs32(regs, &frame->sregs))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
if (restore_sigregs_gprs_high(regs, frame->gprs_high))
|
||||||
|
goto badframe;
|
||||||
|
|
||||||
return regs->gprs[2];
|
return regs->gprs[2];
|
||||||
|
|
||||||
|
@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void)
|
||||||
|
|
||||||
if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
|
if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
if (restore_sigregs_gprs_high(regs, frame->gprs_high))
|
||||||
|
goto badframe;
|
||||||
|
|
||||||
err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
|
err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
|
||||||
st.ss_sp = compat_ptr(ss_sp);
|
st.ss_sp = compat_ptr(ss_sp);
|
||||||
|
@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
|
||||||
|
|
||||||
if (save_sigregs32(regs, &frame->sregs))
|
if (save_sigregs32(regs, &frame->sregs))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
if (save_sigregs_gprs_high(regs, frame->gprs_high))
|
||||||
|
goto give_sigsegv;
|
||||||
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
|
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
|
@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/* Create the ucontext. */
|
/* Create the ucontext. */
|
||||||
err |= __put_user(0, &frame->uc.uc_flags);
|
err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
|
||||||
err |= __put_user(0, &frame->uc.uc_link);
|
err |= __put_user(0, &frame->uc.uc_link);
|
||||||
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
|
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
|
||||||
err |= __put_user(sas_ss_flags(regs->gprs[15]),
|
err |= __put_user(sas_ss_flags(regs->gprs[15]),
|
||||||
&frame->uc.uc_stack.ss_flags);
|
&frame->uc.uc_stack.ss_flags);
|
||||||
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
||||||
err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
|
err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
|
||||||
|
err |= save_sigregs_gprs_high(regs, frame->gprs_high);
|
||||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||||
if (err)
|
if (err)
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
|
@ -409,7 +409,7 @@ sys32_munmap_wrapper:
|
||||||
.globl sys32_truncate_wrapper
|
.globl sys32_truncate_wrapper
|
||||||
sys32_truncate_wrapper:
|
sys32_truncate_wrapper:
|
||||||
llgtr %r2,%r2 # const char *
|
llgtr %r2,%r2 # const char *
|
||||||
llgfr %r3,%r3 # unsigned long
|
lgfr %r3,%r3 # long
|
||||||
jg sys_truncate # branch to system call
|
jg sys_truncate # branch to system call
|
||||||
|
|
||||||
.globl sys32_ftruncate_wrapper
|
.globl sys32_ftruncate_wrapper
|
||||||
|
|
|
@ -185,9 +185,6 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
|
||||||
{
|
{
|
||||||
struct ftrace_graph_ent trace;
|
struct ftrace_graph_ent trace;
|
||||||
|
|
||||||
/* Nmi's are currently unsupported. */
|
|
||||||
if (unlikely(in_nmi()))
|
|
||||||
goto out;
|
|
||||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||||
goto out;
|
goto out;
|
||||||
if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
|
if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
|
||||||
|
|
|
@ -55,6 +55,8 @@ void *module_alloc(unsigned long size)
|
||||||
/* Free memory returned from module_alloc */
|
/* Free memory returned from module_alloc */
|
||||||
void module_free(struct module *mod, void *module_region)
|
void module_free(struct module *mod, void *module_region)
|
||||||
{
|
{
|
||||||
|
vfree(mod->arch.syminfo);
|
||||||
|
mod->arch.syminfo = NULL;
|
||||||
vfree(module_region);
|
vfree(module_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,6 +404,7 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||||
struct module *me)
|
struct module *me)
|
||||||
{
|
{
|
||||||
vfree(me->arch.syminfo);
|
vfree(me->arch.syminfo);
|
||||||
|
me->arch.syminfo = NULL;
|
||||||
return module_bug_finalize(hdr, sechdrs, me);
|
return module_bug_finalize(hdr, sechdrs, me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
enum s390_regset {
|
enum s390_regset {
|
||||||
REGSET_GENERAL,
|
REGSET_GENERAL,
|
||||||
REGSET_FP,
|
REGSET_FP,
|
||||||
|
REGSET_GENERAL_EXTENDED,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -879,6 +880,67 @@ static int s390_compat_regs_set(struct task_struct *target,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s390_compat_regs_high_get(struct task_struct *target,
|
||||||
|
const struct user_regset *regset,
|
||||||
|
unsigned int pos, unsigned int count,
|
||||||
|
void *kbuf, void __user *ubuf)
|
||||||
|
{
|
||||||
|
compat_ulong_t *gprs_high;
|
||||||
|
|
||||||
|
gprs_high = (compat_ulong_t *)
|
||||||
|
&task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
|
||||||
|
if (kbuf) {
|
||||||
|
compat_ulong_t *k = kbuf;
|
||||||
|
while (count > 0) {
|
||||||
|
*k++ = *gprs_high;
|
||||||
|
gprs_high += 2;
|
||||||
|
count -= sizeof(*k);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
compat_ulong_t __user *u = ubuf;
|
||||||
|
while (count > 0) {
|
||||||
|
if (__put_user(*gprs_high, u++))
|
||||||
|
return -EFAULT;
|
||||||
|
gprs_high += 2;
|
||||||
|
count -= sizeof(*u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s390_compat_regs_high_set(struct task_struct *target,
|
||||||
|
const struct user_regset *regset,
|
||||||
|
unsigned int pos, unsigned int count,
|
||||||
|
const void *kbuf, const void __user *ubuf)
|
||||||
|
{
|
||||||
|
compat_ulong_t *gprs_high;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
gprs_high = (compat_ulong_t *)
|
||||||
|
&task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
|
||||||
|
if (kbuf) {
|
||||||
|
const compat_ulong_t *k = kbuf;
|
||||||
|
while (count > 0) {
|
||||||
|
*gprs_high = *k++;
|
||||||
|
*gprs_high += 2;
|
||||||
|
count -= sizeof(*k);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const compat_ulong_t __user *u = ubuf;
|
||||||
|
while (count > 0 && !rc) {
|
||||||
|
unsigned long word;
|
||||||
|
rc = __get_user(word, u++);
|
||||||
|
if (rc)
|
||||||
|
break;
|
||||||
|
*gprs_high = word;
|
||||||
|
*gprs_high += 2;
|
||||||
|
count -= sizeof(*u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct user_regset s390_compat_regsets[] = {
|
static const struct user_regset s390_compat_regsets[] = {
|
||||||
[REGSET_GENERAL] = {
|
[REGSET_GENERAL] = {
|
||||||
.core_note_type = NT_PRSTATUS,
|
.core_note_type = NT_PRSTATUS,
|
||||||
|
@ -896,6 +958,14 @@ static const struct user_regset s390_compat_regsets[] = {
|
||||||
.get = s390_fpregs_get,
|
.get = s390_fpregs_get,
|
||||||
.set = s390_fpregs_set,
|
.set = s390_fpregs_set,
|
||||||
},
|
},
|
||||||
|
[REGSET_GENERAL_EXTENDED] = {
|
||||||
|
.core_note_type = NT_PRXSTATUS,
|
||||||
|
.n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
|
||||||
|
.size = sizeof(compat_long_t),
|
||||||
|
.align = sizeof(compat_long_t),
|
||||||
|
.get = s390_compat_regs_high_get,
|
||||||
|
.set = s390_compat_regs_high_set,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct user_regset_view user_s390_compat_view = {
|
static const struct user_regset_view user_s390_compat_view = {
|
||||||
|
|
|
@ -729,7 +729,7 @@ static void __init setup_hwcaps(void)
|
||||||
|
|
||||||
if ((facility_list & (1UL << (31 - 22)))
|
if ((facility_list & (1UL << (31 - 22)))
|
||||||
&& (facility_list & (1UL << (31 - 30))))
|
&& (facility_list & (1UL << (31 - 30))))
|
||||||
elf_hwcap |= 1UL << 8;
|
elf_hwcap |= HWCAP_S390_ETF3EH;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for additional facilities with store-facility-list-extended.
|
* Check for additional facilities with store-facility-list-extended.
|
||||||
|
@ -748,11 +748,20 @@ static void __init setup_hwcaps(void)
|
||||||
__stfle(&facility_list_extended, 1) > 0) {
|
__stfle(&facility_list_extended, 1) > 0) {
|
||||||
if ((facility_list_extended & (1ULL << (63 - 42)))
|
if ((facility_list_extended & (1ULL << (63 - 42)))
|
||||||
&& (facility_list_extended & (1ULL << (63 - 44))))
|
&& (facility_list_extended & (1ULL << (63 - 44))))
|
||||||
elf_hwcap |= 1UL << 6;
|
elf_hwcap |= HWCAP_S390_DFP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Huge page support HWCAP_S390_HPAGE is bit 7.
|
||||||
|
*/
|
||||||
if (MACHINE_HAS_HPAGE)
|
if (MACHINE_HAS_HPAGE)
|
||||||
elf_hwcap |= 1UL << 7;
|
elf_hwcap |= HWCAP_S390_HPAGE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 64-bit register support for 31-bit processes
|
||||||
|
* HWCAP_S390_HIGH_GPRS is bit 9.
|
||||||
|
*/
|
||||||
|
elf_hwcap |= HWCAP_S390_HIGH_GPRS;
|
||||||
|
|
||||||
switch (S390_lowcore.cpu_id.machine) {
|
switch (S390_lowcore.cpu_id.machine) {
|
||||||
case 0x9672:
|
case 0x9672:
|
||||||
|
|
|
@ -43,7 +43,7 @@ swsusp_arch_suspend:
|
||||||
lghi %r1,0x1000
|
lghi %r1,0x1000
|
||||||
|
|
||||||
/* Save CPU address */
|
/* Save CPU address */
|
||||||
stap __LC_CPU_ADDRESS(%r1)
|
stap __LC_CPU_ADDRESS(%r0)
|
||||||
|
|
||||||
/* Store registers */
|
/* Store registers */
|
||||||
mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
|
mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
|
||||||
|
@ -69,8 +69,21 @@ swsusp_arch_suspend:
|
||||||
stmg %r0,%r15,0x280(%r1) /* store general registers */
|
stmg %r0,%r15,0x280(%r1) /* store general registers */
|
||||||
|
|
||||||
stpt 0x328(%r1) /* store timer */
|
stpt 0x328(%r1) /* store timer */
|
||||||
|
stck __SF_EMPTY(%r15) /* store clock */
|
||||||
stckc 0x330(%r1) /* store clock comparator */
|
stckc 0x330(%r1) /* store clock comparator */
|
||||||
|
|
||||||
|
/* Update cputime accounting before going to sleep */
|
||||||
|
lg %r0,__LC_LAST_UPDATE_TIMER
|
||||||
|
slg %r0,0x328(%r1)
|
||||||
|
alg %r0,__LC_SYSTEM_TIMER
|
||||||
|
stg %r0,__LC_SYSTEM_TIMER
|
||||||
|
mvc __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
|
||||||
|
lg %r0,__LC_LAST_UPDATE_CLOCK
|
||||||
|
slg %r0,__SF_EMPTY(%r15)
|
||||||
|
alg %r0,__LC_STEAL_TIMER
|
||||||
|
stg %r0,__LC_STEAL_TIMER
|
||||||
|
mvc __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)
|
||||||
|
|
||||||
/* Activate DAT */
|
/* Activate DAT */
|
||||||
stosm __SF_EMPTY(%r15),0x04
|
stosm __SF_EMPTY(%r15),0x04
|
||||||
|
|
||||||
|
@ -159,8 +172,7 @@ pgm_check_entry:
|
||||||
larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
|
larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
|
||||||
stap 0(%r1)
|
stap 0(%r1)
|
||||||
llgh %r2,0(%r1)
|
llgh %r2,0(%r1)
|
||||||
lghi %r3,0x1000
|
llgh %r1,__LC_CPU_ADDRESS(%r0) /* Suspend CPU address: r1 */
|
||||||
llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
|
|
||||||
cgr %r1,%r2
|
cgr %r1,%r2
|
||||||
je restore_registers /* r1 = r2 -> nothing to do */
|
je restore_registers /* r1 = r2 -> nothing to do */
|
||||||
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
|
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
|
||||||
|
@ -200,8 +212,11 @@ restart_suspend:
|
||||||
|
|
||||||
restore_registers:
|
restore_registers:
|
||||||
/* Restore registers */
|
/* Restore registers */
|
||||||
lghi %r13,0x1000 /* %r1 = pointer to save arae */
|
lghi %r13,0x1000 /* %r1 = pointer to save area */
|
||||||
|
|
||||||
|
/* Ignore time spent in suspended state. */
|
||||||
|
llgf %r1,0x318(%r13)
|
||||||
|
stck __LC_LAST_UPDATE_CLOCK(%r1)
|
||||||
spt 0x328(%r13) /* reprogram timer */
|
spt 0x328(%r13) /* reprogram timer */
|
||||||
//sckc 0x330(%r13) /* set clock comparator */
|
//sckc 0x330(%r13) /* set clock comparator */
|
||||||
|
|
||||||
|
@ -229,9 +244,6 @@ restore_registers:
|
||||||
/* Load old stack */
|
/* Load old stack */
|
||||||
lg %r15,0x2f8(%r13)
|
lg %r15,0x2f8(%r13)
|
||||||
|
|
||||||
/* Pointer to save area */
|
|
||||||
lghi %r13,0x1000
|
|
||||||
|
|
||||||
/* Restore prefix register */
|
/* Restore prefix register */
|
||||||
spx 0x318(%r13)
|
spx 0x318(%r13)
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||||
goto out_up;
|
goto out_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put vDSO base into mm struct. We need to do this before calling
|
||||||
|
* install_special_mapping or the perf counter mmap tracking code
|
||||||
|
* will fail to recognise it as a vDSO (since arch_vma_name fails).
|
||||||
|
*/
|
||||||
|
current->mm->context.vdso_base = vdso_base;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* our vma flags don't have VM_WRITE so by default, the process
|
* our vma flags don't have VM_WRITE so by default, the process
|
||||||
* isn't allowed to write those pages.
|
* isn't allowed to write those pages.
|
||||||
|
@ -267,14 +274,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||||
VM_ALWAYSDUMP,
|
VM_ALWAYSDUMP,
|
||||||
vdso_pagelist);
|
vdso_pagelist);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_up;
|
current->mm->context.vdso_base = 0;
|
||||||
|
|
||||||
/* Put vDSO base into mm struct */
|
|
||||||
current->mm->context.vdso_base = vdso_base;
|
|
||||||
|
|
||||||
up_write(&mm->mmap_sem);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_up:
|
out_up:
|
||||||
up_write(&mm->mmap_sem);
|
up_write(&mm->mmap_sem);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -51,6 +51,7 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
. = ALIGN(PAGE_SIZE);
|
||||||
_eshared = .; /* End of shareable data */
|
_eshared = .; /* End of shareable data */
|
||||||
|
_sdata = .; /* Start of data section */
|
||||||
|
|
||||||
EXCEPTION_TABLE(16) :data
|
EXCEPTION_TABLE(16) :data
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,13 @@ void __delay(unsigned long loops)
|
||||||
asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
|
asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __udelay_disabled(unsigned long usecs)
|
static void __udelay_disabled(unsigned long long usecs)
|
||||||
{
|
{
|
||||||
unsigned long mask, cr0, cr0_saved;
|
unsigned long mask, cr0, cr0_saved;
|
||||||
u64 clock_saved;
|
u64 clock_saved;
|
||||||
|
|
||||||
clock_saved = local_tick_disable();
|
clock_saved = local_tick_disable();
|
||||||
set_clock_comparator(get_clock() + ((u64) usecs << 12));
|
set_clock_comparator(get_clock() + (usecs << 12));
|
||||||
__ctl_store(cr0_saved, 0, 0);
|
__ctl_store(cr0_saved, 0, 0);
|
||||||
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
|
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
|
||||||
__ctl_load(cr0 , 0, 0);
|
__ctl_load(cr0 , 0, 0);
|
||||||
|
@ -46,20 +46,25 @@ static void __udelay_disabled(unsigned long usecs)
|
||||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __udelay_enabled(unsigned long usecs)
|
static void __udelay_enabled(unsigned long long usecs)
|
||||||
{
|
{
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
u64 end, time;
|
u64 clock_saved;
|
||||||
|
u64 end;
|
||||||
|
|
||||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
|
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
|
||||||
end = get_clock() + ((u64) usecs << 12);
|
end = get_clock() + (usecs << 12);
|
||||||
do {
|
do {
|
||||||
time = end < S390_lowcore.clock_comparator ?
|
clock_saved = 0;
|
||||||
end : S390_lowcore.clock_comparator;
|
if (end < S390_lowcore.clock_comparator) {
|
||||||
set_clock_comparator(time);
|
clock_saved = local_tick_disable();
|
||||||
|
set_clock_comparator(end);
|
||||||
|
}
|
||||||
trace_hardirqs_on();
|
trace_hardirqs_on();
|
||||||
__load_psw_mask(mask);
|
__load_psw_mask(mask);
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
if (clock_saved)
|
||||||
|
local_tick_enable(clock_saved);
|
||||||
} while (get_clock() < end);
|
} while (get_clock() < end);
|
||||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +72,7 @@ static void __udelay_enabled(unsigned long usecs)
|
||||||
/*
|
/*
|
||||||
* Waits for 'usecs' microseconds using the TOD clock comparator.
|
* Waits for 'usecs' microseconds using the TOD clock comparator.
|
||||||
*/
|
*/
|
||||||
void __udelay(unsigned long usecs)
|
void __udelay(unsigned long long usecs)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -101,11 +106,11 @@ EXPORT_SYMBOL(__udelay);
|
||||||
* Simple udelay variant. To be used on startup and reboot
|
* Simple udelay variant. To be used on startup and reboot
|
||||||
* when the interrupt handler isn't working.
|
* when the interrupt handler isn't working.
|
||||||
*/
|
*/
|
||||||
void udelay_simple(unsigned long usecs)
|
void udelay_simple(unsigned long long usecs)
|
||||||
{
|
{
|
||||||
u64 end;
|
u64 end;
|
||||||
|
|
||||||
end = get_clock() + ((u64) usecs << 12);
|
end = get_clock() + (usecs << 12);
|
||||||
while (get_clock() < end)
|
while (get_clock() < end)
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
|
||||||
tmp1 = -4096UL;
|
tmp1 = -4096UL;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
|
"0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
|
||||||
" jz 7f\n"
|
"9: jz 7f\n"
|
||||||
"1:"ALR" %0,%3\n"
|
"1:"ALR" %0,%3\n"
|
||||||
" "SLR" %1,%3\n"
|
" "SLR" %1,%3\n"
|
||||||
" "SLR" %2,%3\n"
|
" "SLR" %2,%3\n"
|
||||||
|
@ -47,7 +47,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
|
||||||
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
||||||
" jnh 4f\n"
|
" jnh 4f\n"
|
||||||
"3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
|
"3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
|
||||||
" "SLR" %0,%4\n"
|
"10:"SLR" %0,%4\n"
|
||||||
" "ALR" %2,%4\n"
|
" "ALR" %2,%4\n"
|
||||||
"4:"LHI" %4,-1\n"
|
"4:"LHI" %4,-1\n"
|
||||||
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
|
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
|
||||||
|
@ -61,7 +61,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
|
||||||
" j 8f\n"
|
" j 8f\n"
|
||||||
"7:"SLR" %0,%0\n"
|
"7:"SLR" %0,%0\n"
|
||||||
"8: \n"
|
"8: \n"
|
||||||
EX_TABLE(0b,2b) EX_TABLE(3b,4b)
|
EX_TABLE(0b,2b) EX_TABLE(3b,4b) EX_TABLE(9b,2b) EX_TABLE(10b,4b)
|
||||||
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
||||||
: "d" (reg0) : "cc", "memory");
|
: "d" (reg0) : "cc", "memory");
|
||||||
return size;
|
return size;
|
||||||
|
@ -82,7 +82,7 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
|
||||||
tmp1 = -4096UL;
|
tmp1 = -4096UL;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
|
"0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
|
||||||
" jz 4f\n"
|
"6: jz 4f\n"
|
||||||
"1:"ALR" %0,%3\n"
|
"1:"ALR" %0,%3\n"
|
||||||
" "SLR" %1,%3\n"
|
" "SLR" %1,%3\n"
|
||||||
" "SLR" %2,%3\n"
|
" "SLR" %2,%3\n"
|
||||||
|
@ -93,11 +93,11 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
|
||||||
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
||||||
" jnh 5f\n"
|
" jnh 5f\n"
|
||||||
"3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n"
|
"3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n"
|
||||||
" "SLR" %0,%4\n"
|
"7:"SLR" %0,%4\n"
|
||||||
" j 5f\n"
|
" j 5f\n"
|
||||||
"4:"SLR" %0,%0\n"
|
"4:"SLR" %0,%0\n"
|
||||||
"5: \n"
|
"5: \n"
|
||||||
EX_TABLE(0b,2b) EX_TABLE(3b,5b)
|
EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
|
||||||
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
||||||
: "d" (reg0) : "cc", "memory");
|
: "d" (reg0) : "cc", "memory");
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -36,12 +36,12 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
|
||||||
tmp1 = -256UL;
|
tmp1 = -256UL;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"0: mvcp 0(%0,%2),0(%1),%3\n"
|
"0: mvcp 0(%0,%2),0(%1),%3\n"
|
||||||
" jz 8f\n"
|
"10:jz 8f\n"
|
||||||
"1:"ALR" %0,%3\n"
|
"1:"ALR" %0,%3\n"
|
||||||
" la %1,256(%1)\n"
|
" la %1,256(%1)\n"
|
||||||
" la %2,256(%2)\n"
|
" la %2,256(%2)\n"
|
||||||
"2: mvcp 0(%0,%2),0(%1),%3\n"
|
"2: mvcp 0(%0,%2),0(%1),%3\n"
|
||||||
" jnz 1b\n"
|
"11:jnz 1b\n"
|
||||||
" j 8f\n"
|
" j 8f\n"
|
||||||
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
|
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
|
||||||
" "LHI" %3,-4096\n"
|
" "LHI" %3,-4096\n"
|
||||||
|
@ -50,7 +50,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
|
||||||
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
||||||
" jnh 5f\n"
|
" jnh 5f\n"
|
||||||
"4: mvcp 0(%4,%2),0(%1),%3\n"
|
"4: mvcp 0(%4,%2),0(%1),%3\n"
|
||||||
" "SLR" %0,%4\n"
|
"12:"SLR" %0,%4\n"
|
||||||
" "ALR" %2,%4\n"
|
" "ALR" %2,%4\n"
|
||||||
"5:"LHI" %4,-1\n"
|
"5:"LHI" %4,-1\n"
|
||||||
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
|
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
|
||||||
|
@ -65,6 +65,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
|
||||||
"8:"SLR" %0,%0\n"
|
"8:"SLR" %0,%0\n"
|
||||||
"9: \n"
|
"9: \n"
|
||||||
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
|
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
|
||||||
|
EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b)
|
||||||
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
||||||
: : "cc", "memory");
|
: : "cc", "memory");
|
||||||
return size;
|
return size;
|
||||||
|
@ -85,12 +86,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
|
||||||
tmp1 = -256UL;
|
tmp1 = -256UL;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"0: mvcs 0(%0,%1),0(%2),%3\n"
|
"0: mvcs 0(%0,%1),0(%2),%3\n"
|
||||||
" jz 5f\n"
|
"7: jz 5f\n"
|
||||||
"1:"ALR" %0,%3\n"
|
"1:"ALR" %0,%3\n"
|
||||||
" la %1,256(%1)\n"
|
" la %1,256(%1)\n"
|
||||||
" la %2,256(%2)\n"
|
" la %2,256(%2)\n"
|
||||||
"2: mvcs 0(%0,%1),0(%2),%3\n"
|
"2: mvcs 0(%0,%1),0(%2),%3\n"
|
||||||
" jnz 1b\n"
|
"8: jnz 1b\n"
|
||||||
" j 5f\n"
|
" j 5f\n"
|
||||||
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
|
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
|
||||||
" "LHI" %3,-4096\n"
|
" "LHI" %3,-4096\n"
|
||||||
|
@ -99,11 +100,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
|
||||||
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
|
||||||
" jnh 6f\n"
|
" jnh 6f\n"
|
||||||
"4: mvcs 0(%4,%1),0(%2),%3\n"
|
"4: mvcs 0(%4,%1),0(%2),%3\n"
|
||||||
" "SLR" %0,%4\n"
|
"9:"SLR" %0,%4\n"
|
||||||
" j 6f\n"
|
" j 6f\n"
|
||||||
"5:"SLR" %0,%0\n"
|
"5:"SLR" %0,%0\n"
|
||||||
"6: \n"
|
"6: \n"
|
||||||
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
|
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
|
||||||
|
EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
|
||||||
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
|
||||||
: : "cc", "memory");
|
: : "cc", "memory");
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -279,7 +279,10 @@ int s390_enable_sie(void)
|
||||||
/* lets check if we are allowed to replace the mm */
|
/* lets check if we are allowed to replace the mm */
|
||||||
task_lock(tsk);
|
task_lock(tsk);
|
||||||
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
|
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
|
||||||
tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
|
#ifdef CONFIG_AIO
|
||||||
|
!hlist_empty(&tsk->mm->ioctx_list) ||
|
||||||
|
#endif
|
||||||
|
tsk->mm != tsk->active_mm) {
|
||||||
task_unlock(tsk);
|
task_unlock(tsk);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +298,10 @@ int s390_enable_sie(void)
|
||||||
/* Now lets check again if something happened */
|
/* Now lets check again if something happened */
|
||||||
task_lock(tsk);
|
task_lock(tsk);
|
||||||
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
|
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
|
||||||
tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
|
#ifdef CONFIG_AIO
|
||||||
|
!hlist_empty(&tsk->mm->ioctx_list) ||
|
||||||
|
#endif
|
||||||
|
tsk->mm != tsk->active_mm) {
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
task_unlock(tsk);
|
task_unlock(tsk);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -2508,8 +2508,6 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
|
||||||
device->stopped &= ~DASD_UNRESUMED_PM;
|
device->stopped &= ~DASD_UNRESUMED_PM;
|
||||||
|
|
||||||
dasd_schedule_device_bh(device);
|
dasd_schedule_device_bh(device);
|
||||||
if (device->block)
|
|
||||||
dasd_schedule_block_bh(device->block);
|
|
||||||
|
|
||||||
if (device->discipline->restore)
|
if (device->discipline->restore)
|
||||||
rc = device->discipline->restore(device);
|
rc = device->discipline->restore(device);
|
||||||
|
@ -2520,6 +2518,9 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
|
||||||
*/
|
*/
|
||||||
device->stopped |= DASD_UNRESUMED_PM;
|
device->stopped |= DASD_UNRESUMED_PM;
|
||||||
|
|
||||||
|
if (device->block)
|
||||||
|
dasd_schedule_block_bh(device->block);
|
||||||
|
|
||||||
dasd_put_device(device);
|
dasd_put_device(device);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2338,6 +2338,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
|
||||||
/* Calculate number of blocks/records per track. */
|
/* Calculate number of blocks/records per track. */
|
||||||
blksize = block->bp_block;
|
blksize = block->bp_block;
|
||||||
blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
|
blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
|
||||||
|
if (blk_per_trk == 0)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
/* Calculate record id of first and last block. */
|
/* Calculate record id of first and last block. */
|
||||||
first_rec = first_trk = blk_rq_pos(req) >> block->s2b_shift;
|
first_rec = first_trk = blk_rq_pos(req) >> block->s2b_shift;
|
||||||
first_offs = sector_div(first_trk, blk_per_trk);
|
first_offs = sector_div(first_trk, blk_per_trk);
|
||||||
|
@ -3211,6 +3213,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device)
|
||||||
int dasd_eckd_restore_device(struct dasd_device *device)
|
int dasd_eckd_restore_device(struct dasd_device *device)
|
||||||
{
|
{
|
||||||
struct dasd_eckd_private *private;
|
struct dasd_eckd_private *private;
|
||||||
|
struct dasd_eckd_characteristics temp_rdc_data;
|
||||||
int is_known, rc;
|
int is_known, rc;
|
||||||
struct dasd_uid temp_uid;
|
struct dasd_uid temp_uid;
|
||||||
|
|
||||||
|
@ -3245,15 +3248,17 @@ int dasd_eckd_restore_device(struct dasd_device *device)
|
||||||
dasd_eckd_read_features(device);
|
dasd_eckd_read_features(device);
|
||||||
|
|
||||||
/* Read Device Characteristics */
|
/* Read Device Characteristics */
|
||||||
memset(&private->rdc_data, 0, sizeof(private->rdc_data));
|
|
||||||
rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
|
rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
|
||||||
&private->rdc_data, 64);
|
&temp_rdc_data, 64);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DBF_EVENT(DBF_WARNING,
|
DBF_EVENT(DBF_WARNING,
|
||||||
"Read device characteristics failed, rc=%d for "
|
"Read device characteristics failed, rc=%d for "
|
||||||
"device: %s", rc, dev_name(&device->cdev->dev));
|
"device: %s", rc, dev_name(&device->cdev->dev));
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
spin_lock(get_ccwdev_lock(device->cdev));
|
||||||
|
memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data));
|
||||||
|
spin_unlock(get_ccwdev_lock(device->cdev));
|
||||||
|
|
||||||
/* add device to alias management */
|
/* add device to alias management */
|
||||||
dasd_alias_add_device(device);
|
dasd_alias_add_device(device);
|
||||||
|
|
|
@ -1361,11 +1361,13 @@ static int raw3270_pm_start(struct ccw_device *cdev)
|
||||||
|
|
||||||
void raw3270_pm_unfreeze(struct raw3270_view *view)
|
void raw3270_pm_unfreeze(struct raw3270_view *view)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_TN3270_CONSOLE
|
||||||
struct raw3270 *rp;
|
struct raw3270 *rp;
|
||||||
|
|
||||||
rp = view->dev;
|
rp = view->dev;
|
||||||
if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
|
if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
|
||||||
ccw_device_force_console();
|
ccw_device_force_console();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ccw_device_id raw3270_id[] = {
|
static struct ccw_device_id raw3270_id[] = {
|
||||||
|
|
|
@ -265,13 +265,11 @@ struct ccwdev_iter {
|
||||||
static void *
|
static void *
|
||||||
cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
|
cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
|
||||||
{
|
{
|
||||||
struct ccwdev_iter *iter;
|
struct ccwdev_iter *iter = s->private;
|
||||||
|
|
||||||
if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
|
if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
|
||||||
return NULL;
|
return NULL;
|
||||||
iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
|
memset(iter, 0, sizeof(*iter));
|
||||||
if (!iter)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
|
iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
|
||||||
iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
|
iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
|
||||||
return iter;
|
return iter;
|
||||||
|
@ -280,8 +278,6 @@ cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
|
||||||
static void
|
static void
|
||||||
cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
|
cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
|
||||||
{
|
{
|
||||||
if (!IS_ERR(it))
|
|
||||||
kfree(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -378,14 +374,15 @@ static const struct seq_operations cio_ignore_proc_seq_ops = {
|
||||||
static int
|
static int
|
||||||
cio_ignore_proc_open(struct inode *inode, struct file *file)
|
cio_ignore_proc_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
return seq_open(file, &cio_ignore_proc_seq_ops);
|
return seq_open_private(file, &cio_ignore_proc_seq_ops,
|
||||||
|
sizeof(struct ccwdev_iter));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct file_operations cio_ignore_proc_fops = {
|
static const struct file_operations cio_ignore_proc_fops = {
|
||||||
.open = cio_ignore_proc_open,
|
.open = cio_ignore_proc_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.llseek = seq_lseek,
|
.llseek = seq_lseek,
|
||||||
.release = seq_release,
|
.release = seq_release_private,
|
||||||
.write = cio_ignore_write,
|
.write = cio_ignore_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,6 @@ int chp_new(struct chp_id chpid)
|
||||||
chp->state = 1;
|
chp->state = 1;
|
||||||
chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
|
chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
|
||||||
chp->dev.release = chp_release;
|
chp->dev.release = chp_release;
|
||||||
dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
|
|
||||||
|
|
||||||
/* Obtain channel path description and fill it in. */
|
/* Obtain channel path description and fill it in. */
|
||||||
ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
|
ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
|
||||||
|
@ -411,6 +410,7 @@ int chp_new(struct chp_id chpid)
|
||||||
} else {
|
} else {
|
||||||
chp->cmg = -1;
|
chp->cmg = -1;
|
||||||
}
|
}
|
||||||
|
dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
|
||||||
|
|
||||||
/* make it known to the system */
|
/* make it known to the system */
|
||||||
ret = device_register(&chp->dev);
|
ret = device_register(&chp->dev);
|
||||||
|
|
|
@ -1609,7 +1609,7 @@ int ccw_purge_blacklisted(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_set_disconnected(struct ccw_device *cdev)
|
void ccw_device_set_disconnected(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
if (!cdev)
|
if (!cdev)
|
||||||
return;
|
return;
|
||||||
|
@ -1705,7 +1705,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
|
||||||
ccw_device_trigger_reprobe(cdev);
|
ccw_device_trigger_reprobe(cdev);
|
||||||
break;
|
break;
|
||||||
case DISC:
|
case DISC:
|
||||||
device_set_disconnected(cdev);
|
ccw_device_set_disconnected(cdev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -125,6 +125,7 @@ int ccw_device_stlck(struct ccw_device *);
|
||||||
void ccw_device_trigger_reprobe(struct ccw_device *);
|
void ccw_device_trigger_reprobe(struct ccw_device *);
|
||||||
void ccw_device_kill_io(struct ccw_device *);
|
void ccw_device_kill_io(struct ccw_device *);
|
||||||
int ccw_device_notify(struct ccw_device *, int);
|
int ccw_device_notify(struct ccw_device *, int);
|
||||||
|
void ccw_device_set_disconnected(struct ccw_device *cdev);
|
||||||
void ccw_device_set_notoper(struct ccw_device *cdev);
|
void ccw_device_set_notoper(struct ccw_device *cdev);
|
||||||
|
|
||||||
/* qdio needs this. */
|
/* qdio needs this. */
|
||||||
|
|
|
@ -387,19 +387,35 @@ ccw_device_done(struct ccw_device *cdev, int state)
|
||||||
|
|
||||||
cdev->private->state = state;
|
cdev->private->state = state;
|
||||||
|
|
||||||
if (state == DEV_STATE_BOXED) {
|
switch (state) {
|
||||||
|
case DEV_STATE_BOXED:
|
||||||
CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
|
CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
|
||||||
cdev->private->dev_id.devno, sch->schid.sch_no);
|
cdev->private->dev_id.devno, sch->schid.sch_no);
|
||||||
if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
|
if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
|
||||||
ccw_device_schedule_sch_unregister(cdev);
|
ccw_device_schedule_sch_unregister(cdev);
|
||||||
cdev->private->flags.donotify = 0;
|
cdev->private->flags.donotify = 0;
|
||||||
}
|
break;
|
||||||
if (state == DEV_STATE_NOT_OPER) {
|
case DEV_STATE_NOT_OPER:
|
||||||
CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
|
CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
|
||||||
cdev->private->dev_id.devno, sch->schid.sch_no);
|
cdev->private->dev_id.devno, sch->schid.sch_no);
|
||||||
if (!ccw_device_notify(cdev, CIO_GONE))
|
if (!ccw_device_notify(cdev, CIO_GONE))
|
||||||
ccw_device_schedule_sch_unregister(cdev);
|
ccw_device_schedule_sch_unregister(cdev);
|
||||||
|
else
|
||||||
|
ccw_device_set_disconnected(cdev);
|
||||||
cdev->private->flags.donotify = 0;
|
cdev->private->flags.donotify = 0;
|
||||||
|
break;
|
||||||
|
case DEV_STATE_DISCONNECTED:
|
||||||
|
CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel "
|
||||||
|
"%04x\n", cdev->private->dev_id.devno,
|
||||||
|
sch->schid.sch_no);
|
||||||
|
if (!ccw_device_notify(cdev, CIO_NO_PATH))
|
||||||
|
ccw_device_schedule_sch_unregister(cdev);
|
||||||
|
else
|
||||||
|
ccw_device_set_disconnected(cdev);
|
||||||
|
cdev->private->flags.donotify = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdev->private->flags.donotify) {
|
if (cdev->private->flags.donotify) {
|
||||||
|
@ -671,6 +687,10 @@ ccw_device_offline(struct ccw_device *cdev)
|
||||||
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
|
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (cdev->private->state == DEV_STATE_BOXED) {
|
||||||
|
ccw_device_done(cdev, DEV_STATE_BOXED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (ccw_device_is_orphan(cdev)) {
|
if (ccw_device_is_orphan(cdev)) {
|
||||||
ccw_device_done(cdev, DEV_STATE_OFFLINE);
|
ccw_device_done(cdev, DEV_STATE_OFFLINE);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -730,11 +750,10 @@ ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event)
|
||||||
static void ccw_device_generic_notoper(struct ccw_device *cdev,
|
static void ccw_device_generic_notoper(struct ccw_device *cdev,
|
||||||
enum dev_event dev_event)
|
enum dev_event dev_event)
|
||||||
{
|
{
|
||||||
struct subchannel *sch;
|
if (!ccw_device_notify(cdev, CIO_GONE))
|
||||||
|
ccw_device_schedule_sch_unregister(cdev);
|
||||||
ccw_device_set_notoper(cdev);
|
else
|
||||||
sch = to_subchannel(cdev->dev.parent);
|
ccw_device_set_disconnected(cdev);
|
||||||
css_schedule_eval(sch->schid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -361,7 +361,7 @@ static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
|
||||||
.ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
|
.ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
|
||||||
.FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
|
.FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
|
||||||
};
|
};
|
||||||
static struct CPRBX static_cprbx = {
|
static struct CPRBX local_cprbx = {
|
||||||
.cprb_len = 0x00dc,
|
.cprb_len = 0x00dc,
|
||||||
.cprb_ver_id = 0x02,
|
.cprb_ver_id = 0x02,
|
||||||
.func_id = {0x54, 0x32},
|
.func_id = {0x54, 0x32},
|
||||||
|
@ -372,7 +372,7 @@ static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
|
||||||
|
|
||||||
msg->hdr = static_type6_hdrX;
|
msg->hdr = static_type6_hdrX;
|
||||||
msg->hdr.FromCardLen2 = random_number_length,
|
msg->hdr.FromCardLen2 = random_number_length,
|
||||||
msg->cprbx = static_cprbx;
|
msg->cprbx = local_cprbx;
|
||||||
msg->cprbx.rpl_datal = random_number_length,
|
msg->cprbx.rpl_datal = random_number_length,
|
||||||
msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
|
msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
|
||||||
memcpy(msg->function_code, msg->hdr.function_code, 0x02);
|
memcpy(msg->function_code, msg->hdr.function_code, 0x02);
|
||||||
|
@ -561,7 +561,8 @@ static int convert_response_ica(struct zcrypt_device *zdev,
|
||||||
if (msg->cprbx.cprb_ver_id == 0x02)
|
if (msg->cprbx.cprb_ver_id == 0x02)
|
||||||
return convert_type86_ica(zdev, reply,
|
return convert_type86_ica(zdev, reply,
|
||||||
outputdata, outputdatalength);
|
outputdata, outputdatalength);
|
||||||
/* no break, incorrect cprb version is an unknown response */
|
/* Fall through, no break, incorrect cprb version is an unknown
|
||||||
|
* response */
|
||||||
default: /* Unknown response type, this should NEVER EVER happen */
|
default: /* Unknown response type, this should NEVER EVER happen */
|
||||||
zdev->online = 0;
|
zdev->online = 0;
|
||||||
return -EAGAIN; /* repeat the request on a different device. */
|
return -EAGAIN; /* repeat the request on a different device. */
|
||||||
|
@ -587,7 +588,8 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
|
||||||
}
|
}
|
||||||
if (msg->cprbx.cprb_ver_id == 0x02)
|
if (msg->cprbx.cprb_ver_id == 0x02)
|
||||||
return convert_type86_xcrb(zdev, reply, xcRB);
|
return convert_type86_xcrb(zdev, reply, xcRB);
|
||||||
/* no break, incorrect cprb version is an unknown response */
|
/* Fall through, no break, incorrect cprb version is an unknown
|
||||||
|
* response */
|
||||||
default: /* Unknown response type, this should NEVER EVER happen */
|
default: /* Unknown response type, this should NEVER EVER happen */
|
||||||
xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
|
xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
|
||||||
zdev->online = 0;
|
zdev->online = 0;
|
||||||
|
@ -610,7 +612,8 @@ static int convert_response_rng(struct zcrypt_device *zdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (msg->cprbx.cprb_ver_id == 0x02)
|
if (msg->cprbx.cprb_ver_id == 0x02)
|
||||||
return convert_type86_rng(zdev, reply, data);
|
return convert_type86_rng(zdev, reply, data);
|
||||||
/* no break, incorrect cprb version is an unknown response */
|
/* Fall through, no break, incorrect cprb version is an unknown
|
||||||
|
* response */
|
||||||
default: /* Unknown response type, this should NEVER EVER happen */
|
default: /* Unknown response type, this should NEVER EVER happen */
|
||||||
zdev->online = 0;
|
zdev->online = 0;
|
||||||
return -EAGAIN; /* repeat the request on a different device. */
|
return -EAGAIN; /* repeat the request on a different device. */
|
||||||
|
|
|
@ -361,6 +361,7 @@ typedef struct elf64_shdr {
|
||||||
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
|
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
|
||||||
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
|
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
|
||||||
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
|
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
|
||||||
|
#define NT_PRXSTATUS 0x300 /* s390 upper register halves */
|
||||||
|
|
||||||
|
|
||||||
/* Note header in a PT_NOTE section */
|
/* Note header in a PT_NOTE section */
|
||||||
|
|
|
@ -346,8 +346,9 @@ config SLUB_STATS
|
||||||
|
|
||||||
config DEBUG_KMEMLEAK
|
config DEBUG_KMEMLEAK
|
||||||
bool "Kernel memory leak detector"
|
bool "Kernel memory leak detector"
|
||||||
depends on DEBUG_KERNEL && EXPERIMENTAL && (X86 || ARM || PPC) && \
|
depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
|
||||||
!MEMORY_HOTPLUG
|
(X86 || ARM || PPC || S390)
|
||||||
|
|
||||||
select DEBUG_FS if SYSFS
|
select DEBUG_FS if SYSFS
|
||||||
select STACKTRACE if STACKTRACE_SUPPORT
|
select STACKTRACE if STACKTRACE_SUPPORT
|
||||||
select KALLSYMS
|
select KALLSYMS
|
||||||
|
@ -370,7 +371,7 @@ config DEBUG_KMEMLEAK
|
||||||
config DEBUG_KMEMLEAK_EARLY_LOG_SIZE
|
config DEBUG_KMEMLEAK_EARLY_LOG_SIZE
|
||||||
int "Maximum kmemleak early log entries"
|
int "Maximum kmemleak early log entries"
|
||||||
depends on DEBUG_KMEMLEAK
|
depends on DEBUG_KMEMLEAK
|
||||||
range 200 2000
|
range 200 40000
|
||||||
default 400
|
default 400
|
||||||
help
|
help
|
||||||
Kmemleak must track all the memory allocations to avoid
|
Kmemleak must track all the memory allocations to avoid
|
||||||
|
|
Loading…
Reference in a new issue