forked from Minki/linux
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: (27 commits) [S390] Fix checkstack for s390 [S390] fix initialization of stp [S390] 3215: Remove tasklet. [S390] console flush on panic / reboot [S390] introduce dirty bit for kvm live migration [S390] Add ioctl support for EMC Symmetrix Subsystem Control I/O [S390] xpram: per device block request queues. [S390] dasd: fix message flood for unsolicited interrupts [S390] Move private simple udelay function to arch/s390/lib/delay.c. [S390] dcssblk: add >2G DCSSs support and stacked contiguous DCSSs support. [S390] ptrace changes [S390] s390: use sys_pause for 31bit pause entry point [S390] qdio enhanced SIGA (iqdio) support. [S390] cio: fix cio_tpi. [S390] cio: Correct use of ! and & [S390] cio: inline assembly cleanup [S390] bus_id -> dev_set_name() for css and ccw busses [S390] bus_id ->dev_name() conversions in qdio [S390] Use s390_root_dev_* in kvm_virtio. [S390] more bus_id -> dev_name conversions ...
This commit is contained in:
commit
37d9869ed9
@ -70,13 +70,19 @@ Command line parameters
|
||||
|
||||
Note: While already known devices can be added to the list of devices to be
|
||||
ignored, there will be no effect on then. However, if such a device
|
||||
disappears and then reappears, it will then be ignored.
|
||||
disappears and then reappears, it will then be ignored. To make
|
||||
known devices go away, you need the "purge" command (see below).
|
||||
|
||||
For example,
|
||||
"echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
|
||||
will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
|
||||
devices.
|
||||
|
||||
You can remove already known but now ignored devices via
|
||||
"echo purge > /proc/cio_ignore"
|
||||
All devices ignored but still registered and not online (= not in use)
|
||||
will be deregistered and thus removed from the system.
|
||||
|
||||
The devices can be specified either by bus id (0.x.abcd) or, for 2.4 backward
|
||||
compatibility, by the device number in hexadecimal (0xabcd or abcd). Device
|
||||
numbers given as 0xabcd will be interpreted as 0.0.abcd.
|
||||
@ -98,8 +104,7 @@ debugfs entries
|
||||
handling).
|
||||
|
||||
- /sys/kernel/debug/s390dbf/cio_msg/sprintf
|
||||
Various debug messages from the common I/O-layer, including messages
|
||||
printed when cio_msg=yes.
|
||||
Various debug messages from the common I/O-layer.
|
||||
|
||||
- /sys/kernel/debug/s390dbf/cio_trace/hex_ascii
|
||||
Logs the calling of functions in the common I/O-layer and, if applicable,
|
||||
|
@ -74,6 +74,7 @@ config S390
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_KVM if 64BIT
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
|
||||
* Bugreports.to..: <Linux390@de.ibm.com>
|
||||
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
|
||||
* EMC Symmetrix ioctl Copyright EMC Corporation, 2008
|
||||
* Author.........: Nigel Hislop <hislop_nigel@emc.com>
|
||||
*
|
||||
* This file is the interface of the DASD device driver, which is exported to user space
|
||||
* any future changes wrt the API will result in a change of the APIVERSION reported
|
||||
@ -202,6 +204,16 @@ typedef struct attrib_data_t {
|
||||
#define DASD_SEQ_PRESTAGE 0x4
|
||||
#define DASD_REC_ACCESS 0x5
|
||||
|
||||
/*
|
||||
* Perform EMC Symmetrix I/O
|
||||
*/
|
||||
typedef struct dasd_symmio_parms {
|
||||
unsigned char reserved[8]; /* compat with older releases */
|
||||
unsigned long long psf_data; /* char * cast to u64 */
|
||||
unsigned long long rssd_result; /* char * cast to u64 */
|
||||
int psf_data_len;
|
||||
int rssd_result_len;
|
||||
} __attribute__ ((packed)) dasd_symmio_parms_t;
|
||||
|
||||
/********************************************************************************
|
||||
* SECTION: Definition of IOCTLs
|
||||
@ -247,6 +259,7 @@ typedef struct attrib_data_t {
|
||||
/* Set Attributes (cache operations) */
|
||||
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t)
|
||||
|
||||
#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t)
|
||||
|
||||
#endif /* DASD_H */
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define _S390_DELAY_H
|
||||
|
||||
extern void __udelay(unsigned long usecs);
|
||||
extern void udelay_simple(unsigned long usecs);
|
||||
extern void __delay(unsigned long loops);
|
||||
|
||||
#define udelay(n) __udelay(n)
|
||||
|
@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE];
|
||||
#define RCP_GR_BIT 50
|
||||
#define RCP_GC_BIT 49
|
||||
|
||||
/* User dirty bit for KVM's migration feature */
|
||||
#define KVM_UD_BIT 47
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
/* Bits in the segment table address-space-control-element */
|
||||
@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep)
|
||||
unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
|
||||
|
||||
skey = page_get_storage_key(page_to_phys(page));
|
||||
if (skey & _PAGE_CHANGED)
|
||||
if (skey & _PAGE_CHANGED) {
|
||||
set_bit_simple(RCP_GC_BIT, pgste);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (skey & _PAGE_REFERENCED)
|
||||
set_bit_simple(RCP_GR_BIT, pgste);
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste))
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
|
||||
SetPageDirty(page);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
|
||||
SetPageReferenced(page);
|
||||
#endif
|
||||
@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte)
|
||||
return pte;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PGSTE
|
||||
/*
|
||||
* Get (and clear) the user dirty bit for a PTE.
|
||||
*/
|
||||
static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
|
||||
pte_t *ptep)
|
||||
{
|
||||
int dirty;
|
||||
unsigned long *pgste;
|
||||
struct page *page;
|
||||
unsigned int skey;
|
||||
|
||||
if (!mm->context.pgstes)
|
||||
return -EINVAL;
|
||||
rcp_lock(ptep);
|
||||
pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
|
||||
page = virt_to_page(pte_val(*ptep));
|
||||
skey = page_get_storage_key(page_to_phys(page));
|
||||
if (skey & _PAGE_CHANGED) {
|
||||
set_bit_simple(RCP_GC_BIT, pgste);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
|
||||
SetPageDirty(page);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
|
||||
if (skey & _PAGE_CHANGED)
|
||||
page_clear_dirty(page);
|
||||
rcp_unlock(ptep);
|
||||
return dirty;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
|
||||
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
|
@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *);
|
||||
|
||||
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
|
||||
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
|
||||
#define user_stack_pointer(regs)((regs)->gprs[15])
|
||||
#define regs_return_value(regs)((regs)->gprs[2])
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
extern void show_regs(struct pt_regs * regs);
|
||||
|
@ -299,7 +299,13 @@ struct qdio_ssqd_desc {
|
||||
u8 mbccnt;
|
||||
u16 qdioac2;
|
||||
u64 sch_token;
|
||||
u64:64;
|
||||
u8 mro;
|
||||
u8 mri;
|
||||
u8:8;
|
||||
u8 sbalic;
|
||||
u16:16;
|
||||
u8:8;
|
||||
u8 mmwc;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* params are: ccw_device, qdio_error, queue_number,
|
||||
|
80
arch/s390/include/asm/syscall.h
Normal file
80
arch/s390/include/asm/syscall.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Access to user system call parameters and results
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_SYSCALL_H
|
||||
#define _ASM_SYSCALL_H 1
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
static inline long syscall_get_nr(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (regs->trap != __LC_SVC_OLD_PSW)
|
||||
return -1;
|
||||
return regs->gprs[2];
|
||||
}
|
||||
|
||||
static inline void syscall_rollback(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs->gprs[2] = regs->orig_gpr2;
|
||||
}
|
||||
|
||||
static inline long syscall_get_error(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
|
||||
}
|
||||
|
||||
static inline long syscall_get_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return regs->gprs[2];
|
||||
}
|
||||
|
||||
static inline void syscall_set_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
int error, long val)
|
||||
{
|
||||
regs->gprs[2] = error ? -error : val;
|
||||
}
|
||||
|
||||
static inline void syscall_get_arguments(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
unsigned int i, unsigned int n,
|
||||
unsigned long *args)
|
||||
{
|
||||
BUG_ON(i + n > 6);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (test_tsk_thread_flag(task, TIF_31BIT)) {
|
||||
if (i + n == 6)
|
||||
args[--n] = (u32) regs->args[0];
|
||||
while (n-- > 0)
|
||||
args[n] = (u32) regs->gprs[2 + i + n];
|
||||
}
|
||||
#endif
|
||||
if (i + n == 6)
|
||||
args[--n] = regs->args[0];
|
||||
memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0]));
|
||||
}
|
||||
|
||||
static inline void syscall_set_arguments(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
unsigned int i, unsigned int n,
|
||||
const unsigned long *args)
|
||||
{
|
||||
BUG_ON(i + n > 6);
|
||||
if (i + n == 6)
|
||||
regs->args[0] = args[--n];
|
||||
memcpy(®s->gprs[2 + i], args, n * sizeof(args[0]));
|
||||
}
|
||||
|
||||
#endif /* _ASM_SYSCALL_H */
|
@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
* thread information flags bit numbers
|
||||
*/
|
||||
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
|
||||
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
|
||||
#define TIF_SIGPENDING 2 /* signal pending */
|
||||
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
||||
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
|
||||
@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
|
||||
|
||||
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
||||
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
|
||||
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
||||
|
@ -608,14 +608,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct time
|
||||
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
|
||||
}
|
||||
|
||||
/* These are here just in case some old sparc32 binary calls it. */
|
||||
asmlinkage long sys32_pause(void)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
|
||||
size_t count, u32 poshi, u32 poslo)
|
||||
{
|
||||
|
@ -206,7 +206,6 @@ long sys32_gettimeofday(struct compat_timeval __user *tv,
|
||||
struct timezone __user *tz);
|
||||
long sys32_settimeofday(struct compat_timeval __user *tv,
|
||||
struct timezone __user *tz);
|
||||
long sys32_pause(void);
|
||||
long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
|
||||
u32 poshi, u32 poslo);
|
||||
long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
|
||||
|
@ -128,8 +128,6 @@ sys32_alarm_wrapper:
|
||||
llgfr %r2,%r2 # unsigned int
|
||||
jg sys_alarm # branch to system call
|
||||
|
||||
#sys32_pause_wrapper # void
|
||||
|
||||
.globl compat_sys_utime_wrapper
|
||||
compat_sys_utime_wrapper:
|
||||
llgtr %r2,%r2 # char *
|
||||
|
@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
|
||||
SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
|
||||
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
|
||||
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING)
|
||||
|
||||
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
|
||||
@ -318,6 +318,8 @@ sysc_work:
|
||||
bo BASED(sysc_reschedule)
|
||||
tm __TI_flags+3(%r9),_TIF_SIGPENDING
|
||||
bnz BASED(sysc_sigpending)
|
||||
tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
|
||||
bnz BASED(sysc_notify_resume)
|
||||
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
|
||||
bo BASED(sysc_restart)
|
||||
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
|
||||
@ -355,6 +357,16 @@ sysc_sigpending:
|
||||
bo BASED(sysc_singlestep)
|
||||
b BASED(sysc_work_loop)
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
|
||||
#
|
||||
sysc_notify_resume:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Ldo_notify_resume)
|
||||
la %r14,BASED(sysc_work_loop)
|
||||
br %r1 # call do_notify_resume
|
||||
|
||||
|
||||
#
|
||||
# _TIF_RESTART_SVC is set, set up registers and restart svc
|
||||
#
|
||||
@ -378,20 +390,21 @@ sysc_singlestep:
|
||||
br %r1 # branch to do_single_step
|
||||
|
||||
#
|
||||
# call trace before and after sys_call
|
||||
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
||||
# and after the system call
|
||||
#
|
||||
sysc_tracesys:
|
||||
l %r1,BASED(.Ltrace)
|
||||
l %r1,BASED(.Ltrace_entry)
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,0
|
||||
srl %r7,2
|
||||
st %r7,SP_R2(%r15)
|
||||
basr %r14,%r1
|
||||
clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
|
||||
cl %r2,BASED(.Lnr_syscalls)
|
||||
bnl BASED(sysc_tracenogo)
|
||||
l %r8,BASED(.Lsysc_table)
|
||||
l %r7,SP_R2(%r15) # strace might have changed the
|
||||
sll %r7,2 # system call
|
||||
lr %r7,%r2
|
||||
sll %r7,2 # *4
|
||||
l %r8,0(%r7,%r8)
|
||||
sysc_tracego:
|
||||
lm %r3,%r6,SP_R3(%r15)
|
||||
@ -401,9 +414,8 @@ sysc_tracego:
|
||||
sysc_tracenogo:
|
||||
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
|
||||
bz BASED(sysc_return)
|
||||
l %r1,BASED(.Ltrace)
|
||||
l %r1,BASED(.Ltrace_exit)
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,1
|
||||
la %r14,BASED(sysc_return)
|
||||
br %r1
|
||||
|
||||
@ -666,6 +678,8 @@ io_work_loop:
|
||||
bo BASED(io_reschedule)
|
||||
tm __TI_flags+3(%r9),_TIF_SIGPENDING
|
||||
bnz BASED(io_sigpending)
|
||||
tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
|
||||
bnz BASED(io_notify_resume)
|
||||
b BASED(io_restore)
|
||||
io_work_done:
|
||||
|
||||
@ -704,6 +718,19 @@ io_sigpending:
|
||||
TRACE_IRQS_OFF
|
||||
b BASED(io_work_loop)
|
||||
|
||||
#
|
||||
# _TIF_SIGPENDING is set, call do_signal
|
||||
#
|
||||
io_notify_resume:
|
||||
TRACE_IRQS_ON
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Ldo_notify_resume)
|
||||
basr %r14,%r1 # call do_signal
|
||||
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
|
||||
TRACE_IRQS_OFF
|
||||
b BASED(io_work_loop)
|
||||
|
||||
/*
|
||||
* External interrupt handler routine
|
||||
*/
|
||||
@ -1070,6 +1097,8 @@ cleanup_io_leave_insn:
|
||||
.Ldo_IRQ: .long do_IRQ
|
||||
.Ldo_extint: .long do_extint
|
||||
.Ldo_signal: .long do_signal
|
||||
.Ldo_notify_resume:
|
||||
.long do_notify_resume
|
||||
.Lhandle_per: .long do_single_step
|
||||
.Ldo_execve: .long do_execve
|
||||
.Lexecve_tail: .long execve_tail
|
||||
@ -1079,7 +1108,8 @@ cleanup_io_leave_insn:
|
||||
.Lpreempt_schedule_irq:
|
||||
.long preempt_schedule_irq
|
||||
#endif
|
||||
.Ltrace: .long syscall_trace
|
||||
.Ltrace_entry: .long do_syscall_trace_enter
|
||||
.Ltrace_exit: .long do_syscall_trace_exit
|
||||
.Lschedtail: .long schedule_tail
|
||||
.Lsysc_table: .long sys_call_table
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
|
@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
|
||||
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
|
||||
STACK_SIZE = 1 << STACK_SHIFT
|
||||
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING)
|
||||
|
||||
#define BASED(name) name-system_call(%r13)
|
||||
@ -310,6 +310,8 @@ sysc_work:
|
||||
jo sysc_reschedule
|
||||
tm __TI_flags+7(%r9),_TIF_SIGPENDING
|
||||
jnz sysc_sigpending
|
||||
tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
|
||||
jnz sysc_notify_resume
|
||||
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
|
||||
jo sysc_restart
|
||||
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
|
||||
@ -344,6 +346,14 @@ sysc_sigpending:
|
||||
jo sysc_singlestep
|
||||
j sysc_work_loop
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
|
||||
#
|
||||
sysc_notify_resume:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
larl %r14,sysc_work_loop
|
||||
jg do_notify_resume # call do_notify_resume
|
||||
|
||||
#
|
||||
# _TIF_RESTART_SVC is set, set up registers and restart svc
|
||||
#
|
||||
@ -367,20 +377,19 @@ sysc_singlestep:
|
||||
jg do_single_step # branch to do_sigtrap
|
||||
|
||||
#
|
||||
# call syscall_trace before and after system call
|
||||
# special linkage: %r12 contains the return address for trace_svc
|
||||
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
||||
# and after the system call
|
||||
#
|
||||
sysc_tracesys:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,0
|
||||
srl %r7,2
|
||||
stg %r7,SP_R2(%r15)
|
||||
brasl %r14,syscall_trace
|
||||
brasl %r14,do_syscall_trace_enter
|
||||
lghi %r0,NR_syscalls
|
||||
clg %r0,SP_R2(%r15)
|
||||
clgr %r0,%r2
|
||||
jnh sysc_tracenogo
|
||||
lg %r7,SP_R2(%r15) # strace might have changed the
|
||||
sll %r7,2 # system call
|
||||
slag %r7,%r2,2 # *4
|
||||
lgf %r8,0(%r7,%r10)
|
||||
sysc_tracego:
|
||||
lmg %r3,%r6,SP_R3(%r15)
|
||||
@ -391,9 +400,8 @@ sysc_tracenogo:
|
||||
tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
|
||||
jz sysc_return
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,1
|
||||
larl %r14,sysc_return # return point is sysc_return
|
||||
jg syscall_trace
|
||||
jg do_syscall_trace_exit
|
||||
|
||||
#
|
||||
# a new process exits the kernel with ret_from_fork
|
||||
@ -672,6 +680,8 @@ io_work_loop:
|
||||
jo io_reschedule
|
||||
tm __TI_flags+7(%r9),_TIF_SIGPENDING
|
||||
jnz io_sigpending
|
||||
tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
|
||||
jnz io_notify_resume
|
||||
j io_restore
|
||||
io_work_done:
|
||||
|
||||
@ -712,6 +722,18 @@ io_sigpending:
|
||||
TRACE_IRQS_OFF
|
||||
j io_work_loop
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
|
||||
#
|
||||
io_notify_resume:
|
||||
TRACE_IRQS_ON
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
brasl %r14,do_notify_resume # call do_notify_resume
|
||||
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
|
||||
TRACE_IRQS_OFF
|
||||
j io_work_loop
|
||||
|
||||
/*
|
||||
* External interrupt handler routine
|
||||
*/
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/signal.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/regset.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage void
|
||||
syscall_trace(struct pt_regs *regs, int entryexit)
|
||||
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(current->audit_context) && entryexit)
|
||||
audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
|
||||
|
||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
goto out;
|
||||
if (!(current->ptrace & PT_PTRACED))
|
||||
goto out;
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||
? 0x80 : 0));
|
||||
long ret;
|
||||
|
||||
/*
|
||||
* If the debuffer has set an invalid system call number,
|
||||
* we prepare to skip the system call restart handling.
|
||||
* The sysc_tracesys code in entry.S stored the system
|
||||
* call number to gprs[2].
|
||||
*/
|
||||
if (!entryexit && regs->gprs[2] >= NR_syscalls)
|
||||
ret = regs->gprs[2];
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
(tracehook_report_syscall_entry(regs) ||
|
||||
regs->gprs[2] >= NR_syscalls)) {
|
||||
/*
|
||||
* Tracing decided this syscall should not happen or the
|
||||
* debugger stored an invalid system call number. Skip
|
||||
* the system call and the system call restart handling.
|
||||
*/
|
||||
regs->trap = -1;
|
||||
|
||||
/*
|
||||
* this isn't the same as continuing with a signal, but it will do
|
||||
* for normal use. strace only continues with a signal if the
|
||||
* stopping signal is not SIGTRAP. -brl
|
||||
*/
|
||||
if (current->exit_code) {
|
||||
send_sig(current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
ret = -1;
|
||||
}
|
||||
out:
|
||||
if (unlikely(current->audit_context) && !entryexit)
|
||||
audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
|
||||
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
|
||||
regs->gprs[4], regs->gprs[5]);
|
||||
|
||||
if (unlikely(current->audit_context))
|
||||
audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
|
||||
AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
|
||||
regs->gprs[2], regs->orig_gpr2,
|
||||
regs->gprs[3], regs->gprs[4],
|
||||
regs->gprs[5]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(current->audit_context))
|
||||
audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
|
||||
regs->gprs[2]);
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
tracehook_report_syscall_exit(regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/lowcore.h>
|
||||
@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs)
|
||||
*/
|
||||
if (current->thread.per_info.single_step)
|
||||
set_thread_flag(TIF_SINGLE_STEP);
|
||||
|
||||
/*
|
||||
* Let tracing know that we've done the handler setup.
|
||||
*/
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs)
|
||||
set_thread_flag(TIF_RESTART_SVC);
|
||||
}
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs)
|
||||
{
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
tracehook_notify_resume(regs);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper) /* 25 old stime syscall *
|
||||
SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper)
|
||||
SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper)
|
||||
NI_SYSCALL /* old fstat syscall */
|
||||
SYSCALL(sys_pause,sys_pause,sys32_pause)
|
||||
SYSCALL(sys_pause,sys_pause,sys_pause)
|
||||
SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */
|
||||
NI_SYSCALL /* old stty syscall */
|
||||
NI_SYSCALL /* old gtty syscall */
|
||||
|
@ -1356,7 +1356,7 @@ static void __init stp_reset(void)
|
||||
|
||||
stp_page = alloc_bootmem_pages(PAGE_SIZE);
|
||||
rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
|
||||
if (rc == 1)
|
||||
if (rc == 0)
|
||||
set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
|
||||
else if (stp_online) {
|
||||
printk(KERN_WARNING "Running on non STP capable machine.\n");
|
||||
|
@ -92,3 +92,16 @@ out:
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple udelay variant. To be used on startup and reboot
|
||||
* when the interrupt handler isn't working.
|
||||
*/
|
||||
void udelay_simple(unsigned long usecs)
|
||||
{
|
||||
u64 end;
|
||||
|
||||
end = get_clock() + ((u64) usecs << 12);
|
||||
while (get_clock() < end)
|
||||
cpu_relax();
|
||||
}
|
||||
|
@ -43,21 +43,41 @@
|
||||
#define DCSS_FINDSEG 0x0c
|
||||
#define DCSS_LOADNOLY 0x10
|
||||
#define DCSS_SEGEXT 0x18
|
||||
#define DCSS_LOADSHRX 0x20
|
||||
#define DCSS_LOADNSRX 0x24
|
||||
#define DCSS_FINDSEGX 0x2c
|
||||
#define DCSS_SEGEXTX 0x38
|
||||
#define DCSS_FINDSEGA 0x0c
|
||||
|
||||
struct qrange {
|
||||
unsigned int start; // 3byte start address, 1 byte type
|
||||
unsigned int end; // 3byte end address, 1 byte reserved
|
||||
unsigned long start; /* last byte type */
|
||||
unsigned long end; /* last byte reserved */
|
||||
};
|
||||
|
||||
struct qout64 {
|
||||
int segstart;
|
||||
int segend;
|
||||
unsigned long segstart;
|
||||
unsigned long segend;
|
||||
int segcnt;
|
||||
int segrcnt;
|
||||
struct qrange range[6];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
struct qrange_old {
|
||||
unsigned int start; /* last byte type */
|
||||
unsigned int end; /* last byte reserved */
|
||||
};
|
||||
|
||||
/* output area format for the Diag x'64' old subcode x'18' */
|
||||
struct qout64_old {
|
||||
int segstart;
|
||||
int segend;
|
||||
int segcnt;
|
||||
int segrcnt;
|
||||
struct qrange_old range[6];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct qin64 {
|
||||
char qopcode;
|
||||
char rsrv1[3];
|
||||
@ -86,6 +106,55 @@ static DEFINE_MUTEX(dcss_lock);
|
||||
static LIST_HEAD(dcss_list);
|
||||
static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
|
||||
"EW/EN-MIXED" };
|
||||
static int loadshr_scode, loadnsr_scode, findseg_scode;
|
||||
static int segext_scode, purgeseg_scode;
|
||||
static int scode_set;
|
||||
|
||||
/* set correct Diag x'64' subcodes. */
|
||||
static int
|
||||
dcss_set_subcodes(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
char *name = kmalloc(8 * sizeof(char), GFP_DMA);
|
||||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rx = (unsigned long) name;
|
||||
ry = DCSS_FINDSEGX;
|
||||
|
||||
strcpy(name, "dummy");
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
"0: ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
" j 2f\n"
|
||||
"1: la %2,3\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
|
||||
kfree(name);
|
||||
/* Diag x'64' new subcodes are supported, set to new subcodes */
|
||||
if (rc != 3) {
|
||||
loadshr_scode = DCSS_LOADSHRX;
|
||||
loadnsr_scode = DCSS_LOADNSRX;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
findseg_scode = DCSS_FINDSEGX;
|
||||
segext_scode = DCSS_SEGEXTX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Diag x'64' new subcodes are not supported, set to old subcodes */
|
||||
loadshr_scode = DCSS_LOADNOLY;
|
||||
loadnsr_scode = DCSS_LOADNSR;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
findseg_scode = DCSS_FINDSEG;
|
||||
segext_scode = DCSS_SEGEXT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the 8 bytes, ebcdic VM segment name from
|
||||
@ -135,25 +204,45 @@ segment_by_name (char *name)
|
||||
* Perform a function on a dcss segment.
|
||||
*/
|
||||
static inline int
|
||||
dcss_diag (__u8 func, void *parameter,
|
||||
dcss_diag(int *func, void *parameter,
|
||||
unsigned long *ret1, unsigned long *ret2)
|
||||
{
|
||||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (scode_set == 0) {
|
||||
rc = dcss_set_subcodes();
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
scode_set = 1;
|
||||
}
|
||||
rx = (unsigned long) parameter;
|
||||
ry = (unsigned long) func;
|
||||
asm volatile(
|
||||
ry = (unsigned long) *func;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
" sam31\n"
|
||||
" diag %0,%1,0x64\n"
|
||||
" sam64\n"
|
||||
/* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
|
||||
if (*func > DCSS_SEGEXT)
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
/* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */
|
||||
else
|
||||
asm volatile(
|
||||
" sam31\n"
|
||||
" diag %0,%1,0x64\n"
|
||||
" sam64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
#else
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
#endif
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
#endif
|
||||
*ret1 = rx;
|
||||
*ret2 = ry;
|
||||
return rc;
|
||||
@ -190,14 +279,45 @@ query_segment_type (struct dcss_segment *seg)
|
||||
qin->qoutlen = sizeof(struct qout64);
|
||||
memcpy (qin->qname, seg->dcss_name, 8);
|
||||
|
||||
diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
|
||||
diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc);
|
||||
|
||||
if (diag_cc < 0) {
|
||||
rc = diag_cc;
|
||||
goto out_free;
|
||||
}
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
|
||||
rc = dcss_diag_translate_rc (vmrc);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/* Only old format of output area of Diagnose x'64' is supported,
|
||||
copy data for the new format. */
|
||||
if (segext_scode == DCSS_SEGEXT) {
|
||||
struct qout64_old *qout_old;
|
||||
qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA);
|
||||
if (qout_old == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(qout_old, qout, sizeof(struct qout64_old));
|
||||
qout->segstart = (unsigned long) qout_old->segstart;
|
||||
qout->segend = (unsigned long) qout_old->segend;
|
||||
qout->segcnt = qout_old->segcnt;
|
||||
qout->segrcnt = qout_old->segrcnt;
|
||||
|
||||
if (qout->segcnt > 6)
|
||||
qout->segrcnt = 6;
|
||||
for (i = 0; i < qout->segrcnt; i++) {
|
||||
qout->range[i].start =
|
||||
(unsigned long) qout_old->range[i].start;
|
||||
qout->range[i].end =
|
||||
(unsigned long) qout_old->range[i].end;
|
||||
}
|
||||
kfree(qout_old);
|
||||
}
|
||||
#endif
|
||||
if (qout->segcnt > 6) {
|
||||
rc = -ENOTSUPP;
|
||||
goto out_free;
|
||||
@ -268,6 +388,30 @@ segment_type (char* name)
|
||||
return seg.vm_segtype;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if segment collides with other segments that are currently loaded
|
||||
* returns 1 if this is the case, 0 if no collision was found
|
||||
*/
|
||||
static int
|
||||
segment_overlaps_others (struct dcss_segment *seg)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct dcss_segment *tmp;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&dcss_lock));
|
||||
list_for_each(l, &dcss_list) {
|
||||
tmp = list_entry(l, struct dcss_segment, list);
|
||||
if ((tmp->start_addr >> 20) > (seg->end >> 20))
|
||||
continue;
|
||||
if ((tmp->end >> 20) < (seg->start_addr >> 20))
|
||||
continue;
|
||||
if (seg == tmp)
|
||||
continue;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* real segment loading function, called from segment_load
|
||||
*/
|
||||
@ -276,7 +420,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
{
|
||||
struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
|
||||
GFP_DMA);
|
||||
int dcss_command, rc, diag_cc;
|
||||
int rc, diag_cc;
|
||||
unsigned long start_addr, end_addr, dummy;
|
||||
|
||||
if (seg == NULL) {
|
||||
rc = -ENOMEM;
|
||||
@ -287,6 +432,13 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
|
||||
if (loadshr_scode == DCSS_LOADSHRX) {
|
||||
if (segment_overlaps_others(seg)) {
|
||||
rc = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
|
||||
if (rc)
|
||||
@ -316,20 +468,28 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
}
|
||||
|
||||
if (do_nonshared)
|
||||
dcss_command = DCSS_LOADNSR;
|
||||
diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
else
|
||||
dcss_command = DCSS_LOADNOLY;
|
||||
|
||||
diag_cc = dcss_diag(dcss_command, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_load: could not load segment %s - "
|
||||
"diag returned error (%ld)\n",name,seg->end);
|
||||
rc = dcss_diag_translate_rc (seg->end);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
if (diag_cc < 0) {
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name,
|
||||
&dummy, &dummy);
|
||||
rc = diag_cc;
|
||||
goto out_resource;
|
||||
}
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_load: could not load segment %s - "
|
||||
"diag returned error (%ld)\n",
|
||||
name, end_addr);
|
||||
rc = dcss_diag_translate_rc(end_addr);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name,
|
||||
&dummy, &dummy);
|
||||
goto out_resource;
|
||||
}
|
||||
seg->start_addr = start_addr;
|
||||
seg->end = end_addr;
|
||||
seg->do_nonshared = do_nonshared;
|
||||
atomic_set(&seg->ref_count, 1);
|
||||
list_add(&seg->list, &dcss_list);
|
||||
@ -423,8 +583,8 @@ int
|
||||
segment_modify_shared (char *name, int do_nonshared)
|
||||
{
|
||||
struct dcss_segment *seg;
|
||||
unsigned long dummy;
|
||||
int dcss_command, rc, diag_cc;
|
||||
unsigned long start_addr, end_addr, dummy;
|
||||
int rc, diag_cc;
|
||||
|
||||
mutex_lock(&dcss_lock);
|
||||
seg = segment_by_name (name);
|
||||
@ -445,38 +605,51 @@ segment_modify_shared (char *name, int do_nonshared)
|
||||
goto out_unlock;
|
||||
}
|
||||
release_resource(seg->res);
|
||||
if (do_nonshared) {
|
||||
dcss_command = DCSS_LOADNSR;
|
||||
if (do_nonshared)
|
||||
seg->res->flags &= ~IORESOURCE_READONLY;
|
||||
} else {
|
||||
dcss_command = DCSS_LOADNOLY;
|
||||
else
|
||||
if (seg->vm_segtype == SEG_TYPE_SR ||
|
||||
seg->vm_segtype == SEG_TYPE_ER)
|
||||
seg->res->flags |= IORESOURCE_READONLY;
|
||||
}
|
||||
|
||||
if (request_resource(&iomem_resource, seg->res)) {
|
||||
PRINT_WARN("segment_modify_shared: could not reload segment %s"
|
||||
" - overlapping resources\n", name);
|
||||
rc = -EBUSY;
|
||||
kfree(seg->res);
|
||||
goto out_del;
|
||||
goto out_del_mem;
|
||||
}
|
||||
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
if (do_nonshared)
|
||||
diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
else
|
||||
diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
if (diag_cc < 0) {
|
||||
rc = diag_cc;
|
||||
goto out_del_res;
|
||||
}
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
diag_cc = dcss_diag(dcss_command, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_modify_shared: could not reload segment %s"
|
||||
" - diag returned error (%ld)\n",name,seg->end);
|
||||
rc = dcss_diag_translate_rc (seg->end);
|
||||
goto out_del;
|
||||
" - diag returned error (%ld)\n",
|
||||
name, end_addr);
|
||||
rc = dcss_diag_translate_rc(end_addr);
|
||||
goto out_del_res;
|
||||
}
|
||||
seg->start_addr = start_addr;
|
||||
seg->end = end_addr;
|
||||
seg->do_nonshared = do_nonshared;
|
||||
rc = 0;
|
||||
goto out_unlock;
|
||||
out_del:
|
||||
out_del_res:
|
||||
release_resource(seg->res);
|
||||
kfree(seg->res);
|
||||
out_del_mem:
|
||||
vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
list_del(&seg->list);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
kfree(seg);
|
||||
out_unlock:
|
||||
mutex_unlock(&dcss_lock);
|
||||
@ -510,7 +683,7 @@ segment_unload(char *name)
|
||||
kfree(seg->res);
|
||||
vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
list_del(&seg->list);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
kfree(seg);
|
||||
out_unlock:
|
||||
mutex_unlock(&dcss_lock);
|
||||
@ -545,7 +718,7 @@ segment_save(char *name)
|
||||
endpfn = (seg->end) >> PAGE_SHIFT;
|
||||
sprintf(cmd1, "DEFSEG %s", name);
|
||||
for (i=0; i<seg->segcnt; i++) {
|
||||
sprintf(cmd1+strlen(cmd1), " %X-%X %s",
|
||||
sprintf(cmd1+strlen(cmd1), " %lX-%lX %s",
|
||||
seg->range[i].start >> PAGE_SHIFT,
|
||||
seg->range[i].end >> PAGE_SHIFT,
|
||||
segtype_string[seg->range[i].start & 0xff]);
|
||||
|
@ -215,7 +215,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
|
||||
return rc;
|
||||
}
|
||||
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
|
||||
device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 1,
|
||||
device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1,
|
||||
8 * sizeof(long));
|
||||
debug_register_view(device->debug_area, &debug_sprintf_view);
|
||||
debug_set_level(device->debug_area, DBF_WARNING);
|
||||
@ -933,7 +933,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
|
||||
MESSAGE(KERN_DEBUG,
|
||||
"invalid status in handle_killed_request: "
|
||||
"bus_id %s, status %02x",
|
||||
cdev->dev.bus_id, cqr->status);
|
||||
dev_name(&cdev->dev), cqr->status);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -942,7 +942,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
|
||||
device != dasd_device_from_cdev_locked(cdev) ||
|
||||
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
|
||||
MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -982,11 +982,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
printk(KERN_WARNING"%s(%s): request timed out\n",
|
||||
__func__, cdev->dev.bus_id);
|
||||
__func__, dev_name(&cdev->dev));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING"%s(%s): unknown error %ld\n",
|
||||
__func__, cdev->dev.bus_id, PTR_ERR(irb));
|
||||
__func__, dev_name(&cdev->dev), PTR_ERR(irb));
|
||||
}
|
||||
dasd_handle_killed_request(cdev, intparm);
|
||||
return;
|
||||
@ -995,7 +995,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
now = get_clock();
|
||||
|
||||
DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
|
||||
cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) |
|
||||
dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) |
|
||||
irb->scsw.cmd.dstat), (unsigned int) intparm);
|
||||
|
||||
/* check for unsolicited interrupts */
|
||||
@ -1019,7 +1019,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
if (!device ||
|
||||
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
|
||||
MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1037,7 +1037,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
if (cqr->status != DASD_CQR_IN_IO) {
|
||||
MESSAGE(KERN_DEBUG,
|
||||
"invalid status: bus_id %s, status %02x",
|
||||
cdev->dev.bus_id, cqr->status);
|
||||
dev_name(&cdev->dev), cqr->status);
|
||||
return;
|
||||
}
|
||||
DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
|
||||
@ -2134,14 +2134,14 @@ int dasd_generic_probe(struct ccw_device *cdev,
|
||||
if (ret) {
|
||||
printk(KERN_WARNING
|
||||
"dasd_generic_probe: could not set ccw-device options "
|
||||
"for %s\n", cdev->dev.bus_id);
|
||||
"for %s\n", dev_name(&cdev->dev));
|
||||
return ret;
|
||||
}
|
||||
ret = dasd_add_sysfs_files(cdev);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING
|
||||
"dasd_generic_probe: could not add sysfs entries "
|
||||
"for %s\n", cdev->dev.bus_id);
|
||||
"for %s\n", dev_name(&cdev->dev));
|
||||
return ret;
|
||||
}
|
||||
cdev->handler = &dasd_int_handler;
|
||||
@ -2152,13 +2152,13 @@ int dasd_generic_probe(struct ccw_device *cdev,
|
||||
* initial probe.
|
||||
*/
|
||||
if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
|
||||
(dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0))
|
||||
(dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
|
||||
ret = ccw_device_set_online(cdev);
|
||||
if (ret)
|
||||
printk(KERN_WARNING
|
||||
"dasd_generic_probe: could not initially "
|
||||
"online ccw-device %s; return code: %d\n",
|
||||
cdev->dev.bus_id, ret);
|
||||
dev_name(&cdev->dev), ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2224,7 +2224,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
|
||||
printk (KERN_WARNING
|
||||
"dasd_generic couldn't online device %s "
|
||||
"- discipline DIAG not available\n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
dasd_delete_device(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -2248,7 +2248,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
|
||||
printk (KERN_WARNING
|
||||
"dasd_generic couldn't online device %s "
|
||||
"with discipline %s rc=%i\n",
|
||||
cdev->dev.bus_id, discipline->name, rc);
|
||||
dev_name(&cdev->dev), discipline->name, rc);
|
||||
module_put(discipline->owner);
|
||||
module_put(base_discipline->owner);
|
||||
dasd_delete_device(device);
|
||||
@ -2259,7 +2259,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
|
||||
if (device->state <= DASD_STATE_KNOWN) {
|
||||
printk (KERN_WARNING
|
||||
"dasd_generic discipline not found for %s\n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
rc = -ENODEV;
|
||||
dasd_set_target_state(device, DASD_STATE_NEW);
|
||||
if (device->block)
|
||||
@ -2267,7 +2267,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
|
||||
dasd_delete_device(device);
|
||||
} else
|
||||
pr_debug("dasd_generic device %s found\n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
|
||||
/* FIXME: we have to wait for the root device but we don't want
|
||||
* to wait for each single device but for all at once. */
|
||||
|
@ -1397,7 +1397,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
|
||||
DEV_MESSAGE(KERN_ERR, cqr->startdev,
|
||||
"ERP on alias device for request %p,"
|
||||
" recover on base device %s", cqr,
|
||||
cqr->block->base->cdev->dev.bus_id);
|
||||
dev_name(&cqr->block->base->cdev->dev));
|
||||
}
|
||||
dasd_eckd_reset_ccw_to_base_io(cqr);
|
||||
erp->startdev = cqr->block->base;
|
||||
|
@ -515,9 +515,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
|
||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&cdev->dev));
|
||||
if (IS_ERR(devmap))
|
||||
devmap = dasd_add_busid(cdev->dev.bus_id,
|
||||
devmap = dasd_add_busid(dev_name(&cdev->dev),
|
||||
DASD_FEATURE_DEFAULT);
|
||||
return devmap;
|
||||
}
|
||||
@ -584,7 +584,7 @@ dasd_delete_device(struct dasd_device *device)
|
||||
unsigned long flags;
|
||||
|
||||
/* First remove device pointer from devmap. */
|
||||
devmap = dasd_find_busid(device->cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&device->cdev->dev));
|
||||
BUG_ON(IS_ERR(devmap));
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
if (devmap->device != device) {
|
||||
@ -674,7 +674,7 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
int ro_flag;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
if (!IS_ERR(devmap))
|
||||
ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
|
||||
else
|
||||
@ -723,7 +723,7 @@ dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
int erplog;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
if (!IS_ERR(devmap))
|
||||
erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
|
||||
else
|
||||
@ -770,7 +770,7 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
int use_diag;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
if (!IS_ERR(devmap))
|
||||
use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
|
||||
else
|
||||
@ -876,7 +876,7 @@ dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
int alias;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
|
||||
spin_unlock(&dasd_devmap_lock);
|
||||
@ -899,7 +899,7 @@ dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
char *vendor;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
|
||||
vendor = devmap->uid.vendor;
|
||||
@ -924,7 +924,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
char ua_string[3];
|
||||
struct dasd_uid *uid;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
|
||||
spin_unlock(&dasd_devmap_lock);
|
||||
@ -972,7 +972,7 @@ dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
struct dasd_devmap *devmap;
|
||||
int eer_flag;
|
||||
|
||||
devmap = dasd_find_busid(dev->bus_id);
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
if (!IS_ERR(devmap) && devmap->device)
|
||||
eer_flag = dasd_eer_enabled(devmap->device);
|
||||
else
|
||||
@ -1034,7 +1034,7 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
|
||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&cdev->dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
spin_lock(&dasd_devmap_lock);
|
||||
@ -1057,7 +1057,7 @@ dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
|
||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&cdev->dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
|
||||
@ -1077,7 +1077,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
|
||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&cdev->dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
|
||||
@ -1093,7 +1093,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
|
||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||
devmap = dasd_find_busid(dev_name(&cdev->dev));
|
||||
if (IS_ERR(devmap))
|
||||
return PTR_ERR(devmap);
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
* Bugreports.to..: <Linux390@de.ibm.com>
|
||||
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
|
||||
* EMC Symmetrix ioctl Copyright EMC Corporation, 2008
|
||||
* Author.........: Nigel Hislop <hislop_nigel@emc.com>
|
||||
*
|
||||
*/
|
||||
|
||||
@ -84,7 +86,7 @@ dasd_eckd_probe (struct ccw_device *cdev)
|
||||
if (ret) {
|
||||
printk(KERN_WARNING
|
||||
"dasd_eckd_probe: could not set ccw-device options "
|
||||
"for %s\n", cdev->dev.bus_id);
|
||||
"for %s\n", dev_name(&cdev->dev));
|
||||
return ret;
|
||||
}
|
||||
ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
|
||||
@ -1501,12 +1503,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
|
||||
return;
|
||||
}
|
||||
|
||||
/* just report other unsolicited interrupts */
|
||||
DEV_MESSAGE(KERN_DEBUG, device, "%s",
|
||||
"unsolicited interrupt received");
|
||||
device->discipline->dump_sense(device, NULL, irb);
|
||||
dasd_schedule_device_bh(device);
|
||||
if ((irb->scsw.cmd.cc == 1) &&
|
||||
(irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
|
||||
(irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) &&
|
||||
(irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) {
|
||||
/* fake irb do nothing, they are handled elsewhere */
|
||||
dasd_schedule_device_bh(device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(irb->esw.esw0.erw.cons)) {
|
||||
/* just report other unsolicited interrupts */
|
||||
DEV_MESSAGE(KERN_ERR, device, "%s",
|
||||
"unsolicited interrupt received");
|
||||
} else {
|
||||
DEV_MESSAGE(KERN_ERR, device, "%s",
|
||||
"unsolicited interrupt received "
|
||||
"(sense available)");
|
||||
device->discipline->dump_sense(device, NULL, irb);
|
||||
}
|
||||
|
||||
dasd_schedule_device_bh(device);
|
||||
return;
|
||||
};
|
||||
|
||||
@ -2068,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue syscall I/O to EMC Symmetrix array.
|
||||
* CCWs are PSF and RSSD
|
||||
*/
|
||||
static int dasd_symm_io(struct dasd_device *device, void __user *argp)
|
||||
{
|
||||
struct dasd_symmio_parms usrparm;
|
||||
char *psf_data, *rssd_result;
|
||||
struct dasd_ccw_req *cqr;
|
||||
struct ccw1 *ccw;
|
||||
int rc;
|
||||
|
||||
/* Copy parms from caller */
|
||||
rc = -EFAULT;
|
||||
if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
|
||||
goto out;
|
||||
#ifndef CONFIG_64BIT
|
||||
/* Make sure pointers are sane even on 31 bit. */
|
||||
if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
/* alloc I/O data area */
|
||||
psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
|
||||
rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
|
||||
if (!psf_data || !rssd_result) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* get syscall header from user space */
|
||||
rc = -EFAULT;
|
||||
if (copy_from_user(psf_data,
|
||||
(void __user *)(unsigned long) usrparm.psf_data,
|
||||
usrparm.psf_data_len))
|
||||
goto out_free;
|
||||
|
||||
/* sanity check on syscall header */
|
||||
if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* setup CCWs for PSF + RSSD */
|
||||
cqr = dasd_smalloc_request("ECKD", 2 , 0, device);
|
||||
if (IS_ERR(cqr)) {
|
||||
DEV_MESSAGE(KERN_WARNING, device, "%s",
|
||||
"Could not allocate initialization request");
|
||||
rc = PTR_ERR(cqr);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
cqr->startdev = device;
|
||||
cqr->memdev = device;
|
||||
cqr->retries = 3;
|
||||
cqr->expires = 10 * HZ;
|
||||
cqr->buildclk = get_clock();
|
||||
cqr->status = DASD_CQR_FILLED;
|
||||
|
||||
/* Build the ccws */
|
||||
ccw = cqr->cpaddr;
|
||||
|
||||
/* PSF ccw */
|
||||
ccw->cmd_code = DASD_ECKD_CCW_PSF;
|
||||
ccw->count = usrparm.psf_data_len;
|
||||
ccw->flags |= CCW_FLAG_CC;
|
||||
ccw->cda = (__u32)(addr_t) psf_data;
|
||||
|
||||
ccw++;
|
||||
|
||||
/* RSSD ccw */
|
||||
ccw->cmd_code = DASD_ECKD_CCW_RSSD;
|
||||
ccw->count = usrparm.rssd_result_len;
|
||||
ccw->flags = CCW_FLAG_SLI ;
|
||||
ccw->cda = (__u32)(addr_t) rssd_result;
|
||||
|
||||
rc = dasd_sleep_on(cqr);
|
||||
if (rc)
|
||||
goto out_sfree;
|
||||
|
||||
rc = -EFAULT;
|
||||
if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result,
|
||||
rssd_result, usrparm.rssd_result_len))
|
||||
goto out_sfree;
|
||||
rc = 0;
|
||||
|
||||
out_sfree:
|
||||
dasd_sfree_request(cqr, cqr->memdev);
|
||||
out_free:
|
||||
kfree(rssd_result);
|
||||
kfree(psf_data);
|
||||
out:
|
||||
DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
|
||||
{
|
||||
@ -2086,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
|
||||
return dasd_eckd_reserve(device);
|
||||
case BIODASDSLCK:
|
||||
return dasd_eckd_steal_lock(device);
|
||||
case BIODASDSYMMIO:
|
||||
return dasd_symm_io(device, argp);
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
@ -2145,13 +2261,13 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
|
||||
/* dump the sense data */
|
||||
len = sprintf(page, KERN_ERR PRINTK_HEADER
|
||||
" I/O status report for device %s:\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
|
||||
" in req: %p CS: 0x%02X DS: 0x%02X\n", req,
|
||||
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
|
||||
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
|
||||
" device %s: Failing CCW: %p\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
(void *) (addr_t) irb->scsw.cmd.cpa);
|
||||
if (irb->esw.esw0.erw.cons) {
|
||||
for (sl = 0; sl < 4; sl++) {
|
||||
|
@ -309,7 +309,8 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
|
||||
do_gettimeofday(&tv);
|
||||
header.tv_sec = tv.tv_sec;
|
||||
header.tv_usec = tv.tv_usec;
|
||||
strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
|
||||
strncpy(header.busid, dev_name(&device->cdev->dev),
|
||||
DASD_EER_BUSID_SIZE);
|
||||
|
||||
spin_lock_irqsave(&bufferlock, flags);
|
||||
list_for_each_entry(eerb, &bufferlist, list) {
|
||||
@ -349,7 +350,8 @@ static void dasd_eer_write_snss_trigger(struct dasd_device *device,
|
||||
do_gettimeofday(&tv);
|
||||
header.tv_sec = tv.tv_sec;
|
||||
header.tv_usec = tv.tv_usec;
|
||||
strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
|
||||
strncpy(header.busid, dev_name(&device->cdev->dev),
|
||||
DASD_EER_BUSID_SIZE);
|
||||
|
||||
spin_lock_irqsave(&bufferlock, flags);
|
||||
list_for_each_entry(eerb, &bufferlist, list) {
|
||||
|
@ -451,13 +451,13 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
|
||||
}
|
||||
len = sprintf(page, KERN_ERR PRINTK_HEADER
|
||||
" I/O status report for device %s:\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
|
||||
" in req: %p CS: 0x%02X DS: 0x%02X\n", req,
|
||||
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
|
||||
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
|
||||
" device %s: Failing CCW: %p\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
(void *) (addr_t) irb->scsw.cmd.cpa);
|
||||
if (irb->esw.esw0.erw.cons) {
|
||||
for (sl = 0; sl < 4; sl++) {
|
||||
|
@ -126,7 +126,7 @@ do { \
|
||||
#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
|
||||
do { \
|
||||
printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
|
||||
d_device->cdev->dev.bus_id, d_args); \
|
||||
dev_name(&d_device->cdev->dev), d_args); \
|
||||
DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
|
||||
} while(0)
|
||||
|
||||
@ -140,7 +140,7 @@ do { \
|
||||
#define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\
|
||||
do { \
|
||||
printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
|
||||
d_device->cdev->dev.bus_id, d_args); \
|
||||
dev_name(&d_device->cdev->dev), d_args); \
|
||||
} while(0)
|
||||
|
||||
#define MESSAGE_LOG(d_loglevel,d_string,d_args...)\
|
||||
|
@ -67,7 +67,7 @@ dasd_devices_show(struct seq_file *m, void *v)
|
||||
return 0;
|
||||
}
|
||||
/* Print device number. */
|
||||
seq_printf(m, "%s", device->cdev->dev.bus_id);
|
||||
seq_printf(m, "%s", dev_name(&device->cdev->dev));
|
||||
/* Print discipline string. */
|
||||
if (device != NULL && device->discipline != NULL)
|
||||
seq_printf(m, "(%s)", device->discipline->name);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x)
|
||||
#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x)
|
||||
|
||||
|
||||
static int dcssblk_open(struct inode *inode, struct file *filp);
|
||||
static int dcssblk_release(struct inode *inode, struct file *filp);
|
||||
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
|
||||
@ -48,26 +47,6 @@ static struct block_device_operations dcssblk_devops = {
|
||||
.direct_access = dcssblk_direct_access,
|
||||
};
|
||||
|
||||
static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
|
||||
static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
|
||||
static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
|
||||
static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show,
|
||||
dcssblk_save_store);
|
||||
static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show,
|
||||
dcssblk_shared_store);
|
||||
|
||||
static struct device *dcssblk_root_dev;
|
||||
|
||||
struct dcssblk_dev_info {
|
||||
struct list_head lh;
|
||||
struct device dev;
|
||||
@ -80,8 +59,42 @@ struct dcssblk_dev_info {
|
||||
unsigned char save_pending;
|
||||
unsigned char is_shared;
|
||||
struct request_queue *dcssblk_queue;
|
||||
int num_of_segments;
|
||||
struct list_head seg_list;
|
||||
};
|
||||
|
||||
struct segment_info {
|
||||
struct list_head lh;
|
||||
char segment_name[BUS_ID_SIZE];
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
int segment_type;
|
||||
};
|
||||
|
||||
static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
|
||||
size_t count);
|
||||
static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t dcssblk_seglist_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf);
|
||||
|
||||
static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
|
||||
static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
|
||||
static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
|
||||
dcssblk_save_store);
|
||||
static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
|
||||
dcssblk_shared_store);
|
||||
static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
|
||||
|
||||
static struct device *dcssblk_root_dev;
|
||||
|
||||
static LIST_HEAD(dcssblk_devices);
|
||||
static struct rw_semaphore dcssblk_devices_sem;
|
||||
|
||||
@ -91,8 +104,15 @@ static struct rw_semaphore dcssblk_devices_sem;
|
||||
static void
|
||||
dcssblk_release_segment(struct device *dev)
|
||||
{
|
||||
PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id);
|
||||
kfree(container_of(dev, struct dcssblk_dev_info, dev));
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry, *temp;
|
||||
|
||||
dev_info = container_of(dev, struct dcssblk_dev_info, dev);
|
||||
list_for_each_entry_safe(entry, temp, &dev_info->seg_list, lh) {
|
||||
list_del(&entry->lh);
|
||||
kfree(entry);
|
||||
}
|
||||
kfree(dev_info);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
@ -142,6 +162,169 @@ dcssblk_get_device_by_name(char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the struct segment_info from seg_list
|
||||
* for the given name.
|
||||
* down_read(&dcssblk_devices_sem) must be held.
|
||||
*/
|
||||
static struct segment_info *
|
||||
dcssblk_get_segment_by_name(char *name)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
|
||||
list_for_each_entry(dev_info, &dcssblk_devices, lh) {
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
if (!strcmp(name, entry->segment_name))
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the highest address of the multi-segment block.
|
||||
*/
|
||||
static unsigned long
|
||||
dcssblk_find_highest_addr(struct dcssblk_dev_info *dev_info)
|
||||
{
|
||||
unsigned long highest_addr;
|
||||
struct segment_info *entry;
|
||||
|
||||
highest_addr = 0;
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
if (highest_addr < entry->end)
|
||||
highest_addr = entry->end;
|
||||
}
|
||||
return highest_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the lowest address of the multi-segment block.
|
||||
*/
|
||||
static unsigned long
|
||||
dcssblk_find_lowest_addr(struct dcssblk_dev_info *dev_info)
|
||||
{
|
||||
int set_first;
|
||||
unsigned long lowest_addr;
|
||||
struct segment_info *entry;
|
||||
|
||||
set_first = 0;
|
||||
lowest_addr = 0;
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
if (set_first == 0) {
|
||||
lowest_addr = entry->start;
|
||||
set_first = 1;
|
||||
} else {
|
||||
if (lowest_addr > entry->start)
|
||||
lowest_addr = entry->start;
|
||||
}
|
||||
}
|
||||
return lowest_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check continuity of segments.
|
||||
*/
|
||||
static int
|
||||
dcssblk_is_continuous(struct dcssblk_dev_info *dev_info)
|
||||
{
|
||||
int i, j, rc;
|
||||
struct segment_info *sort_list, *entry, temp;
|
||||
|
||||
if (dev_info->num_of_segments <= 1)
|
||||
return 0;
|
||||
|
||||
sort_list = kzalloc(
|
||||
sizeof(struct segment_info) * dev_info->num_of_segments,
|
||||
GFP_KERNEL);
|
||||
if (sort_list == NULL)
|
||||
return -ENOMEM;
|
||||
i = 0;
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
memcpy(&sort_list[i], entry, sizeof(struct segment_info));
|
||||
i++;
|
||||
}
|
||||
|
||||
/* sort segments */
|
||||
for (i = 0; i < dev_info->num_of_segments; i++)
|
||||
for (j = 0; j < dev_info->num_of_segments; j++)
|
||||
if (sort_list[j].start > sort_list[i].start) {
|
||||
memcpy(&temp, &sort_list[i],
|
||||
sizeof(struct segment_info));
|
||||
memcpy(&sort_list[i], &sort_list[j],
|
||||
sizeof(struct segment_info));
|
||||
memcpy(&sort_list[j], &temp,
|
||||
sizeof(struct segment_info));
|
||||
}
|
||||
|
||||
/* check continuity */
|
||||
for (i = 0; i < dev_info->num_of_segments - 1; i++) {
|
||||
if ((sort_list[i].end + 1) != sort_list[i+1].start) {
|
||||
PRINT_ERR("Segment %s is not contiguous with "
|
||||
"segment %s\n",
|
||||
sort_list[i].segment_name,
|
||||
sort_list[i+1].segment_name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* EN and EW are allowed in a block device */
|
||||
if (sort_list[i].segment_type != sort_list[i+1].segment_type) {
|
||||
if (!(sort_list[i].segment_type & SEGMENT_EXCLUSIVE) ||
|
||||
(sort_list[i].segment_type == SEG_TYPE_ER) ||
|
||||
!(sort_list[i+1].segment_type &
|
||||
SEGMENT_EXCLUSIVE) ||
|
||||
(sort_list[i+1].segment_type == SEG_TYPE_ER)) {
|
||||
PRINT_ERR("Segment %s has different type from "
|
||||
"segment %s\n",
|
||||
sort_list[i].segment_name,
|
||||
sort_list[i+1].segment_name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
out:
|
||||
kfree(sort_list);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a segment
|
||||
*/
|
||||
static int
|
||||
dcssblk_load_segment(char *name, struct segment_info **seg_info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* already loaded? */
|
||||
down_read(&dcssblk_devices_sem);
|
||||
*seg_info = dcssblk_get_segment_by_name(name);
|
||||
up_read(&dcssblk_devices_sem);
|
||||
if (*seg_info != NULL)
|
||||
return -EEXIST;
|
||||
|
||||
/* get a struct segment_info */
|
||||
*seg_info = kzalloc(sizeof(struct segment_info), GFP_KERNEL);
|
||||
if (*seg_info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy((*seg_info)->segment_name, name);
|
||||
|
||||
/* load the segment */
|
||||
rc = segment_load(name, SEGMENT_SHARED,
|
||||
&(*seg_info)->start, &(*seg_info)->end);
|
||||
if (rc < 0) {
|
||||
segment_warning(rc, (*seg_info)->segment_name);
|
||||
kfree(*seg_info);
|
||||
} else {
|
||||
INIT_LIST_HEAD(&(*seg_info)->lh);
|
||||
(*seg_info)->segment_type = rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dcssblk_unregister_callback(struct device *dev)
|
||||
{
|
||||
device_unregister(dev);
|
||||
@ -165,6 +348,7 @@ static ssize_t
|
||||
dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry, *temp;
|
||||
int rc;
|
||||
|
||||
if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
|
||||
@ -172,46 +356,46 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
|
||||
down_write(&dcssblk_devices_sem);
|
||||
dev_info = container_of(dev, struct dcssblk_dev_info, dev);
|
||||
if (atomic_read(&dev_info->use_count)) {
|
||||
PRINT_ERR("share: segment %s is busy!\n",
|
||||
dev_info->segment_name);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (inbuf[0] == '1') {
|
||||
// reload segment in shared mode
|
||||
rc = segment_modify_shared(dev_info->segment_name,
|
||||
SEGMENT_SHARED);
|
||||
if (rc < 0) {
|
||||
BUG_ON(rc == -EINVAL);
|
||||
if (rc != -EAGAIN)
|
||||
goto removeseg;
|
||||
} else {
|
||||
dev_info->is_shared = 1;
|
||||
switch (dev_info->segment_type) {
|
||||
case SEG_TYPE_SR:
|
||||
case SEG_TYPE_ER:
|
||||
case SEG_TYPE_SC:
|
||||
set_disk_ro(dev_info->gd,1);
|
||||
/* reload segments in shared mode */
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
rc = segment_modify_shared(entry->segment_name,
|
||||
SEGMENT_SHARED);
|
||||
if (rc < 0) {
|
||||
BUG_ON(rc == -EINVAL);
|
||||
if (rc != -EAGAIN)
|
||||
goto removeseg;
|
||||
}
|
||||
}
|
||||
dev_info->is_shared = 1;
|
||||
switch (dev_info->segment_type) {
|
||||
case SEG_TYPE_SR:
|
||||
case SEG_TYPE_ER:
|
||||
case SEG_TYPE_SC:
|
||||
set_disk_ro(dev_info->gd, 1);
|
||||
}
|
||||
} else if (inbuf[0] == '0') {
|
||||
// reload segment in exclusive mode
|
||||
/* reload segments in exclusive mode */
|
||||
if (dev_info->segment_type == SEG_TYPE_SC) {
|
||||
PRINT_ERR("Segment type SC (%s) cannot be loaded in "
|
||||
"non-shared mode\n", dev_info->segment_name);
|
||||
"non-shared mode\n", dev_info->segment_name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rc = segment_modify_shared(dev_info->segment_name,
|
||||
SEGMENT_EXCLUSIVE);
|
||||
if (rc < 0) {
|
||||
BUG_ON(rc == -EINVAL);
|
||||
if (rc != -EAGAIN)
|
||||
goto removeseg;
|
||||
} else {
|
||||
dev_info->is_shared = 0;
|
||||
set_disk_ro(dev_info->gd, 0);
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
rc = segment_modify_shared(entry->segment_name,
|
||||
SEGMENT_EXCLUSIVE);
|
||||
if (rc < 0) {
|
||||
BUG_ON(rc == -EINVAL);
|
||||
if (rc != -EAGAIN)
|
||||
goto removeseg;
|
||||
}
|
||||
}
|
||||
dev_info->is_shared = 0;
|
||||
set_disk_ro(dev_info->gd, 0);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
@ -220,8 +404,14 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
|
||||
goto out;
|
||||
|
||||
removeseg:
|
||||
PRINT_ERR("Could not reload segment %s, removing it now!\n",
|
||||
dev_info->segment_name);
|
||||
PRINT_ERR("Could not reload segment(s) of the device %s, removing "
|
||||
"segment(s) now!\n",
|
||||
dev_info->segment_name);
|
||||
temp = entry;
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
if (entry != temp)
|
||||
segment_unload(entry->segment_name);
|
||||
}
|
||||
list_del(&dev_info->lh);
|
||||
|
||||
del_gendisk(dev_info->gd);
|
||||
@ -254,6 +444,7 @@ static ssize_t
|
||||
dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
|
||||
if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
|
||||
return -EINVAL;
|
||||
@ -263,14 +454,16 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
|
||||
if (inbuf[0] == '1') {
|
||||
if (atomic_read(&dev_info->use_count) == 0) {
|
||||
// device is idle => we save immediately
|
||||
PRINT_INFO("Saving segment %s\n",
|
||||
PRINT_INFO("Saving segment(s) of the device %s\n",
|
||||
dev_info->segment_name);
|
||||
segment_save(dev_info->segment_name);
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
segment_save(entry->segment_name);
|
||||
}
|
||||
} else {
|
||||
// device is busy => we save it when it becomes
|
||||
// idle in dcssblk_release
|
||||
PRINT_INFO("Segment %s is currently busy, it will "
|
||||
"be saved when it becomes idle...\n",
|
||||
PRINT_INFO("Device %s is currently busy, segment(s) "
|
||||
"will be saved when it becomes idle...\n",
|
||||
dev_info->segment_name);
|
||||
dev_info->save_pending = 1;
|
||||
}
|
||||
@ -279,7 +472,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
|
||||
// device is busy & the user wants to undo his save
|
||||
// request
|
||||
dev_info->save_pending = 0;
|
||||
PRINT_INFO("Pending save for segment %s deactivated\n",
|
||||
PRINT_INFO("Pending save for segment(s) of the device "
|
||||
"%s deactivated\n",
|
||||
dev_info->segment_name);
|
||||
}
|
||||
} else {
|
||||
@ -290,67 +484,124 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* device attribute for showing all segments in a device
|
||||
*/
|
||||
static ssize_t
|
||||
dcssblk_seglist_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
|
||||
down_read(&dcssblk_devices_sem);
|
||||
dev_info = container_of(dev, struct dcssblk_dev_info, dev);
|
||||
i = 0;
|
||||
buf[0] = '\0';
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
strcpy(&buf[i], entry->segment_name);
|
||||
i += strlen(entry->segment_name);
|
||||
buf[i] = '\n';
|
||||
i++;
|
||||
}
|
||||
up_read(&dcssblk_devices_sem);
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* device attribute for adding devices
|
||||
*/
|
||||
static ssize_t
|
||||
dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc, i;
|
||||
int rc, i, j, num_of_segments;
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *seg_info, *temp;
|
||||
char *local_buf;
|
||||
unsigned long seg_byte_size;
|
||||
|
||||
dev_info = NULL;
|
||||
seg_info = NULL;
|
||||
if (dev != dcssblk_root_dev) {
|
||||
rc = -EINVAL;
|
||||
goto out_nobuf;
|
||||
}
|
||||
if ((count < 1) || (buf[0] == '\0') || (buf[0] == '\n')) {
|
||||
rc = -ENAMETOOLONG;
|
||||
goto out_nobuf;
|
||||
}
|
||||
|
||||
local_buf = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (local_buf == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out_nobuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse input
|
||||
*/
|
||||
num_of_segments = 0;
|
||||
for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) {
|
||||
local_buf[i] = toupper(buf[i]);
|
||||
}
|
||||
local_buf[i] = '\0';
|
||||
if ((i == 0) || (i > 8)) {
|
||||
rc = -ENAMETOOLONG;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* already loaded?
|
||||
*/
|
||||
down_read(&dcssblk_devices_sem);
|
||||
dev_info = dcssblk_get_device_by_name(local_buf);
|
||||
up_read(&dcssblk_devices_sem);
|
||||
if (dev_info != NULL) {
|
||||
PRINT_WARN("Segment %s already loaded!\n", local_buf);
|
||||
rc = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* get a struct dcssblk_dev_info
|
||||
*/
|
||||
dev_info = kzalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL);
|
||||
if (dev_info == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
for (j = i; (buf[j] != ':') &&
|
||||
(buf[j] != '\0') &&
|
||||
(buf[j] != '\n') &&
|
||||
j < count; j++) {
|
||||
local_buf[j-i] = toupper(buf[j]);
|
||||
}
|
||||
local_buf[j-i] = '\0';
|
||||
if (((j - i) == 0) || ((j - i) > 8)) {
|
||||
rc = -ENAMETOOLONG;
|
||||
goto seg_list_del;
|
||||
}
|
||||
|
||||
rc = dcssblk_load_segment(local_buf, &seg_info);
|
||||
if (rc < 0)
|
||||
goto seg_list_del;
|
||||
/*
|
||||
* get a struct dcssblk_dev_info
|
||||
*/
|
||||
if (num_of_segments == 0) {
|
||||
dev_info = kzalloc(sizeof(struct dcssblk_dev_info),
|
||||
GFP_KERNEL);
|
||||
if (dev_info == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(dev_info->segment_name, local_buf);
|
||||
dev_info->segment_type = seg_info->segment_type;
|
||||
INIT_LIST_HEAD(&dev_info->seg_list);
|
||||
}
|
||||
list_add_tail(&seg_info->lh, &dev_info->seg_list);
|
||||
num_of_segments++;
|
||||
i = j;
|
||||
|
||||
if ((buf[j] == '\0') || (buf[j] == '\n'))
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(dev_info->segment_name, local_buf);
|
||||
strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE);
|
||||
/* no trailing colon at the end of the input */
|
||||
if ((i > 0) && (buf[i-1] == ':')) {
|
||||
rc = -ENAMETOOLONG;
|
||||
goto seg_list_del;
|
||||
}
|
||||
strlcpy(local_buf, buf, i + 1);
|
||||
dev_info->num_of_segments = num_of_segments;
|
||||
rc = dcssblk_is_continuous(dev_info);
|
||||
if (rc < 0)
|
||||
goto seg_list_del;
|
||||
|
||||
dev_info->start = dcssblk_find_lowest_addr(dev_info);
|
||||
dev_info->end = dcssblk_find_highest_addr(dev_info);
|
||||
|
||||
dev_set_name(&dev_info->dev, dev_info->segment_name);
|
||||
dev_info->dev.release = dcssblk_release_segment;
|
||||
INIT_LIST_HEAD(&dev_info->lh);
|
||||
|
||||
dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
|
||||
if (dev_info->gd == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto free_dev_info;
|
||||
goto seg_list_del;
|
||||
}
|
||||
dev_info->gd->major = dcssblk_major;
|
||||
dev_info->gd->fops = &dcssblk_devops;
|
||||
@ -360,65 +611,52 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
|
||||
dev_info->gd->driverfs_dev = &dev_info->dev;
|
||||
blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
|
||||
blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
|
||||
/*
|
||||
* load the segment
|
||||
*/
|
||||
rc = segment_load(local_buf, SEGMENT_SHARED,
|
||||
&dev_info->start, &dev_info->end);
|
||||
if (rc < 0) {
|
||||
segment_warning(rc, dev_info->segment_name);
|
||||
goto dealloc_gendisk;
|
||||
}
|
||||
|
||||
seg_byte_size = (dev_info->end - dev_info->start + 1);
|
||||
set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
|
||||
PRINT_INFO("Loaded segment %s, size = %lu Byte, "
|
||||
PRINT_INFO("Loaded segment(s) %s, size = %lu Byte, "
|
||||
"capacity = %lu (512 Byte) sectors\n", local_buf,
|
||||
seg_byte_size, seg_byte_size >> 9);
|
||||
|
||||
dev_info->segment_type = rc;
|
||||
dev_info->save_pending = 0;
|
||||
dev_info->is_shared = 1;
|
||||
dev_info->dev.parent = dcssblk_root_dev;
|
||||
|
||||
/*
|
||||
* get minor, add to list
|
||||
*get minor, add to list
|
||||
*/
|
||||
down_write(&dcssblk_devices_sem);
|
||||
if (dcssblk_get_device_by_name(local_buf)) {
|
||||
up_write(&dcssblk_devices_sem);
|
||||
if (dcssblk_get_segment_by_name(local_buf)) {
|
||||
rc = -EEXIST;
|
||||
goto unload_seg;
|
||||
goto release_gd;
|
||||
}
|
||||
rc = dcssblk_assign_free_minor(dev_info);
|
||||
if (rc) {
|
||||
up_write(&dcssblk_devices_sem);
|
||||
PRINT_ERR("No free minor number available! "
|
||||
"Unloading segment...\n");
|
||||
goto unload_seg;
|
||||
}
|
||||
if (rc)
|
||||
goto release_gd;
|
||||
sprintf(dev_info->gd->disk_name, "dcssblk%d",
|
||||
MINOR(disk_devt(dev_info->gd)));
|
||||
list_add_tail(&dev_info->lh, &dcssblk_devices);
|
||||
|
||||
if (!try_module_get(THIS_MODULE)) {
|
||||
rc = -ENODEV;
|
||||
goto list_del;
|
||||
goto dev_list_del;
|
||||
}
|
||||
/*
|
||||
* register the device
|
||||
*/
|
||||
rc = device_register(&dev_info->dev);
|
||||
if (rc) {
|
||||
PRINT_ERR("Segment %s could not be registered RC=%d\n",
|
||||
local_buf, rc);
|
||||
module_put(THIS_MODULE);
|
||||
goto list_del;
|
||||
goto dev_list_del;
|
||||
}
|
||||
get_device(&dev_info->dev);
|
||||
rc = device_create_file(&dev_info->dev, &dev_attr_shared);
|
||||
if (rc)
|
||||
goto unregister_dev;
|
||||
rc = device_create_file(&dev_info->dev, &dev_attr_save);
|
||||
if (rc)
|
||||
goto unregister_dev;
|
||||
rc = device_create_file(&dev_info->dev, &dev_attr_seglist);
|
||||
if (rc)
|
||||
goto unregister_dev;
|
||||
|
||||
@ -434,7 +672,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
|
||||
set_disk_ro(dev_info->gd,0);
|
||||
break;
|
||||
}
|
||||
PRINT_DEBUG("Segment %s loaded successfully\n", local_buf);
|
||||
up_write(&dcssblk_devices_sem);
|
||||
rc = count;
|
||||
goto out;
|
||||
@ -445,20 +682,27 @@ unregister_dev:
|
||||
dev_info->gd->queue = NULL;
|
||||
put_disk(dev_info->gd);
|
||||
device_unregister(&dev_info->dev);
|
||||
segment_unload(dev_info->segment_name);
|
||||
list_for_each_entry(seg_info, &dev_info->seg_list, lh) {
|
||||
segment_unload(seg_info->segment_name);
|
||||
}
|
||||
put_device(&dev_info->dev);
|
||||
up_write(&dcssblk_devices_sem);
|
||||
goto out;
|
||||
list_del:
|
||||
dev_list_del:
|
||||
list_del(&dev_info->lh);
|
||||
up_write(&dcssblk_devices_sem);
|
||||
unload_seg:
|
||||
segment_unload(local_buf);
|
||||
dealloc_gendisk:
|
||||
release_gd:
|
||||
blk_cleanup_queue(dev_info->dcssblk_queue);
|
||||
dev_info->gd->queue = NULL;
|
||||
put_disk(dev_info->gd);
|
||||
free_dev_info:
|
||||
up_write(&dcssblk_devices_sem);
|
||||
seg_list_del:
|
||||
if (dev_info == NULL)
|
||||
goto out;
|
||||
list_for_each_entry_safe(seg_info, temp, &dev_info->seg_list, lh) {
|
||||
list_del(&seg_info->lh);
|
||||
segment_unload(seg_info->segment_name);
|
||||
kfree(seg_info);
|
||||
}
|
||||
kfree(dev_info);
|
||||
out:
|
||||
kfree(local_buf);
|
||||
@ -473,6 +717,7 @@ static ssize_t
|
||||
dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
int rc, i;
|
||||
char *local_buf;
|
||||
|
||||
@ -499,26 +744,28 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
|
||||
dev_info = dcssblk_get_device_by_name(local_buf);
|
||||
if (dev_info == NULL) {
|
||||
up_write(&dcssblk_devices_sem);
|
||||
PRINT_WARN("Segment %s is not loaded!\n", local_buf);
|
||||
PRINT_WARN("Device %s is not loaded!\n", local_buf);
|
||||
rc = -ENODEV;
|
||||
goto out_buf;
|
||||
}
|
||||
if (atomic_read(&dev_info->use_count) != 0) {
|
||||
up_write(&dcssblk_devices_sem);
|
||||
PRINT_WARN("Segment %s is in use!\n", local_buf);
|
||||
PRINT_WARN("Device %s is in use!\n", local_buf);
|
||||
rc = -EBUSY;
|
||||
goto out_buf;
|
||||
}
|
||||
list_del(&dev_info->lh);
|
||||
|
||||
list_del(&dev_info->lh);
|
||||
del_gendisk(dev_info->gd);
|
||||
blk_cleanup_queue(dev_info->dcssblk_queue);
|
||||
dev_info->gd->queue = NULL;
|
||||
put_disk(dev_info->gd);
|
||||
device_unregister(&dev_info->dev);
|
||||
segment_unload(dev_info->segment_name);
|
||||
PRINT_DEBUG("Segment %s unloaded successfully\n",
|
||||
dev_info->segment_name);
|
||||
|
||||
/* unload all related segments */
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh)
|
||||
segment_unload(entry->segment_name);
|
||||
|
||||
put_device(&dev_info->dev);
|
||||
up_write(&dcssblk_devices_sem);
|
||||
|
||||
@ -550,6 +797,7 @@ static int
|
||||
dcssblk_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
int rc;
|
||||
|
||||
dev_info = inode->i_bdev->bd_disk->private_data;
|
||||
@ -560,9 +808,11 @@ dcssblk_release(struct inode *inode, struct file *filp)
|
||||
down_write(&dcssblk_devices_sem);
|
||||
if (atomic_dec_and_test(&dev_info->use_count)
|
||||
&& (dev_info->save_pending)) {
|
||||
PRINT_INFO("Segment %s became idle and is being saved now\n",
|
||||
PRINT_INFO("Device %s became idle and is being saved now\n",
|
||||
dev_info->segment_name);
|
||||
segment_save(dev_info->segment_name);
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
segment_save(entry->segment_name);
|
||||
}
|
||||
dev_info->save_pending = 0;
|
||||
}
|
||||
up_write(&dcssblk_devices_sem);
|
||||
@ -602,7 +852,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
|
||||
case SEG_TYPE_SC:
|
||||
/* cannot write to these segments */
|
||||
if (bio_data_dir(bio) == WRITE) {
|
||||
PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
|
||||
PRINT_WARN("rejecting write to ro device %s\n",
|
||||
dev_name(&dev_info->dev));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -657,7 +908,7 @@ static void
|
||||
dcssblk_check_params(void)
|
||||
{
|
||||
int rc, i, j, k;
|
||||
char buf[9];
|
||||
char buf[DCSSBLK_PARM_LEN + 1];
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
|
||||
for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
|
||||
@ -665,15 +916,16 @@ dcssblk_check_params(void)
|
||||
for (j = i; (dcssblk_segments[j] != ',') &&
|
||||
(dcssblk_segments[j] != '\0') &&
|
||||
(dcssblk_segments[j] != '(') &&
|
||||
(j - i) < 8; j++)
|
||||
(j < DCSSBLK_PARM_LEN); j++)
|
||||
{
|
||||
buf[j-i] = dcssblk_segments[j];
|
||||
}
|
||||
buf[j-i] = '\0';
|
||||
rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
|
||||
if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
|
||||
for (k = 0; buf[k] != '\0'; k++)
|
||||
for (k = 0; (buf[k] != ':') && (buf[k] != '\0'); k++)
|
||||
buf[k] = toupper(buf[k]);
|
||||
buf[k] = '\0';
|
||||
if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
|
||||
down_read(&dcssblk_devices_sem);
|
||||
dev_info = dcssblk_get_device_by_name(buf);
|
||||
@ -740,10 +992,12 @@ module_exit(dcssblk_exit);
|
||||
|
||||
module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
|
||||
MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
|
||||
"comma-separated list, each name max. 8 chars.\n"
|
||||
"Adding \"(local)\" to segment name equals echoing 0 to "
|
||||
"/sys/devices/dcssblk/<segment name>/shared after loading "
|
||||
"the segment - \n"
|
||||
"e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\"");
|
||||
"comma-separated list, names in each set separated "
|
||||
"by commas are separated by colons, each set contains "
|
||||
"names of contiguous segments and each name max. 8 chars.\n"
|
||||
"Adding \"(local)\" to the end of each set equals echoing 0 "
|
||||
"to /sys/devices/dcssblk/<device name>/shared after loading "
|
||||
"the contiguous segments - \n"
|
||||
"e.g. segments=\"mydcss1,mydcss2:mydcss3,mydcss4(local)\"");
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -56,6 +56,7 @@ typedef struct {
|
||||
static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
|
||||
static unsigned int xpram_sizes[XPRAM_MAX_DEVS];
|
||||
static struct gendisk *xpram_disks[XPRAM_MAX_DEVS];
|
||||
static struct request_queue *xpram_queues[XPRAM_MAX_DEVS];
|
||||
static unsigned int xpram_pages;
|
||||
static int xpram_devs;
|
||||
|
||||
@ -330,18 +331,22 @@ static int __init xpram_setup_sizes(unsigned long pages)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct request_queue *xpram_queue;
|
||||
|
||||
static int __init xpram_setup_blkdev(void)
|
||||
{
|
||||
unsigned long offset;
|
||||
int i, rc = -ENOMEM;
|
||||
|
||||
for (i = 0; i < xpram_devs; i++) {
|
||||
struct gendisk *disk = alloc_disk(1);
|
||||
if (!disk)
|
||||
xpram_disks[i] = alloc_disk(1);
|
||||
if (!xpram_disks[i])
|
||||
goto out;
|
||||
xpram_disks[i] = disk;
|
||||
xpram_queues[i] = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!xpram_queues[i]) {
|
||||
put_disk(xpram_disks[i]);
|
||||
goto out;
|
||||
}
|
||||
blk_queue_make_request(xpram_queues[i], xpram_make_request);
|
||||
blk_queue_hardsect_size(xpram_queues[i], 4096);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -351,18 +356,6 @@ static int __init xpram_setup_blkdev(void)
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Assign the other needed values: make request function, sizes and
|
||||
* hardsect size. All the minor devices feature the same value.
|
||||
*/
|
||||
xpram_queue = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!xpram_queue) {
|
||||
rc = -ENOMEM;
|
||||
goto out_unreg;
|
||||
}
|
||||
blk_queue_make_request(xpram_queue, xpram_make_request);
|
||||
blk_queue_hardsect_size(xpram_queue, 4096);
|
||||
|
||||
/*
|
||||
* Setup device structures.
|
||||
*/
|
||||
@ -377,18 +370,18 @@ static int __init xpram_setup_blkdev(void)
|
||||
disk->first_minor = i;
|
||||
disk->fops = &xpram_devops;
|
||||
disk->private_data = &xpram_devices[i];
|
||||
disk->queue = xpram_queue;
|
||||
disk->queue = xpram_queues[i];
|
||||
sprintf(disk->disk_name, "slram%d", i);
|
||||
set_capacity(disk, xpram_sizes[i] << 1);
|
||||
add_disk(disk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
out_unreg:
|
||||
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
|
||||
out:
|
||||
while (i--)
|
||||
while (i--) {
|
||||
blk_cleanup_queue(xpram_queues[i]);
|
||||
put_disk(xpram_disks[i]);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -400,10 +393,10 @@ static void __exit xpram_exit(void)
|
||||
int i;
|
||||
for (i = 0; i < xpram_devs; i++) {
|
||||
del_gendisk(xpram_disks[i]);
|
||||
blk_cleanup_queue(xpram_queues[i]);
|
||||
put_disk(xpram_disks[i]);
|
||||
}
|
||||
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
|
||||
blk_cleanup_queue(xpram_queue);
|
||||
}
|
||||
|
||||
static int __init xpram_init(void)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bootmem.h>
|
||||
@ -88,7 +89,6 @@ struct raw3215_info {
|
||||
int count; /* number of bytes in output buffer */
|
||||
int written; /* number of bytes in write requests */
|
||||
struct tty_struct *tty; /* pointer to tty structure if present */
|
||||
struct tasklet_struct tasklet;
|
||||
struct raw3215_req *queued_read; /* pointer to queued read requests */
|
||||
struct raw3215_req *queued_write;/* pointer to queued write requests */
|
||||
wait_queue_head_t empty_wait; /* wait queue for flushing */
|
||||
@ -341,21 +341,14 @@ raw3215_try_io(struct raw3215_info *raw)
|
||||
}
|
||||
|
||||
/*
|
||||
* The bottom half handler routine for 3215 devices. It tries to start
|
||||
* the next IO and wakes up processes waiting on the tty.
|
||||
* Try to start the next IO and wake up processes waiting on the tty.
|
||||
*/
|
||||
static void
|
||||
raw3215_tasklet(void *data)
|
||||
static void raw3215_next_io(struct raw3215_info *raw)
|
||||
{
|
||||
struct raw3215_info *raw;
|
||||
struct tty_struct *tty;
|
||||
unsigned long flags;
|
||||
|
||||
raw = (struct raw3215_info *) data;
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_mk_write_req(raw);
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
tty = raw->tty;
|
||||
if (tty != NULL &&
|
||||
RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
|
||||
@ -380,7 +373,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
cstat = irb->scsw.cmd.cstat;
|
||||
dstat = irb->scsw.cmd.dstat;
|
||||
if (cstat != 0)
|
||||
tasklet_schedule(&raw->tasklet);
|
||||
raw3215_next_io(raw);
|
||||
if (dstat & 0x01) { /* we got a unit exception */
|
||||
dstat &= ~0x01; /* we can ignore it */
|
||||
}
|
||||
@ -390,7 +383,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
break;
|
||||
/* Attention interrupt, someone hit the enter key */
|
||||
raw3215_mk_read_req(raw);
|
||||
tasklet_schedule(&raw->tasklet);
|
||||
raw3215_next_io(raw);
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x0C:
|
||||
@ -448,7 +441,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
raw->queued_read == NULL) {
|
||||
wake_up_interruptible(&raw->empty_wait);
|
||||
}
|
||||
tasklet_schedule(&raw->tasklet);
|
||||
raw3215_next_io(raw);
|
||||
break;
|
||||
default:
|
||||
/* Strange interrupt, I'll do my best to clean up */
|
||||
@ -460,7 +453,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
raw->flags &= ~RAW3215_WORKING;
|
||||
raw3215_free_req(req);
|
||||
}
|
||||
tasklet_schedule(&raw->tasklet);
|
||||
raw3215_next_io(raw);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -674,9 +667,6 @@ raw3215_probe (struct ccw_device *cdev)
|
||||
kfree(raw);
|
||||
return -ENOMEM;
|
||||
}
|
||||
tasklet_init(&raw->tasklet,
|
||||
(void (*)(unsigned long)) raw3215_tasklet,
|
||||
(unsigned long) raw);
|
||||
init_waitqueue_head(&raw->empty_wait);
|
||||
|
||||
cdev->dev.driver_data = raw;
|
||||
@ -775,11 +765,11 @@ static struct tty_driver *con3215_device(struct console *c, int *index)
|
||||
}
|
||||
|
||||
/*
|
||||
* panic() calls console_unblank before the system enters a
|
||||
* disabled, endless loop.
|
||||
* panic() calls con3215_flush through a panic_notifier
|
||||
* before the system enters a disabled, endless loop.
|
||||
*/
|
||||
static void
|
||||
con3215_unblank(void)
|
||||
con3215_flush(void)
|
||||
{
|
||||
struct raw3215_info *raw;
|
||||
unsigned long flags;
|
||||
@ -790,6 +780,23 @@ con3215_unblank(void)
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
static int con3215_notify(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
con3215_flush();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block on_panic_nb = {
|
||||
.notifier_call = con3215_notify,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static struct notifier_block on_reboot_nb = {
|
||||
.notifier_call = con3215_notify,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* The console structure for the 3215 console
|
||||
*/
|
||||
@ -797,7 +804,6 @@ static struct console con3215 = {
|
||||
.name = "ttyS",
|
||||
.write = con3215_write,
|
||||
.device = con3215_device,
|
||||
.unblank = con3215_unblank,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
};
|
||||
|
||||
@ -846,9 +852,6 @@ con3215_init(void)
|
||||
cdev->handler = raw3215_irq;
|
||||
|
||||
raw->flags |= RAW3215_FIXED;
|
||||
tasklet_init(&raw->tasklet,
|
||||
(void (*)(unsigned long)) raw3215_tasklet,
|
||||
(unsigned long) raw);
|
||||
init_waitqueue_head(&raw->empty_wait);
|
||||
|
||||
/* Request the console irq */
|
||||
@ -859,6 +862,8 @@ con3215_init(void)
|
||||
raw3215[0] = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
|
||||
register_reboot_notifier(&on_reboot_nb);
|
||||
register_console(&con3215);
|
||||
return 0;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/cio.h>
|
||||
@ -528,11 +529,11 @@ con3270_wait_write(struct con3270 *cp)
|
||||
}
|
||||
|
||||
/*
|
||||
* panic() calls console_unblank before the system enters a
|
||||
* disabled, endless loop.
|
||||
* panic() calls con3270_flush through a panic_notifier
|
||||
* before the system enters a disabled, endless loop.
|
||||
*/
|
||||
static void
|
||||
con3270_unblank(void)
|
||||
con3270_flush(void)
|
||||
{
|
||||
struct con3270 *cp;
|
||||
unsigned long flags;
|
||||
@ -554,6 +555,23 @@ con3270_unblank(void)
|
||||
spin_unlock_irqrestore(&cp->view.lock, flags);
|
||||
}
|
||||
|
||||
static int con3270_notify(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
con3270_flush();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block on_panic_nb = {
|
||||
.notifier_call = con3270_notify,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static struct notifier_block on_reboot_nb = {
|
||||
.notifier_call = con3270_notify,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* The console structure for the 3270 console
|
||||
*/
|
||||
@ -561,7 +579,6 @@ static struct console con3270 = {
|
||||
.name = "tty3270",
|
||||
.write = con3270_write,
|
||||
.device = con3270_device,
|
||||
.unblank = con3270_unblank,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
};
|
||||
|
||||
@ -623,6 +640,8 @@ con3270_init(void)
|
||||
condev->cline->len = 0;
|
||||
con3270_create_status(condev);
|
||||
condev->input = alloc_string(&condev->freemem, 80);
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
|
||||
register_reboot_notifier(&on_reboot_nb);
|
||||
register_console(&con3270);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1171,7 +1171,7 @@ static int raw3270_create_attributes(struct raw3270 *rp)
|
||||
rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
|
||||
MKDEV(IBM_TTY3270_MAJOR, rp->minor),
|
||||
NULL,
|
||||
"tty%s", rp->cdev->dev.bus_id);
|
||||
"tty%s", dev_name(&rp->cdev->dev));
|
||||
if (IS_ERR(rp->clttydev)) {
|
||||
rc = PTR_ERR(rp->clttydev);
|
||||
goto out_ttydev;
|
||||
@ -1180,7 +1180,7 @@ static int raw3270_create_attributes(struct raw3270 *rp)
|
||||
rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
|
||||
MKDEV(IBM_FS3270_MAJOR, rp->minor),
|
||||
NULL,
|
||||
"tub%s", rp->cdev->dev.bus_id);
|
||||
"tub%s", dev_name(&rp->cdev->dev));
|
||||
if (!IS_ERR(rp->cltubdev))
|
||||
goto out;
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "sclp.h"
|
||||
#include "sclp_rw.h"
|
||||
@ -172,7 +173,7 @@ sclp_console_device(struct console *c, int *index)
|
||||
* will be flushed to the SCLP.
|
||||
*/
|
||||
static void
|
||||
sclp_console_unblank(void)
|
||||
sclp_console_flush(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -188,6 +189,24 @@ sclp_console_unblank(void)
|
||||
spin_unlock_irqrestore(&sclp_con_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
sclp_console_notify(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
sclp_console_flush();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block on_panic_nb = {
|
||||
.notifier_call = sclp_console_notify,
|
||||
.priority = 1,
|
||||
};
|
||||
|
||||
static struct notifier_block on_reboot_nb = {
|
||||
.notifier_call = sclp_console_notify,
|
||||
.priority = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* used to register the SCLP console to the kernel and to
|
||||
* give printk necessary information
|
||||
@ -197,7 +216,6 @@ static struct console sclp_console =
|
||||
.name = sclp_console_name,
|
||||
.write = sclp_console_write,
|
||||
.device = sclp_console_device,
|
||||
.unblank = sclp_console_unblank,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = 0 /* ttyS0 */
|
||||
};
|
||||
@ -241,6 +259,8 @@ sclp_console_init(void)
|
||||
sclp_con_width_htab = 8;
|
||||
|
||||
/* enable printk-access to this driver */
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
|
||||
register_reboot_notifier(&on_reboot_nb);
|
||||
register_console(&sclp_console);
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include "sclp.h"
|
||||
|
||||
@ -743,24 +745,30 @@ sclp_vt220_con_device(struct console *c, int *index)
|
||||
return sclp_vt220_driver;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called from panic when the kernel is going to give up.
|
||||
* We have to make sure that all buffers will be flushed to the SCLP.
|
||||
* Note that this function may be called from within an interrupt context.
|
||||
*/
|
||||
static void
|
||||
sclp_vt220_con_unblank(void)
|
||||
static int
|
||||
sclp_vt220_notify(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
__sclp_vt220_flush_buffer();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block on_panic_nb = {
|
||||
.notifier_call = sclp_vt220_notify,
|
||||
.priority = 1,
|
||||
};
|
||||
|
||||
static struct notifier_block on_reboot_nb = {
|
||||
.notifier_call = sclp_vt220_notify,
|
||||
.priority = 1,
|
||||
};
|
||||
|
||||
/* Structure needed to register with printk */
|
||||
static struct console sclp_vt220_console =
|
||||
{
|
||||
.name = SCLP_VT220_CONSOLE_NAME,
|
||||
.write = sclp_vt220_con_write,
|
||||
.device = sclp_vt220_con_device,
|
||||
.unblank = sclp_vt220_con_unblank,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = SCLP_VT220_CONSOLE_INDEX
|
||||
};
|
||||
@ -776,6 +784,8 @@ sclp_vt220_con_init(void)
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Attach linux console */
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
|
||||
register_reboot_notifier(&on_reboot_nb);
|
||||
register_console(&sclp_vt220_console);
|
||||
return 0;
|
||||
}
|
||||
|
@ -910,7 +910,7 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request,
|
||||
* should proceed with the new tape... this
|
||||
* should probably be done in user space!
|
||||
*/
|
||||
PRINT_WARN("(%s): Swap Tape Device!\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev));
|
||||
return tape_3590_erp_basic(device, request, irb, -EIO);
|
||||
}
|
||||
|
||||
@ -1003,40 +1003,43 @@ tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb)
|
||||
/* Exception Message */
|
||||
switch (sense->fmt.f70.emc) {
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): Data degraded\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("(%s): Data degraded\n",
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x03:
|
||||
PRINT_WARN("(%s): Data degraded in partion %i\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.mp);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.mp);
|
||||
break;
|
||||
case 0x04:
|
||||
PRINT_WARN("(%s): Medium degraded\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("(%s): Medium degraded\n",
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x05:
|
||||
PRINT_WARN("(%s): Medium degraded in partition %i\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.mp);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.mp);
|
||||
break;
|
||||
case 0x06:
|
||||
PRINT_WARN("(%s): Block 0 Error\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("(%s): Block 0 Error\n",
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x07:
|
||||
PRINT_WARN("(%s): Medium Exception 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.md);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.md);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.emc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.emc);
|
||||
break;
|
||||
}
|
||||
/* Service Message */
|
||||
switch (sense->fmt.f70.smc) {
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): Reference Media maintenance procedure %i\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.md);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.md);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f70.smc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f70.smc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1054,101 +1057,101 @@ tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb)
|
||||
switch (sense->fmt.f71.emc) {
|
||||
case 0x01:
|
||||
PRINT_WARN("(%s): Effect of failure is unknown\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): CU Exception - no performance impact\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x03:
|
||||
PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x04:
|
||||
PRINT_WARN("(%s): CU Exception on device path 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x05:
|
||||
PRINT_WARN("(%s): CU Exception on library path 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x06:
|
||||
PRINT_WARN("(%s): CU Exception on node 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x07:
|
||||
PRINT_WARN("(%s): CU Exception on partition 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.emc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.emc);
|
||||
}
|
||||
/* Service Message */
|
||||
switch (sense->fmt.f71.smc) {
|
||||
case 0x01:
|
||||
PRINT_WARN("(%s): Repair impact is unknown\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): Repair will not impact cu performance\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x03:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable node "
|
||||
"0x%x on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable nodes "
|
||||
"(0x%x-0x%x) on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x04:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable cannel path "
|
||||
"0x%x on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable cannel paths "
|
||||
"(0x%x-0x%x) on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x05:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable device path "
|
||||
"0x%x on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable device paths "
|
||||
"(0x%x-0x%x) on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x06:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable library path "
|
||||
"0x%x on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable library paths "
|
||||
"(0x%x-0x%x) on CU\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x07:
|
||||
PRINT_WARN("(%s): Repair will disable access to CU\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.smc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.smc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1165,104 +1168,104 @@ tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb)
|
||||
switch (sense->fmt.f71.emc) {
|
||||
case 0x01:
|
||||
PRINT_WARN("(%s): Effect of failure is unknown\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): DV Exception - no performance impact\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x03:
|
||||
PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x04:
|
||||
PRINT_WARN("(%s): DV Exception on loader 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x05:
|
||||
PRINT_WARN("(%s): DV Exception on message display 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
|
||||
break;
|
||||
case 0x06:
|
||||
PRINT_WARN("(%s): DV Exception in tape path\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x07:
|
||||
PRINT_WARN("(%s): DV Exception in drive\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.emc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.emc);
|
||||
}
|
||||
/* Service Message */
|
||||
switch (sense->fmt.f71.smc) {
|
||||
case 0x01:
|
||||
PRINT_WARN("(%s): Repair impact is unknown\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x02:
|
||||
PRINT_WARN("(%s): Repair will not impact device performance\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x03:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable channel path "
|
||||
"0x%x on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable channel path "
|
||||
"(0x%x-0x%x) on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x04:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable interface 0x%x "
|
||||
"on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable interfaces "
|
||||
"(0x%x-0x%x) on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x05:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable loader 0x%x "
|
||||
"on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable loader "
|
||||
"(0x%x-0x%x) on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x07:
|
||||
PRINT_WARN("(%s): Repair will disable access to DV\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case 0x08:
|
||||
if (sense->fmt.f71.mdf == 0)
|
||||
PRINT_WARN("(%s): Repair will disable message "
|
||||
"display 0x%x on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1]);
|
||||
else
|
||||
PRINT_WARN("(%s): Repair will disable message "
|
||||
"displays (0x%x-0x%x) on DV\n",
|
||||
device->cdev->dev.bus_id,
|
||||
dev_name(&device->cdev->dev),
|
||||
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
|
||||
break;
|
||||
case 0x09:
|
||||
PRINT_WARN("(%s): Clean DV\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev));
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.smc);
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.smc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1279,18 +1282,18 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
|
||||
return;
|
||||
if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) {
|
||||
if (tape_3590_msg[sense->mc] != NULL)
|
||||
PRINT_WARN("(%s): %s\n", device->cdev->dev.bus_id,
|
||||
PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev),
|
||||
tape_3590_msg[sense->mc]);
|
||||
else {
|
||||
PRINT_WARN("(%s): Message Code 0x%x\n",
|
||||
device->cdev->dev.bus_id, sense->mc);
|
||||
dev_name(&device->cdev->dev), sense->mc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (sense->mc == 0xf0) {
|
||||
/* Standard Media Information Message */
|
||||
PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, "
|
||||
"RC=%02x-%04x-%02x\n", device->cdev->dev.bus_id,
|
||||
"RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev),
|
||||
sense->fmt.f70.sev, sense->mc,
|
||||
sense->fmt.f70.emc, sense->fmt.f70.smc,
|
||||
sense->fmt.f70.refcode, sense->fmt.f70.mid,
|
||||
@ -1302,7 +1305,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
|
||||
/* Standard I/O Subsystem Service Information Message */
|
||||
PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, "
|
||||
"MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.sev,
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.sev,
|
||||
device->cdev->id.dev_model,
|
||||
sense->mc, sense->fmt.f71.emc,
|
||||
sense->fmt.f71.smc, sense->fmt.f71.refcode1,
|
||||
@ -1314,7 +1317,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
|
||||
/* Standard Device Service Information Message */
|
||||
PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, "
|
||||
"MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
|
||||
device->cdev->dev.bus_id, sense->fmt.f71.sev,
|
||||
dev_name(&device->cdev->dev), sense->fmt.f71.sev,
|
||||
device->cdev->id.dev_model,
|
||||
sense->mc, sense->fmt.f71.emc,
|
||||
sense->fmt.f71.smc, sense->fmt.f71.refcode1,
|
||||
@ -1327,7 +1330,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
|
||||
return;
|
||||
}
|
||||
PRINT_WARN("(%s): Device Message(%x)\n",
|
||||
device->cdev->dev.bus_id, sense->mc);
|
||||
dev_name(&device->cdev->dev), sense->mc);
|
||||
}
|
||||
|
||||
static int tape_3590_crypt_error(struct tape_device *device,
|
||||
@ -1336,10 +1339,11 @@ static int tape_3590_crypt_error(struct tape_device *device,
|
||||
u8 cu_rc, ekm_rc1;
|
||||
u16 ekm_rc2;
|
||||
u32 drv_rc;
|
||||
char *bus_id, *sense;
|
||||
const char *bus_id;
|
||||
char *sense;
|
||||
|
||||
sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;
|
||||
bus_id = device->cdev->dev.bus_id;
|
||||
bus_id = dev_name(&device->cdev->dev);
|
||||
cu_rc = sense[0];
|
||||
drv_rc = *((u32*) &sense[5]) & 0xffffff;
|
||||
ekm_rc1 = sense[9];
|
||||
@ -1440,7 +1444,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
|
||||
* "device intervention" is not very meaningfull
|
||||
*/
|
||||
PRINT_WARN("(%s): Tape operation when medium not loaded\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
tape_med_state_set(device, MS_UNLOADED);
|
||||
tape_3590_schedule_work(device, TO_CRYPT_OFF);
|
||||
return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
|
||||
@ -1487,18 +1491,18 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
|
||||
|
||||
case 0x6020:
|
||||
PRINT_WARN("(%s): Cartridge of wrong type ?\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE);
|
||||
|
||||
case 0x8011:
|
||||
PRINT_WARN("(%s): Another host has reserved the tape device\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
return tape_3590_erp_basic(device, request, irb, -EPERM);
|
||||
case 0x8013:
|
||||
PRINT_WARN("(%s): Another host has privileged access to the "
|
||||
"tape device\n", device->cdev->dev.bus_id);
|
||||
"tape device\n", dev_name(&device->cdev->dev));
|
||||
PRINT_WARN("(%s): To solve the problem unload the current "
|
||||
"cartridge!\n", device->cdev->dev.bus_id);
|
||||
"cartridge!\n", dev_name(&device->cdev->dev));
|
||||
return tape_3590_erp_basic(device, request, irb, -EPERM);
|
||||
default:
|
||||
return tape_3590_erp_basic(device, request, irb, -EIO);
|
||||
|
@ -278,7 +278,7 @@ tapeblock_cleanup_device(struct tape_device *device)
|
||||
|
||||
if (!device->blk_data.disk) {
|
||||
PRINT_ERR("(%s): No gendisk to clean up!\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
goto cleanup_queue;
|
||||
}
|
||||
|
||||
|
@ -215,12 +215,12 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
|
||||
case MS_UNLOADED:
|
||||
device->tape_generic_status |= GMT_DR_OPEN(~0);
|
||||
PRINT_INFO("(%s): Tape is unloaded\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
case MS_LOADED:
|
||||
device->tape_generic_status &= ~GMT_DR_OPEN(~0);
|
||||
PRINT_INFO("(%s): Tape has been mounted\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
break;
|
||||
default:
|
||||
// print nothing
|
||||
@ -415,7 +415,7 @@ tape_generic_offline(struct tape_device *device)
|
||||
device->cdev_id);
|
||||
PRINT_WARN("(%s): Set offline failed "
|
||||
"- drive in use.\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
spin_unlock_irq(get_ccwdev_lock(device->cdev));
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -538,7 +538,8 @@ tape_generic_probe(struct ccw_device *cdev)
|
||||
ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
|
||||
if (ret) {
|
||||
tape_put_device(device);
|
||||
PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id);
|
||||
PRINT_ERR("probe failed for tape device %s\n",
|
||||
dev_name(&cdev->dev));
|
||||
return ret;
|
||||
}
|
||||
cdev->dev.driver_data = device;
|
||||
@ -546,7 +547,7 @@ tape_generic_probe(struct ccw_device *cdev)
|
||||
device->cdev = cdev;
|
||||
ccw_device_get_id(cdev, &dev_id);
|
||||
device->cdev_id = devid_to_int(&dev_id);
|
||||
PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
|
||||
PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -616,7 +617,7 @@ tape_generic_remove(struct ccw_device *cdev)
|
||||
device->cdev_id);
|
||||
PRINT_WARN("(%s): Drive in use vanished - "
|
||||
"expect trouble!\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
PRINT_WARN("State was %i\n", device->tape_state);
|
||||
tape_state_set(device, TS_NOT_OPER);
|
||||
__tape_discard_requests(device);
|
||||
@ -840,7 +841,7 @@ tape_dump_sense(struct tape_device* device, struct tape_request *request,
|
||||
PRINT_INFO("-------------------------------------------------\n");
|
||||
PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n",
|
||||
irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa);
|
||||
PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id);
|
||||
PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev));
|
||||
if (request != NULL)
|
||||
PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]);
|
||||
|
||||
@ -1051,7 +1052,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
device = (struct tape_device *) cdev->dev.driver_data;
|
||||
if (device == NULL) {
|
||||
PRINT_ERR("could not get device structure for %s "
|
||||
"in interrupt\n", cdev->dev.bus_id);
|
||||
"in interrupt\n", dev_name(&cdev->dev));
|
||||
return;
|
||||
}
|
||||
request = (struct tape_request *) intparm;
|
||||
@ -1064,13 +1065,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
switch (PTR_ERR(irb)) {
|
||||
case -ETIMEDOUT:
|
||||
PRINT_WARN("(%s): Request timed out\n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
case -EIO:
|
||||
__tape_end_request(device, request, -EIO);
|
||||
break;
|
||||
default:
|
||||
PRINT_ERR("(%s): Unexpected i/o error %li\n",
|
||||
cdev->dev.bus_id,
|
||||
dev_name(&cdev->dev),
|
||||
PTR_ERR(irb));
|
||||
}
|
||||
return;
|
||||
|
@ -52,7 +52,7 @@ static int tape_proc_show(struct seq_file *m, void *v)
|
||||
return 0;
|
||||
spin_lock_irq(get_ccwdev_lock(device->cdev));
|
||||
seq_printf(m, "%d\t", (int) n);
|
||||
seq_printf(m, "%-10.10s ", device->cdev->dev.bus_id);
|
||||
seq_printf(m, "%-10.10s ", dev_name(&device->cdev->dev));
|
||||
seq_printf(m, "%04X/", device->cdev->id.cu_type);
|
||||
seq_printf(m, "%02X\t", device->cdev->id.cu_model);
|
||||
seq_printf(m, "%04X/", device->cdev->id.dev_type);
|
||||
|
@ -47,7 +47,7 @@ tape_std_assign_timeout(unsigned long data)
|
||||
rc = tape_cancel_io(device, request);
|
||||
if(rc)
|
||||
PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n",
|
||||
device->cdev->dev.bus_id, rc);
|
||||
dev_name(&device->cdev->dev), rc);
|
||||
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ tape_std_assign(struct tape_device *device)
|
||||
|
||||
if (rc != 0) {
|
||||
PRINT_WARN("%s: assign failed - device might be busy\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
|
||||
device->cdev_id);
|
||||
} else {
|
||||
@ -106,7 +106,7 @@ tape_std_unassign (struct tape_device *device)
|
||||
DBF_EVENT(3, "(%08x): Can't unassign device\n",
|
||||
device->cdev_id);
|
||||
PRINT_WARN("(%s): Can't unassign device - device gone\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -120,7 +120,8 @@ tape_std_unassign (struct tape_device *device)
|
||||
|
||||
if ((rc = tape_do_io(device, request)) != 0) {
|
||||
DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);
|
||||
PRINT_WARN("%s: Unassign failed\n", device->cdev->dev.bus_id);
|
||||
PRINT_WARN("%s: Unassign failed\n",
|
||||
dev_name(&device->cdev->dev));
|
||||
} else {
|
||||
DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);
|
||||
}
|
||||
@ -634,10 +635,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count)
|
||||
DBF_EXCEPTION(6, "xcom parm\n");
|
||||
if (*device->modeset_byte & 0x08)
|
||||
PRINT_INFO("(%s) Compression is currently on\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
else
|
||||
PRINT_INFO("(%s) Compression is currently off\n",
|
||||
device->cdev->dev.bus_id);
|
||||
dev_name(&device->cdev->dev));
|
||||
PRINT_INFO("Use 1 to switch compression on, 0 to "
|
||||
"switch it off\n");
|
||||
return -EINVAL;
|
||||
|
@ -724,8 +724,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
|
||||
|
||||
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||
if (dev) {
|
||||
snprintf(dev->bus_id, BUS_ID_SIZE, "%s",
|
||||
priv->internal_name);
|
||||
dev_set_name(dev, priv->internal_name);
|
||||
dev->bus = &iucv_bus;
|
||||
dev->parent = iucv_root;
|
||||
dev->driver = &vmlogrdr_driver;
|
||||
@ -751,7 +750,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
|
||||
priv->class_device = device_create_drvdata(vmlogrdr_class, dev,
|
||||
MKDEV(vmlogrdr_major,
|
||||
priv->minor_num),
|
||||
priv, "%s", dev->bus_id);
|
||||
priv, "%s", dev_name(dev));
|
||||
if (IS_ERR(priv->class_device)) {
|
||||
ret = PTR_ERR(priv->class_device);
|
||||
priv->class_device=NULL;
|
||||
|
@ -886,11 +886,11 @@ static int ur_set_online(struct ccw_device *cdev)
|
||||
goto fail_free_cdev;
|
||||
if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) {
|
||||
if (urd->class == DEV_CLASS_UR_I)
|
||||
sprintf(node_id, "vmrdr-%s", cdev->dev.bus_id);
|
||||
sprintf(node_id, "vmrdr-%s", dev_name(&cdev->dev));
|
||||
if (urd->class == DEV_CLASS_UR_O)
|
||||
sprintf(node_id, "vmpun-%s", cdev->dev.bus_id);
|
||||
sprintf(node_id, "vmpun-%s", dev_name(&cdev->dev));
|
||||
} else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) {
|
||||
sprintf(node_id, "vmprt-%s", cdev->dev.bus_id);
|
||||
sprintf(node_id, "vmprt-%s", dev_name(&cdev->dev));
|
||||
} else {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto fail_free_cdev;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "cio.h"
|
||||
#include "cio_debug.h"
|
||||
#include "css.h"
|
||||
#include "device.h"
|
||||
|
||||
/*
|
||||
* "Blacklisting" of certain devices:
|
||||
@ -191,9 +192,9 @@ static int blacklist_parse_parameters(char *str, range_action action,
|
||||
rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
|
||||
msgtrigger);
|
||||
if (rc)
|
||||
totalrc = 1;
|
||||
totalrc = -EINVAL;
|
||||
} else
|
||||
totalrc = 1;
|
||||
totalrc = -EINVAL;
|
||||
}
|
||||
|
||||
return totalrc;
|
||||
@ -240,8 +241,10 @@ static int blacklist_parse_proc_parameters(char *buf)
|
||||
rc = blacklist_parse_parameters(buf, free, 0);
|
||||
else if (strcmp("add", parm) == 0)
|
||||
rc = blacklist_parse_parameters(buf, add, 0);
|
||||
else if (strcmp("purge", parm) == 0)
|
||||
return ccw_purge_blacklisted();
|
||||
else
|
||||
return 1;
|
||||
return -EINVAL;
|
||||
|
||||
css_schedule_reprobe();
|
||||
|
||||
@ -353,7 +356,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
|
||||
}
|
||||
ret = blacklist_parse_proc_parameters(buf);
|
||||
if (ret)
|
||||
rc = -EINVAL;
|
||||
rc = ret;
|
||||
else
|
||||
rc = user_len;
|
||||
|
||||
|
@ -269,8 +269,7 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
|
||||
goto error;
|
||||
}
|
||||
|
||||
snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
|
||||
gdev->cdev[0]->dev.bus_id);
|
||||
dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
|
||||
|
||||
rc = device_add(&gdev->dev);
|
||||
if (rc)
|
||||
|
@ -393,8 +393,7 @@ int chp_new(struct chp_id chpid)
|
||||
chp->state = 1;
|
||||
chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
|
||||
chp->dev.release = chp_release;
|
||||
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid,
|
||||
chpid.id);
|
||||
dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
|
||||
|
||||
/* Obtain channel path description and fill it in. */
|
||||
ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
|
||||
|
@ -261,7 +261,7 @@ static int chsc_examine_irb(struct chsc_request *request)
|
||||
{
|
||||
int backed_up;
|
||||
|
||||
if (!scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND)
|
||||
if (!(scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND))
|
||||
return -EIO;
|
||||
backed_up = scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHAIN_CHECK;
|
||||
request->irb.scsw.cmd.cstat &= ~SCHN_STAT_CHAIN_CHECK;
|
||||
|
@ -114,6 +114,7 @@ cio_tpi(void)
|
||||
struct tpi_info *tpi_info;
|
||||
struct subchannel *sch;
|
||||
struct irb *irb;
|
||||
int irq_context;
|
||||
|
||||
tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
|
||||
if (tpi (NULL) != 1)
|
||||
@ -126,7 +127,9 @@ cio_tpi(void)
|
||||
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
|
||||
if (!sch)
|
||||
return 1;
|
||||
local_bh_disable();
|
||||
irq_context = in_interrupt();
|
||||
if (!irq_context)
|
||||
local_bh_disable();
|
||||
irq_enter ();
|
||||
spin_lock(sch->lock);
|
||||
memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
|
||||
@ -134,7 +137,8 @@ cio_tpi(void)
|
||||
sch->driver->irq(sch);
|
||||
spin_unlock(sch->lock);
|
||||
irq_exit ();
|
||||
_local_bh_enable();
|
||||
if (!irq_context)
|
||||
_local_bh_enable();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -153,7 +157,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
|
||||
CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
|
||||
"subchannel 0.%x.%04x!\n", sch->schid.ssid,
|
||||
sch->schid.sch_no);
|
||||
sprintf(dbf_text, "no%s", sch->dev.bus_id);
|
||||
sprintf(dbf_text, "no%s", dev_name(&sch->dev));
|
||||
CIO_TRACE_EVENT(0, dbf_text);
|
||||
CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
|
||||
|
||||
@ -171,7 +175,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
|
||||
union orb *orb;
|
||||
|
||||
CIO_TRACE_EVENT(4, "stIO");
|
||||
CIO_TRACE_EVENT(4, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(4, dev_name(&sch->dev));
|
||||
|
||||
orb = &to_io_private(sch)->orb;
|
||||
memset(orb, 0, sizeof(union orb));
|
||||
@ -232,7 +236,7 @@ cio_resume (struct subchannel *sch)
|
||||
int ccode;
|
||||
|
||||
CIO_TRACE_EVENT (4, "resIO");
|
||||
CIO_TRACE_EVENT (4, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(4, dev_name(&sch->dev));
|
||||
|
||||
ccode = rsch (sch->schid);
|
||||
|
||||
@ -269,7 +273,7 @@ cio_halt(struct subchannel *sch)
|
||||
return -ENODEV;
|
||||
|
||||
CIO_TRACE_EVENT (2, "haltIO");
|
||||
CIO_TRACE_EVENT (2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
|
||||
/*
|
||||
* Issue "Halt subchannel" and process condition code
|
||||
@ -304,7 +308,7 @@ cio_clear(struct subchannel *sch)
|
||||
return -ENODEV;
|
||||
|
||||
CIO_TRACE_EVENT (2, "clearIO");
|
||||
CIO_TRACE_EVENT (2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
|
||||
/*
|
||||
* Issue "Clear subchannel" and process condition code
|
||||
@ -340,7 +344,7 @@ cio_cancel (struct subchannel *sch)
|
||||
return -ENODEV;
|
||||
|
||||
CIO_TRACE_EVENT (2, "cancelIO");
|
||||
CIO_TRACE_EVENT (2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
|
||||
ccode = xsch (sch->schid);
|
||||
|
||||
@ -404,7 +408,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
|
||||
int ret;
|
||||
|
||||
CIO_TRACE_EVENT (2, "ensch");
|
||||
CIO_TRACE_EVENT (2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
|
||||
if (sch_is_pseudo_sch(sch))
|
||||
return -EINVAL;
|
||||
@ -454,7 +458,7 @@ int cio_disable_subchannel(struct subchannel *sch)
|
||||
int ret;
|
||||
|
||||
CIO_TRACE_EVENT (2, "dissch");
|
||||
CIO_TRACE_EVENT (2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
|
||||
if (sch_is_pseudo_sch(sch))
|
||||
return 0;
|
||||
@ -571,8 +575,10 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
|
||||
}
|
||||
mutex_init(&sch->reg_mutex);
|
||||
/* Set a name for the subchannel */
|
||||
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
|
||||
schid.sch_no);
|
||||
if (cio_is_console(schid))
|
||||
sch->dev.init_name = cio_get_console_sch_name(schid);
|
||||
else
|
||||
dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no);
|
||||
|
||||
/*
|
||||
* The first subchannel that is not-operational (ccode==3)
|
||||
@ -677,6 +683,7 @@ do_IRQ (struct pt_regs *regs)
|
||||
|
||||
#ifdef CONFIG_CCW_CONSOLE
|
||||
static struct subchannel console_subchannel;
|
||||
static char console_sch_name[10] = "0.x.xxxx";
|
||||
static struct io_subchannel_private console_priv;
|
||||
static int console_subchannel_in_use;
|
||||
|
||||
@ -827,6 +834,12 @@ cio_get_console_subchannel(void)
|
||||
return &console_subchannel;
|
||||
}
|
||||
|
||||
const char *cio_get_console_sch_name(struct subchannel_id schid)
|
||||
{
|
||||
snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no);
|
||||
return (const char *)console_sch_name;
|
||||
}
|
||||
|
||||
#endif
|
||||
static int
|
||||
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
|
||||
@ -846,19 +859,6 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
|
||||
return -EBUSY; /* uhm... */
|
||||
}
|
||||
|
||||
/* we can't use the normal udelay here, since it enables external interrupts */
|
||||
|
||||
static void udelay_reset(unsigned long usecs)
|
||||
{
|
||||
uint64_t start_cc, end_cc;
|
||||
|
||||
asm volatile ("STCK %0" : "=m" (start_cc));
|
||||
do {
|
||||
cpu_relax();
|
||||
asm volatile ("STCK %0" : "=m" (end_cc));
|
||||
} while (((end_cc - start_cc)/4096) < usecs);
|
||||
}
|
||||
|
||||
static int
|
||||
__clear_io_subchannel_easy(struct subchannel_id schid)
|
||||
{
|
||||
@ -874,7 +874,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
|
||||
if (schid_equal(&ti.schid, &schid))
|
||||
return 0;
|
||||
}
|
||||
udelay_reset(100);
|
||||
udelay_simple(100);
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -882,7 +882,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
|
||||
static void __clear_chsc_subchannel_easy(void)
|
||||
{
|
||||
/* It seems we can only wait for a bit here :/ */
|
||||
udelay_reset(100);
|
||||
udelay_simple(100);
|
||||
}
|
||||
|
||||
static int pgm_check_occured;
|
||||
@ -892,7 +892,7 @@ static void cio_reset_pgm_check_handler(void)
|
||||
pgm_check_occured = 1;
|
||||
}
|
||||
|
||||
static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
|
||||
static int stsch_reset(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -117,11 +117,15 @@ extern int cio_is_console(struct subchannel_id);
|
||||
extern struct subchannel *cio_get_console_subchannel(void);
|
||||
extern spinlock_t * cio_get_console_lock(void);
|
||||
extern void *cio_get_console_priv(void);
|
||||
extern const char *cio_get_console_sch_name(struct subchannel_id schid);
|
||||
extern const char *cio_get_console_cdev_name(struct subchannel *sch);
|
||||
#else
|
||||
#define cio_is_console(schid) 0
|
||||
#define cio_get_console_subchannel() NULL
|
||||
#define cio_get_console_lock() NULL
|
||||
#define cio_get_console_priv() NULL
|
||||
#define cio_get_console_sch_name(schid) NULL
|
||||
#define cio_get_console_cdev_name(sch) NULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -698,7 +698,7 @@ static int __init setup_css(int nr)
|
||||
return -ENOMEM;
|
||||
css->pseudo_subchannel->dev.parent = &css->device;
|
||||
css->pseudo_subchannel->dev.release = css_subchannel_release;
|
||||
sprintf(css->pseudo_subchannel->dev.bus_id, "defunct");
|
||||
dev_set_name(&css->pseudo_subchannel->dev, "defunct");
|
||||
ret = cio_create_sch_lock(css->pseudo_subchannel);
|
||||
if (ret) {
|
||||
kfree(css->pseudo_subchannel);
|
||||
@ -707,7 +707,7 @@ static int __init setup_css(int nr)
|
||||
mutex_init(&css->mutex);
|
||||
css->valid = 1;
|
||||
css->cssid = nr;
|
||||
sprintf(css->device.bus_id, "css%x", nr);
|
||||
dev_set_name(&css->device, "css%x", nr);
|
||||
css->device.release = channel_subsystem_release;
|
||||
tod_high = (u32) (get_clock() >> 32);
|
||||
css_generate_pgid(css, tod_high);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "device.h"
|
||||
#include "ioasm.h"
|
||||
#include "io_sch.h"
|
||||
#include "blacklist.h"
|
||||
|
||||
static struct timer_list recovery_timer;
|
||||
static DEFINE_SPINLOCK(recovery_lock);
|
||||
@ -296,36 +297,33 @@ static void ccw_device_unregister(struct ccw_device *cdev)
|
||||
device_del(&cdev->dev);
|
||||
}
|
||||
|
||||
static void ccw_device_remove_orphan_cb(struct device *dev)
|
||||
static void ccw_device_remove_orphan_cb(struct work_struct *work)
|
||||
{
|
||||
struct ccw_device *cdev = to_ccwdev(dev);
|
||||
struct ccw_device_private *priv;
|
||||
struct ccw_device *cdev;
|
||||
|
||||
priv = container_of(work, struct ccw_device_private, kick_work);
|
||||
cdev = priv->cdev;
|
||||
ccw_device_unregister(cdev);
|
||||
put_device(&cdev->dev);
|
||||
/* Release cdev reference for workqueue processing. */
|
||||
put_device(&cdev->dev);
|
||||
}
|
||||
|
||||
static void ccw_device_remove_sch_cb(struct device *dev)
|
||||
{
|
||||
struct subchannel *sch;
|
||||
|
||||
sch = to_subchannel(dev);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
put_device(&sch->dev);
|
||||
}
|
||||
static void ccw_device_call_sch_unregister(struct work_struct *work);
|
||||
|
||||
static void
|
||||
ccw_device_remove_disconnected(struct ccw_device *cdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Forced offline in disconnected state means
|
||||
* 'throw away device'.
|
||||
*/
|
||||
/* Get cdev reference for workqueue processing. */
|
||||
if (!get_device(&cdev->dev))
|
||||
return;
|
||||
if (ccw_device_is_orphan(cdev)) {
|
||||
/*
|
||||
* Deregister ccw device.
|
||||
@ -335,23 +333,13 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
|
||||
spin_lock_irqsave(cdev->ccwlock, flags);
|
||||
cdev->private->state = DEV_STATE_NOT_OPER;
|
||||
spin_unlock_irqrestore(cdev->ccwlock, flags);
|
||||
rc = device_schedule_callback(&cdev->dev,
|
||||
ccw_device_remove_orphan_cb);
|
||||
if (rc)
|
||||
CIO_MSG_EVENT(0, "Couldn't unregister orphan "
|
||||
"0.%x.%04x\n",
|
||||
cdev->private->dev_id.ssid,
|
||||
cdev->private->dev_id.devno);
|
||||
return;
|
||||
}
|
||||
/* Deregister subchannel, which will kill the ccw device. */
|
||||
rc = device_schedule_callback(cdev->dev.parent,
|
||||
ccw_device_remove_sch_cb);
|
||||
if (rc)
|
||||
CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
|
||||
"0.%x.%04x\n",
|
||||
cdev->private->dev_id.ssid,
|
||||
cdev->private->dev_id.devno);
|
||||
PREPARE_WORK(&cdev->private->kick_work,
|
||||
ccw_device_remove_orphan_cb);
|
||||
} else
|
||||
/* Deregister subchannel, which will kill the ccw device. */
|
||||
PREPARE_WORK(&cdev->private->kick_work,
|
||||
ccw_device_call_sch_unregister);
|
||||
queue_work(slow_path_wq, &cdev->private->kick_work);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -970,12 +958,17 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
|
||||
|
||||
priv = container_of(work, struct ccw_device_private, kick_work);
|
||||
cdev = priv->cdev;
|
||||
/* Get subchannel reference for local processing. */
|
||||
if (!get_device(cdev->dev.parent))
|
||||
return;
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
css_sch_device_unregister(sch);
|
||||
/* Reset intparm to zeroes. */
|
||||
sch->schib.pmcw.intparm = 0;
|
||||
cio_modify(sch);
|
||||
/* Release cdev reference for workqueue processing.*/
|
||||
put_device(&cdev->dev);
|
||||
/* Release subchannel reference for local processing. */
|
||||
put_device(&sch->dev);
|
||||
}
|
||||
|
||||
@ -1001,6 +994,8 @@ io_subchannel_recog_done(struct ccw_device *cdev)
|
||||
PREPARE_WORK(&cdev->private->kick_work,
|
||||
ccw_device_call_sch_unregister);
|
||||
queue_work(slow_path_wq, &cdev->private->kick_work);
|
||||
/* Release subchannel reference for asynchronous recognition. */
|
||||
put_device(&sch->dev);
|
||||
if (atomic_dec_and_test(&ccw_device_init_count))
|
||||
wake_up(&ccw_device_init_wq);
|
||||
break;
|
||||
@ -1040,8 +1035,11 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
|
||||
init_timer(&priv->timer);
|
||||
|
||||
/* Set an initial name for the device. */
|
||||
snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
|
||||
sch->schid.ssid, sch->schib.pmcw.dev);
|
||||
if (cio_is_console(sch->schid))
|
||||
cdev->dev.init_name = cio_get_console_cdev_name(sch);
|
||||
else
|
||||
dev_set_name(&cdev->dev, "0.%x.%04x",
|
||||
sch->schid.ssid, sch->schib.pmcw.dev);
|
||||
|
||||
/* Increase counter of devices currently in recognition. */
|
||||
atomic_inc(&ccw_device_init_count);
|
||||
@ -1106,7 +1104,7 @@ static void io_subchannel_irq(struct subchannel *sch)
|
||||
cdev = sch_get_cdev(sch);
|
||||
|
||||
CIO_TRACE_EVENT(3, "IRQ");
|
||||
CIO_TRACE_EVENT(3, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(3, dev_name(&sch->dev));
|
||||
if (cdev)
|
||||
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
|
||||
}
|
||||
@ -1476,6 +1474,45 @@ static void ccw_device_schedule_recovery(void)
|
||||
spin_unlock_irqrestore(&recovery_lock, flags);
|
||||
}
|
||||
|
||||
static int purge_fn(struct device *dev, void *data)
|
||||
{
|
||||
struct ccw_device *cdev = to_ccwdev(dev);
|
||||
struct ccw_device_private *priv = cdev->private;
|
||||
int unreg;
|
||||
|
||||
spin_lock_irq(cdev->ccwlock);
|
||||
unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) &&
|
||||
(priv->state == DEV_STATE_OFFLINE);
|
||||
spin_unlock_irq(cdev->ccwlock);
|
||||
if (!unreg)
|
||||
goto out;
|
||||
if (!get_device(&cdev->dev))
|
||||
goto out;
|
||||
CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
|
||||
priv->dev_id.devno);
|
||||
PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister);
|
||||
queue_work(slow_path_wq, &cdev->private->kick_work);
|
||||
|
||||
out:
|
||||
/* Abort loop in case of pending signal. */
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ccw_purge_blacklisted - purge unused, blacklisted devices
|
||||
*
|
||||
* Unregister all ccw devices that are offline and on the blacklist.
|
||||
*/
|
||||
int ccw_purge_blacklisted(void)
|
||||
{
|
||||
CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
|
||||
bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_set_disconnected(struct ccw_device *cdev)
|
||||
{
|
||||
if (!cdev)
|
||||
@ -1492,7 +1529,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
|
||||
struct subchannel *sch = to_subchannel(cdev->dev.parent);
|
||||
|
||||
CIO_TRACE_EVENT(2, "notoper");
|
||||
CIO_TRACE_EVENT(2, sch->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
|
||||
ccw_device_set_timeout(cdev, 0);
|
||||
cio_disable_subchannel(sch);
|
||||
cdev->private->state = DEV_STATE_NOT_OPER;
|
||||
@ -1591,6 +1628,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
|
||||
|
||||
#ifdef CONFIG_CCW_CONSOLE
|
||||
static struct ccw_device console_cdev;
|
||||
static char console_cdev_name[10] = "0.x.xxxx";
|
||||
static struct ccw_device_private console_private;
|
||||
static int console_cdev_in_use;
|
||||
|
||||
@ -1661,6 +1699,14 @@ ccw_device_probe_console(void)
|
||||
console_cdev.online = 1;
|
||||
return &console_cdev;
|
||||
}
|
||||
|
||||
|
||||
const char *cio_get_console_cdev_name(struct subchannel *sch)
|
||||
{
|
||||
snprintf(console_cdev_name, 10, "0.%x.%04x",
|
||||
sch->schid.ssid, sch->schib.pmcw.dev);
|
||||
return (const char *)console_cdev_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -1673,7 +1719,7 @@ __ccwdev_check_busid(struct device *dev, void *id)
|
||||
|
||||
bus_id = id;
|
||||
|
||||
return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
|
||||
return (strncmp(bus_id, dev_name(dev), BUS_ID_SIZE) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,6 +86,7 @@ int ccw_device_is_orphan(struct ccw_device *);
|
||||
int ccw_device_recognition(struct ccw_device *);
|
||||
int ccw_device_online(struct ccw_device *);
|
||||
int ccw_device_offline(struct ccw_device *);
|
||||
int ccw_purge_blacklisted(void);
|
||||
|
||||
/* Function prototypes for device status and basic sense stuff. */
|
||||
void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
|
||||
|
@ -52,8 +52,10 @@ static void ccw_timeout_log(struct ccw_device *cdev)
|
||||
printk(KERN_WARNING "cio: orb:\n");
|
||||
print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
orb, sizeof(*orb), 0);
|
||||
printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id);
|
||||
printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id);
|
||||
printk(KERN_WARNING "cio: ccw device bus id: %s\n",
|
||||
dev_name(&cdev->dev));
|
||||
printk(KERN_WARNING "cio: subchannel bus id: %s\n",
|
||||
dev_name(&sch->dev));
|
||||
printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, "
|
||||
"vpm: %02x\n", sch->lpm, sch->opm, sch->vpm);
|
||||
|
||||
|
@ -498,7 +498,7 @@ ccw_device_stlck(struct ccw_device *cdev)
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
|
||||
CIO_TRACE_EVENT(2, "stl lock");
|
||||
CIO_TRACE_EVENT(2, cdev->dev.bus_id);
|
||||
CIO_TRACE_EVENT(2, dev_name(&cdev->dev));
|
||||
|
||||
buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
|
||||
if (!buf)
|
||||
|
@ -123,7 +123,7 @@ struct ccw_device_private {
|
||||
void *cmb_wait; /* deferred cmb enable/disable */
|
||||
};
|
||||
|
||||
static inline int ssch(struct subchannel_id schid, volatile union orb *addr)
|
||||
static inline int ssch(struct subchannel_id schid, union orb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode = -EIO;
|
||||
@ -134,7 +134,9 @@ static inline int ssch(struct subchannel_id schid, volatile union orb *addr)
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc", "memory");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
@ -147,7 +149,9 @@ static inline int rsch(struct subchannel_id schid)
|
||||
" rsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc", "memory");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
@ -160,7 +164,9 @@ static inline int csch(struct subchannel_id schid)
|
||||
" csch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
@ -173,7 +179,9 @@ static inline int hsch(struct subchannel_id schid)
|
||||
" hsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
@ -186,7 +194,9 @@ static inline int xsch(struct subchannel_id schid)
|
||||
" .insn rre,0xb2760000,%1,0\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
|
@ -23,38 +23,39 @@ struct tpi_info {
|
||||
* Some S390 specific IO instructions as inline
|
||||
*/
|
||||
|
||||
static inline int stsch(struct subchannel_id schid,
|
||||
volatile struct schib *addr)
|
||||
static inline int stsch(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" stsch 0(%2)\n"
|
||||
" stsch 0(%3)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int stsch_err(struct subchannel_id schid,
|
||||
volatile struct schib *addr)
|
||||
static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" stsch 0(%2)\n"
|
||||
" stsch 0(%3)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "+d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int msch(struct subchannel_id schid,
|
||||
volatile struct schib *addr)
|
||||
static inline int msch(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
@ -63,12 +64,13 @@ static inline int msch(struct subchannel_id schid,
|
||||
" msch 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int msch_err(struct subchannel_id schid,
|
||||
volatile struct schib *addr)
|
||||
static inline int msch_err(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
@ -79,33 +81,38 @@ static inline int msch_err(struct subchannel_id schid,
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int tsch(struct subchannel_id schid,
|
||||
volatile struct irb *addr)
|
||||
static inline int tsch(struct subchannel_id schid, struct irb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tsch 0(%2)\n"
|
||||
" tsch 0(%3)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int tpi( volatile struct tpi_info *addr)
|
||||
static inline int tpi(struct tpi_info *addr)
|
||||
{
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tpi 0(%1)\n"
|
||||
" tpi 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "a" (addr), "m" (*addr) : "cc");
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,14 @@
|
||||
#define QDIO_BUSY_BIT_GIVE_UP 2000000 /* 2 seconds = eternity */
|
||||
#define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */
|
||||
|
||||
/*
|
||||
* if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
|
||||
* till next initiative to give transmitted skbs back to the stack is too long.
|
||||
* Therefore polling is started in case of multicast queue is filled more
|
||||
* than 50 percent.
|
||||
*/
|
||||
#define QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */
|
||||
|
||||
enum qdio_irq_states {
|
||||
QDIO_IRQ_STATE_INACTIVE,
|
||||
QDIO_IRQ_STATE_ESTABLISHED,
|
||||
@ -195,6 +203,9 @@ struct qdio_output_q {
|
||||
/* PCIs are enabled for the queue */
|
||||
int pci_out_enabled;
|
||||
|
||||
/* IQDIO: output multiple buffers (enhanced SIGA) */
|
||||
int use_enh_siga;
|
||||
|
||||
/* timer to check for more outbound work */
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
@ -155,7 +155,7 @@ static int qstat_seq_open(struct inode *inode, struct file *filp)
|
||||
static void get_queue_name(struct qdio_q *q, struct ccw_device *cdev, char *name)
|
||||
{
|
||||
memset(name, 0, sizeof(name));
|
||||
sprintf(name, "%s", cdev->dev.bus_id);
|
||||
sprintf(name, "%s", dev_name(&cdev->dev));
|
||||
if (q->is_input_q)
|
||||
sprintf(name + strlen(name), "_input");
|
||||
else
|
||||
|
@ -316,6 +316,9 @@ static inline int qdio_do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
|
||||
unsigned int fc = 0;
|
||||
unsigned long schid;
|
||||
|
||||
if (q->u.out.use_enh_siga) {
|
||||
fc = 3;
|
||||
}
|
||||
if (!is_qebsm(q))
|
||||
schid = *((u32 *)&q->irq_ptr->schid);
|
||||
else {
|
||||
@ -851,6 +854,12 @@ static void __qdio_outbound_processing(struct qdio_q *q)
|
||||
if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q))
|
||||
return;
|
||||
|
||||
if ((queue_type(q) == QDIO_IQDIO_QFMT) &&
|
||||
(atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) {
|
||||
tasklet_schedule(&q->tasklet);
|
||||
return;
|
||||
}
|
||||
|
||||
if (q->u.out.pci_out_enabled)
|
||||
return;
|
||||
|
||||
@ -956,7 +965,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
|
||||
char dbf_text[15];
|
||||
|
||||
QDIO_DBF_TEXT2(1, trace, "ick2");
|
||||
sprintf(dbf_text, "%s", cdev->dev.bus_id);
|
||||
sprintf(dbf_text, "%s", dev_name(&cdev->dev));
|
||||
QDIO_DBF_TEXT2(1, trace, dbf_text);
|
||||
QDIO_DBF_HEX2(0, trace, &intparm, sizeof(int));
|
||||
QDIO_DBF_HEX2(0, trace, &dstat, sizeof(int));
|
||||
@ -1443,6 +1452,8 @@ int qdio_establish(struct qdio_initialize *init_data)
|
||||
}
|
||||
|
||||
qdio_setup_ssqd_info(irq_ptr);
|
||||
sprintf(dbf_text, "qDmmwc%2x", irq_ptr->ssqd_desc.mmwc);
|
||||
QDIO_DBF_TEXT2(0, setup, dbf_text);
|
||||
sprintf(dbf_text, "qib ac%2x", irq_ptr->qib.ac);
|
||||
QDIO_DBF_TEXT2(0, setup, dbf_text);
|
||||
|
||||
@ -1615,12 +1626,21 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||
if (multicast_outbound(q))
|
||||
qdio_kick_outbound_q(q);
|
||||
else
|
||||
/*
|
||||
* One siga-w per buffer required for unicast
|
||||
* HiperSockets.
|
||||
*/
|
||||
while (count--)
|
||||
if ((q->irq_ptr->ssqd_desc.mmwc > 1) &&
|
||||
(count > 1) &&
|
||||
(count <= q->irq_ptr->ssqd_desc.mmwc)) {
|
||||
/* exploit enhanced SIGA */
|
||||
q->u.out.use_enh_siga = 1;
|
||||
qdio_kick_outbound_q(q);
|
||||
} else {
|
||||
/*
|
||||
* One siga-w per buffer required for unicast
|
||||
* HiperSockets.
|
||||
*/
|
||||
q->u.out.use_enh_siga = 0;
|
||||
while (count--)
|
||||
qdio_kick_outbound_q(q);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -892,8 +892,8 @@ static void ap_scan_bus(struct work_struct *unused)
|
||||
|
||||
ap_dev->device.bus = &ap_bus_type;
|
||||
ap_dev->device.parent = ap_root_device;
|
||||
snprintf(ap_dev->device.bus_id, BUS_ID_SIZE, "card%02x",
|
||||
AP_QID_DEVICE(ap_dev->qid));
|
||||
dev_set_name(&ap_dev->device, "card%02x",
|
||||
AP_QID_DEVICE(ap_dev->qid));
|
||||
ap_dev->device.release = ap_device_release;
|
||||
rc = device_register(&ap_dev->device);
|
||||
if (rc) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <asm/kvm_virtio.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/s390_ext.h>
|
||||
#include <asm/s390_rdev.h>
|
||||
|
||||
#define VIRTIO_SUBCODE_64 0x0D00
|
||||
|
||||
@ -241,10 +242,7 @@ static struct virtio_config_ops kvm_vq_configspace_ops = {
|
||||
* The root device for the kvm virtio devices.
|
||||
* This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2.
|
||||
*/
|
||||
static struct device kvm_root = {
|
||||
.parent = NULL,
|
||||
.bus_id = "kvm_s390",
|
||||
};
|
||||
static struct device *kvm_root;
|
||||
|
||||
/*
|
||||
* adds a new device and register it with virtio
|
||||
@ -261,7 +259,7 @@ static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset)
|
||||
return;
|
||||
}
|
||||
|
||||
kdev->vdev.dev.parent = &kvm_root;
|
||||
kdev->vdev.dev.parent = kvm_root;
|
||||
kdev->vdev.id.device = d->type;
|
||||
kdev->vdev.config = &kvm_vq_configspace_ops;
|
||||
kdev->desc = d;
|
||||
@ -317,15 +315,16 @@ static int __init kvm_devices_init(void)
|
||||
if (!MACHINE_IS_KVM)
|
||||
return -ENODEV;
|
||||
|
||||
rc = device_register(&kvm_root);
|
||||
if (rc) {
|
||||
kvm_root = s390_root_dev_register("kvm_s390");
|
||||
if (IS_ERR(kvm_root)) {
|
||||
rc = PTR_ERR(kvm_root);
|
||||
printk(KERN_ERR "Could not register kvm_s390 root device");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
|
||||
if (rc) {
|
||||
device_unregister(&kvm_root);
|
||||
s390_root_dev_unregister(kvm_root);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ claw_probe(struct ccwgroup_device *cgdev)
|
||||
probe_error(cgdev);
|
||||
put_device(&cgdev->dev);
|
||||
printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
|
||||
cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
|
||||
dev_name(&cgdev->cdev[0]->dev), __func__, __LINE__);
|
||||
CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
|
||||
return rc;
|
||||
}
|
||||
@ -584,7 +584,7 @@ claw_irq_handler(struct ccw_device *cdev,
|
||||
if (!cdev->dev.driver_data) {
|
||||
printk(KERN_WARNING "claw: unsolicited interrupt for device:"
|
||||
"%s received c-%02x d-%02x\n",
|
||||
cdev->dev.bus_id, irb->scsw.cmd.cstat,
|
||||
dev_name(&cdev->dev), irb->scsw.cmd.cstat,
|
||||
irb->scsw.cmd.dstat);
|
||||
CLAW_DBF_TEXT(2, trace, "badirq");
|
||||
return;
|
||||
@ -598,7 +598,7 @@ claw_irq_handler(struct ccw_device *cdev,
|
||||
p_ch = &privptr->channel[WRITE];
|
||||
else {
|
||||
printk(KERN_WARNING "claw: Can't determine channel for "
|
||||
"interrupt, device %s\n", cdev->dev.bus_id);
|
||||
"interrupt, device %s\n", dev_name(&cdev->dev));
|
||||
CLAW_DBF_TEXT(2, trace, "badchan");
|
||||
return;
|
||||
}
|
||||
@ -662,7 +662,7 @@ claw_irq_handler(struct ccw_device *cdev,
|
||||
printk(KERN_WARNING "claw: unsolicited "
|
||||
"interrupt for device:"
|
||||
"%s received c-%02x d-%02x\n",
|
||||
cdev->dev.bus_id,
|
||||
dev_name(&cdev->dev),
|
||||
irb->scsw.cmd.cstat,
|
||||
irb->scsw.cmd.dstat);
|
||||
return;
|
||||
@ -1136,19 +1136,20 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
|
||||
break;
|
||||
case -ENODEV:
|
||||
printk(KERN_EMERG "%s: Missing device called "
|
||||
"for IO ENODEV\n", cdev->dev.bus_id);
|
||||
"for IO ENODEV\n", dev_name(&cdev->dev));
|
||||
break;
|
||||
case -EIO:
|
||||
printk(KERN_EMERG "%s: Status pending... EIO \n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
break;
|
||||
case -EINVAL:
|
||||
printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_EMERG "%s: Unknown error in "
|
||||
"Do_IO %d\n",cdev->dev.bus_id, return_code);
|
||||
"Do_IO %d\n", dev_name(&cdev->dev),
|
||||
return_code);
|
||||
}
|
||||
}
|
||||
CLAW_DBF_TEXT(4, trace, "ccwret");
|
||||
@ -2848,11 +2849,11 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
|
||||
struct chbk *p_ch;
|
||||
struct ccw_dev_id dev_id;
|
||||
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id);
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cdev->dev));
|
||||
privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
|
||||
p_ch = &privptr->channel[i];
|
||||
p_ch->cdev = cdev;
|
||||
snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id);
|
||||
snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", dev_name(&cdev->dev));
|
||||
ccw_device_get_id(cdev, &dev_id);
|
||||
p_ch->devno = dev_id.devno;
|
||||
if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
|
||||
@ -2879,7 +2880,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
|
||||
int ret;
|
||||
struct ccw_dev_id dev_id;
|
||||
|
||||
printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
|
||||
printk(KERN_INFO "claw: add for %s\n",
|
||||
dev_name(&cgdev->cdev[READ]->dev));
|
||||
CLAW_DBF_TEXT(2, setup, "new_dev");
|
||||
privptr = cgdev->dev.driver_data;
|
||||
cgdev->cdev[READ]->dev.driver_data = privptr;
|
||||
@ -2903,14 +2905,16 @@ claw_new_device(struct ccwgroup_device *cgdev)
|
||||
if (ret != 0) {
|
||||
printk(KERN_WARNING
|
||||
"claw: ccw_device_set_online %s READ failed "
|
||||
"with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
|
||||
"with ret = %d\n", dev_name(&cgdev->cdev[READ]->dev),
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
ret = ccw_device_set_online(cgdev->cdev[WRITE]);
|
||||
if (ret != 0) {
|
||||
printk(KERN_WARNING
|
||||
"claw: ccw_device_set_online %s WRITE failed "
|
||||
"with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
|
||||
"with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev)
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
|
||||
@ -2986,7 +2990,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
|
||||
struct net_device *ndev;
|
||||
int ret;
|
||||
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
|
||||
priv = cgdev->dev.driver_data;
|
||||
if (!priv)
|
||||
return -ENODEV;
|
||||
@ -3016,11 +3020,11 @@ claw_remove_device(struct ccwgroup_device *cgdev)
|
||||
struct claw_privbk *priv;
|
||||
|
||||
BUG_ON(!cgdev);
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
|
||||
CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
|
||||
priv = cgdev->dev.driver_data;
|
||||
BUG_ON(!priv);
|
||||
printk(KERN_INFO "claw: %s() called %s will be removed.\n",
|
||||
__func__,cgdev->cdev[0]->dev.bus_id);
|
||||
__func__, dev_name(&cgdev->cdev[0]->dev));
|
||||
if (cgdev->state == CCWGROUP_ONLINE)
|
||||
claw_shutdown_device(cgdev);
|
||||
claw_remove_files(&cgdev->dev);
|
||||
|
@ -85,7 +85,7 @@
|
||||
#define CLAW_MAX_DEV 256 /* max claw devices */
|
||||
#define MAX_NAME_LEN 8 /* host name, adapter name length */
|
||||
#define CLAW_FRAME_SIZE 4096
|
||||
#define CLAW_ID_SIZE BUS_ID_SIZE+3
|
||||
#define CLAW_ID_SIZE 20+3
|
||||
|
||||
/* state machine codes used in claw_irq_handler */
|
||||
|
||||
|
@ -277,18 +277,18 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
|
||||
|
||||
CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
|
||||
"irb error %ld on device %s\n",
|
||||
PTR_ERR(irb), cdev->dev.bus_id);
|
||||
PTR_ERR(irb), dev_name(&cdev->dev));
|
||||
|
||||
switch (PTR_ERR(irb)) {
|
||||
case -EIO:
|
||||
ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
|
||||
ctcm_pr_warn("i/o-error on device %s\n", dev_name(&cdev->dev));
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
|
||||
ctcm_pr_warn("timeout on device %s\n", dev_name(&cdev->dev));
|
||||
break;
|
||||
default:
|
||||
ctcm_pr_warn("unknown error %ld on device %s\n",
|
||||
PTR_ERR(irb), cdev->dev.bus_id);
|
||||
PTR_ERR(irb), dev_name(&cdev->dev));
|
||||
}
|
||||
return PTR_ERR(irb);
|
||||
}
|
||||
@ -1182,7 +1182,7 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
|
||||
int dstat;
|
||||
|
||||
CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
|
||||
"Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id);
|
||||
"Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
|
||||
|
||||
if (ctcm_check_irb_error(cdev, irb))
|
||||
return;
|
||||
@ -1208,14 +1208,14 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
|
||||
ch = priv->channel[WRITE];
|
||||
else {
|
||||
ctcm_pr_err("ctcm: Can't determine channel for interrupt, "
|
||||
"device %s\n", cdev->dev.bus_id);
|
||||
"device %s\n", dev_name(&cdev->dev));
|
||||
return;
|
||||
}
|
||||
|
||||
dev = ch->netdev;
|
||||
if (dev == NULL) {
|
||||
ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
|
||||
__func__, cdev->dev.bus_id, ch);
|
||||
__func__, dev_name(&cdev->dev), ch);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1329,7 +1329,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
|
||||
|
||||
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
|
||||
"%s(%s), type %d, proto %d",
|
||||
__func__, cdev->dev.bus_id, type, priv->protocol);
|
||||
__func__, dev_name(&cdev->dev), type, priv->protocol);
|
||||
|
||||
ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
|
||||
if (ch == NULL)
|
||||
@ -1358,7 +1358,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
|
||||
goto nomem_return;
|
||||
|
||||
ch->cdev = cdev;
|
||||
snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id);
|
||||
snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev));
|
||||
ch->type = type;
|
||||
|
||||
/**
|
||||
@ -1518,8 +1518,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
||||
|
||||
type = get_channel_type(&cdev0->id);
|
||||
|
||||
snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id);
|
||||
snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id);
|
||||
snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
|
||||
snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
|
||||
|
||||
ret = add_channel(cdev0, type, priv);
|
||||
if (ret)
|
||||
|
@ -104,7 +104,7 @@
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
|
||||
#define CTCM_ID_SIZE BUS_ID_SIZE+3
|
||||
#define CTCM_ID_SIZE 20+3
|
||||
|
||||
struct ctcm_profile {
|
||||
unsigned long maxmulti;
|
||||
|
@ -492,7 +492,7 @@ lcs_start_channel(struct lcs_channel *channel)
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
LCS_DBF_TEXT_(4,trace,"ssch%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace,"ssch%s", dev_name(&channel->ccwdev->dev));
|
||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
rc = ccw_device_start(channel->ccwdev,
|
||||
channel->ccws + channel->io_idx, 0, 0,
|
||||
@ -501,7 +501,8 @@ lcs_start_channel(struct lcs_channel *channel)
|
||||
channel->state = LCS_CH_STATE_RUNNING;
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
if (rc) {
|
||||
LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4,trace,"essh%s",
|
||||
dev_name(&channel->ccwdev->dev));
|
||||
PRINT_ERR("Error in starting channel, rc=%d!\n", rc);
|
||||
}
|
||||
return rc;
|
||||
@ -514,12 +515,13 @@ lcs_clear_channel(struct lcs_channel *channel)
|
||||
int rc;
|
||||
|
||||
LCS_DBF_TEXT(4,trace,"clearch");
|
||||
LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev));
|
||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
rc = ccw_device_clear(channel->ccwdev, (addr_t) channel);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
if (rc) {
|
||||
LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace, "ecsc%s",
|
||||
dev_name(&channel->ccwdev->dev));
|
||||
return rc;
|
||||
}
|
||||
wait_event(channel->wait_q, (channel->state == LCS_CH_STATE_CLEARED));
|
||||
@ -540,13 +542,14 @@ lcs_stop_channel(struct lcs_channel *channel)
|
||||
if (channel->state == LCS_CH_STATE_STOPPED)
|
||||
return 0;
|
||||
LCS_DBF_TEXT(4,trace,"haltsch");
|
||||
LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev));
|
||||
channel->state = LCS_CH_STATE_INIT;
|
||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
rc = ccw_device_halt(channel->ccwdev, (addr_t) channel);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
||||
if (rc) {
|
||||
LCS_DBF_TEXT_(4,trace,"ehsc%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace, "ehsc%s",
|
||||
dev_name(&channel->ccwdev->dev));
|
||||
return rc;
|
||||
}
|
||||
/* Asynchronous halt initialted. Wait for its completion. */
|
||||
@ -632,10 +635,11 @@ __lcs_resume_channel(struct lcs_channel *channel)
|
||||
return 0;
|
||||
if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND)
|
||||
return 0;
|
||||
LCS_DBF_TEXT_(5, trace, "rsch%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(5, trace, "rsch%s", dev_name(&channel->ccwdev->dev));
|
||||
rc = ccw_device_resume(channel->ccwdev);
|
||||
if (rc) {
|
||||
LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(4, trace, "ersc%s",
|
||||
dev_name(&channel->ccwdev->dev));
|
||||
PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc);
|
||||
} else
|
||||
channel->state = LCS_CH_STATE_RUNNING;
|
||||
@ -1302,18 +1306,18 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
|
||||
|
||||
switch (PTR_ERR(irb)) {
|
||||
case -EIO:
|
||||
PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
|
||||
PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev));
|
||||
LCS_DBF_TEXT(2, trace, "ckirberr");
|
||||
LCS_DBF_TEXT_(2, trace, " rc%d", -EIO);
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
|
||||
PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev));
|
||||
LCS_DBF_TEXT(2, trace, "ckirberr");
|
||||
LCS_DBF_TEXT_(2, trace, " rc%d", -ETIMEDOUT);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
LCS_DBF_TEXT(2, trace, "ckirberr");
|
||||
LCS_DBF_TEXT(2, trace, " rc???");
|
||||
}
|
||||
@ -1390,7 +1394,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
|
||||
cstat = irb->scsw.cmd.cstat;
|
||||
dstat = irb->scsw.cmd.dstat;
|
||||
LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(5, trace, "Rint%s", dev_name(&cdev->dev));
|
||||
LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.cstat,
|
||||
irb->scsw.cmd.dstat);
|
||||
LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.fctl,
|
||||
@ -1400,7 +1404,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||
rc = lcs_get_problem(cdev, irb);
|
||||
if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
|
||||
PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
|
||||
cdev->dev.bus_id, dstat, cstat);
|
||||
dev_name(&cdev->dev), dstat, cstat);
|
||||
if (rc) {
|
||||
channel->state = LCS_CH_STATE_ERROR;
|
||||
}
|
||||
@ -1463,7 +1467,7 @@ lcs_tasklet(unsigned long data)
|
||||
int rc;
|
||||
|
||||
channel = (struct lcs_channel *) data;
|
||||
LCS_DBF_TEXT_(5, trace, "tlet%s",channel->ccwdev->dev.bus_id);
|
||||
LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev));
|
||||
|
||||
/* Check for processed buffers. */
|
||||
iob = channel->iob;
|
||||
@ -2244,7 +2248,7 @@ lcs_recovery(void *ptr)
|
||||
return 0;
|
||||
LCS_DBF_TEXT(4, trace, "recover2");
|
||||
gdev = card->gdev;
|
||||
PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
|
||||
PRINT_WARN("Recovery of device %s started...\n", dev_name(&gdev->dev));
|
||||
rc = __lcs_shutdown_device(gdev, 1);
|
||||
rc = lcs_new_device(gdev);
|
||||
if (!rc)
|
||||
|
@ -1724,7 +1724,7 @@ static int netiucv_register_device(struct net_device *ndev)
|
||||
IUCV_DBF_TEXT(trace, 3, __func__);
|
||||
|
||||
if (dev) {
|
||||
snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
|
||||
dev_set_name(dev, "net%s", ndev->name);
|
||||
dev->bus = &iucv_bus;
|
||||
dev->parent = iucv_root;
|
||||
/*
|
||||
|
@ -90,11 +90,11 @@ struct qeth_dbf_info {
|
||||
#define CARD_RDEV(card) card->read.ccwdev
|
||||
#define CARD_WDEV(card) card->write.ccwdev
|
||||
#define CARD_DDEV(card) card->data.ccwdev
|
||||
#define CARD_BUS_ID(card) card->gdev->dev.bus_id
|
||||
#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
|
||||
#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
|
||||
#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
|
||||
#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
|
||||
#define CARD_BUS_ID(card) dev_name(&card->gdev->dev)
|
||||
#define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev)
|
||||
#define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev)
|
||||
#define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev)
|
||||
#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev)
|
||||
|
||||
/**
|
||||
* card stuff
|
||||
|
@ -745,7 +745,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
|
||||
SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
|
||||
QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
|
||||
PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
|
||||
cdev->dev.bus_id, dstat, cstat);
|
||||
dev_name(&cdev->dev), dstat, cstat);
|
||||
print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
|
||||
16, 1, irb, 64, 1);
|
||||
return 1;
|
||||
@ -784,12 +784,12 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
|
||||
|
||||
switch (PTR_ERR(irb)) {
|
||||
case -EIO:
|
||||
PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
|
||||
PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev));
|
||||
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
|
||||
QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO);
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
|
||||
PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev));
|
||||
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
|
||||
QETH_DBF_TEXT_(TRACE, 2, " rc%d", -ETIMEDOUT);
|
||||
if (intparm == QETH_RCD_PARM) {
|
||||
@ -803,7 +803,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
|
||||
break;
|
||||
default:
|
||||
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
|
||||
cdev->dev.bus_id);
|
||||
dev_name(&cdev->dev));
|
||||
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
|
||||
QETH_DBF_TEXT(TRACE, 2, " rc???");
|
||||
}
|
||||
@ -4081,7 +4081,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
||||
if (!get_device(dev))
|
||||
return -ENODEV;
|
||||
|
||||
QETH_DBF_TEXT_(SETUP, 2, "%s", gdev->dev.bus_id);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "%s", dev_name(&gdev->dev));
|
||||
|
||||
card = qeth_alloc_card();
|
||||
if (!card) {
|
||||
|
@ -30,7 +30,7 @@ s390_root_dev_register(const char *name)
|
||||
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
|
||||
dev_set_name(dev, name);
|
||||
dev->release = s390_root_dev_release;
|
||||
ret = device_register(dev);
|
||||
if (ret) {
|
||||
|
@ -283,8 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
|
||||
unit->port = port;
|
||||
unit->fcp_lun = fcp_lun;
|
||||
|
||||
snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx",
|
||||
(unsigned long long) fcp_lun);
|
||||
dev_set_name(&unit->sysfs_device, "0x%016llx",
|
||||
(unsigned long long) fcp_lun);
|
||||
unit->sysfs_device.parent = &port->sysfs_device;
|
||||
unit->sysfs_device.release = zfcp_sysfs_unit_release;
|
||||
dev_set_drvdata(&unit->sysfs_device, unit);
|
||||
@ -610,8 +610,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
||||
atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
|
||||
atomic_set(&port->refcount, 0);
|
||||
|
||||
snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx",
|
||||
(unsigned long long) wwpn);
|
||||
dev_set_name(&port->sysfs_device, "0x%016llx", wwpn);
|
||||
port->sysfs_device.parent = &adapter->ccw_device->dev;
|
||||
|
||||
port->sysfs_device.release = zfcp_sysfs_port_release;
|
||||
|
@ -596,7 +596,7 @@ struct zfcp_data {
|
||||
struct semaphore config_sema; /* serialises configuration
|
||||
changes */
|
||||
atomic_t loglevel; /* current loglevel */
|
||||
char init_busid[BUS_ID_SIZE];
|
||||
char init_busid[20];
|
||||
u64 init_wwpn;
|
||||
u64 init_fcp_lun;
|
||||
struct kmem_cache *fsf_req_qtcb_cache;
|
||||
@ -619,7 +619,7 @@ struct zfcp_fsf_req_qtcb {
|
||||
#define ZFCP_SET 0x00000100
|
||||
#define ZFCP_CLEAR 0x00000200
|
||||
|
||||
#define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id)
|
||||
#define zfcp_get_busid_by_adapter(adapter) (dev_name(&adapter->ccw_device->dev))
|
||||
|
||||
/*
|
||||
* Helper functions for request ID management.
|
||||
|
@ -1376,7 +1376,7 @@ static int zfcp_erp_thread(void *data)
|
||||
struct zfcp_erp_action *act;
|
||||
unsigned long flags;
|
||||
|
||||
daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id);
|
||||
daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
|
||||
/* Block all signals */
|
||||
siginitsetinv(¤t->blocked, 0);
|
||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
|
||||
|
@ -381,7 +381,7 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
|
||||
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
|
||||
|
||||
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
|
||||
unit->port->adapter->ccw_device->dev.bus_id);
|
||||
dev_name(&unit->port->adapter->ccw_device->dev));
|
||||
ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
|
||||
(unsigned long long) unit->port->wwpn);
|
||||
ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
|
||||
|
@ -81,7 +81,10 @@ my (@stack, $re, $dre, $x, $xs);
|
||||
$re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o;
|
||||
} elsif ($arch =~ /^s390x?$/) {
|
||||
# 11160: a7 fb ff 60 aghi %r15,-160
|
||||
$re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o;
|
||||
# or
|
||||
# 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15)
|
||||
$re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})
|
||||
(?:\(\%r15\))?$/ox;
|
||||
} elsif ($arch =~ /^sh64$/) {
|
||||
#XXX: we only check for the immediate case presently,
|
||||
# though we will want to check for the movi/sub
|
||||
|
Loading…
Reference in New Issue
Block a user