Commit da1ba891 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
  [S390] guest page hinting light
  [S390] tty3270: fix put_char fail/success conversion.
  [S390] compat ptrace cleanup
  [S390] s390mach compile warning
  [S390] cio: Fix parsing mechanism for blacklisted devices.
  [S390] cio: Remove cio_msg kernel parameter.
  [S390] s390-kvm: leave sie context on work. Removes preemption requirement
  [S390] s390: Optimize user and work TIF check
parents 8b2cc917 45e576b1
...@@ -8,17 +8,6 @@ Command line parameters ...@@ -8,17 +8,6 @@ Command line parameters
Enable logging of debug information in case of ccw device timeouts. Enable logging of debug information in case of ccw device timeouts.
* cio_msg = yes | no
Determines whether information on found devices and sensed device
characteristics should be shown during startup or when new devices are
found, i. e. messages of the types "Detected device 0.0.4711 on subchannel
0.0.0042" and "SenseID: Device 0.0.4711 reports: ...".
Default is off.
* cio_ignore = {all} | * cio_ignore = {all} |
{<device> | <range of devices>} | {<device> | <range of devices>} |
{!<device> | !<range of devices>} {!<device> | !<range of devices>}
......
...@@ -430,6 +430,13 @@ config CMM_IUCV ...@@ -430,6 +430,13 @@ config CMM_IUCV
Select this option to enable the special message interface to Select this option to enable the special message interface to
the cooperative memory management. the cooperative memory management.
config PAGE_STATES
bool "Unused page notification"
help
This enables the notification of unused pages to the
hypervisor. The ESSA instruction is used to do the states
changes between a page that has content and the unused state.
config VIRT_TIMER config VIRT_TIMER
bool "Virtual CPU timer support" bool "Virtual CPU timer support"
help help
......
...@@ -121,7 +121,7 @@ sys32_ptrace_wrapper: ...@@ -121,7 +121,7 @@ sys32_ptrace_wrapper:
lgfr %r3,%r3 # long lgfr %r3,%r3 # long
llgtr %r4,%r4 # long llgtr %r4,%r4 # long
llgfr %r5,%r5 # long llgfr %r5,%r5 # long
jg sys_ptrace # branch to system call jg compat_sys_ptrace # branch to system call
.globl sys32_alarm_wrapper .globl sys32_alarm_wrapper
sys32_alarm_wrapper: sys32_alarm_wrapper:
......
...@@ -279,8 +279,6 @@ sysc_do_restart: ...@@ -279,8 +279,6 @@ sysc_do_restart:
st %r2,SP_R2(%r15) # store return value (change R2 on stack) st %r2,SP_R2(%r15) # store return value (change R2 on stack)
sysc_return: sysc_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
bno BASED(sysc_restore)
tm __TI_flags+3(%r9),_TIF_WORK_SVC tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.) bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_restore: sysc_restore:
...@@ -312,6 +310,8 @@ sysc_work_loop: ...@@ -312,6 +310,8 @@ sysc_work_loop:
# One of the work bits is on. Find out which one. # One of the work bits is on. Find out which one.
# #
sysc_work: sysc_work:
tm SP_PSW+1(%r15),0x01 # returning to user ?
bno BASED(sysc_restore)
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
bo BASED(sysc_mcck_pending) bo BASED(sysc_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
...@@ -602,12 +602,6 @@ io_no_vtime: ...@@ -602,12 +602,6 @@ io_no_vtime:
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
basr %r14,%r1 # branch to standard irq handler basr %r14,%r1 # branch to standard irq handler
io_return: io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
bno BASED(io_preempt) # no -> check for preemptive scheduling
#else
bno BASED(io_restore) # no-> skip resched & signal
#endif
tm __TI_flags+3(%r9),_TIF_WORK_INT tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.) bnz BASED(io_work) # there is work to do (signals etc.)
io_restore: io_restore:
...@@ -629,10 +623,18 @@ io_restore_trace_psw: ...@@ -629,10 +623,18 @@ io_restore_trace_psw:
.long 0, io_restore_trace + 0x80000000 .long 0, io_restore_trace + 0x80000000
#endif #endif
#ifdef CONFIG_PREEMPT #
io_preempt: # switch to kernel stack, then check the TIF bits
#
io_work:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifndef CONFIG_PREEMPT
bno BASED(io_restore) # no-> skip resched & signal
#else
bnz BASED(io_work_user) # no -> check for preemptive scheduling
# check for preemptive scheduling
icm %r0,15,__TI_precount(%r9) icm %r0,15,__TI_precount(%r9)
bnz BASED(io_restore) bnz BASED(io_restore) # preemption disabled
l %r1,SP_R15(%r15) l %r1,SP_R15(%r15)
s %r1,BASED(.Lc_spsize) s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
...@@ -646,10 +648,7 @@ io_resume_loop: ...@@ -646,10 +648,7 @@ io_resume_loop:
br %r1 # call schedule br %r1 # call schedule
#endif #endif
# io_work_user:
# switch to kernel stack, then check the TIF bits
#
io_work:
l %r1,__LC_KERNEL_STACK l %r1,__LC_KERNEL_STACK
s %r1,BASED(.Lc_spsize) s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
......
...@@ -271,8 +271,6 @@ sysc_noemu: ...@@ -271,8 +271,6 @@ sysc_noemu:
stg %r2,SP_R2(%r15) # store return value (change R2 on stack) stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
sysc_return: sysc_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
jno sysc_restore
tm __TI_flags+7(%r9),_TIF_WORK_SVC tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.) jnz sysc_work # there is work to do (signals etc.)
sysc_restore: sysc_restore:
...@@ -304,6 +302,8 @@ sysc_work_loop: ...@@ -304,6 +302,8 @@ sysc_work_loop:
# One of the work bits is on. Find out which one. # One of the work bits is on. Find out which one.
# #
sysc_work: sysc_work:
tm SP_PSW+1(%r15),0x01 # returning to user ?
jno sysc_restore
tm __TI_flags+7(%r9),_TIF_MCCK_PENDING tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
jo sysc_mcck_pending jo sysc_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
...@@ -585,12 +585,6 @@ io_no_vtime: ...@@ -585,12 +585,6 @@ io_no_vtime:
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler brasl %r14,do_IRQ # call standard irq handler
io_return: io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
jno io_preempt # no -> check for preemptive scheduling
#else
jno io_restore # no-> skip resched & signal
#endif
tm __TI_flags+7(%r9),_TIF_WORK_INT tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.) jnz io_work # there is work to do (signals etc.)
io_restore: io_restore:
...@@ -612,10 +606,41 @@ io_restore_trace_psw: ...@@ -612,10 +606,41 @@ io_restore_trace_psw:
.quad 0, io_restore_trace .quad 0, io_restore_trace
#endif #endif
#ifdef CONFIG_PREEMPT #
io_preempt: # There is work todo, we need to check if we return to userspace, then
# check, if we are in SIE, if yes leave it
#
io_work:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifndef CONFIG_PREEMPT
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
jnz io_work_user # yes -> no need to check for SIE
la %r1, BASED(sie_opcode) # we return to kernel here
lg %r2, SP_PSW+8(%r15)
clc 0(2,%r1), 0(%r2) # is current instruction = SIE?
jne io_restore # no-> return to kernel
lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE
aghi %r1, 4
stg %r1, SP_PSW+8(%r15)
j io_restore # return to kernel
#else
jno io_restore # no-> skip resched & signal
#endif
#else
jnz io_work_user # yes -> do resched & signal
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
la %r1, BASED(sie_opcode)
lg %r2, SP_PSW+8(%r15)
clc 0(2,%r1), 0(%r2) # is current instruction = SIE?
jne 0f # no -> leave PSW alone
lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE
aghi %r1, 4
stg %r1, SP_PSW+8(%r15)
0:
#endif
# check for preemptive scheduling
icm %r0,15,__TI_precount(%r9) icm %r0,15,__TI_precount(%r9)
jnz io_restore jnz io_restore # preemption is disabled
# switch to kernel stack # switch to kernel stack
lg %r1,SP_R15(%r15) lg %r1,SP_R15(%r15)
aghi %r1,-SP_SIZE aghi %r1,-SP_SIZE
...@@ -629,10 +654,7 @@ io_resume_loop: ...@@ -629,10 +654,7 @@ io_resume_loop:
jg preempt_schedule_irq jg preempt_schedule_irq
#endif #endif
# io_work_user:
# switch to kernel stack, then check TIF bits
#
io_work:
lg %r1,__LC_KERNEL_STACK lg %r1,__LC_KERNEL_STACK
aghi %r1,-SP_SIZE aghi %r1,-SP_SIZE
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
...@@ -653,6 +675,11 @@ io_work_loop: ...@@ -653,6 +675,11 @@ io_work_loop:
j io_restore j io_restore
io_work_done: io_work_done:
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
sie_opcode:
.long 0xb2140000
#endif
# #
# _TIF_MCCK_PENDING is set, call handler # _TIF_MCCK_PENDING is set, call handler
# #
......
...@@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) ...@@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
return 0; return 0;
} }
static int long arch_ptrace(struct task_struct *child, long request, long addr, long data)
do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
{ {
ptrace_area parea; ptrace_area parea;
int copied, ret; int copied, ret;
...@@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) ...@@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
return 0; return 0;
} }
static int long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) compat_ulong_t caddr, compat_ulong_t cdata)
{ {
unsigned int tmp; /* 4 bytes !! */ unsigned long addr = caddr;
unsigned long data = cdata;
ptrace_area_emu31 parea; ptrace_area_emu31 parea;
int copied, ret; int copied, ret;
switch (request) { switch (request) {
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
/* read word at location addr. */
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
return -EIO;
return put_user(tmp, (unsigned int __force __user *) data);
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
return peek_user_emu31(child, addr, data); return peek_user_emu31(child, addr, data);
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
/* write the word at location addr. */
tmp = data;
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
if (copied != sizeof(tmp))
return -EIO;
return 0;
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
/* write the word at location addr in the USER area */ /* write the word at location addr in the USER area */
return poke_user_emu31(child, addr, data); return poke_user_emu31(child, addr, data);
...@@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) ...@@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
copied += sizeof(unsigned int); copied += sizeof(unsigned int);
} }
return 0; return 0;
case PTRACE_GETEVENTMSG:
return put_user((__u32) child->ptrace_message,
(unsigned int __force __user *) data);
case PTRACE_GETSIGINFO:
if (child->last_siginfo == NULL)
return -EINVAL;
return copy_siginfo_to_user32((compat_siginfo_t
__force __user *) data,
child->last_siginfo);
case PTRACE_SETSIGINFO:
if (child->last_siginfo == NULL)
return -EINVAL;
return copy_siginfo_from_user32(child->last_siginfo,
(compat_siginfo_t
__force __user *) data);
} }
return ptrace_request(child, request, addr, data); return compat_ptrace_request(child, request, addr, data);
} }
#endif #endif
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
switch (request) {
case PTRACE_SYSCALL:
/* continue and stop at next (return from) syscall */
case PTRACE_CONT:
/* restart after signal. */
if (!valid_signal(data))
return -EIO;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
/* make sure the single step bit is not set. */
user_disable_single_step(child);
wake_up_process(child);
return 0;
case PTRACE_KILL:
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
return 0;
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
user_disable_single_step(child);
wake_up_process(child);
return 0;
case PTRACE_SINGLESTEP:
/* set the trap flag. */
if (!valid_signal(data))
return -EIO;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
user_enable_single_step(child);
/* give it a chance to run. */
wake_up_process(child);
return 0;
/* Do requests that differ for 31/64 bit */
default:
#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT))
return do_ptrace_emu31(child, request, addr, data);
#endif
return do_ptrace_normal(child, request, addr, data);
}
/* Not reached. */
return -EIO;
}
asmlinkage void asmlinkage void
syscall_trace(struct pt_regs *regs, int entryexit) syscall_trace(struct pt_regs *regs, int entryexit)
{ {
......
...@@ -22,7 +22,6 @@ config KVM ...@@ -22,7 +22,6 @@ config KVM
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select ANON_INODES select ANON_INODES
select S390_SWITCH_AMODE select S390_SWITCH_AMODE
select PREEMPT
---help--- ---help---
Support hosting paravirtualized guest machines using the SIE Support hosting paravirtualized guest machines using the SIE
virtualization capability on the mainframe. This should work virtualization capability on the mainframe. This should work
......
...@@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = { ...@@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = {
static int handle_noop(struct kvm_vcpu *vcpu) static int handle_noop(struct kvm_vcpu *vcpu)
{ {
switch (vcpu->arch.sie_block->icptcode) { switch (vcpu->arch.sie_block->icptcode) {
case 0x0:
vcpu->stat.exit_null++;
break;
case 0x10: case 0x10:
vcpu->stat.exit_external_request++; vcpu->stat.exit_external_request++;
break; break;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
struct kvm_stats_debugfs_item debugfs_entries[] = { struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "userspace_handled", VCPU_STAT(exit_userspace) }, { "userspace_handled", VCPU_STAT(exit_userspace) },
{ "exit_null", VCPU_STAT(exit_null) },
{ "exit_validity", VCPU_STAT(exit_validity) }, { "exit_validity", VCPU_STAT(exit_validity) },
{ "exit_stop_request", VCPU_STAT(exit_stop_request) }, { "exit_stop_request", VCPU_STAT(exit_stop_request) },
{ "exit_external_request", VCPU_STAT(exit_external_request) }, { "exit_external_request", VCPU_STAT(exit_external_request) },
...@@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK; vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
restore_fp_regs(&vcpu->arch.guest_fpregs); restore_fp_regs(&vcpu->arch.guest_fpregs);
restore_access_regs(vcpu->arch.guest_acrs); restore_access_regs(vcpu->arch.guest_acrs);
if (signal_pending(current))
atomic_set_mask(CPUSTAT_STOP_INT,
&vcpu->arch.sie_block->cpuflags);
} }
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
......
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PAGE_STATES) += page-states.o
...@@ -126,6 +126,9 @@ void __init mem_init(void) ...@@ -126,6 +126,9 @@ void __init mem_init(void)
/* clear the zero-page */ /* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE); memset(empty_zero_page, 0, PAGE_SIZE);
/* Setup guest page hinting */
cmma_init();
/* this will put all low memory onto the freelists */ /* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem(); totalram_pages += free_all_bootmem();
......
/*
* arch/s390/mm/page-states.c
*
* Copyright IBM Corp. 2008
*
* Guest page hinting for unused pages.
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/init.h>
#define ESSA_SET_STABLE 1
#define ESSA_SET_UNUSED 2
static int cmma_flag;
static int __init cmma(char *str)
{
char *parm;
parm = strstrip(str);
if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) {
cmma_flag = 1;
return 1;
}
cmma_flag = 0;
if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0)
return 1;
return 0;
}
__setup("cmma=", cmma);
void __init cmma_init(void)
{
register unsigned long tmp asm("0") = 0;
register int rc asm("1") = -EOPNOTSUPP;
if (!cmma_flag)
return;
asm volatile(
" .insn rrf,0xb9ab0000,%1,%1,0,0\n"
"0: la %0,0\n"
"1:\n"
EX_TABLE(0b,1b)
: "+&d" (rc), "+&d" (tmp));
if (rc)
cmma_flag = 0;
}
void arch_free_page(struct page *page, int order)
{
int i, rc;
if (!cmma_flag)
return;
for (i = 0; i < (1 << order); i++)
asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
: "=&d" (rc)
: "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
"i" (ESSA_SET_UNUSED));
}
void arch_alloc_page(struct page *page, int order)
{
int i, rc;
if (!cmma_flag)
return;
for (i = 0; i < (1 << order); i++)
asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
: "=&d" (rc)
: "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
"i" (ESSA_SET_STABLE));
}
...@@ -965,8 +965,7 @@ tty3270_write_room(struct tty_struct *tty) ...@@ -965,8 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
* Insert character into the screen at the current position with the * Insert character into the screen at the current position with the
* current color and highlight. This function does NOT do cursor movement. * current color and highlight. This function does NOT do cursor movement.
*/ */
static int static void tty3270_put_character(struct tty3270 *tp, char ch)
tty3270_put_character(struct tty3270 *tp, char ch)
{ {
struct tty3270_line *line; struct tty3270_line *line;
struct tty3270_cell *cell; struct tty3270_cell *cell;
...@@ -986,7 +985,6 @@ tty3270_put_character(struct tty3270 *tp, char ch) ...@@ -986,7 +985,6 @@ tty3270_put_character(struct tty3270 *tp, char ch)
cell->character = tp->view.ascebc[(unsigned int) ch]; cell->character = tp->view.ascebc[(unsigned int) ch];
cell->highlight = tp->highlight; cell->highlight = tp->highlight;
cell->f_color = tp->f_color; cell->f_color = tp->f_color;
return 1;
} }
/* /*
...@@ -1612,16 +1610,15 @@ tty3270_write(struct tty_struct * tty, ...@@ -1612,16 +1610,15 @@ tty3270_write(struct tty_struct * tty,
/* /*
* Put single characters to the ttys character buffer * Put single characters to the ttys character buffer
*/ */
static void static int tty3270_put_char(struct tty_struct *tty, unsigned char ch)
tty3270_put_char(struct tty_struct *tty, unsigned char ch)
{ {
struct tty3270 *tp; struct tty3270 *tp;
tp = tty->driver_data; tp = tty->driver_data;
if (!tp) if (!tp || tp->char_count >= TTY3270_CHAR_BUF_SIZE)
return; return 0;
if (tp->char_count < TTY3270_CHAR_BUF_SIZE) tp->char_buf[tp->char_count++] = ch;
tp->char_buf[tp->char_count++] = ch; return 1;
} }
/* /*
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/cio.h>
#include "blacklist.h" #include "blacklist.h"
#include "cio.h" #include "cio.h"
...@@ -43,164 +44,169 @@ typedef enum {add, free} range_action; ...@@ -43,164 +44,169 @@ typedef enum {add, free} range_action;
* Function: blacklist_range * Function: blacklist_range
* (Un-)blacklist the devices from-to * (Un-)blacklist the devices from-to
*/ */
static void static int blacklist_range(range_action action, unsigned int from_ssid,
blacklist_range (range_action action, unsigned int from, unsigned int to, unsigned int to_ssid, unsigned int from,
unsigned int ssid) unsigned int to, int msgtrigger)
{ {
if (!to) if ((from_ssid > to_ssid) || ((from_ssid == to_ssid) && (from > to))) {
to = from; if (msgtrigger)
printk(KERN_WARNING "cio: Invalid cio_ignore range "
if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) { "0.%x.%04x-0.%x.%04x\n", from_ssid, from,
printk (KERN_WARNING "cio: Invalid blacklist range " to_ssid, to);
"0.%x.%04x to 0.%x.%04x, skipping\n", return 1;
ssid, from, ssid, to);
return;
} }
for (; from <= to; from++) {
while ((from_ssid < to_ssid) || ((from_ssid == to_ssid) &&
(from <= to))) {
if (action == add) if (action == add)
set_bit (from, bl_dev[ssid]); set_bit(from, bl_dev[from_ssid]);
else else
clear_bit (from, bl_dev[ssid]); clear_bit(from, bl_dev[from_ssid]);
from++;
if (from > __MAX_SUBCHANNEL) {
from_ssid++;
from = 0;
}
} }
return 0;
} }
/* static int pure_hex(char **cp, unsigned int *val, int min_digit,
* Function: blacklist_busid int max_digit, int max_val)
* Get devno/busid from given string.
* Shamelessly grabbed from dasd_devmap.c.
*/
static int
blacklist_busid(char **str, int *id0, int *ssid, int *devno)
{ {
int val, old_style; int diff;
char *sav; unsigned int value;
sav = *str; diff = 0;
*val = 0;
/* check for leading '0x' */ while (isxdigit(**cp) && (diff <= max_digit)) {
old_style = 0;
if ((*str)[0] == '0' && (*str)[1] == 'x') { if (isdigit(**cp))
*str += 2; value = **cp - '0';
old_style = 1; else
} value = tolower(**cp) - 'a' + 10;
if (!isxdigit((*str)[0])) /* We require at least one hex digit */ *val = *val * 16 + value;
goto confused; (*cp)++;
val = simple_strtoul(*str, str, 16); diff++;
if (old_style || (*str)[0] != '.') {
*id0 = *ssid = 0;
if (val < 0 || val > 0xffff)
goto confused;
*devno = val;
if ((*str)[0] != ',' && (*str)[0] != '-' &&
(*str)[0] != '\n' && (*str)[0] != '\0')
goto confused;
return 0;
} }
/* New style x.y.z busid */
if (val < 0 || val > 0xff) if ((diff < min_digit) || (diff > max_digit) || (*val > max_val))
goto confused; return 1;
*id0 = val;
(*str)++;
if (!isxdigit((*str)[0])) /* We require at least one hex digit */
goto confused;
val = simple_strtoul(*str, str, 16);
if (val < 0 || val > 0xff || (*str)++[0] != '.')
goto confused;
*ssid = val;
if (!isxdigit((*str)[0])) /* We require at least one hex digit */
goto confused;
val = simple_strtoul(*str, str, 16);
if (val < 0 || val > 0xffff)
goto confused;
*devno = val;
if ((*str)[0] != ',' && (*str)[0] != '-' &&
(*str)[0] != '\n' && (*str)[0] != '\0')
goto confused;
return 0; return 0;
confused:
strsep(str, ",\n");
printk(KERN_WARNING "cio: Invalid cio_ignore parameter '%s'\n", sav);
return 1;
} }
static int static int parse_busid(char *str, int *cssid, int *ssid, int *devno,
blacklist_parse_parameters (char *str, range_action action) int msgtrigger)
{ {
int from, to, from_id0, to_id0, from_ssid, to_ssid; char *str_work;
int val, rc, ret;
while (*str != 0 && *str != '\n') {
range_action ra = action; rc = 1;
while(*str == ',')
str++; if (*str == '\0')
if (*str == '!') { goto out;
ra = !action;
++str; /* old style */
str_work = str;
val = simple_strtoul(str, &str_work, 16);
if (*str_work == '\0') {
if (val <= __MAX_SUBCHANNEL) {
*devno = val;
*ssid = 0;
*cssid = 0;
rc = 0;
} }
goto out;
}
/* /* new style */
* Since we have to parse the proc commands and the str_work = str;
* kernel arguments we have to check four cases ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID);
*/ if (ret || (str_work[0] != '.'))
if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 || goto out;
strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) { str_work++;
int j; ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID);
if (ret || (str_work[0] != '.'))
str += 3; goto out;
for (j=0; j <= __MAX_SSID; j++) str_work++;
blacklist_range(ra, 0, __MAX_SUBCHANNEL, j); ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL);
} else { if (ret || (str_work[0] != '\0'))
int rc; goto out;
rc = 0;
out:
if (rc && msgtrigger)
printk(KERN_WARNING "cio: Invalid cio_ignore device '%s'\n",
str);
return rc;
}
rc = blacklist_busid(&str, &from_id0, static int blacklist_parse_parameters(char *str, range_action action,
&from_ssid, &from); int msgtrigger)
if (rc) {
continue; int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
to = from; int rc, totalrc;
to_id0 = from_id0; char *parm;
to_ssid = from_ssid; range_action ra;
if (*str == '-') {
str++; totalrc = 0;
rc = blacklist_busid(&str, &to_id0,
&to_ssid, &to); while ((parm = strsep(&str, ","))) {
if (rc) rc = 0;
continue; ra = action;
} if (*parm == '!') {
if (*str == '-') { if (ra == add)
printk(KERN_WARNING "cio: invalid cio_ignore " ra = free;
"parameter '%s'\n", else
strsep(&str, ",\n")); ra = add;
continue; parm++;
} }
if ((from_id0 != to_id0) || if (strcmp(parm, "all") == 0) {
(from_ssid != to_ssid)) { from_cssid = 0;
printk(KERN_WARNING "cio: invalid cio_ignore " from_ssid = 0;
"range %x.%x.%04x-%x.%x.%04x\n", from = 0;
from_id0, from_ssid, from, to_cssid = __MAX_CSSID;
to_id0, to_ssid, to); to_ssid = __MAX_SSID;
continue; to = __MAX_SUBCHANNEL;
} else {
rc = parse_busid(strsep(&parm, "-"), &from_cssid,
&from_ssid, &from, msgtrigger);
if (!rc) {
if (parm != NULL)
rc = parse_busid(parm, &to_cssid,
&to_ssid, &to,
msgtrigger);
else {
to_cssid = from_cssid;
to_ssid = from_ssid;
to = from;
}
} }
blacklist_range (ra, from, to, to_ssid);
} }
if (!rc) {
rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
msgtrigger);
if (rc)
totalrc = 1;
} else
totalrc = 1;
} }
return 1;
return totalrc;
} }
/* Parsing the commandline for blacklist parameters, e.g. to blacklist
* bus ids 0.0.1234, 0.0.1235 and 0.0.1236, you could use any of:
* - cio_ignore=1234-1236
* - cio_ignore=0x1234-0x1235,1236
* - cio_ignore=0x1234,1235-1236
* - cio_ignore=1236 cio_ignore=1234-0x1236
* - cio_ignore=1234 cio_ignore=1236 cio_ignore=0x1235
* - cio_ignore=0.0.1234-0.0.1236
* - cio_ignore=0.0.1234,0x1235,1236
* - ...
*/
static int __init static int __init
blacklist_setup (char *str) blacklist_setup (char *str)
{ {
CIO_MSG_EVENT(6, "Reading blacklist parameters\n"); CIO_MSG_EVENT(6, "Reading blacklist parameters\n");
return blacklist_parse_parameters (str, add); if (blacklist_parse_parameters(str, add, 1))
return 0;
return 1;
} }
__setup ("cio_ignore=", blacklist_setup); __setup ("cio_ignore=", blacklist_setup);
...@@ -224,27 +230,23 @@ is_blacklisted (int ssid, int devno) ...@@ -224,27 +230,23 @@ is_blacklisted (int ssid, int devno)
* Function: blacklist_parse_proc_parameters * Function: blacklist_parse_proc_parameters
* parse the stuff which is piped to /proc/cio_ignore * parse the stuff which is piped to /proc/cio_ignore
*/ */
static void static int blacklist_parse_proc_parameters(char *buf)
blacklist_parse_proc_parameters (char *buf)
{ {
if (strncmp (buf, "free ", 5) == 0) { int rc;
blacklist_parse_parameters (buf + 5, free); char *parm;
} else if (strncmp (buf, "add ", 4) == 0) {
/* parm = strsep(&buf, " ");
* We don't need to check for known devices since
* css_probe_device will handle this correctly. if (strcmp("free", parm) == 0)
*/ rc = blacklist_parse_parameters(buf, free, 0);
blacklist_parse_parameters (buf + 4, add); else if (strcmp("add", parm) == 0)
} else { rc = blacklist_parse_parameters(buf, add, 0);
printk (KERN_WARNING "cio: cio_ignore: Parse error; \n" else
KERN_WARNING "try using 'free all|<devno-range>," return 1;
"<devno-range>,...'\n"
KERN_WARNING "or 'add <devno-range>,"
"<devno-range>,...'\n");
return;
}
css_schedule_reprobe(); css_schedule_reprobe();
return rc;
} }
/* Iterator struct for all devices. */ /* Iterator struct for all devices. */
...@@ -328,6 +330,8 @@ cio_ignore_write(struct file *file, const char __user *user_buf, ...@@ -328,6 +330,8 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
size_t user_len, loff_t *offset) size_t user_len, loff_t *offset)
{ {
char *buf; char *buf;
size_t i;
ssize_t rc, ret;
if (*offset) if (*offset)
return -EINVAL; return -EINVAL;
...@@ -336,16 +340,27 @@ cio_ignore_write(struct file *file, const char __user *user_buf, ...@@ -336,16 +340,27 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
buf = vmalloc (user_len + 1); /* maybe better use the stack? */ buf = vmalloc (user_len + 1); /* maybe better use the stack? */
if (buf == NULL) if (buf == NULL)
return -ENOMEM; return -ENOMEM;
memset(buf, 0, user_len + 1);
if (strncpy_from_user (buf, user_buf, user_len) < 0) { if (strncpy_from_user (buf, user_buf, user_len) < 0) {
vfree (buf); rc = -EFAULT;
return -EFAULT; goto out_free;
} }
buf[user_len] = '\0';
blacklist_parse_proc_parameters (buf); i = user_len - 1;
while ((i >= 0) && (isspace(buf[i]) || (buf[i] == 0))) {
buf[i] = '\0';
i--;
}
ret = blacklist_parse_proc_parameters(buf);
if (ret)
rc = -EINVAL;
else
rc = user_len;
out_free:
vfree (buf); vfree (buf);
return user_len; return rc;
} }
static const struct seq_operations cio_ignore_proc_seq_ops = { static const struct seq_operations cio_ignore_proc_seq_ops = {
......
...@@ -39,23 +39,6 @@ debug_info_t *cio_debug_msg_id; ...@@ -39,23 +39,6 @@ debug_info_t *cio_debug_msg_id;
debug_info_t *cio_debug_trace_id; debug_info_t *cio_debug_trace_id;
debug_info_t *cio_debug_crw_id; debug_info_t *cio_debug_crw_id;
int cio_show_msg;
static int __init
cio_setup (char *parm)
{
if (!strcmp (parm, "yes"))
cio_show_msg = 1;
else if (!strcmp (parm, "no"))
cio_show_msg = 0;
else
printk(KERN_ERR "cio: cio_setup: "
"invalid cio_msg parameter '%s'", parm);
return 1;
}
__setup ("cio_msg=", cio_setup);
/* /*
* Function: cio_debug_init * Function: cio_debug_init
* Initializes three debug logs for common I/O: * Initializes three debug logs for common I/O:
...@@ -166,7 +149,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) ...@@ -166,7 +149,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
stsch (sch->schid, &sch->schib); stsch (sch->schid, &sch->schib);
CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
"subchannel 0.%x.%04x!\n", sch->schid.ssid, "subchannel 0.%x.%04x!\n", sch->schid.ssid,
sch->schid.sch_no); sch->schid.sch_no);
sprintf(dbf_text, "no%s", sch->dev.bus_id); sprintf(dbf_text, "no%s", sch->dev.bus_id);
...@@ -567,10 +550,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -567,10 +550,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
* ... just being curious we check for non I/O subchannels * ... just being curious we check for non I/O subchannels
*/ */
if (sch->st != 0) { if (sch->st != 0) {
CIO_DEBUG(KERN_INFO, 0, CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports "
"Subchannel 0.%x.%04x reports " "non-I/O subchannel type %04X\n",
"non-I/O subchannel type %04X\n", sch->schid.ssid, sch->schid.sch_no, sch->st);
sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */ /* We stop here for non-io subchannels. */
err = sch->st; err = sch->st;
goto out; goto out;
...@@ -588,7 +570,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -588,7 +570,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
* This device must not be known to Linux. So we simply * This device must not be known to Linux. So we simply
* say that there is no device and return ENODEV. * say that there is no device and return ENODEV.
*/ */
CIO_MSG_EVENT(4, "Blacklisted device detected " CIO_MSG_EVENT(6, "Blacklisted device detected "
"at devno %04X, subchannel set %x\n", "at devno %04X, subchannel set %x\n",
sch->schib.pmcw.dev, sch->schid.ssid); sch->schib.pmcw.dev, sch->schid.ssid);
err = -ENODEV; err = -ENODEV;
...@@ -601,12 +583,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) ...@@ -601,12 +583,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
sch->lpm = sch->schib.pmcw.pam & sch->opm; sch->lpm = sch->schib.pmcw.pam & sch->opm;
sch->isc = 3; sch->isc = 3;
CIO_DEBUG(KERN_INFO, 0, CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X "
"Detected device %04x on subchannel 0.%x.%04X" "- PIM = %02X, PAM = %02X, POM = %02X\n",
" - PIM = %02X, PAM = %02X, POM = %02X\n", sch->schib.pmcw.dev, sch->schid.ssid,
sch->schib.pmcw.dev, sch->schid.ssid, sch->schid.sch_no, sch->schib.pmcw.pim,
sch->schid.sch_no, sch->schib.pmcw.pim, sch->schib.pmcw.pam, sch->schib.pmcw.pom);
sch->schib.pmcw.pam, sch->schib.pmcw.pom);
/* /*
* We now have to initially ... * We now have to initially ...
......
...@@ -118,6 +118,4 @@ extern void *cio_get_console_priv(void); ...@@ -118,6 +118,4 @@ extern void *cio_get_console_priv(void);
#define cio_get_console_priv() NULL #define cio_get_console_priv() NULL
#endif #endif
extern int cio_show_msg;
#endif #endif
...@@ -31,10 +31,4 @@ static inline void CIO_HEX_EVENT(int level, void *data, int length) ...@@ -31,10 +31,4 @@ static inline void CIO_HEX_EVENT(int level, void *data, int length)
} }
} }
#define CIO_DEBUG(printk_level, event_level, msg...) do { \
if (cio_show_msg) \
printk(printk_level "cio: " msg); \
CIO_MSG_EVENT(event_level, msg); \
} while (0)
#endif #endif
...@@ -570,7 +570,7 @@ static void reprobe_all(struct work_struct *unused) ...@@ -570,7 +570,7 @@ static void reprobe_all(struct work_struct *unused)
{ {
int ret; int ret;
CIO_MSG_EVENT(2, "reprobe start\n"); CIO_MSG_EVENT(4, "reprobe start\n");
need_reprobe = 0; need_reprobe = 0;
/* Make sure initial subchannel scan is done. */ /* Make sure initial subchannel scan is done. */
...@@ -578,7 +578,7 @@ static void reprobe_all(struct work_struct *unused) ...@@ -578,7 +578,7 @@ static void reprobe_all(struct work_struct *unused)
atomic_read(&ccw_device_init_count) == 0); atomic_read(&ccw_device_init_count) == 0);
ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
need_reprobe); need_reprobe);
} }
......
...@@ -341,7 +341,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) ...@@ -341,7 +341,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(&cdev->dev, rc = device_schedule_callback(&cdev->dev,
ccw_device_remove_orphan_cb); ccw_device_remove_orphan_cb);
if (rc) if (rc)
CIO_MSG_EVENT(2, "Couldn't unregister orphan " CIO_MSG_EVENT(0, "Couldn't unregister orphan "
"0.%x.%04x\n", "0.%x.%04x\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -351,7 +351,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) ...@@ -351,7 +351,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(cdev->dev.parent, rc = device_schedule_callback(cdev->dev.parent,
ccw_device_remove_sch_cb); ccw_device_remove_sch_cb);
if (rc) if (rc)
CIO_MSG_EVENT(2, "Couldn't unregister disconnected device " CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
"0.%x.%04x\n", "0.%x.%04x\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -397,7 +397,7 @@ int ccw_device_set_offline(struct ccw_device *cdev) ...@@ -397,7 +397,7 @@ int ccw_device_set_offline(struct ccw_device *cdev)
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else { else {
CIO_MSG_EVENT(2, "ccw_device_offline returned %d, " CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n", "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid, ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -433,7 +433,7 @@ int ccw_device_set_online(struct ccw_device *cdev) ...@@ -433,7 +433,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else { else {
CIO_MSG_EVENT(2, "ccw_device_online returned %d, " CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
"device 0.%x.%04x\n", "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid, ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -451,7 +451,7 @@ int ccw_device_set_online(struct ccw_device *cdev) ...@@ -451,7 +451,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else else
CIO_MSG_EVENT(2, "ccw_device_offline returned %d, " CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n", "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid, ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -803,7 +803,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch, ...@@ -803,7 +803,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch,
other_sch = to_subchannel(get_device(cdev->dev.parent)); other_sch = to_subchannel(get_device(cdev->dev.parent));
ret = device_move(&cdev->dev, &sch->dev); ret = device_move(&cdev->dev, &sch->dev);
if (ret) { if (ret) {
CIO_MSG_EVENT(2, "Moving disconnected device 0.%x.%04x failed " CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed "
"(ret=%d)!\n", cdev->private->dev_id.ssid, "(ret=%d)!\n", cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret); cdev->private->dev_id.devno, ret);
put_device(&other_sch->dev); put_device(&other_sch->dev);
...@@ -933,7 +933,7 @@ io_subchannel_register(struct work_struct *work) ...@@ -933,7 +933,7 @@ io_subchannel_register(struct work_struct *work)
ret = device_reprobe(&cdev->dev); ret = device_reprobe(&cdev->dev);
if (ret) if (ret)
/* We can't do much here. */ /* We can't do much here. */
CIO_MSG_EVENT(2, "device_reprobe() returned" CIO_MSG_EVENT(0, "device_reprobe() returned"
" %d for 0.%x.%04x\n", ret, " %d for 0.%x.%04x\n", ret,
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -1086,7 +1086,7 @@ static void ccw_device_move_to_sch(struct work_struct *work) ...@@ -1086,7 +1086,7 @@ static void ccw_device_move_to_sch(struct work_struct *work)
rc = device_move(&cdev->dev, &sch->dev); rc = device_move(&cdev->dev, &sch->dev);
mutex_unlock(&sch->reg_mutex); mutex_unlock(&sch->reg_mutex);
if (rc) { if (rc) {
CIO_MSG_EVENT(2, "Moving device 0.%x.%04x to subchannel " CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel "
"0.%x.%04x failed (ret=%d)!\n", "0.%x.%04x failed (ret=%d)!\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
...@@ -1446,8 +1446,7 @@ ccw_device_remove (struct device *dev) ...@@ -1446,8 +1446,7 @@ ccw_device_remove (struct device *dev)
wait_event(cdev->private->wait_q, wait_event(cdev->private->wait_q,
dev_fsm_final_state(cdev)); dev_fsm_final_state(cdev));
else else
//FIXME: we can't fail! CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n", "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid, ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -1524,7 +1523,7 @@ static int recovery_check(struct device *dev, void *data) ...@@ -1524,7 +1523,7 @@ static int recovery_check(struct device *dev, void *data)
spin_lock_irq(cdev->ccwlock); spin_lock_irq(cdev->ccwlock);
switch (cdev->private->state) { switch (cdev->private->state) {
case DEV_STATE_DISCONNECTED: case DEV_STATE_DISCONNECTED:
CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n", CIO_MSG_EVENT(4, "recovery: trigger 0.%x.%04x\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
dev_fsm_event(cdev, DEV_EVENT_VERIFY); dev_fsm_event(cdev, DEV_EVENT_VERIFY);
...@@ -1554,7 +1553,7 @@ static void recovery_work_func(struct work_struct *unused) ...@@ -1554,7 +1553,7 @@ static void recovery_work_func(struct work_struct *unused)
} }
spin_unlock_irq(&recovery_lock); spin_unlock_irq(&recovery_lock);
} else } else
CIO_MSG_EVENT(2, "recovery: end\n"); CIO_MSG_EVENT(4, "recovery: end\n");
} }
static DECLARE_WORK(recovery_work, recovery_work_func); static DECLARE_WORK(recovery_work, recovery_work_func);
...@@ -1572,7 +1571,7 @@ void ccw_device_schedule_recovery(void) ...@@ -1572,7 +1571,7 @@ void ccw_device_schedule_recovery(void)
{ {
unsigned long flags; unsigned long flags;
CIO_MSG_EVENT(2, "recovery: schedule\n"); CIO_MSG_EVENT(4, "recovery: schedule\n");
spin_lock_irqsave(&recovery_lock, flags); spin_lock_irqsave(&recovery_lock, flags);
if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) { if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
recovery_phase = 0; recovery_phase = 0;
......
...@@ -322,10 +322,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) ...@@ -322,10 +322,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
same_dev = 0; /* Keep the compiler quiet... */ same_dev = 0; /* Keep the compiler quiet... */
switch (state) { switch (state) {
case DEV_STATE_NOT_OPER: case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2, CIO_MSG_EVENT(2, "SenseID : unknown device %04x on "
"SenseID : unknown device %04x on subchannel " "subchannel 0.%x.%04x\n",
"0.%x.%04x\n", cdev->private->dev_id.devno, cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no); sch->schid.ssid, sch->schid.sch_no);
break; break;
case DEV_STATE_OFFLINE: case DEV_STATE_OFFLINE:
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
...@@ -348,20 +348,19 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) ...@@ -348,20 +348,19 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return; return;
} }
/* Issue device info message. */ /* Issue device info message. */
CIO_DEBUG(KERN_INFO, 2, CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
"SenseID : device 0.%x.%04x reports: " "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = " "%04X/%02X\n",
"%04X/%02X\n", cdev->private->dev_id.ssid,
cdev->private->dev_id.ssid, cdev->private->dev_id.devno,
cdev->private->dev_id.devno, cdev->id.cu_type, cdev->id.cu_model,
cdev->id.cu_type, cdev->id.cu_model, cdev->id.dev_type, cdev->id.dev_model);
cdev->id.dev_type, cdev->id.dev_model);
break; break;
case DEV_STATE_BOXED: case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2, CIO_MSG_EVENT(0, "SenseID : boxed device %04x on "
"SenseID : boxed device %04x on subchannel " " subchannel 0.%x.%04x\n",
"0.%x.%04x\n", cdev->private->dev_id.devno, cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no); sch->schid.ssid, sch->schid.sch_no);
break; break;
} }
cdev->private->state = state; cdev->private->state = state;
...@@ -443,9 +442,8 @@ ccw_device_done(struct ccw_device *cdev, int state) ...@@ -443,9 +442,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED) if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2, CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
"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->private->flags.donotify) { if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0; cdev->private->flags.donotify = 0;
...@@ -900,7 +898,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -900,7 +898,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
/* Basic sense hasn't started. Try again. */ /* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb); ccw_device_do_sense(cdev, irb);
else { else {
CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited " CIO_MSG_EVENT(0, "0.%x.%04x: unsolicited "
"interrupt during w4sense...\n", "interrupt during w4sense...\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno); cdev->private->dev_id.devno);
...@@ -1169,8 +1167,10 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -1169,8 +1167,10 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
static void static void
ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
{ {
CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n", CIO_MSG_EVENT(0, "Internal state [%i][%i] not handled for device "
cdev->private->state, dev_event); "0.%x.%04x\n", cdev->private->state, dev_event,
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
BUG(); BUG();
} }
......
...@@ -214,7 +214,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev) ...@@ -214,7 +214,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
* sense id information. So, for intervention required, * sense id information. So, for intervention required,
* we use the "whack it until it talks" strategy... * we use the "whack it until it talks" strategy...
*/ */
CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel " CIO_MSG_EVENT(0, "SenseID : device %04x on Subchannel "
"0.%x.%04x reports cmd reject\n", "0.%x.%04x reports cmd reject\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no); sch->schid.sch_no);
...@@ -239,7 +239,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev) ...@@ -239,7 +239,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
lpm = to_io_private(sch)->orb.lpm; lpm = to_io_private(sch)->orb.lpm;
if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x " CIO_MSG_EVENT(4, "SenseID : path %02X for device %04x "
"on subchannel 0.%x.%04x is " "on subchannel 0.%x.%04x is "
"'not operational'\n", lpm, "'not operational'\n", lpm,
cdev->private->dev_id.devno, cdev->private->dev_id.devno,
......
...@@ -79,7 +79,7 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev) ...@@ -79,7 +79,7 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
/* ret is 0, -EBUSY, -EACCES or -ENODEV */ /* ret is 0, -EBUSY, -EACCES or -ENODEV */
if (ret != -EACCES) if (ret != -EACCES)
return ret; return ret;
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not " "0.%x.%04x, lpm %02X, became 'not "
"operational'\n", "operational'\n",
cdev->private->dev_id.devno, cdev->private->dev_id.devno,
...@@ -159,7 +159,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev) ...@@ -159,7 +159,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
u8 lpm; u8 lpm;
lpm = to_io_private(sch)->orb.lpm; lpm = to_io_private(sch)->orb.lpm;
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x," CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n", " lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, lpm); sch->schid.sch_no, lpm);
...@@ -275,7 +275,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) ...@@ -275,7 +275,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
return ret; return ret;
} }
/* PGID command failed on this path. */ /* PGID command failed on this path. */
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n", "0.%x.%04x, lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask); sch->schid.sch_no, cdev->private->imask);
...@@ -317,7 +317,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev) ...@@ -317,7 +317,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
return ret; return ret;
} }
/* nop command failed on this path. */ /* nop command failed on this path. */
CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel " CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n", "0.%x.%04x, lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask); sch->schid.sch_no, cdev->private->imask);
...@@ -362,7 +362,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev) ...@@ -362,7 +362,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
return -EAGAIN; return -EAGAIN;
} }
if (irb->scsw.cc == 3) { if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x," CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n", " lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask); sch->schid.sch_no, cdev->private->imask);
...@@ -391,7 +391,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev) ...@@ -391,7 +391,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
return -ETIME; return -ETIME;
} }
if (irb->scsw.cc == 3) { if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x," CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n", " lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid, cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask); sch->schid.sch_no, cdev->private->imask);
......
...@@ -48,10 +48,11 @@ s390_collect_crw_info(void *param) ...@@ -48,10 +48,11 @@ s390_collect_crw_info(void *param)
int ccode; int ccode;
struct semaphore *sem; struct semaphore *sem;
unsigned int chain; unsigned int chain;
int ignore;
sem = (struct semaphore *)param; sem = (struct semaphore *)param;
repeat: repeat:
down_interruptible(sem); ignore = down_interruptible(sem);
chain = 0; chain = 0;
while (1) { while (1) {
if (unlikely(chain > 1)) { if (unlikely(chain > 1)) {
......
...@@ -104,6 +104,7 @@ struct sie_block { ...@@ -104,6 +104,7 @@ struct sie_block {
struct kvm_vcpu_stat { struct kvm_vcpu_stat {
u32 exit_userspace; u32 exit_userspace;
u32 exit_null;
u32 exit_external_request; u32 exit_external_request;
u32 exit_external_interrupt; u32 exit_external_interrupt;
u32 exit_stop_request; u32 exit_stop_request;
......
...@@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr) ...@@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr)
return skey; return skey;
} }
#ifdef CONFIG_PAGE_STATES
struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);
#define HAVE_ARCH_FREE_PAGE
#define HAVE_ARCH_ALLOC_PAGE
#endif
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */ /* to align the pointer to the (next) page boundary */
......
...@@ -471,6 +471,8 @@ struct task_struct; ...@@ -471,6 +471,8 @@ struct task_struct;
extern void user_enable_single_step(struct task_struct *); extern void user_enable_single_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *);
#define __ARCH_WANT_COMPAT_SYS_PTRACE
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define regs_return_value(regs)((regs)->gprs[2]) #define regs_return_value(regs)((regs)->gprs[2])
......
...@@ -116,6 +116,12 @@ extern void pfault_fini(void); ...@@ -116,6 +116,12 @@ extern void pfault_fini(void);
#define pfault_fini() do { } while (0) #define pfault_fini() do { } while (0)
#endif /* CONFIG_PFAULT */ #endif /* CONFIG_PFAULT */
#ifdef CONFIG_PAGE_STATES
extern void cmma_init(void);
#else
static inline void cmma_init(void) { }
#endif
#define finish_arch_switch(prev) do { \ #define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \ set_fs(current->thread.mm_segment); \
account_vtime(prev); \ account_vtime(prev); \
......
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