Commit f144c78e 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: (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
  ...
parents ef1f7a7e 6fca97a9
...@@ -14,10 +14,11 @@ ...@@ -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 @@ ...@@ -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 ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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 *)&regs->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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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: ...@@ -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) ...@@ -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(&current->tracing_graph_pause))) if (unlikely(atomic_read(&current->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) ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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[] = { ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 *); ...@@ -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) ...@@ -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;
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; 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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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
......
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