Commit d5cb012f authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: arch fixes.

Base s390 bug fixes:
 - arch: Do create_proc_entry for debug feature outside spin locked code.
 - arch: Fix system call tracing for 64 bit kernels.
 - arch: Export empty_zero_page for use in binfmt_elf32 module.
 - arch: Fix call trace output and remove dead remote-debug code.
 - arch: Correct OUTPUT_ARCH for 64 bit compiles.
 - arch: Fix in_atomic.
 - arch: Fix broken _PAGE_INVALID_xxx definitions.
 - arch: Add __kernel_old_dev_t for 64 bit.
 - arch: adapt to new do_fork interface.
 - arch: set CR5 to get program checks for space switching instructions.
 - cio: Fix /proc output of blacklist ranges.
 - cio: Restructure chsc to avoid GFP_KERNEL allocation while holding a lock.
 - cio: Fix wait_cons_dev.
 - qdio: use GFP_ATOMIC for memory allocations in interrupt.
parent fe25c0b6
...@@ -19,6 +19,9 @@ CONFIG_SYSVIPC=y ...@@ -19,6 +19,9 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=17 CONFIG_LOG_BUF_SHIFT=17
# CONFIG_EMBEDDED is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# #
# Loadable module support # Loadable module support
...@@ -162,6 +165,7 @@ CONFIG_IPV6=m ...@@ -162,6 +165,7 @@ CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_PRIVACY is not set
# CONFIG_INET6_AH is not set # CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set # CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
# CONFIG_XFRM_USER is not set # CONFIG_XFRM_USER is not set
# #
...@@ -228,6 +232,10 @@ CONFIG_NET_ETHERNET=y ...@@ -228,6 +232,10 @@ CONFIG_NET_ETHERNET=y
# #
# Ethernet (1000 Mbit) # Ethernet (1000 Mbit)
# #
#
# Ethernet (10000 Mbit)
#
# CONFIG_PPP is not set # CONFIG_PPP is not set
# CONFIG_SLIP is not set # CONFIG_SLIP is not set
...@@ -262,6 +270,7 @@ CONFIG_EXT2_FS=y ...@@ -262,6 +270,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
CONFIG_JBD=y CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set # CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y CONFIG_FS_MBCACHE=y
...@@ -292,6 +301,7 @@ CONFIG_FS_MBCACHE=y ...@@ -292,6 +301,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_PROC_FS=y CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set # CONFIG_TMPFS is not set
CONFIG_RAMFS=y CONFIG_RAMFS=y
......
...@@ -851,9 +851,17 @@ int debug_register_view(debug_info_t * id, struct debug_view *view) ...@@ -851,9 +851,17 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
int i; int i;
unsigned long flags; unsigned long flags;
mode_t mode = S_IFREG; mode_t mode = S_IFREG;
struct proc_dir_entry *pde;
if (!id) if (!id)
goto out; goto out;
pde = create_proc_entry(view->name, mode, id->proc_root_entry);
if (!pde){
printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name);
rc = -1;
goto out;
}
spin_lock_irqsave(&id->lock, flags); spin_lock_irqsave(&id->lock, flags);
for (i = 0; i < DEBUG_MAX_VIEWS; i++) { for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
if (id->views[i] == NULL) if (id->views[i] == NULL)
...@@ -864,6 +872,7 @@ int debug_register_view(debug_info_t * id, struct debug_view *view) ...@@ -864,6 +872,7 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
id->name,view->name); id->name,view->name);
printk(KERN_WARNING printk(KERN_WARNING
"debug: maximum number of views reached (%i)!\n", i); "debug: maximum number of views reached (%i)!\n", i);
remove_proc_entry(pde->name, id->proc_root_entry);
rc = -1; rc = -1;
} }
else { else {
...@@ -872,11 +881,8 @@ int debug_register_view(debug_info_t * id, struct debug_view *view) ...@@ -872,11 +881,8 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
mode |= S_IRUSR; mode |= S_IRUSR;
if (view->input_proc) if (view->input_proc)
mode |= S_IWUSR; mode |= S_IWUSR;
id->proc_entries[i] = create_proc_entry(view->name, mode, pde->proc_fops = &debug_file_ops;
id->proc_root_entry); id->proc_entries[i] = pde;
if (id->proc_entries[i] != NULL)
id->proc_entries[i]->proc_fops = &debug_file_ops;
rc = 0;
} }
spin_unlock_irqrestore(&id->lock, flags); spin_unlock_irqrestore(&id->lock, flags);
out: out:
......
...@@ -249,14 +249,14 @@ sysc_restart: ...@@ -249,14 +249,14 @@ sysc_restart:
# special linkage: %r12 contains the return address for trace_svc # special linkage: %r12 contains the return address for trace_svc
# #
sysc_tracesys: sysc_tracesys:
srl %r7,3 srl %r7,2
stg %r7,SP_R2(%r15) stg %r7,SP_R2(%r15)
brasl %r14,syscall_trace brasl %r14,syscall_trace
larl %r1,.Lnr_syscalls larl %r1,.Lnr_syscalls
clc SP_R2(8,%r15),0(%r1) clc SP_R2(8,%r15),0(%r1)
jl sysc_tracego jl sysc_tracego
lg %r7,SP_R2(%r15) # strace might have changed the lg %r7,SP_R2(%r15) # strace might have changed the
sll %r7,3 # system call sll %r7,2 # system call
lgf %r8,0(%r7,%r10) lgf %r8,0(%r7,%r10)
sysc_tracego: sysc_tracego:
lmg %r3,%r6,SP_R3(%r15) lmg %r3,%r6,SP_R3(%r15)
......
...@@ -573,7 +573,7 @@ startup:basr %r13,0 # get base ...@@ -573,7 +573,7 @@ startup:basr %r13,0 # get base
.long .Lduct # cr2: dispatchable unit control table .long .Lduct # cr2: dispatchable unit control table
.long 0 # cr3: instruction authorization .long 0 # cr3: instruction authorization
.long 0 # cr4: instruction authorization .long 0 # cr4: instruction authorization
.long 0 # cr5: various things .long 0xffffffff # cr5: primary-aste origin
.long 0 # cr6: I/O interrupts .long 0 # cr6: I/O interrupts
.long 0 # cr7: secondary space segment table .long 0 # cr7: secondary space segment table
.long 0 # cr8: access registers translation .long 0 # cr8: access registers translation
......
...@@ -586,7 +586,7 @@ startup:basr %r13,0 # get base ...@@ -586,7 +586,7 @@ startup:basr %r13,0 # get base
.quad .Lduct # cr2: dispatchable unit control table .quad .Lduct # cr2: dispatchable unit control table
.quad 0 # cr3: instruction authorization .quad 0 # cr3: instruction authorization
.quad 0 # cr4: instruction authorization .quad 0 # cr4: instruction authorization
.quad 0 # cr5: various things .quad 0xffffffffffffffff # cr5: primary-aste origin
.quad 0 # cr6: I/O interrupts .quad 0 # cr6: I/O interrupts
.quad 0 # cr7: secondary space segment table .quad 0 # cr7: secondary space segment table
.quad 0 # cr8: access registers translation .quad 0 # cr8: access registers translation
......
...@@ -166,7 +166,6 @@ __asm__(".align 4\n" ...@@ -166,7 +166,6 @@ __asm__(".align 4\n"
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{ {
struct task_struct *p;
struct pt_regs regs; struct pt_regs regs;
memset(&regs, 0, sizeof(regs)); memset(&regs, 0, sizeof(regs));
...@@ -180,8 +179,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -180,8 +179,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.orig_gpr2 = -1; regs.orig_gpr2 = -1;
/* Ok, create the new process.. */ /* Ok, create the new process.. */
p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
return IS_ERR(p) ? PTR_ERR(p) : p->pid; 0, &regs, 0, NULL, NULL);
} }
/* /*
...@@ -272,16 +271,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -272,16 +271,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
asmlinkage int sys_fork(struct pt_regs regs) asmlinkage int sys_fork(struct pt_regs regs)
{ {
struct task_struct *p; return do_fork(SIGCHLD, regs.gprs[15], &regs, 0, NULL, NULL);
p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
asmlinkage int sys_clone(struct pt_regs regs) asmlinkage int sys_clone(struct pt_regs regs)
{ {
unsigned long clone_flags; unsigned long clone_flags;
unsigned long newsp; unsigned long newsp;
struct task_struct *p;
int *parent_tidptr, *child_tidptr; int *parent_tidptr, *child_tidptr;
clone_flags = regs.gprs[3]; clone_flags = regs.gprs[3];
...@@ -290,9 +286,8 @@ asmlinkage int sys_clone(struct pt_regs regs) ...@@ -290,9 +286,8 @@ asmlinkage int sys_clone(struct pt_regs regs)
child_tidptr = (int *) regs.gprs[5]; child_tidptr = (int *) regs.gprs[5];
if (!newsp) if (!newsp)
newsp = regs.gprs[15]; newsp = regs.gprs[15];
p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
/* /*
...@@ -307,10 +302,8 @@ asmlinkage int sys_clone(struct pt_regs regs) ...@@ -307,10 +302,8 @@ asmlinkage int sys_clone(struct pt_regs regs)
*/ */
asmlinkage int sys_vfork(struct pt_regs regs) asmlinkage int sys_vfork(struct pt_regs regs)
{ {
struct task_struct *p; return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
regs.gprs[15], &regs, 0, NULL, NULL); regs.gprs[15], &regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
/* /*
......
...@@ -59,6 +59,7 @@ extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); ...@@ -59,6 +59,7 @@ extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(overflowuid); EXPORT_SYMBOL(overflowuid);
EXPORT_SYMBOL(overflowgid); EXPORT_SYMBOL(overflowgid);
EXPORT_SYMBOL(empty_zero_page);
#ifdef CONFIG_S390_SUPPORT #ifdef CONFIG_S390_SUPPORT
/* /*
......
...@@ -469,7 +469,7 @@ static struct task_struct *__devinit fork_by_hand(void) ...@@ -469,7 +469,7 @@ static struct task_struct *__devinit fork_by_hand(void)
/* don't care about the psw and regs settings since we'll never /* don't care about the psw and regs settings since we'll never
reschedule the forked task. */ reschedule the forked task. */
memset(&regs,0,sizeof(struct pt_regs)); memset(&regs,0,sizeof(struct pt_regs));
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL); return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
} }
int __cpu_up(unsigned int cpu) int __cpu_up(unsigned int cpu)
...@@ -498,6 +498,7 @@ int __cpu_up(unsigned int cpu) ...@@ -498,6 +498,7 @@ int __cpu_up(unsigned int cpu)
printk("failed fork for CPU %d", cpu); printk("failed fork for CPU %d", cpu);
return -EIO; return -EIO;
} }
wake_up_forked_process(idle);
/* /*
* We remove it from the pidhash and the runqueue * We remove it from the pidhash and the runqueue
......
...@@ -282,7 +282,7 @@ static void inline do_trap(long interruption_code, int signr, char *str, ...@@ -282,7 +282,7 @@ static void inline do_trap(long interruption_code, int signr, char *str,
const struct exception_table_entry *fixup; const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
if (fixup) if (fixup)
regs->psw.addr = fixup->fixup | ~PSW_ADDR_INSN; regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
else else
die(str, regs, interruption_code); die(str, regs, interruption_code);
} }
...@@ -293,27 +293,14 @@ static inline void *get_check_address(struct pt_regs *regs) ...@@ -293,27 +293,14 @@ static inline void *get_check_address(struct pt_regs *regs)
return (void *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); return (void *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
} }
int do_debugger_trap(struct pt_regs *regs,int signal) static int do_debugger_trap(struct pt_regs *regs)
{ {
if(regs->psw.mask&PSW_MASK_PSTATE) if ((regs->psw.mask & PSW_MASK_PSTATE) &&
{ (current->ptrace & PT_PTRACED)) {
if(current->ptrace & PT_PTRACED) force_sig(SIGTRAP,current);
force_sig(signal,current);
else
return 1;
}
else
{
#ifdef CONFIG_REMOTE_DEBUG
if(gdb_stub_initialised)
{
gdb_stub_handle_exception(regs, signal);
return 0; return 0;
} }
#endif
return 1; return 1;
}
return 0;
} }
#define DO_ERROR(signr, str, name) \ #define DO_ERROR(signr, str, name) \
...@@ -400,7 +387,7 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) ...@@ -400,7 +387,7 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
*((__u16 *)opcode)=*((__u16 *)location); *((__u16 *)opcode)=*((__u16 *)location);
if (*((__u16 *)opcode)==S390_BREAKPOINT_U16) if (*((__u16 *)opcode)==S390_BREAKPOINT_U16)
{ {
if(do_debugger_trap(regs,SIGTRAP)) if(do_debugger_trap(regs))
signal = SIGILL; signal = SIGILL;
} }
#ifdef CONFIG_MATHEMU #ifdef CONFIG_MATHEMU
...@@ -659,7 +646,7 @@ void handle_per_exception(struct pt_regs *regs) ...@@ -659,7 +646,7 @@ void handle_per_exception(struct pt_regs *regs)
per_info->lowcore.words.address=S390_lowcore.per_address; per_info->lowcore.words.address=S390_lowcore.per_address;
per_info->lowcore.words.access_id=S390_lowcore.per_access_id; per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
} }
if (do_debugger_trap(regs,SIGTRAP)) { if (do_debugger_trap(regs)) {
/* I've seen this possibly a task structure being reused ? */ /* I've seen this possibly a task structure being reused ? */
printk("Spurious per exception detected\n"); printk("Spurious per exception detected\n");
printk("switching off per tracing for this task.\n"); printk("switching off per tracing for this task.\n");
......
...@@ -12,7 +12,7 @@ ENTRY(_start) ...@@ -12,7 +12,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4; jiffies = jiffies_64 + 4;
#else #else
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
OUTPUT_ARCH(s390) OUTPUT_ARCH(s390:64-bit)
ENTRY(_start) ENTRY(_start)
jiffies = jiffies_64; jiffies = jiffies_64;
#endif #endif
......
/* /*
* drivers/s390/cio/blacklist.c * drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices * S/390 common I/O routines -- blacklisting of specific devices
* $Revision: 1.23 $ * $Revision: 1.24 $
* *
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -197,7 +197,7 @@ static int cio_ignore_read (char *page, char **start, off_t off, ...@@ -197,7 +197,7 @@ static int cio_ignore_read (char *page, char **start, off_t off,
while (++devno < __MAX_SUBCHANNELS) while (++devno < __MAX_SUBCHANNELS)
if (!test_bit(devno, bl_dev)) if (!test_bit(devno, bl_dev))
break; break;
len += sprintf(page + len, "-0x%04lx", devno); len += sprintf(page + len, "-0x%04lx", --devno);
} }
len += sprintf(page + len, "\n"); len += sprintf(page + len, "\n");
} }
......
/* /*
* drivers/s390/cio/chsc.c * drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call * S/390 common I/O routines -- channel subsystem call
* $Revision: 1.67 $ * $Revision: 1.69 $
* *
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -71,12 +71,11 @@ chsc_validate_chpids(struct subchannel *sch) ...@@ -71,12 +71,11 @@ chsc_validate_chpids(struct subchannel *sch)
} }
/* FIXME: this is _always_ called for every subchannel. shouldn't we /* FIXME: this is _always_ called for every subchannel. shouldn't we
* process more than one at a time?*/ * process more than one at a time? */
static int static int
chsc_get_sch_desc_irq(int irq) chsc_get_sch_desc_irq(int irq, void *page)
{ {
int ccode, chpid, j; int ccode, chpid, j;
int ret;
struct { struct {
struct chsc_header request; struct chsc_header request;
...@@ -100,11 +99,7 @@ chsc_get_sch_desc_irq(int irq) ...@@ -100,11 +99,7 @@ chsc_get_sch_desc_irq(int irq)
u16 fla[8]; /* full link addresses 0-7 */ u16 fla[8]; /* full link addresses 0-7 */
} *ssd_area; } *ssd_area;
ssd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); ssd_area = page;
if (!ssd_area) {
CIO_CRW_EVENT(0, "No memory for ssd area!\n");
return -ENOMEM;
}
ssd_area->request = (struct chsc_header) { ssd_area->request = (struct chsc_header) {
.length = 0x0010, .length = 0x0010,
...@@ -117,34 +112,29 @@ chsc_get_sch_desc_irq(int irq) ...@@ -117,34 +112,29 @@ chsc_get_sch_desc_irq(int irq)
ccode = chsc(ssd_area); ccode = chsc(ssd_area);
if (ccode > 0) { if (ccode > 0) {
pr_debug("chsc returned with ccode = %d\n", ccode); pr_debug("chsc returned with ccode = %d\n", ccode);
ret = (ccode == 3) ? -ENODEV : -EBUSY; return (ccode == 3) ? -ENODEV : -EBUSY;
goto out;
} }
switch (ssd_area->response.code) { switch (ssd_area->response.code) {
case 0x0001: /* everything ok */ case 0x0001: /* everything ok */
ret = 0;
break; break;
case 0x0002: case 0x0002:
CIO_CRW_EVENT(2, "Invalid command!\n"); CIO_CRW_EVENT(2, "Invalid command!\n");
case 0x0003: case 0x0003:
CIO_CRW_EVENT(2, "Error in chsc request block!\n"); CIO_CRW_EVENT(2, "Error in chsc request block!\n");
ret = -EINVAL; return -EINVAL;
break; break;
case 0x0004: case 0x0004:
CIO_CRW_EVENT(2, "Model does not provide ssd\n"); CIO_CRW_EVENT(2, "Model does not provide ssd\n");
ret = -EOPNOTSUPP; return -EOPNOTSUPP;
break; break;
default: default:
CIO_CRW_EVENT(2, "Unknown CHSC response %d\n", CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",
ssd_area->response.code); ssd_area->response.code);
ret = -EIO; return -EIO;
break; break;
} }
if (ret != 0)
goto out;
/* /*
* ssd_area->st stores the type of the detected * ssd_area->st stores the type of the detected
* subchannel, with the following definitions: * subchannel, with the following definitions:
...@@ -167,14 +157,14 @@ chsc_get_sch_desc_irq(int irq) ...@@ -167,14 +157,14 @@ chsc_get_sch_desc_irq(int irq)
* time since this code was written; since we don't know which * time since this code was written; since we don't know which
* fields have meaning and what to do with it we just jump out * fields have meaning and what to do with it we just jump out
*/ */
goto out; return 0;
} else { } else {
const char *type[4] = {"I/O", "chsc", "message", "ADM"}; const char *type[4] = {"I/O", "chsc", "message", "ADM"};
CIO_CRW_EVENT(6, "ssd: sch %x is %s subchannel\n", CIO_CRW_EVENT(6, "ssd: sch %x is %s subchannel\n",
irq, type[ssd_area->st]); irq, type[ssd_area->st]);
if (ioinfo[irq] == NULL) if (ioinfo[irq] == NULL)
/* FIXME: we should do device rec. here... */ /* FIXME: we should do device rec. here... */
goto out; return 0;
ioinfo[irq]->ssd_info.valid = 1; ioinfo[irq]->ssd_info.valid = 1;
ioinfo[irq]->ssd_info.type = ssd_area->st; ioinfo[irq]->ssd_info.type = ssd_area->st;
...@@ -195,9 +185,8 @@ chsc_get_sch_desc_irq(int irq) ...@@ -195,9 +185,8 @@ chsc_get_sch_desc_irq(int irq)
ioinfo[irq]->ssd_info.fla[j] = ssd_area->fla[j]; ioinfo[irq]->ssd_info.fla[j] = ssd_area->fla[j];
} }
} }
out:
free_page ((unsigned long) ssd_area); return 0;
return ret;
} }
static int static int
...@@ -205,6 +194,7 @@ chsc_get_sch_descriptions(void) ...@@ -205,6 +194,7 @@ chsc_get_sch_descriptions(void)
{ {
int irq; int irq;
int err; int err;
void *page;
CIO_TRACE_EVENT( 4, "gsdesc"); CIO_TRACE_EVENT( 4, "gsdesc");
...@@ -212,11 +202,15 @@ chsc_get_sch_descriptions(void) ...@@ -212,11 +202,15 @@ chsc_get_sch_descriptions(void)
* get information about chpids and link addresses * get information about chpids and link addresses
* by executing the chsc command 'store subchannel description' * by executing the chsc command 'store subchannel description'
*/ */
page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!page)
return -ENOMEM;
for (irq = 0; irq <= highest_subchannel; irq++) { for (irq = 0; irq <= highest_subchannel; irq++) {
/* /*
* retrieve information for each sch * retrieve information for each sch
*/ */
err = chsc_get_sch_desc_irq(irq); err = chsc_get_sch_desc_irq(irq, page);
if (err) { if (err) {
static int cio_chsc_err_msg; static int cio_chsc_err_msg;
...@@ -230,8 +224,10 @@ chsc_get_sch_descriptions(void) ...@@ -230,8 +224,10 @@ chsc_get_sch_descriptions(void)
} }
return err; return err;
} }
clear_page(page);
} }
cio_chsc_desc_avail = 1; cio_chsc_desc_avail = 1;
free_page((unsigned long)page);
return 0; return 0;
} }
...@@ -352,14 +348,14 @@ s390_set_chpid_offline( __u8 chpid) ...@@ -352,14 +348,14 @@ s390_set_chpid_offline( __u8 chpid)
static int static int
s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask, s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
struct subchannel *sch) struct subchannel *sch, void *page)
{ {
int found; int found;
int chp; int chp;
int ccode; int ccode;
/* Update our ssd_info */ /* Update our ssd_info */
if (chsc_get_sch_desc_irq(sch->irq)) if (chsc_get_sch_desc_irq(sch->irq, page))
return 0; return 0;
found = 0; found = 0;
...@@ -396,6 +392,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) ...@@ -396,6 +392,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
int irq; int irq;
int ret; int ret;
char dbf_txt[15]; char dbf_txt[15];
void *page;
sprintf(dbf_txt, "accpr%x", chpid); sprintf(dbf_txt, "accpr%x", chpid);
CIO_TRACE_EVENT( 2, dbf_txt); CIO_TRACE_EVENT( 2, dbf_txt);
...@@ -412,22 +409,13 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) ...@@ -412,22 +409,13 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
* will we have to do. * will we have to do.
*/ */
if (!cio_chsc_desc_avail)
chsc_get_sch_descriptions();
if (!cio_chsc_desc_avail) {
/*
* Something went wrong...
*/
CIO_CRW_EVENT(0, "Error: Could not retrieve "
"subchannel descriptions, will not process css"
"machine check...\n");
return;
}
if (!test_bit(chpid, chpids_logical)) if (!test_bit(chpid, chpids_logical))
return; /* no need to do the rest */ return; /* no need to do the rest */
page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!page)
return;
for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
int chp_mask; int chp_mask;
...@@ -450,7 +438,10 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) ...@@ -450,7 +438,10 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
spin_lock_irq(&sch->lock); spin_lock_irq(&sch->lock);
chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch); chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask,
sch, page);
clear_page(page);
if (chp_mask == 0) { if (chp_mask == 0) {
spin_unlock_irq(&sch->lock); spin_unlock_irq(&sch->lock);
...@@ -475,6 +466,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) ...@@ -475,6 +466,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
if (fla_mask != 0) if (fla_mask != 0)
break; break;
} }
free_page((unsigned long)page);
} }
static void static void
......
/* /*
* drivers/s390/cio/cio.c * drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls * S/390 common I/O routines -- low level i/o calls
* $Revision: 1.97 $ * $Revision: 1.98 $
* *
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -146,7 +146,7 @@ cio_tpi(void) ...@@ -146,7 +146,7 @@ cio_tpi(void)
/* Not status pending or not operational. */ /* Not status pending or not operational. */
return 1; return 1;
sch = ioinfo[tpi_info->irq]; sch = ioinfo[tpi_info->irq];
if (sch) if (!sch)
return 1; return 1;
irq_enter (); irq_enter ();
spin_lock(&sch->lock); spin_lock(&sch->lock);
...@@ -658,8 +658,7 @@ wait_cons_dev (void) ...@@ -658,8 +658,7 @@ wait_cons_dev (void)
* before entering the spinlock we may already have * before entering the spinlock we may already have
* processed the interrupt on a different CPU... * processed the interrupt on a different CPU...
*/ */
if (!console_subchannel_in_use || if (!console_subchannel_in_use)
console_subchannel.schib.scsw.actl == 0)
return; return;
/* disable all but isc 7 (console device) */ /* disable all but isc 7 (console device) */
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
#include "ioasm.h" #include "ioasm.h"
#include "chsc.h" #include "chsc.h"
#define VERSION_QDIO_C "$Revision: 1.48 $" #define VERSION_QDIO_C "$Revision: 1.49 $"
/****************** MODULE PARAMETER VARIABLES ********************/ /****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
...@@ -1668,6 +1668,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1668,6 +1668,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
switch (irq_ptr->state) { switch (irq_ptr->state) {
case QDIO_IRQ_STATE_INACTIVE: case QDIO_IRQ_STATE_INACTIVE:
/* FIXME: defer this past interrupt time */
qdio_establish_handle_irq(cdev, cstat, dstat); qdio_establish_handle_irq(cdev, cstat, dstat);
break; break;
...@@ -1763,7 +1764,8 @@ qdio_check_siga_needs(int sch) ...@@ -1763,7 +1764,8 @@ qdio_check_siga_needs(int sch)
u8 ocnt; u8 ocnt;
} *ssqd_area; } *ssqd_area;
ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); /* FIXME make this GFP_KERNEL */
ssqd_area = (void *)get_zeroed_page(GFP_ATOMIC | GFP_DMA);
if (!ssqd_area) { if (!ssqd_area) {
QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
"SIGAs for sch x%x.\n", sch); "SIGAs for sch x%x.\n", sch);
...@@ -2644,6 +2646,7 @@ qdio_establish(struct ccw_device *cdev) ...@@ -2644,6 +2646,7 @@ qdio_establish(struct ccw_device *cdev)
return result; return result;
} }
/* FIXME: don't wait forever if hardware is broken */
wait_event(cdev->private->wait_q, wait_event(cdev->private->wait_q,
irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED || irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
irq_ptr->state == QDIO_IRQ_STATE_ERR); irq_ptr->state == QDIO_IRQ_STATE_ERR);
......
...@@ -83,7 +83,7 @@ extern void do_call_softirq(void); ...@@ -83,7 +83,7 @@ extern void do_call_softirq(void);
#define invoke_softirq() do_call_softirq() #define invoke_softirq() do_call_softirq()
#ifdef CONFIG_PREEMPT #ifdef CONFIG_PREEMPT
# define in_atomic() (in_interrupt() || preempt_count() == PREEMPT_ACTIVE) # define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else #else
# define in_atomic() (preempt_count() != 0) # define in_atomic() (preempt_count() != 0)
......
...@@ -218,9 +218,9 @@ extern char empty_zero_page[PAGE_SIZE]; ...@@ -218,9 +218,9 @@ extern char empty_zero_page[PAGE_SIZE];
/* Mask and four different kinds of invalid pages. */ /* Mask and four different kinds of invalid pages. */
#define _PAGE_INVALID_MASK 0x601 #define _PAGE_INVALID_MASK 0x601
#define _PAGE_INVALID_EMPTY 0x400 #define _PAGE_INVALID_EMPTY 0x400
#define _PAGE_INVALID_NONE 0x001 #define _PAGE_INVALID_NONE 0x401
#define _PAGE_INVALID_SWAP 0x200 #define _PAGE_INVALID_SWAP 0x600
#define _PAGE_INVALID_FILE 0x201 #define _PAGE_INVALID_FILE 0x601
#ifndef __s390x__ #ifndef __s390x__
......
...@@ -65,6 +65,7 @@ typedef __kernel_uid_t __kernel_old_uid_t; ...@@ -65,6 +65,7 @@ typedef __kernel_uid_t __kernel_old_uid_t;
typedef __kernel_gid_t __kernel_old_gid_t; typedef __kernel_gid_t __kernel_old_gid_t;
typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_uid_t __kernel_uid32_t;
typedef __kernel_gid_t __kernel_gid32_t; typedef __kernel_gid_t __kernel_gid32_t;
typedef unsigned short __kernel_old_dev_t;
#endif /* __s390x__ */ #endif /* __s390x__ */
......
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