Commit 86a7dc29 authored by Linus Torvalds's avatar Linus Torvalds

Fix Rules.make removal merge

parents 59db688e 34725cc4
......@@ -20,36 +20,37 @@ LDFLAGS_BLOB := --format binary --oformat elf32-s390
CFLAGS += -pipe -fno-strength-reduce
HEAD := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
HEAD := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-y += arch/s390/mm/ arch/s390/kernel/
core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/
libs-y += arch/$(ARCH)/lib/
drivers-y += drivers/s390/
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
libs-y += arch/s390/lib/
drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/$(ARCH)/boot $(1)
all: image listing
makeboot = $(call descend,arch/$(ARCH)/boot,$(1))
BOOTIMAGE= arch/$(ARCH)/boot/image
listing image: vmlinux
$(call makeboot,arch/$(ARCH)/boot/$@)
listing install image: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@)
install: vmlinux
$(call makeboot, $@)
archmrproper:
archclean:
+@$(call makeboot,clean)
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/$(ARCH)/boot
archmrproper:
prepare: include/asm-$(ARCH)/offsets.h
arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
include/config/MARKER
include/asm-$(ARCH)/offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
@$(generate-asm-offsets.h) < $< > $@
include/asm-$(ARCH)/offsets.h: include/asm-$(ARCH)/offsets.h.tmp
include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
@echo -n ' Generating $@'
@$(generate-asm-offsets.h) < $< > $@.tmp
@$(update-if-changed)
CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \
......
......@@ -2,24 +2,19 @@
# Makefile for the linux s390-specific parts of the memory manager.
#
EXTRA_TARGETS := image listing
EXTRA_AFLAGS := -traditional
quiet_cmd_listing = OBJDUMP $(echo_target)
cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
quiet_cmd_listing = OBJDUMP $@
cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
--disassemble-zeroes --reloc vmlinux > $@
$(obj)/image: vmlinux
$(obj)/image: vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/listing: vmlinux
$(obj)/listing: vmlinux FORCE
$(call if_changed,listing)
image: $(obj)/image
listing: $(obj)/listing
clean:
rm -f $(obj)/image $(obj)/listing
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)"
install: $(CONFIGURE) $(obj)/image
sh -x $(obj)/install.sh $(KERNELRELEASE) $(obj)/image \
System.map Kerntypes "$(INSTALL_PATH)"
......@@ -321,6 +321,8 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_DES is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEST is not set
#
......
......@@ -47,7 +47,8 @@ SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2
SP_TRAP = (SP_ORIG_R2+GPR_SIZE)
SP_SIZE = (SP_TRAP+4)
_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
/*
* Base Address of this Module --- saved in __LC_ENTRY_BASE
......@@ -181,6 +182,7 @@ system_call:
GET_THREAD_INFO # load pointer to task_struct to R9
sll %r7,2
stosm 24(%r15),0x03 # reenable interrupts
sysc_do_restart:
l %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE
bo BASED(sysc_tracesys)
......@@ -191,7 +193,7 @@ system_call:
sysc_return:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_leave:
RESTORE_ALL 1
......@@ -202,7 +204,7 @@ sysc_leave:
sysc_work_loop:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bz BASED(sysc_leave) # there is no work to do
#
# One of the work bits is on. Find out which one.
......@@ -213,6 +215,8 @@ sysc_work:
bo BASED(sysc_reschedule)
tm __TI_flags+3(%r9),_TIF_SIGPENDING
bo BASED(sysc_sigpending)
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
bo BASED(sysc_restart)
b BASED(sysc_leave)
#
......@@ -236,15 +240,27 @@ sysc_sigpending:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
b BASED(sysc_leave) # out of here, do NOT recheck
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
stosm 24(%r15),0x03 # reenable interrupts
l %r7,SP_R2(%r15) # load new svc number
sll %r7,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_restart) # restart svc
#
# call trace before and after sys_call
#
sysc_tracesys:
l %r1,BASED(.Ltrace)
srl %r7,2
st %r7,SP_R2(4,%r15)
st %r7,SP_R2(%r15)
basr %r14,%r1
l %r7,SP_R2(4,%r15) # strace might have changed the
l %r7,SP_R2(%r15) # strace might have changed the
n %r7,BASED(.Lc256) # system call
sll %r7,2
l %r8,sys_call_table-entry_base(%r7,%r13)
......@@ -354,7 +370,7 @@ sys_call_table:
.long sys_write
.long sys_open /* 5 */
.long sys_close
.long sys_ni_syscall /* old waitpid syscall holder */
.long sys_restart_syscall
.long sys_creat
.long sys_link
.long sys_unlink /* 10 */
......@@ -752,7 +768,7 @@ io_return:
#else
bno BASED(io_leave) # no-> skip resched & signal
#endif
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.)
io_leave:
RESTORE_ALL 0
......@@ -788,7 +804,7 @@ io_resume_loop:
io_work_loop:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+3(%r9),_TIF_WORK_MASK
tm __TI_flags+3(%r9),_TIF_WORK_INT
bz BASED(io_leave) # there is no work to do
#
# One of the work bits is on. Find out which one.
......
......@@ -59,3 +59,4 @@ EXPORT_SYMBOL(csum_fold);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_device);
EXPORT_SYMBOL_NOVERS(do_call_softirq);
EXPORT_SYMBOL(sys_wait4);
......@@ -397,6 +397,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn =
do_no_restart_syscall;
clear_thread_flag(TIF_RESTART_SVC);
case -ERESTARTNOHAND:
regs->gprs[2] = -EINTR;
break;
......@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr -= 2;
}
/* Restart the system call with a new system call number */
if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
regs->gprs[2] = __NR_restart_syscall;
set_thread_flag(TIF_RESTART_SVC);
}
}
return 0;
}
......@@ -4,5 +4,5 @@
obj-$(CONFIG_MATHEMU) := math.o qrnnd.o
EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w
EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
EXTRA_AFLAGS := -traditional
......@@ -21,35 +21,36 @@ LDFLAGS_BLOB := --format binary --oformat elf64-s390
CFLAGS += -pipe -fno-strength-reduce
HEAD := arch/s390x/kernel/head.o arch/s390x/kernel/init_task.o
HEAD := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-y += arch/s390x/mm/ arch/s390x/kernel/
core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/
libs-y += arch/$(ARCH)/lib/
drivers-y += drivers/s390/
libs-y += arch/s390x/lib/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/$(ARCH)/boot $(1)
all: image listing
makeboot = $(call descend,arch/$(ARCH)/boot,$(1))
BOOTIMAGE= arch/$(ARCH)/boot/image
listing image: vmlinux
$(call makeboot,arch/$(ARCH)/boot/$@)
listing install image: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@)
install: vmlinux
$(call makeboot, $@)
archmrproper:
archclean:
+@$(call makeboot,clean)
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/$(ARCH)/boot
archmrproper:
prepare: include/asm-$(ARCH)/offsets.h
arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
include/config/MARKER
include/asm-$(ARCH)/offsets.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
@$(generate-asm-offsets.h) < $< > $@
include/asm-$(ARCH)/offsets.h: include/asm-$(ARCH)/offsets.h.tmp
include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
@echo -n ' Generating $@'
@$(generate-asm-offsets.h) < $< > $@.tmp
@$(update-if-changed)
CLEAN_FILES += include/asm-$(ARCH)/offsets.h.tmp \
......
......@@ -2,24 +2,20 @@
# Makefile for the linux s390-specific parts of the memory manager.
#
EXTRA_TARGETS := image listing
EXTRA_AFLAGS := -traditional
quiet_cmd_listing = OBJDUMP $(echo_target)
cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
quiet_cmd_listing = OBJDUMP $@
cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \
--disassemble-zeroes --reloc vmlinux > $@
$(obj)/image: vmlinux
$(obj)/image: vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/listing: vmlinux
$(obj)/listing: vmlinux FORCE
$(call if_changed,listing)
image: $(obj)/image
listing: $(obj)/listing
clean:
rm -f $(obj)/image $(obj)/listing
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)"
install: $(CONFIGURE) $(obj)/image
sh -x $(obj)/install.sh $(KERNELRELEASE) $(obj)/image \
System.map Kerntypes "$(INSTALL_PATH)"
......@@ -382,6 +382,8 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_DES is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEST is not set
#
......
......@@ -47,7 +47,8 @@ SP_ORIG_R2 = STACK_FRAME_OVERHEAD + PT_ORIGGPR2
SP_TRAP = (SP_ORIG_R2+GPR_SIZE)
SP_SIZE = (SP_TRAP+4)
_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
/*
* Register usage in interrupt handlers:
......@@ -161,6 +162,7 @@ system_call:
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
GET_THREAD_INFO # load pointer to task_struct to R9
stosm 48(%r15),0x03 # reenable interrupts
sysc_do_restart:
larl %r10,sys_call_table
sll %r7,3
tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ?
......@@ -177,7 +179,7 @@ sysc_noemu:
sysc_return:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
sysc_leave:
RESTORE_ALL 1
......@@ -188,7 +190,7 @@ sysc_leave:
sysc_work_loop:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jz sysc_leave # there is no work to do
#
# One of the work bits is on. Find out which one.
......@@ -199,6 +201,8 @@ sysc_work:
jo sysc_reschedule
tm __TI_flags+7(%r9),_TIF_SIGPENDING
jo sysc_sigpending
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
jo sysc_restart
j sysc_leave
#
......@@ -220,6 +224,17 @@ sysc_sigpending:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
j sysc_leave # out of here, do NOT recheck
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
stosm 48(%r15),0x03 # reenable interrupts
lg %r7,SP_R2(%r15) # load new svc number
mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_restart # restart svc
#
# call syscall_trace before and after system call
# special linkage: %r12 contains the return address for trace_svc
......@@ -383,7 +398,7 @@ sys_call_table:
.long SYSCALL(sys_write,sys32_write_wrapper)
.long SYSCALL(sys_open,sys32_open_wrapper) /* 5 */
.long SYSCALL(sys_close,sys32_close_wrapper)
.long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old waitpid syscall */
.long SYSCALL(sys_restart_syscall,sys_ni_syscall)
.long SYSCALL(sys_creat,sys32_creat_wrapper)
.long SYSCALL(sys_link,sys32_link_wrapper)
.long SYSCALL(sys_unlink,sys32_unlink_wrapper) /* 10 */
......@@ -777,7 +792,7 @@ io_return:
#else
jno io_leave # no-> skip resched & signal
#endif
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.)
io_leave:
RESTORE_ALL 0
......@@ -813,7 +828,7 @@ io_resume_loop:
io_work_loop:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
GET_THREAD_INFO # load pointer to task_struct to R9
tm __TI_flags+7(%r9),_TIF_WORK_MASK
tm __TI_flags+7(%r9),_TIF_WORK_INT
jz io_leave # there is no work to do
#
# One of the work bits is on. Find out which one.
......
......@@ -83,3 +83,4 @@ EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_device);
EXPORT_SYMBOL_NOVERS(do_call_softirq);
EXPORT_SYMBOL(sys_wait4);
......@@ -391,6 +391,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn =
do_no_restart_syscall;
clear_thread_flag(TIF_RESTART_SVC);
case -ERESTARTNOHAND:
regs->gprs[2] = -EINTR;
break;
......@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr -= 2;
}
/* Restart the system call with a new system call number */
if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
regs->gprs[2] = __NR_restart_syscall;
set_thread_flag(TIF_RESTART_SVC);
}
}
return 0;
}
#
# Makefile for the linux i386-specific parts of the memory manager.
# Makefile for the linux s390-specific parts of the memory manager.
#
obj-y := init.o fault.o ioremap.o extable.o
......@@ -40,7 +40,6 @@ extern spinlock_t modlist_lock;
unsigned long
search_exception_table(unsigned long addr)
{
struct list_head *i;
unsigned long ret = 0;
#ifndef CONFIG_MODULES
......
......@@ -3,6 +3,6 @@
#
obj-y += s390mach.o sysinfo.o
obj-y += cio/ block/ char/ misc/ net/
obj-y += cio/ block/ char/ net/
drivers-y += drivers/s390/built-in.o
......@@ -47,7 +47,7 @@ static sccb_mask_t sclp_send_mask;
static struct list_head sclp_reg_list;
/* sccb queue */
struct list_head sclp_req_queue;
static struct list_head sclp_req_queue;
/* sccb for unconditional read */
static struct sclp_req sclp_read_req;
......@@ -448,7 +448,7 @@ sclp_state_change(struct evbuf_header *evbuf)
spin_unlock_irqrestore(&sclp_lock, flags);
}
struct sclp_register sclp_state_change_event = {
static struct sclp_register sclp_state_change_event = {
.receive_mask = EvTyp_StateChange_Mask,
.receiver_fn = sclp_state_change
};
......@@ -514,7 +514,7 @@ sclp_quiesce(struct evbuf_header *evbuf)
ctrl_alt_del();
}
struct sclp_register sclp_quiesce_event = {
static struct sclp_register sclp_quiesce_event = {
.receive_mask = EvTyp_SigQuiesce_Mask,
.receiver_fn = sclp_quiesce
};
......
......@@ -97,7 +97,7 @@ sclp_console_timeout(unsigned long data)
/*
* Writes the given message to S390 system console
*/
void
static void
sclp_console_write(struct console *console, const char *message,
unsigned int count)
{
......@@ -152,7 +152,7 @@ sclp_console_write(struct console *console, const char *message,
}
/* returns the device number of the SCLP console */
kdev_t
static kdev_t
sclp_console_device(struct console *c)
{
return mk_kdev(sclp_console_major, sclp_console_minor);
......@@ -163,7 +163,7 @@ sclp_console_device(struct console *c)
* is going to give up. We have to make sure that all buffers
* will be flushed to the SCLP.
*/
void
static void
sclp_console_unblank(void)
{
unsigned long flags;
......@@ -187,7 +187,7 @@ sclp_console_unblank(void)
* used to register the SCLP console to the kernel and to
* give printk necessary information
*/
struct console sclp_console =
static struct console sclp_console =
{
.name = sclp_console_name,
.write = sclp_console_write,
......
......@@ -31,7 +31,7 @@
#define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
/* Event type structure for write message and write priority message */
struct sclp_register sclp_rw_event = {
static struct sclp_register sclp_rw_event = {
.send_mask = EvTyp_Msg_Mask | EvTyp_PMsgCmd_Mask
};
......
......@@ -466,7 +466,7 @@ sclp_tty_flush_buffer(struct tty_struct *tty)
/*
* push input to tty
*/
void sclp_tty_input(unsigned char* buf, unsigned int count)
static void sclp_tty_input(unsigned char* buf, unsigned int count)
{
unsigned int cchar;
......@@ -694,7 +694,7 @@ sclp_tty_state_change(struct sclp_register *reg)
{
}
struct sclp_register sclp_input_event =
static struct sclp_register sclp_input_event =
{
.receive_mask = EvTyp_OpCmd_Mask | EvTyp_PMsgCmd_Mask,
.state_change_fn = sclp_tty_state_change,
......
/***********************************************************************
* drivers/s390/char/tape.c
* tape device driver for S/390 and zSeries tapes.
*
* S390 and zSeries version
* Copyright (C) 2001 IBM Corporation
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Michael Holzheu <holzheu@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
*
***********************************************************************
*/
#include "tapedefs.h" // kernel 2.2 compatibility defines
#include <linux/stddef.h> // defines NULL
#include <linux/proc_fs.h> // for /proc/tapedevices
#include <linux/init.h> // for kernel parameters
#include <linux/kmod.h> // for requesting modules
#include <linux/spinlock.h> // for locks
#include <asm/types.h> // for variable types
#ifdef CONFIG_S390_TAPE_DYNAMIC
#include <asm/s390dyn.h>
#endif
#include "tape.h"
#ifdef CONFIG_S390_TAPE_3590
#include "tape3590.h"
#endif
#ifdef CONFIG_S390_TAPE_3490
#include "tape3490.h"
#endif
#ifdef CONFIG_S390_TAPE_3480
#include "tape3480.h"
#endif
#ifdef CONFIG_S390_TAPE_BLOCK
#include "tapeblock.h"
#endif
#ifdef CONFIG_S390_TAPE_CHAR
#include "tapechar.h"
#endif
#ifdef CONFIG_PROC_FS
#include <linux/vmalloc.h>
#endif
#define PRINTK_HEADER "T390:"
#define TAPE_MAX_DEVREGS (256 / TAPE_MINORS_PER_DEV)
#define TAPE_NO_IO 0
#define TAPE_DO_IO 1
#define TAPE_CIO_PRIVATE_DATA
#ifdef CONFIG_KMOD
#define tape_request_module(a) request_module(a)
#else
#define tape_request_module(a)
#endif
/*******************************************************************
* Internal Prototypes
*******************************************************************/
static void tape_do_irq (int irq, void *int_parm, struct pt_regs *regs);
static inline int tape_halt_io(tape_dev_t* td);
static void tape_wait(tape_ccw_req_t* treq);
#ifdef CONFIG_S390_TAPE_DYNAMIC
/* functions for dyn. dev. attach/detach */
static int tape_oper_handler ( int irq, struct _devreg *dreg);
static void tape_noper_handler ( int irq, int status );
#endif
static inline void tape_disable_device(tape_dev_t* td);
static inline int tape_enable_device(tape_dev_t* td);
/*******************************************************************
* GLOBALS
*******************************************************************/
static devreg_t *tape_devreg[TAPE_MAX_DEVREGS];
static int tape_devregct=0;
static int tape_autoprobe = 1;
static tape_discipline_t *tape_first_disc = NULL;
tape_dev_t *tape_first_dev = NULL;
tape_frontend_t *tape_first_front = NULL;
char *tape[256] = { NULL, };
/*
* Lock hirarchy:
* tape_discipline_lock > tape_dev_lock > td->lock
*/
rwlock_t tape_dev_lock=RW_LOCK_UNLOCKED;
static rwlock_t tape_discipline_lock=RW_LOCK_UNLOCKED;
#ifdef TAPE_DEBUG
debug_info_t *tape_dbf_area = NULL;
#endif
const char* tape_med_st_verbose[MS_SIZE]={
"UNKNOWN ",
"LOADED ",
"UNLOADED"
};
const char* tape_state_verbose[TS_SIZE]={
"UNUSED",
"IN_USE",
"INIT ",
"NOT_OP"
};
const char* tape_op_verbose[TO_SIZE] = {
"BLK",
"BSB",
"BSF",
"DSE",
"EGA",
"FSB",
"FSF",
"LDI",
"LBL",
"MSE",
"NOP",
"RBA",
"RBI",
"RBU",
"RBL",
"RDC",
"RFO",
"RSD",
"REW",
"RUN",
"SEN",
"SID",
"SNP",
"SPG",
"SWI",
"SMR",
"SYN",
"TIO",
"UNA",
"WRI",
"WTM",
"MSN",
"LOA",
"RCF", /* 3590 */
"RAT", /* 3590 */
"NOT"
};
/*******************************************************************
* DEVFS Functions
*******************************************************************/
#ifdef CONFIG_DEVFS_FS
/*
* Create devfs root entry (devno in hex) for device td
*/
static inline devfs_handle_t
tape_mkdevfsroot (tape_dev_t* td)
{
char devno [10];
sprintf (devno,"tape/%04x",td->devinfo.devno);
return devfs_mk_dir(NULL, devno, NULL);
}
/*
* Remove devfs root entry for device td
*/
static inline void
tape_rmdevfsroot (tape_dev_t* td)
{
devfs_remove("tape/%04x", td->devinfo.devno);
}
#endif
/*******************************************************************
* PROCFS Functions
*******************************************************************/
#ifdef CONFIG_PROC_FS
/* functions used in tape_proc_file_ops */
static ssize_t tape_proc_devices_read (struct file *file, char *user_buf, size_t user_len, loff_t * offset);
static int tape_proc_devices_open (struct inode *inode, struct file *file);
static int tape_proc_devices_release (struct inode *inode, struct file *file);
/* our proc tapedevices entry */
static struct proc_dir_entry *tape_proc_devices;
typedef struct {
char *data;
int len;
} tape_procinfo_t;
static struct file_operations tape_proc_devices_file_ops =
{
.owner = THIS_MODULE,
.read = tape_proc_devices_read, /* read */
.open = tape_proc_devices_open, /* open */
.release = tape_proc_devices_release, /* close */
};
/*
* Initialize procfs stuff on startup
*/
static inline void
tape_proc_init (void) {
tape_proc_devices = create_proc_entry ("tapedevices",
S_IFREG | S_IRUGO | S_IWUSR,
&proc_root);
if (tape_proc_devices == NULL)
goto error;
tape_proc_devices->proc_fops = &tape_proc_devices_file_ops;
tape_proc_devices->proc_iops = &tape_proc_devices_inode_ops;
return;
error:
PRINT_WARN ("tape: Cannot register procfs entry tapedevices\n");
return;
}
/*
* Open function for /proc/tapedevices
*/
static int
tape_proc_devices_open (struct inode *inode, struct file *file)
{
tape_dev_t* td;
tape_procinfo_t* procinfo;
char* data = NULL;
int size=0,check_size = -1;
int pos=0;
int rc=0;
long lockflags,lockflags2;
tape_ccw_req_t *treq;
procinfo = kmalloc (sizeof(tape_procinfo_t),GFP_KERNEL);
if (!procinfo){
rc = -ENOMEM;
goto out_no_lock;
}
/* Find out mem size for output, ensure that after releasing lock */
/* (vmalloc must not be called with interrupts disabled) no devices */
/* have been added/removed */
do{
size = 100; // Headline
read_lock_irqsave(&tape_dev_lock,lockflags);
for (td=tape_first_dev;td!=NULL;td=td->next)
size+=100; // FIXME: Guess better!
if(size == check_size)
break;
read_unlock_irqrestore(&tape_dev_lock,lockflags);
if(data)
vfree(data);
data=vmalloc(size);
if (!data) {
kfree (procinfo);
rc = -ENOMEM;
goto out_no_lock;
}
check_size = size;
}while (1);
// We have the tape_dev lock now
#ifdef CONFIG_S390_TAPE_CHAR
pos+=sprintf(data+pos,"TapeNo\tDevNo\tCuType\tCuModel\tDevType\tDevMod\tBlkSize\tState\tOp\tMedState\n");
#else
pos+=sprintf(data+pos,"TapeNo\tDevNo\tCuType\tCuModel\tDevType\tDevMod\tState\tOp\tMedState\n");
#endif
for (td=tape_first_dev;td!=NULL;td=td->next) {
s390irq_spin_lock_irqsave (td->devinfo.irq,lockflags2);
treq = tape_get_active_ccw_req(td);
pos+=sprintf(data+pos,"%d\t",td->first_minor/TAPE_MINORS_PER_DEV);
pos+=sprintf(data+pos,"%04X\t",td->devinfo.devno);
pos+=sprintf(data+pos,"%04X\t",td->devinfo.sid_data.cu_type);
pos+=sprintf(data+pos,"%02X\t",td->devinfo.sid_data.cu_model);
pos+=sprintf(data+pos,"%04X\t",td->devinfo.sid_data.dev_type);
pos+=sprintf(data+pos,"%02X\t",td->devinfo.sid_data.dev_model);
#ifdef CONFIG_S390_TAPE_CHAR
if(td->char_data.block_size == 0)
pos+=sprintf(data+pos,"auto\t");
else
pos+=sprintf(data+pos,"%i\t",td->char_data.block_size);
#endif
pos+=sprintf(data+pos,"%s\t",((tape_state_get(td) >= 0) &&
(tape_state_get(td) < TS_SIZE)) ?
tape_state_verbose[tape_state_get (td)] : "UNKNOWN");
pos+=sprintf(data+pos,"%s\t",(treq != NULL) ?
tape_op_verbose[treq->op] : "---");
pos+=sprintf(data+pos,"%s\n",tape_med_st_verbose[td->medium_state]);
s390irq_spin_unlock_irqrestore (td->devinfo.irq,lockflags2);
}
procinfo->data=data;
procinfo->len=pos;
if (pos>size) BUG(); // we've overwritten some memory
file->private_data= (void*) procinfo;
read_unlock_irqrestore(&tape_dev_lock,lockflags);
out_no_lock:
return rc;
}
/*
* Read function for /proc/tapedevices
*/
static ssize_t
tape_proc_devices_read (struct file *file, char *user_buf, size_t user_len, loff_t * offset)
{
loff_t len = 0;
tape_procinfo_t *p_info = (tape_procinfo_t *) file->private_data;
if (*offset >= p_info->len) {
goto out; /* EOF */
} else {
len = user_len<(p_info->len - *offset)?user_len:(p_info->len - *offset);
if (copy_to_user (user_buf, &(p_info->data[*offset]), len))
return -EFAULT;
(*offset) += len;
}
out:
return len;
}
/*
* Close function for /proc/tapedevices
*/
static int
tape_proc_devices_release (struct inode *inode, struct file *file)
{
int rc = 0;
tape_procinfo_t *p_info = (tape_procinfo_t *) file->private_data;
vfree(p_info->data);
kfree (p_info);
return rc;
}
/*
* Cleanup all stuff registered to the procfs
*/
static inline void
tape_proc_cleanup (void)
{
if (tape_proc_devices != NULL)
remove_proc_entry ("tapedevices", &proc_root);
}
#endif /* CONFIG_PROC_FS */
/*******************************************************************
* Wait/Wakeup Functions
*******************************************************************/
static void tape_wake_up_remove(tape_ccw_req_t* treq){
tape_remove_ccw_req(treq->tape_dev,treq);
tape_free_ccw_req(treq);
}
static void tape_wake_up(tape_ccw_req_t* treq){
treq->wakeup = NULL;
wake_up(&treq->wq);
}
static void tape_wake_up_interruptible(tape_ccw_req_t* treq){
treq->wakeup = NULL;
wake_up_interruptible(&treq->wq);
}
#ifdef CONFIG_S390_TAPE_BLOCK
static void tape_schedule_tapeblock(tape_ccw_req_t* treq){
treq->wakeup = NULL;
tapeblock_schedule_exec_io((tape_dev_t*)(treq->tape_dev));;
}
#endif
static void tape_wait_event(tape_ccw_req_t* treq){
wait_event (treq->wq,(treq->wakeup == NULL));
}
static void tape_wait_event_interruptible(tape_ccw_req_t* treq){
wait_event_interruptible(treq->wq,(treq->wakeup == NULL));
if (signal_pending (current)) {
treq->rc = tape_halt_io(treq->tape_dev);
if(treq->rc == -ERESTARTSYS)
PRINT_INFO("IO stopped on irq %d\n",treq->tape_dev->devinfo.irq); /* FIXME: only put into dbf */
else if(treq->rc == 0)
PRINT_INFO("could not stop IO,irq was faster on irq %d\n",treq->tape_dev->devinfo.irq); /* FIXME: only put into dbf */
else
PRINT_WARN("IO error while stopping IO on irq %d\n",treq->tape_dev->devinfo.irq);
}
}
static void tape_wait_event_interruptible_nohaltio(tape_ccw_req_t* treq){
wait_event_interruptible(treq->wq,(treq->wakeup == NULL));
}
/*******************************************************************
* DYNAMIC ATTACH/DETACH Functions
*******************************************************************/
static inline void
tape_init_devregs(void)
{
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
memset(tape_devreg,0,sizeof(devreg_t*) * TAPE_MAX_DEVREGS);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
}
/*
* Alloc a devreg for a devno
*/
static inline devreg_t *
tape_create_devno_devreg (int devno)
{
devreg_t *devreg = kmalloc (sizeof (devreg_t), GFP_KERNEL);
if (devreg != NULL) {
memset (devreg, 0, sizeof (devreg_t));
devreg->ci.devno = devno;
devreg->flag = DEVREG_TYPE_DEVNO;
devreg->oper_func = tape_oper_handler;
}
return devreg;
}
/*
* Alloc a devreg for a cu-type
*/
static inline devreg_t *
tape_create_cu_devreg (int cu_type)
{
devreg_t *devreg = kmalloc (sizeof (devreg_t), GFP_KERNEL);
if (devreg != NULL) {
memset (devreg, 0, sizeof (devreg_t));
devreg->ci.hc.ctype = cu_type;
devreg->flag = DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS;
devreg->oper_func = tape_oper_handler;
}
return devreg;
}
/*
* Create devregs for device numbers from "from" to "to"
*/
static inline void
tape_create_devregs_range(int from, int to)
{
int i;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
for (i=from;i<=to;i++) {
// register for attch/detach of a devno
if(tape_devregct >= TAPE_MAX_DEVREGS){
PRINT_WARN ("Could not create devregs for devno range %04x - %04x.\n",i,to);
PRINT_WARN ("These devices cannot be used. Use autoprobe\n");
PRINT_WARN ("or specify device ranges more precisely!\n");
break;
}
tape_devreg[tape_devregct]=tape_create_devno_devreg(i);
if (tape_devreg[tape_devregct]!=NULL) {
s390_device_register (tape_devreg[tape_devregct++]);
} else {
PRINT_WARN ("Could not create devreg for devno %04x, dyn. attach for this devno deactivated.\n",i);
}
}
write_unlock_irqrestore(&tape_dev_lock,lockflags);
return;
}
/*
* Create a devreg for a discipline
*/
static inline void
tape_create_devreg_for_disc(tape_discipline_t *disc)
{
int devreg_nr;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
for(devreg_nr = 0; devreg_nr < TAPE_MAX_DEVREGS; devreg_nr++){
if(tape_devreg[devreg_nr] == NULL)
break;
}
if(devreg_nr == TAPE_MAX_DEVREGS){
PRINT_WARN ("Could not create devreg for discipline (%x), dyn. attach for this discipline deactivated.\n",disc->cu_type);
goto out_unlock;
}
tape_devreg[devreg_nr] = tape_create_cu_devreg(disc->cu_type);
if (tape_devreg[devreg_nr] != NULL) {
s390_device_register(tape_devreg[devreg_nr]);
} else {
PRINT_WARN("Could not alloc devreg: Out of memory\n");
PRINT_WARN("Dynamic attach/detach will not work!\n");
}
out_unlock:
write_unlock_irqrestore(&tape_dev_lock,lockflags);
return;
}
/*
* Free all devregs
*/
static inline void
tape_delete_all_devregs(void)
{
int i;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
for(i = 0; i < TAPE_MAX_DEVREGS; i++){
if(tape_devreg[i]){
s390_device_unregister(tape_devreg[i]);
kfree(tape_devreg[i]);
}
}
memset(tape_devreg,0,sizeof(devreg_t*) * TAPE_MAX_DEVREGS);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
}
/*
* Free Devregs for a discipline
*/
static inline void
tape_delete_devreg_for_disc(tape_discipline_t* disc)
{
int i;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
for(i = 0; i < TAPE_MAX_DEVREGS; i++){
if(tape_devreg[i]){
if(tape_devreg[i]->ci.hc.ctype == disc->cu_type){
s390_device_unregister(tape_devreg[i]);
kfree(tape_devreg[i]);
tape_devreg[i] = NULL;
}
}
}
write_unlock_irqrestore(&tape_dev_lock,lockflags);
}
/*******************************************************************
* Module/Kernel Parameter Handling
*******************************************************************/
#ifndef MODULE
static char tape_parm_string[1024] __initdata = { 0, };
/*
* Get Kernel parameters (str) seperated by ","
* and store them into the tape[] array
*/
static void
tape_split_parm_string (char *str)
{
char *tmp = str;
int count = 0;
while (tmp != NULL && *tmp != '\0') {
char *end;
int len;
end = strchr (tmp, ',');
if (end == NULL) {
len = strlen (tmp) + 1;
} else {
len = (long) end - (long) tmp + 1;
*end = '\0';
end++;
}
tape[count] = kmalloc (len * sizeof (char), GFP_ATOMIC);
if (tape[count] == NULL) {
printk (KERN_WARNING PRINTK_HEADER
"can't store tape= parameter no %d\n",
count + 1);
break;
}
memcpy (tape[count], tmp, len * sizeof (char));
count++;
tmp = end;
};
}
/*
* This function is called for each "tape=" Kernel parameter
* at Kernel initialization. We need tape_parm_setup because of
* 2.2 compatibility (At least I assume this :-))
*/
void __init
tape_parm_setup (char *str, int *ints)
{
int len = strlen (tape_parm_string);
if (len != 0) {
strcat (tape_parm_string, ",");
}
strcat (tape_parm_string, str);
}
int __init
tape_parm_call_setup (char *str)
{
int dummy;
tape_parm_setup (str, &dummy);
return 1;
}
__setup("tape=", tape_parm_call_setup);
#endif /* not defined MODULE */
/*
* Convert string to int
*/
static inline int
tape_parm_strtoul (char *str, char **stra)
{
char *temp = str;
int val;
if (*temp == '0') {
temp++; /* strip leading zero */
if (*temp == 'x')
temp++; /* strip leading x */
}
val = simple_strtoul (temp, &temp, 16); /* interpret anything as hex */
*stra = temp;
return val;
}
/*
* Parse Kernel/Module Parameters and create devregs for dynamic attach/detach
*/
static inline void
tape_parm_parse (char **str)
{
char *temp;
int from, to;
if (*str==NULL) {
/* no params present -> leave */
return;
}
while (*str) {
temp = *str;
from = 0;
to = 0;
from = tape_parm_strtoul (temp, &temp);
to = from;
if (*temp == '-') {
temp++;
to = tape_parm_strtoul (temp, &temp);
}
tape_create_devregs_range(from,to);
str++;
}
}
/*******************************************************************
* Tape device (td) functions for create, free, enq, deq, enable,
* disable, get and put
*******************************************************************/
/*
* Enable Device
*/
static inline int
tape_enable_device(tape_dev_t* td)
{
#ifdef CONFIG_DEVFS_FS
tape_frontend_t* frontend;
#endif
int rc = 0;
if(td->discipline->setup_device(td) != 0){
rc = -ENOMEM;
goto out;
}
/* Register IRQ */
#ifdef TAPE_CIO_PRIVATE_DATA
#ifdef CONFIG_S390_TAPE_DYNAMIC
rc = s390_request_irq_special (td->devinfo.irq, tape_do_irq,
tape_noper_handler,0, TAPE_MAGIC, &(td->devstat));
#else
rc = s390_request_irq (td->devinfo.irq, tape_do_irq, 0, TAPE_MAGIC, &(td->devstat));
#endif
#else
#ifdef CONFIG_S390_TAPE_DYNAMIC
rc = s390_request_irq_special (td->devinfo.irq, tape_do_irq,
tape_noper_handler,0, (char*)td, &(td->devstat));
#else
rc = s390_request_irq (td->devinfo.irq, tape_do_irq, 0, (char*)td, &(td->devstat));
#endif
#endif /* TAPE_CIO_PRIVATE_DATA */
if (rc){
PRINT_WARN ("Cannot register irq %d, rc=%d\n", td->devinfo.irq, rc);
td->discipline->cleanup_device(td);
goto out;
}
/* Create devfs entries */
#ifdef CONFIG_DEVFS_FS
if (tape_mkdevfsroot(td)==NULL){
PRINT_WARN ("Cannot create a devfs directory for device %04x\n",td->devinfo.devno);
goto out_undo;
}
for (frontend=tape_first_front;frontend!=NULL;frontend=frontend->next){
if(frontend->mkdevfstree(td) == NULL){
goto out_undo;
}
}
#endif
#ifdef TAPE_CIO_PRIVATE_DATA
s390_set_private_data(td->devinfo.irq,td);
#endif
out:
return rc;
out_undo:
tape_disable_device(td);
return -ENOMEM;
}
/*
* Disable Device
*/
static inline void
tape_disable_device(tape_dev_t* td)
{
#ifdef CONFIG_DEVFS_FS
tape_frontend_t* frontend;
#endif
td->discipline->cleanup_device(td);
#ifdef TAPE_CIO_PRIVATE_DATA
s390_set_private_data(td->devinfo.irq,NULL);
#else
ioinfo[td->devinfo.irq]->irq_desc.name = NULL;
#endif
free_irq (td->devinfo.irq, &(td->devstat));
#ifdef CONFIG_DEVFS_FS
for (frontend=tape_first_front;frontend!=NULL;frontend=frontend->next)
frontend->rmdevfstree(td);
tape_rmdevfsroot(td);
#endif
tape_state_set(td,TS_NOT_OPER);
}
/*
* Append Tape device (td) to our tape info list
* Must be called with hold tape_dev_lock
*/
static inline void
tape_enq_device(tape_dev_t* td)
{
tape_dev_t *temptd = NULL;
if (tape_first_dev == NULL) {
tape_first_dev = td;
} else {
temptd = tape_first_dev;
while (temptd->next != NULL)
temptd = temptd->next;
temptd->next = td;
}
}
/*
* Remove Tape device (td) from our tape info list
* Must be called with hold tape_dev_lock
*/
static inline void
tape_deq_device(tape_dev_t* td)
{
tape_dev_t* lasttd;
if (td==tape_first_dev) {
tape_first_dev=td->next;
} else {
lasttd=tape_first_dev;
while (lasttd->next!=td) lasttd=lasttd->next;
lasttd->next=td->next;
}
}
/*
* Get Free minor number
* Must be called with held tape_dev_lock
*/
static inline int
tape_get_new_minor(int devno)
{
int i,tape_num = -1;
tape_dev_t* newtape;
if(!tape_autoprobe){
/* we have static device ranges, so fingure out the */
/* tape_num of the attached tape */
for (i=0;i<tape_devregct;i++){
if (tape_devreg[i]->ci.devno==devno) {
tape_num=TAPE_MINORS_PER_DEV*i;
goto out;
}
}
} else {
/* we are running in autoprobe mode, find a free */
/* tape_num */
i = 0;
newtape=tape_first_dev;
while (newtape!=NULL) {
if (newtape->first_minor==i) {
/* tape num in use. try next one */
i+=TAPE_MINORS_PER_DEV;
newtape=tape_first_dev;
} else {
/* tape num not used by newtape. look at next */
/* tape info */
newtape=newtape->next;
}
}
if(i>255) /* No more minor available */
tape_num = -1;
else
tape_num = i;
}
out:
return tape_num;
}
/*
* Create device: Alloc, enable and enq device
*/
static inline tape_dev_t*
tape_create_device(int irq, int devno, tape_discipline_t* disc)
{
int rc = 0;
int tape_num;
tape_dev_t *td;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
td = kmalloc (sizeof (tape_dev_t), GFP_ATOMIC);
if (td == NULL) {
tape_sprintf_exception (tape_dbf_area,2,"ti:no mem \n");
PRINT_INFO ("tape: can't allocate memory for "
"tape info structure\n");
goto error;
}
memset(td,0,sizeof(tape_dev_t));
tape_num = tape_get_new_minor(devno);
if(tape_num == -1){
PRINT_WARN("tape: could not get minor for tape %x\n",devno);
goto error;
}
rc = get_dev_info_by_irq (irq, &(td->devinfo));
if (rc == -ENODEV) { /* end of device list */
goto error;
}
td->discipline = disc;
atomic_set(&(td->use_count),1);
td->first_minor = tape_num;
td->medium_state = MS_UNKNOWN;
td->next = NULL;
td->discdata = td->treq = NULL;
tape_state_set (td, TS_INIT);
td->discdata=NULL;
td->last_op = TO_NOTHING;
if(td->discipline->setup_device(td) != 0)
goto error;
if(tape_enable_device(td) !=0)
goto error;
tape_enq_device(td);
PRINT_INFO ("using devno %04x with discipline %04x on irq %d as tape device %d\n",devno,disc->cu_type,irq,tape_num/2);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
return td;
error:
tape_sprintf_event (tape_dbf_area,3,"tsetup err: %x\n",rc);
if(td)
kfree (td);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
return NULL;
}
/*
* Free Device storage
*/
static void
tape_free_device(tape_dev_t* td)
{
if (TAPE_BUSY(td))
BUG(); /* one should _not_ free the device when a request is pending */
tape_sprintf_event (tape_dbf_area,6,"free irq: %x\n",td->devinfo.irq);
kfree(td);
}
/*
* Decrement use count of tape structure
* if use count == 0 tape structure is freed
*/
inline void
tape_put_device(tape_dev_t* td)
{
if (td==NULL)
BUG();
if(atomic_dec_and_test(&(td->use_count)))
tape_free_device(td);
}
/*
* Find the tape_dev_t structure associated with member
* and increase use count:
*
* member: TAPE_MEMB_IRQ, TAPE_MEMB_MINOR
*/
tape_dev_t *
__tape_get_device_by_member(unsigned long value, int member)
{
tape_dev_t *td = NULL;
long lockflags;
read_lock_irqsave(&tape_dev_lock,lockflags);
td = tape_first_dev;
while(td != NULL) {
switch(member){
case TAPE_MEMB_IRQ:
if(td->devinfo.irq == value)
goto out;
break;
case TAPE_MEMB_MINOR:
if((value >= td->first_minor) &&
(value < (td->first_minor + TAPE_MINORS_PER_DEV)) )
goto out;
break;
case TAPE_MEMB_QUEUE:
if(((unsigned long)(&td->blk_data.request_queue)) == value)
goto out;
break;
default:
BUG();
}
td = td->next;
}
out:
if(td) // found!
atomic_inc(&(td->use_count));
read_unlock_irqrestore(&tape_dev_lock,lockflags);
return td;
}
/*
* Scan all irqs an create tape devices for all matching cu types
*/
static inline void
tape_create_devs_for_disc(tape_discipline_t* disc)
{
int irq,i;
tape_dev_t* td = NULL;
s390_dev_info_t dinfo;
for (irq = get_irq_first(); irq!=-ENODEV; irq=get_irq_next(irq)) {
if(get_dev_info_by_irq (irq, &dinfo) == -ENODEV)
continue;
if(disc->cu_type != dinfo.sid_data.cu_type)
/* Wrong type - try next one */
continue;
tape_sprintf_event (tape_dbf_area,3,"det irq: %x\n",irq);
tape_sprintf_event (tape_dbf_area,3,"cu : %x\n",disc->cu_type);
if(!tape_autoprobe) {
for( i=0; i<tape_devregct; i++ ) {
if(tape_devreg[i]->ci.devno == dinfo.devno) {
td = tape_create_device(irq, dinfo.devno, disc);
if(!td) {
PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno);
continue;
}
if(disc->init_device)
disc->init_device(td); /* XXX */
tape_state_set (td, TS_UNUSED);
break;
}
}
}
else {
td = tape_create_device(irq,dinfo.devno,disc);
if(!td){
PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno);
continue;
}
if(disc->init_device)
disc->init_device(td); /* XXX */
tape_state_set (td, TS_UNUSED);
}
}
}
/*
* Go through our tape info list and disable, deq and free all devices with
* matching cu type
*/
static inline void
tape_delete_devs_for_disc(tape_discipline_t* disc)
{
tape_dev_t *td;
long lockflags;
write_lock_irqsave(&tape_dev_lock,lockflags);
td = tape_first_dev;
while (td !=NULL){
if(td->discipline == disc){
tape_deq_device(td);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
tape_disable_device(td);
tape_put_device(td);
write_lock_irqsave(&tape_dev_lock,lockflags);
td = tape_first_dev;
} else {
td=td->next;
}
}
write_unlock_irqrestore(&tape_dev_lock,lockflags);
}
/*******************************************************************
* TAPE Request and IO Functions
*******************************************************************/
/*
* Allocate a new tape ccw request
*/
inline tape_ccw_req_t *
tape_alloc_ccw_req (int cplength, int datasize,int idal_buf_size, tape_op_t operation)
{
tape_ccw_req_t* treq;
int kmalloc_flags;
if(in_interrupt())
kmalloc_flags = GFP_ATOMIC;
else
kmalloc_flags = GFP_KERNEL;
treq = (tape_ccw_req_t*) kmalloc(sizeof(tape_ccw_req_t),kmalloc_flags);
if(!treq)
goto error;
memset(treq,0,sizeof(tape_ccw_req_t));
treq->kernbuf_size = datasize;
treq->userbuf_size = datasize;
treq->op = operation;
treq->cplength = cplength;
init_waitqueue_head (&treq->wq);
// alloc small kernel buffer
if(datasize > PAGE_SIZE)
BUG();
if(datasize > 0){
// the kernbuf must be below 2GB --> GFP_DMA
treq->kernbuf = kmalloc(datasize,kmalloc_flags | GFP_DMA);
if(!treq->kernbuf)
goto error;
memset(treq->kernbuf, 0, datasize);
}
// alloc idal kernel buffer
if(idal_buf_size > 0){
treq->idal_buf = idalbuf_alloc(idal_buf_size);
if(!treq->idal_buf)
goto error;
}
if(cplength < 0)
BUG();
// the channel program must be below 2GB --> GFP_DMA
treq->cpaddr = kmalloc(cplength * sizeof(ccw1_t), kmalloc_flags | GFP_DMA);
if(!treq->cpaddr)
goto error;
memset(treq->cpaddr, 0, cplength*sizeof(ccw1_t));
return treq;
error:
tape_sprintf_exception (tape_dbf_area,1,"cqra nomem\n");
if(treq)
tape_free_ccw_req(treq);
return NULL;
}
/*
* Free tape ccw request
*/
void
tape_free_ccw_req (tape_ccw_req_t * treq)
{
if(!treq)
BUG();
if(treq->cpaddr)
kfree(treq->cpaddr);
if(treq->kernbuf)
kfree(treq->kernbuf);
if(treq->idal_buf)
idalbuf_free(treq->idal_buf);
kfree(treq);
}
/*
* Add request to request queue (At the moment queue length = 1)
*/
static inline int
tape_add_ccw_req(tape_dev_t* td,tape_ccw_req_t* treq)
{
if(td->treq)
return -1;
td->treq = treq;
treq->tape_dev = td;
return 0;
}
/*
* Remove request from request queue (At the moment queue length = 1)
*/
int
tape_remove_ccw_req(tape_dev_t* td,tape_ccw_req_t* treq)
{
if(treq != td->treq)
BUG();
td->last_op = treq->op;
td->treq=NULL;
treq->tape_dev=NULL;
return 0;
}
/*
* Get the active ccw request
*/
tape_ccw_req_t*
tape_get_active_ccw_req(tape_dev_t* td)
{
return td->treq;
}
/*
* Stop the active ccw request
*/
static inline int
tape_halt_io(tape_dev_t* td)
{
int retries = 0;
int irq = td->devinfo.irq;
int rc = 0;
long lockflags;
tape_ccw_req_t* treq;
s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags);
treq = tape_get_active_ccw_req(td);
/* check if interrupt has already been processed */
if(!treq)
goto out;
if(treq->wakeup == NULL)
goto out;
while (retries < 5){
if ( retries < 2 )
rc = halt_IO(irq, (long)treq, treq->options);
else
rc = clear_IO(irq, (long)treq, treq->options);
switch (rc) {
case 0: /* termination successful */
rc = -ERESTARTSYS;
goto out;
case -ENODEV:
PRINT_INFO ("device gone, retry\n"); /* FIXME: s390dbf only */
break;
case -EIO:
PRINT_INFO ("I/O error, retry\n"); /* FIXME: s390dbf only */
break;
case -EBUSY:
PRINT_INFO ( "device busy, retry later\n"); /* FIXME: s390dbf only */
break;
default:
PRINT_ERR ( "line %d unknown RC=%d, please report"
" to linux390@de.ibm.com\n", __LINE__, rc);
BUG ();
}
retries ++;
}
out:
s390irq_spin_unlock_irqrestore(td->devinfo.irq, lockflags);
return rc;
}
/*
* The tape IO function:
* tape_do_io MUST be called with locked td lock!
*/
static inline int
__tape_do_io(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type,int io)
{
int rc = 0;
if ((td==NULL) || (treq==NULL))
BUG();
if(tape_state_get(td) == TS_NOT_OPER){
rc = -ENODEV;
goto out;
}
if(TAPE_BUSY(td)){
tape_sprintf_event (tape_dbf_area,1,"tape: IRQ - Tape busy\n");
rc = -EBUSY;
goto out;
}
tape_add_ccw_req(td,treq);
switch(type){
case TAPE_REMOVE_REQ_ON_WAKEUP:
treq->wakeup = tape_wake_up_remove;
break;
case TAPE_NO_WAIT:
// needed for retry
break;
case TAPE_WAIT:
treq->wakeup = tape_wake_up;
treq->wait = tape_wait_event;
break;
case TAPE_WAIT_INTERRUPTIBLE:
treq->wakeup = tape_wake_up_interruptible;
treq->wait = tape_wait_event_interruptible;
break;
case TAPE_WAIT_INTERRUPTIBLE_NOHALTIO:
// neded for dummy load
treq->wakeup = tape_wake_up_interruptible;
treq->wait = tape_wait_event_interruptible_nohaltio;
break;
#ifdef CONFIG_S390_TAPE_BLOCK
case TAPE_SCHED_BLOCK:
treq->wakeup = tape_schedule_tapeblock;
treq->wait = NULL;
break;
#endif
default:
BUG();
}
if(io)
rc = do_IO(td->devinfo.irq,treq->cpaddr,
(unsigned long)treq, 0x00, treq->options);
if(rc) {
tape_sprintf_event (tape_dbf_area,1,"tape: DOIO failed with er = %i\n",rc);
treq->wakeup = NULL;
treq->wait = NULL; /*XXX ??*/
tape_remove_ccw_req(td,treq);
}
out:
return rc;
}
/*
* Do the io request and wait for it
*/
int
tape_do_io_and_wait(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type)
{
int rc = 0;
long lockflags;
if (td==NULL)
BUG();
s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags);
rc = __tape_do_io(td,treq,type,TAPE_DO_IO);
s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags);
if(rc == 0)
tape_wait(treq);
return rc;
}
/*
* Needed for MTLOAD: Just create a wait request without doing io
*/
int
tape_do_wait_req(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type)
{
int rc = 0;
long lockflags;
if (td==NULL)
BUG();
s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags);
rc = __tape_do_io(td,treq,type,TAPE_NO_IO);
s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags);
tape_wait(treq);
return rc;
}
/*
* Just do the io
*/
int
tape_do_io(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type)
{
int rc = 0;
long lockflags;
s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags);
rc = __tape_do_io(td,treq,type,TAPE_DO_IO);
s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags);
return rc;
}
/*
* Just do the io, but we are already locked here (in irq)
*/
int
tape_do_io_irq(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type)
{
return __tape_do_io(td,treq,type,TAPE_DO_IO);
}
/*
* Wait for an io request
*/
static void
tape_wait(tape_ccw_req_t* treq)
{
tape_dev_t* td;
if(treq==NULL)
BUG();
td = treq->tape_dev;
if (td==NULL)
BUG();
if(treq->wait==NULL)
BUG();
treq->wait(treq);
tape_remove_ccw_req(td,treq);
}
/*
* Tape interrupt routine, called from Ingo's I/O layer
*/
static void
tape_do_irq (int irq, void *int_parm, struct pt_regs *regs)
{
tape_dev_t *td;
#ifdef TAPE_CIO_PRIVATE_DATA
td = (tape_dev_t*)s390_get_private_data(irq);
#else
td = (tape_dev_t*)ioinfo[irq]->irq_desc.name;
#endif
if(!td) {
PRINT_ERR ("tape: could not get device structure for irq %d in interrupt\n",irq);
goto out;
}
if(td->devstat.dstat != 0x0c){
tape_sprintf_event (tape_dbf_area,3,"-- Tape Interrupthandler --\n");
tape_dump_sense_dbf(td);
}
if (tape_state_get(td) == TS_NOT_OPER) {
tape_sprintf_event (tape_dbf_area,6,"tape:device is not operational\n");
goto out;
}
td->discipline->irq(td);
out:
return;
}
/*
* Oper Handler is called from Ingo's I/O layer when a new tape device is
* attached. We create a new devinfo for the new device, enable and enq it.
*/
static int
tape_oper_handler ( int irq, struct _devreg *dreg) {
tape_dev_t* td=tape_first_dev;
int rc=0;
s390_dev_info_t dinfo;
tape_discipline_t* disc;
long lockflags;
td = tape_get_device_by_irq(irq);
if (td!=NULL) {
// irq is (still) used by tape. tell ingo to try again later
PRINT_ERR ("tape:Oper handler for irq %d called, but irq is still (internally) used.\n",irq);
rc = -EAGAIN;
goto out;
}
rc = get_dev_info_by_irq (irq, &dinfo);
if (rc == -ENODEV) {
PRINT_ERR ("tape: Cannot get dev info for irq %d in the oper handler.\n",irq);
rc = -EAGAIN;
goto out;
}
read_lock_irqsave(&tape_discipline_lock,lockflags);
disc = tape_first_disc;
while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
disc = (tape_discipline_t *) (disc->next);
if (disc == NULL){
PRINT_WARN ("tape: No matching discipline for cu_type %x found in the oper handler, ignoring device %04x.\n",dinfo.sid_data.cu_type,dinfo.devno);
rc = -ENODEV;
goto out_unlock;
}
/* Allocate tape structure */
td = tape_create_device(irq,dinfo.devno,disc);
if (td == NULL) {
PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno);
rc = -ENOBUFS;
goto out_unlock;
} else {
if(disc->init_device)
disc->init_device(td);
}
tape_state_set (td, TS_UNUSED);
out_unlock:
read_unlock_irqrestore(&tape_discipline_lock,lockflags);
out:
return rc;
}
/*
* Not Oper Handler is called from Ingo's IO layer, when a tape device
* is detached. We deq, disable and free the tape info for this device
*/
static void
tape_noper_handler ( int irq, int status ) {
tape_dev_t *td;
long lockflags;
tape_ccw_req_t *treq;
td = tape_get_device_by_irq(irq);
if (td==NULL) {
PRINT_ERR("tape: not operational handler called for irq %x, but tape does not hold this irq.\n",irq);
goto error;
}
write_lock_irqsave(&tape_dev_lock,lockflags);
tape_deq_device(td);
write_unlock_irqrestore(&tape_dev_lock,lockflags);
tape_disable_device(td);
s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags);
treq = tape_get_active_ccw_req(td);
if (treq) {
// device is in use!
treq->rc= -ENODEV;
if(treq->wakeup)
treq->wakeup (treq);
PRINT_WARN ("Tape #%d is detached while it was busy.\n",td->first_minor/TAPE_MINORS_PER_DEV);
} else {
// device is unused!
PRINT_WARN ("Tape #%d is detached now.\n",td->first_minor/TAPE_MINORS_PER_DEV);
}
s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags);
/* decrement use count twice ! */
tape_put_device(td);
tape_put_device(td);
error:
return;
}
/*
* Write sense data to dbf
*/
void tape_dump_sense_dbf(tape_dev_t* td)
{
devstat_t *stat = &td->devstat;
const char* op;
if(TAPE_BUSY(td))
op = tape_op_verbose[tape_get_active_ccw_req(td)->op];
else
op = "---";
tape_sprintf_event (tape_dbf_area,3,"DSTAT : %02x CSTAT: %02x\n",stat->dstat,stat->cstat);
tape_sprintf_event (tape_dbf_area,3,"DEVICE: %04x OP : %s\n",td->devinfo.devno,op);
tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[0]),*((unsigned int*)&stat->ii.sense.data[4]));
tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[8]),*((unsigned int*)&stat->ii.sense.data[12]));
tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[16]),*((unsigned int*)&stat->ii.sense.data[20]));
tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[24]),*((unsigned int*)&stat->ii.sense.data[28]));
}
/*
* Write sense data to console/dbf
*/
void
tape_dump_sense (tape_dev_t* td)
{
devstat_t *stat = &td->devstat;
#if 1 /* XXX */
PRINT_INFO ("-------------------------------------------------\n");
PRINT_INFO ("DSTAT : %02x CSTAT: %02x CPA: %04x\n",stat->dstat,stat->cstat,stat->cpa);
PRINT_INFO ("DEVICE: %04x\n",td->devinfo.devno);
if(TAPE_BUSY(td))
PRINT_INFO("OP : %s\n",tape_op_verbose[tape_get_active_ccw_req(td)->op]);
PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
" %02X%02X%02X%02X %02X%02X%02X%02X \n",
stat->ii.sense.data[0], stat->ii.sense.data[1],
stat->ii.sense.data[2], stat->ii.sense.data[3],
stat->ii.sense.data[4], stat->ii.sense.data[5],
stat->ii.sense.data[6], stat->ii.sense.data[7],
stat->ii.sense.data[8], stat->ii.sense.data[9],
stat->ii.sense.data[10], stat->ii.sense.data[11],
stat->ii.sense.data[12], stat->ii.sense.data[13],
stat->ii.sense.data[14], stat->ii.sense.data[15]);
PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
" %02X%02X%02X%02X %02X%02X%02X%02X \n",
stat->ii.sense.data[16], stat->ii.sense.data[17],
stat->ii.sense.data[18], stat->ii.sense.data[19],
stat->ii.sense.data[20], stat->ii.sense.data[21],
stat->ii.sense.data[22], stat->ii.sense.data[23],
stat->ii.sense.data[24], stat->ii.sense.data[25],
stat->ii.sense.data[26], stat->ii.sense.data[27],
stat->ii.sense.data[28], stat->ii.sense.data[29],
stat->ii.sense.data[30], stat->ii.sense.data[31]);
PRINT_INFO ("--------------------------------------------------\n");
#endif
}
/*******************************************************************
* TAPE Discipline functions
*******************************************************************/
/*
* Register backend discipline
*/
int
tape_register_discipline(tape_discipline_t *disc)
{
tape_discipline_t *disc_ptr;
long lockflags;
disc->next = NULL;
write_lock_irqsave(&tape_discipline_lock,lockflags);
if (tape_first_disc == NULL) {
tape_first_disc = disc;
} else {
for(disc_ptr = tape_first_disc; disc_ptr->next!=NULL; disc_ptr=(tape_discipline_t*)disc_ptr->next);
disc_ptr->next = disc;
}
tape_create_devs_for_disc(disc);
if(tape_autoprobe)
tape_create_devreg_for_disc(disc);
write_unlock_irqrestore(&tape_discipline_lock,lockflags);
return 0;
}
/*
* Unregister backend discipline
*/
void
tape_unregister_discipline(tape_discipline_t* disc)
{
tape_discipline_t* lastdisc;
long lockflags;
write_lock_irqsave(&tape_discipline_lock,lockflags);
tape_delete_devs_for_disc(disc);
if(tape_autoprobe)
tape_delete_devreg_for_disc(disc);
if (disc==tape_first_disc) {
tape_first_disc=disc->next;
} else {
lastdisc=tape_first_disc;
while (lastdisc->next!=disc) lastdisc=lastdisc->next;
lastdisc->next=disc->next;
}
disc->shutdown();
write_unlock_irqrestore(&tape_discipline_lock,lockflags);
}
/*
* Cleanup all registered disciplines
*/
static inline void
tape_cleanup_disciplines (void)
{
long lockflags;
tape_discipline_t* disc;
/* Unregister all backend disciplines - this also deletes the devices */
write_lock_irqsave(&tape_discipline_lock,lockflags);
disc=tape_first_disc;
while (disc != NULL) {
write_unlock_irqrestore(&tape_discipline_lock,lockflags);
tape_unregister_discipline(disc);
kfree(disc);
write_lock_irqsave(&tape_discipline_lock,lockflags);
disc=tape_first_disc;
}
write_unlock_irqrestore(&tape_discipline_lock,lockflags);
}
/*******************************************************************
* TAPE Init Functions
*******************************************************************/
/*
* tape_print_banner will be called on initialisation and print a nice banner
*/
static inline void
tape_print_banner (void)
{
char *opt_char,*opt_block;
/* print banner */
PRINT_WARN ("IBM zSeries Tape Device Driver (v%d.%02d).\n",TAPE_VERSION_MAJOR,TAPE_VERSION_MINOR);
PRINT_WARN ("(C) IBM Deutschland Entwicklung GmbH, 2000 - 2001\n");
opt_char=opt_block="not present";
#ifdef CONFIG_S390_TAPE_CHAR
opt_char="built in";
#endif
#ifdef CONFIG_S390_TAPE_BLOCK
opt_block="built in";
#endif
/* print feature info */
PRINT_WARN ("character device frontend : %s\n",opt_char);
PRINT_WARN ("block device frontend : %s\n",opt_block);
}
/*
* tape_init will register the driver for each tape.
*/
int
tape_init (void)
{
static int initialized=0;
if (initialized) // Only init the devices once
return 0;
initialized=1;
tape_init_devregs();
#ifdef TAPE_DEBUG
tape_dbf_area = debug_register ( "tape", 2, 2, 3*sizeof(long));
debug_register_view(tape_dbf_area,&debug_sprintf_view);
tape_sprintf_event (tape_dbf_area,3,"begin init\n");
#endif /* TAPE_DEBUG */
tape_print_banner();
#ifndef MODULE
tape_split_parm_string(tape_parm_string);
#endif
#ifdef CONFIG_DEVFS_FS
devfs_mk_dir (NULL, "tape", NULL);
#endif /* CONFIG_DEVFS_FS */
tape_sprintf_event (tape_dbf_area,3,"dev detect\n");
/* Allocate the tape structures */
if (*tape!=NULL) { /* if parameters are present */
PRINT_INFO ("Using ranges supplied in parameters, disabling autoprobe mode.\n");
tape_parm_parse (tape);
tape_autoprobe = 0;
} else {
PRINT_INFO ("No parameters supplied, enabling autoprobe mode for all supported devices.\n");
tape_autoprobe = 1;
}
#ifdef CONFIG_PROC_FS
tape_proc_init();
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_S390_TAPE_3480
tape_register_discipline(tape3480_init());
#else
#ifndef CONFIG_S390_TAPE
tape_request_module("tape_3480_mod");
#endif
#endif /* CONFIG_S390_TAPE_3480 */
#ifdef CONFIG_S390_TAPE_3490
tape_register_discipline(tape3490_init());
#else
#ifndef CONFIG_S390_TAPE
tape_request_module("tape_3490_mod");
#endif
#endif /* CONFIG_S390_TAPE_3490 */
#ifdef CONFIG_S390_TAPE_3590
tape_register_discipline(tape3590_init());
#else
#ifndef CONFIG_S390_TAPE
tape_request_module("tape_3590_mod");
#endif
#endif /* CONFIG_S390_TAPE_3590 */
return 0;
}
/*******************************************************************
* TAPE Module functions
*******************************************************************/
#ifdef MODULE
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver");
MODULE_PARM (tape, "1-" __MODULE_STRING (256) "s");
/*
* The famous init_module
*/
int
init_module (void)
{
#ifdef CONFIG_S390_TAPE_CHAR
tapechar_init ();
#endif
#ifdef CONFIG_S390_TAPE_BLOCK
tapeblock_init ();
#endif
return 0;
}
/*
* Cleanup the frontends
*/
static inline void
tape_cleanup_frontends(void)
{
tape_frontend_t* frontend, *tempfe;
/* Now get rid of the frontends */
#ifdef CONFIG_S390_TAPE_CHAR
tapechar_uninit();
#endif
#ifdef CONFIG_S390_TAPE_BLOCK
tapeblock_uninit();
#endif
frontend=tape_first_front;
while (frontend != NULL) {
tempfe = frontend;
frontend = frontend->next;
kfree (tempfe);
}
}
/*
* Cleanup module
*/
void
cleanup_module (void)
{
tape_sprintf_event (tape_dbf_area,6,"cleaup mod");
tape_cleanup_disciplines();
#ifdef CONFIG_DEVFS_FS
devfs_remove("tape"); /* devfs checks for NULL */
#endif CONFIG_DEVFS_FS
#ifdef CONFIG_PROC_FS
tape_proc_cleanup();
#endif
tape_cleanup_frontends();
/* Deallocate devregs in case of not autoprobe */
if(!tape_autoprobe)
tape_delete_all_devregs();
#ifdef TAPE_DEBUG
debug_unregister (tape_dbf_area);
#endif /* TAPE_DEBUG */
}
#endif /* MODULE */
/*******************************************************************
* TAPE Tapestate functions
*******************************************************************/
inline void
tape_state_set (tape_dev_t * td, tape_state_t newstate)
{
if (td->tape_state == TS_NOT_OPER) {
tape_sprintf_event(tape_dbf_area,3,"ts_set err: not oper\n");
} else {
tape_sprintf_event(tape_dbf_area,4,"ts. dev: %x\n",td->first_minor);
tape_sprintf_event(tape_dbf_area,4,"old ts: %s\n",(((tape_state_get (td) < TO_SIZE) && (tape_state_get (td) >=0 )) ? tape_state_verbose[tape_state_get (td)] : "UNKNOWN TS"));
tape_sprintf_event(tape_dbf_area,4,"%s\n",
(((tape_state_get (td) < TO_SIZE) &&
(tape_state_get (td) >=0 )) ?
tape_state_verbose[tape_state_get (td)] :
"UNKNOWN TS"));
tape_sprintf_event (tape_dbf_area,4,"new ts: \n");
tape_sprintf_event (tape_dbf_area,4,"%s\n",(((newstate < TO_SIZE) &&
(newstate >= 0)) ?
tape_state_verbose[newstate] :
"UNKNOWN TS"));
td->tape_state = newstate;
}
}
inline tape_state_t
tape_state_get (tape_dev_t * td)
{
return (td->tape_state);
}
inline void
tape_med_state_set(tape_dev_t * td, tape_medium_state_t newstate)
{
if(td->medium_state == newstate)
goto out;
switch(newstate){
case MS_UNLOADED:
PRINT_INFO("(%x): Tape is unloaded\n",td->devstat.devno);
break;
case MS_LOADED:
PRINT_INFO("(%x): Tape has been mounted\n",td->devstat.devno);
break;
default:
// print nothing
break;
}
td->medium_state = newstate;
out:
return;
}
/*******************************************************************
* TAPE Exported Functions
*******************************************************************/
EXPORT_SYMBOL(tape_register_discipline);
EXPORT_SYMBOL(tape_unregister_discipline);
EXPORT_SYMBOL(tape_dbf_area);
EXPORT_SYMBOL(tape_alloc_ccw_req);
EXPORT_SYMBOL(tape_free_ccw_req);
EXPORT_SYMBOL(tape_state_set);
EXPORT_SYMBOL(tape_state_get);
EXPORT_SYMBOL(tape_med_state_set);
EXPORT_SYMBOL(tape_state_verbose);
EXPORT_SYMBOL(tape_op_verbose);
EXPORT_SYMBOL(tape_dump_sense);
EXPORT_SYMBOL(tape_dump_sense_dbf);
EXPORT_SYMBOL(tape_do_io);
EXPORT_SYMBOL(tape_do_io_irq);
EXPORT_SYMBOL(tape_do_io_and_wait);
EXPORT_SYMBOL(tape_remove_ccw_req);
EXPORT_SYMBOL(tape_get_active_ccw_req);
......@@ -3,7 +3,7 @@
#
obj-y += airq.o blacklist.o chsc.o cio.o css.o requestirq.o
export-objs += airq.o css.o chsc.o cio.o requestirq.o
export-objs += airq.o css.o cio.o requestirq.o
ccw_device-objs += device.o device_fsm.o device_ops.o
ccw_device-objs += device_id.o device_pgid.o device_status.o
......
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
* $Revision: 1.22 $
* $Revision: 1.23 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -162,10 +162,10 @@ blacklist_parse_proc_parameters (char *buf)
else
blacklist_parse_parameters (buf + 5, free);
} else if (strncmp (buf, "add ", 4) == 0) {
/* FIXME: the old code was checking if the new bl'ed
* devices are already known to the system so
* validate_subchannel would still give a working
* status. is that necessary? */
/*
* We don't need to check for known devices since
* css_probe_device will handle this correctly.
*/
blacklist_parse_parameters (buf + 4, add);
} else {
printk (KERN_WARNING "cio_ignore: Parse error; \n"
......
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
* $Revision: 1.43 $
* $Revision: 1.46 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -37,26 +37,6 @@ static int cio_chsc_desc_avail;
static int new_channel_path(int chpid, int status);
int
chsc(void *data)
{
void *area;
int cc;
if (!data)
return -EINVAL;
area = (void *)get_zeroed_page(GFP_KERNEL);
if (!area)
return -ENOMEM;
memcpy(area, data, PAGE_SIZE);
cc = do_chsc(area);
if (cc == 0)
memcpy(data, area, PAGE_SIZE);
free_page((unsigned long)area);
return cc;
}
static int
set_chp_status(int chp, int status)
{
......@@ -114,22 +94,19 @@ chsc_get_sch_desc_irq(int irq)
* be page-aligned. Implement proper locking or dynamic
* allocation or prove that this function does not have to be
* reentrant! */
static struct chsc_area __attribute__ ((aligned(PAGE_SIZE))) chsc_area_ssd;
static struct ssd_area chsc_area_ssd
__attribute__ ((aligned(PAGE_SIZE)));
typeof (chsc_area_ssd.response_block.response_block_data.ssd_res)
*ssd_res = &chsc_area_ssd.response_block.response_block_data.ssd_res;
typeof (chsc_area_ssd.response_block)
*ssd_res = &chsc_area_ssd.response_block;
chsc_area_ssd = (struct chsc_area) {
chsc_area_ssd = (struct ssd_area) {
.request_block = {
.command_code1 = 0x0010,
.command_code2 = 0x0004,
.request_block_data = {
.ssd_req = {
.f_sch = irq,
.l_sch = irq,
}
}
}
};
ccode = chsc(&chsc_area_ssd);
......@@ -306,14 +283,59 @@ s390_set_chpid_offline( __u8 chpid)
#endif
}
/* this used to be in s390_process_res_acc_*, FIXME: find a better name
* for this function */
static int
s390_check_valid_chpid(u8 chpid)
s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
struct subchannel *sch)
{
int found;
int chp;
int ccode;
/* Update our ssd_info */
if (chsc_get_sch_desc_irq(sch->irq))
return 0;
found = 0;
for (chp = 0; chp <= 7; chp++)
/*
* check if chpid is in information updated by ssd
*/
if (sch->ssd_info.valid &&
sch->ssd_info.chpid[chp] == chpid &&
(sch->ssd_info.fla[chp] & fla_mask) == fla) {
found = 1;
break;
}
if (found == 0)
return 0;
/*
* Do a stsch to update our subchannel structure with the
* new path information and eventually check for logically
* offline chpids.
*/
ccode = stsch(sch->irq, &sch->schib);
if (ccode > 0)
return 0;
return 0x80 >> chp;
}
static void
s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
{
struct subchannel *sch;
int irq;
int ret;
char dbf_txt[15];
sprintf(dbf_txt, "accpr%x", chpid);
CIO_TRACE_EVENT( 2, dbf_txt);
if (fla != 0) {
sprintf(dbf_txt, "fla%x", fla);
CIO_TRACE_EVENT( 2, dbf_txt);
}
/*
* I/O resources may have become accessible.
......@@ -333,31 +355,14 @@ s390_check_valid_chpid(u8 chpid)
CIO_CRW_EVENT(0, "Error: Could not retrieve "
"subchannel descriptions, will not process css"
"machine check...\n");
return 0;
return;
}
if (!test_bit(chpid, chpids_logical))
return 0; /* no need to do the rest */
return 1;
}
static void
s390_process_res_acc_chpid (u8 chpid)
{
struct subchannel *sch;
int irq;
int ccode;
int chp;
int ret;
if (!s390_check_valid_chpid(chpid))
return;
pr_debug( KERN_DEBUG "Looking at chpid %x...\n", chpid);
return; /* no need to do the rest */
for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
int found;
int chp_mask;
sch = ioinfo[irq];
if (!sch) {
......@@ -378,118 +383,29 @@ s390_process_res_acc_chpid (u8 chpid)
spin_lock_irq(&sch->lock);
/* Update our ssd_info */
if (chsc_get_sch_desc_irq(sch->irq))
break;
found = 0;
for (chp = 0; chp <= 7; chp++)
/*
* check if chpid is in information updated by ssd
*/
if (sch->ssd_info.valid &&
(sch->ssd_info.chpid[chp] == chpid)) {
found = 1;
break;
}
chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch);
if (chp_mask == 0) {
if (found == 0) {
spin_unlock_irq(&sch->lock);
continue;
}
/*
* Do a stsch to update our subchannel structure with the
* new path information and eventually check for logically
* offline chpids.
*/
ccode = stsch(sch->irq, &sch->schib);
if (ccode > 0) {
// FIXME: ccw_device_recognition(cdev);
spin_unlock_irq(&sch->lock);
if (fla_mask != 0)
break;
else
continue;
}
sch->lpm = sch->schib.pmcw.pim &
sch->lpm = (sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom;
sch->schib.pmcw.pom)
| chp_mask;
chsc_validate_chpids(sch);
sch->lpm |= (0x80 >> chp);
dev_fsm_event(sch->dev.driver_data, DEV_EVENT_VERIFY);
spin_unlock_irq(&sch->lock);
}
}
static void
s390_process_res_acc_linkaddr ( __u8 chpid, __u16 fla, u32 fla_mask)
{
char dbf_txt[15];
struct subchannel *sch;
int irq;
int ccode;
int ret;
int j;
if (!s390_check_valid_chpid(chpid))
return;
sprintf(dbf_txt, "fla%x", fla);
CIO_TRACE_EVENT( 2, dbf_txt);
pr_debug(KERN_DEBUG "Looking at chpid %x, link addr %x...\n", chpid, fla);
for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
int found;
sch = ioinfo[irq];
if (!sch) {
/* The full program again (see above), grr... */
ret = css_probe_device(irq);
if (ret == -ENXIO)
/* We're through */
return;
return;
}
/*
* Walk through all subchannels and
* look if our chpid and our (masked) link
* address are in somewhere
* Do a stsch for the found subchannels and
* perform path grouping
*/
/* Update our ssd_info */
if (chsc_get_sch_desc_irq(sch->irq))
break;
found = 0;
for (j = 0; j < 8; j++)
if (sch->ssd_info.valid &&
sch->ssd_info.chpid[j] == chpid &&
(sch->ssd_info.fla[j] & fla_mask) == fla) {
found = 1;
break;
}
if (found == 0)
continue;
ccode = stsch(sch->irq, &sch->schib);
if (ccode > 0)
break;
sch->lpm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom;
chsc_validate_chpids(sch);
sch->lpm |= (0x80 >> j);
dev_fsm_event(sch->dev.driver_data, DEV_EVENT_VERIFY);
/* We've found it, get out of here. */
if (fla_mask != 0)
break;
}
}
......@@ -508,7 +424,7 @@ do_process_crw(void *ignore)
* be page-aligned. Implement proper locking or dynamic
* allocation or prove that this function does not have to be
* reentrant! */
static struct chsc_area chsc_area_sei
static struct sei_area chsc_area_sei
__attribute__ ((aligned(PAGE_SIZE))) = {
.request_block = {
.command_code1 = 0x0010,
......@@ -516,8 +432,8 @@ do_process_crw(void *ignore)
}
};
typeof (chsc_area_sei.response_block.response_block_data.sei_res)
*sei_res = &chsc_area_sei.response_block.response_block_data.sei_res;
typeof (chsc_area_sei.response_block)
*sei_res = &chsc_area_sei.response_block;
CIO_TRACE_EVENT( 2, "prcss");
......@@ -582,17 +498,17 @@ do_process_crw(void *ignore)
if ((sei_res->vf & 0x80) == 0) {
pr_debug( KERN_DEBUG "chpid: %x\n", sei_res->rsid);
s390_process_res_acc_chpid (sei_res->rsid);
s390_process_res_acc(sei_res->rsid, 0, 0);
} else if ((sei_res->vf & 0xc0) == 0x80) {
pr_debug( KERN_DEBUG "chpid: %x link addr: %x\n",
sei_res->rsid, sei_res->fla);
s390_process_res_acc_linkaddr (sei_res->rsid,
sei_res->fla, 0xff00);
s390_process_res_acc(sei_res->rsid, sei_res->fla,
0xff00);
} else if ((sei_res->vf & 0xc0) == 0xc0) {
pr_debug( KERN_DEBUG "chpid: %x full link addr: %x\n",
sei_res->rsid, sei_res->fla);
s390_process_res_acc_linkaddr (sei_res->rsid,
sei_res->fla, 0xffff);
s390_process_res_acc(sei_res->rsid, sei_res->fla,
0xffff);
}
pr_debug( KERN_DEBUG "\n");
......@@ -810,4 +726,3 @@ register_channel_paths(void)
}
module_init(register_channel_paths);
EXPORT_SYMBOL(chsc);
......@@ -12,6 +12,86 @@
#define CHSC_SEI_ACC_LINKADDR 2
#define CHSC_SEI_ACC_FULLLINKADDR 3
struct sei_area {
struct {
/* word 0 */
__u16 command_code1;
__u16 command_code2;
/* word 1 */
__u32 reserved1;
/* word 2 */
__u32 reserved2;
/* word 3 */
__u32 reserved3;
} __attribute__ ((packed,aligned(8))) request_block;
struct {
/* word 0 */
__u16 length;
__u16 response_code;
/* word 1 */
__u32 reserved1;
/* word 2 */
__u8 flags;
__u8 vf; /* validity flags */
__u8 rs; /* reporting source */
__u8 cc; /* content code */
/* word 3 */
__u16 fla; /* full link address */
__u16 rsid; /* reporting source id */
/* word 4 */
__u32 reserved2;
/* word 5 */
__u32 reserved3;
/* word 6 */
__u32 ccdf; /* content-code dependent field */
/* word 7 */
__u32 reserved4;
/* word 8 */
__u32 reserved5;
/* word 9 */
__u32 reserved6;
} __attribute__ ((packed,aligned(8))) response_block;
} __attribute__ ((packed,aligned(PAGE_SIZE)));
struct ssd_area {
struct {
/* word 0 */
__u16 command_code1;
__u16 command_code2;
/* word 1 */
__u16 reserved1;
__u16 f_sch; /* first subchannel */
/* word 2 */
__u16 reserved2;
__u16 l_sch; /* last subchannel */
/* word 3 */
__u32 reserved3;
} __attribute__ ((packed,aligned(8))) request_block;
struct {
/* word 0 */
__u16 length;
__u16 response_code;
/* word 1 */
__u32 reserved1;
/* word 2 */
__u8 sch_valid : 1;
__u8 dev_valid : 1;
__u8 st : 3; /* subchannel type */
__u8 zeroes : 3;
__u8 unit_addr; /* unit address */
__u16 devno; /* device number */
/* word 3 */
__u8 path_mask;
__u8 fla_valid_mask;
__u16 sch; /* subchannel */
/* words 4-5 */
__u8 chpid[8]; /* chpids 0-7 */
/* words 6-9 */
__u16 fla[8]; /* full link addresses 0-7 */
} __attribute__ ((packed,aligned(8))) response_block;
} __attribute__ ((packed,aligned(PAGE_SIZE)));
struct channel_path {
int id;
int state;
......
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
* $Revision: 1.89 $
* $Revision: 1.90 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -609,6 +609,7 @@ do_IRQ (struct pt_regs regs)
struct subchannel *sch;
struct irb *irb;
irq_enter ();
/*
* Get interrupt information from lowcore
*/
......@@ -620,28 +621,23 @@ do_IRQ (struct pt_regs regs)
*/
if (tpi_info->adapter_IO == 1 &&
tpi_info->int_type == IO_INTERRUPT_TYPE) {
irq_enter ();
do_adapter_IO (tpi_info->intparm);
irq_exit ();
continue;
}
/* Store interrupt response block to lowcore. */
if (tsch (tpi_info->irq, irb) != 0)
/* Not status pending or not operational. */
continue;
sch = ioinfo[tpi_info->irq];
if (!sch)
continue;
irq_enter ();
if (sch)
spin_lock(&sch->lock);
memcpy (&sch->schib.scsw, &irb->scsw, sizeof (irb->scsw));
/* Store interrupt response block to lowcore. */
if (tsch (tpi_info->irq, irb) == 0 && sch) {
/* Keep subchannel information word up to date. */
memcpy (&sch->schib.scsw, &irb->scsw,
sizeof (irb->scsw));
/* Call interrupt handler if there is one. */
if (sch->driver && sch->driver->irq)
sch->driver->irq(&sch->dev);
}
if (sch)
spin_unlock(&sch->lock);
irq_exit ();
/*
* Are more interrupts pending?
* If so, the tpi instruction will update the lowcore
......@@ -650,6 +646,7 @@ do_IRQ (struct pt_regs regs)
* out of the sie which costs more cycles than it saves.
*/
} while (!MACHINE_IS_VM && tpi (NULL) != 0);
irq_exit ();
}
#ifdef CONFIG_CCW_CONSOLE
......
......@@ -113,7 +113,6 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, unsigned int);
extern int cio_modify (struct subchannel *);
extern int cio_enable_subchannel (struct subchannel *, unsigned int);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
......@@ -127,7 +126,6 @@ extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
/* Use with care. */
extern int cio_tpi (void);
extern struct subchannel *cio_probe_console(void);
extern void cio_release_console(void);
......
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
* $Revision: 1.39 $
* $Revision: 1.40 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -20,6 +20,7 @@
#include "cio.h"
#include "cio_debug.h"
#include "device.h" // FIXME: dito
#include "ioasm.h"
struct subchannel *ioinfo[__MAX_SUBCHANNELS];
unsigned int highest_subchannel;
......@@ -154,6 +155,7 @@ css_process_crw(int irq)
{
static DECLARE_WORK(work, do_process_crw, 0);
struct subchannel *sch;
int ccode, devno;
CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
......@@ -164,9 +166,13 @@ css_process_crw(int irq)
}
if (!sch->dev.driver_data)
return;
devno = sch->schib.pmcw.dev;
/* FIXME: css_process_crw must not know about ccw_device */
dev_fsm_event(sch->dev.driver_data, DEV_EVENT_NOTOPER);
// FIXME: revalidate machine checks?
ccode = stsch(irq, &sch->schib);
if (!ccode)
if (devno != sch->schib.pmcw.dev)
schedule_work(&work);
}
/*
......
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
* $Revision: 1.44 $
* $Revision: 1.45 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -362,18 +362,28 @@ io_subchannel_register(void *data)
sch->dev.driver_data = 0;
kfree (cdev->private);
kfree (cdev);
return;
goto out;
}
ret = subchannel_add_files(cdev->dev.parent);
if (ret)
printk(KERN_WARNING "%s: could not add attributes to %04x\n",
__func__, sch->irq);
out:
put_device(&sch->dev);
}
static void
io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
{
int rc;
if (!get_device(&sch->dev)) {
if (cdev->dev.release)
cdev->dev.release(&cdev->dev);
return;
}
sch->dev.driver_data = cdev;
sch->driver = &io_subchannel_driver;
cdev->ccwlock = &sch->lock;
......@@ -392,12 +402,17 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
/* Do first half of device_register. */
device_initialize(&cdev->dev);
get_device(&sch->dev); /* keep parent refcount in sync. */
/* Start async. device sensing. */
spin_lock_irq(cdev->ccwlock);
ccw_device_recognition(cdev);
rc = ccw_device_recognition(cdev);
spin_unlock_irq(cdev->ccwlock);
if (rc) {
sch->dev.driver_data = 0;
put_device(&sch->dev);
if (cdev->dev.release)
cdev->dev.release(&cdev->dev);
}
}
static int
......
......@@ -112,7 +112,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
CIO_DEBUG(KERN_WARNING, 2,
"SenseID : unknown device %04X on subchannel %04X\n",
sch->schib.pmcw.dev, sch->irq);
device_unregister(&cdev->dev);
sch->dev.driver_data = 0;
put_device(&sch->dev);
if (cdev->dev.release)
cdev->dev.release(&cdev->dev);
break;
case DEV_STATE_OFFLINE:
/* fill out sense information */
......@@ -235,10 +238,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
sch = to_subchannel(cdev->dev.parent);
if (state != DEV_STATE_ONLINE) {
if (state != DEV_STATE_ONLINE)
cio_disable_subchannel(sch);
device_unregister(&cdev->dev);
}
/* Reset device status. */
memset(&cdev->private->irb, 0, sizeof(struct irb));
......@@ -246,6 +247,9 @@ ccw_device_done(struct ccw_device *cdev, int state)
cdev->private->state = state;
wake_up(&cdev->private->wait_q);
if (state != DEV_STATE_ONLINE)
put_device (&cdev->dev);
}
void
......@@ -275,6 +279,8 @@ ccw_device_online(struct ccw_device *cdev)
if (cdev->private->state != DEV_STATE_OFFLINE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
if (!get_device(&cdev->dev))
return -ENODEV;
if (cio_enable_subchannel(sch, sch->schib.pmcw.isc) != 0) {
/* Couldn't enable the subchannel for i/o. Sick device. */
dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
......@@ -683,19 +689,19 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_qdio_init_irq,
[DEV_EVENT_TIMEOUT] ccw_device_qdio_init_timeout,
[DEV_EVENT_VERIFY] ccw_device_nop, //FIXME
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_QDIO_ACTIVE] {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_irq,
[DEV_EVENT_TIMEOUT] ccw_device_nop,
[DEV_EVENT_VERIFY] ccw_device_nop, //FIXME
[DEV_EVENT_VERIFY] ccw_device_nop,
},
[DEV_STATE_QDIO_CLEANUP] {
[DEV_EVENT_NOTOPER] ccw_device_online_notoper,
[DEV_EVENT_INTERRUPT] ccw_device_qdio_cleanup_irq,
[DEV_EVENT_TIMEOUT] ccw_device_qdio_cleanup_timeout,
[DEV_EVENT_VERIFY] ccw_device_nop, //FIXME
[DEV_EVENT_VERIFY] ccw_device_nop,
},
/* states to wait for i/o completion before doing something */
[DEV_STATE_ONLINE_VERIFY] {
......
......@@ -260,7 +260,7 @@ extern __inline__ int xsch(int irq)
return ccode;
}
extern __inline__ int do_chsc(void *chsc_area)
extern __inline__ int chsc(void *chsc_area)
{
int cc;
......
......@@ -53,8 +53,9 @@
#include "device.h"
#include "airq.h"
#include "qdio.h"
#include "ioasm.h"
#define VERSION_QDIO_C "$Revision: 1.16 $"
#define VERSION_QDIO_C "$Revision: 1.18 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
......@@ -1573,33 +1574,33 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
{
struct qdio_irq *irq_ptr;
struct qdio_q *q;
int irq;
int cstat,dstat;
char dbf_text[15]="qintXXXX";
char dbf_text[15];
irq = cdev->private->irq; /* FIXME: use different dbg */
cstat = irb->scsw.cstat;
dstat = irb->scsw.dstat;
*((int*)(&dbf_text[4]))=irq;
QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
QDIO_DBF_TEXT4(0, trace, "qint");
sprintf(dbf_text, "%s", cdev->dev.bus_id);
QDIO_DBF_TEXT4(0, trace, dbf_text);
if (!intparm || !cdev) {
QDIO_PRINT_STUPID("got unsolicited interrupt in qdio " \
"handler, irq 0x%x\n",irq);
"handler, device %s\n", cdev->dev.bus_id);
return;
}
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr) {
sprintf(dbf_text,"uint%4x",irq);
QDIO_DBF_TEXT2(1, trace, "uint");
sprintf(dbf_text,"%s", cdev->dev.bus_id);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_PRINT_ERR("received interrupt on unused irq 0x%04x!\n",
irq);
QDIO_PRINT_ERR("received interrupt on unused device %s!\n",
cdev->dev.bus_id);
return;
}
qdio_irq_check_sense(irq, irb);
qdio_irq_check_sense(irq_ptr->irq, irb);
if (cstat & SCHN_STAT_PCI) {
qdio_handle_pci(irq_ptr);
......@@ -1607,21 +1608,22 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
if ((cstat&~SCHN_STAT_PCI)||dstat) {
sprintf(dbf_text,"ick2%4x",irq);
QDIO_DBF_TEXT2(1, trace, "ick2");
sprintf(dbf_text,"%s", cdev->dev.bus_id);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_DBF_HEX2(0,trace,&intparm,sizeof(int));
QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
QDIO_PRINT_ERR("received check condition on activate " \
"queues on irq 0x%x (cs=x%x, ds=x%x).\n",
irq,cstat,dstat);
"queues on device %s (cs=x%x, ds=x%x).\n",
cdev->dev.bus_id, cstat, dstat);
if (irq_ptr->no_input_qs) {
q=irq_ptr->input_qs[0];
} else if (irq_ptr->no_output_qs) {
q=irq_ptr->output_qs[0];
} else {
QDIO_PRINT_ERR("oops... no queue registered on irq " \
"0x%x!?\n",irq);
QDIO_PRINT_ERR("oops... no queue registered for " \
"device %s!?\n", cdev->dev.bus_id);
goto omit_handler_call;
}
q->handler(q->irq,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
......
#
# S/390 miscellaneous devices
#
# placeholder for stuff to come...
/*
* $Id: ctcmain.c,v 1.29 2002/12/06 12:31:38 cohuck Exp $
* $Id: ctcmain.c,v 1.30 2002/12/09 13:56:20 aberg Exp $
*
* CTC / ESCON network driver
*
......@@ -36,7 +36,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.29 $
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.30 $
*
*/
......@@ -279,7 +279,7 @@ static void
print_banner(void)
{
static int printed = 0;
char vbuf[] = "$Revision: 1.29 $";
char vbuf[] = "$Revision: 1.30 $";
char *version = vbuf;
if (printed)
......@@ -2821,7 +2821,7 @@ ctc_remove_files(struct device *dev)
* @returns 0 on success, !0 on failure.
*/
int
static int
ctc_probe_device(struct ccwgroup_device *cgdev)
{
struct ctc_priv *priv;
......@@ -2864,7 +2864,7 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
*
* @returns 0 on success, !0 on failure.
*/
int
static int
ctc_new_device(struct ccwgroup_device *cgdev)
{
char read_id[CTC_ID_SIZE];
......@@ -2941,7 +2941,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
*
* @returns 0 on success, !0 on failure.
*/
int
static int
ctc_shutdown_device(struct ccwgroup_device *cgdev)
{
struct ctc_priv *priv;
......@@ -2975,7 +2975,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
}
int
static int
ctc_remove_device(struct ccwgroup_device *cgdev)
{
struct ctc_priv *priv;
......@@ -2991,7 +2991,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev)
return 0;
}
struct ccwgroup_driver ctc_group_driver = {
static struct ccwgroup_driver ctc_group_driver = {
.name = "ctc",
.max_slaves = 2,
.driver_id = 0xC3E3C3,
......
/*
* $Id: cu3088.c,v 1.21 2002/12/03 16:26:45 cohuck Exp $
* $Id: cu3088.c,v 1.22 2002/12/10 09:53:55 cohuck Exp $
*
* CTC / LCS ccw_device driver
*
......@@ -172,5 +172,5 @@ MODULE_LICENSE("GPL");
module_init(cu3088_init);
module_exit(cu3088_exit);
EXPORT_SYMBOL(register_cu3088_discipline);
EXPORT_SYMBOL(unregister_cu3088_discipline);
EXPORT_SYMBOL_GPL(register_cu3088_discipline);
EXPORT_SYMBOL_GPL(unregister_cu3088_discipline);
......@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
* $Revision: 1.41 $ $Date: 2002/12/06 12:42:01 $
* $Revision: 1.42 $ $Date: 2002/12/09 13:55:28 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -59,7 +59,7 @@
/**
* initialization string for output
*/
#define VERSION_LCS_C "$Revision: 1.41 $"
#define VERSION_LCS_C "$Revision: 1.42 $"
static const char *version="LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
......@@ -1576,7 +1576,7 @@ lcs_get_frames_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
/**
* get network statistics for ifconfig and other user programs
*/
struct net_device_stats *
static struct net_device_stats *
lcs_getstats(struct net_device *dev)
{
struct lcs_card *card;
......@@ -1590,7 +1590,7 @@ lcs_getstats(struct net_device *dev)
* stop lcs device
* This function will be called by user doing ifconfig xxx down
*/
int
static int
lcs_stop_device(struct net_device *dev)
{
struct lcs_card *card;
......@@ -1612,7 +1612,7 @@ lcs_stop_device(struct net_device *dev)
* start lcs device and make it runnable
* This function will be called by user doing ifconfig xxx up
*/
int
static int
lcs_open_device(struct net_device *dev)
{
struct lcs_card *card;
......@@ -1678,7 +1678,7 @@ static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
/**
* lcs_probe_device is called on establishing a new ccwgroup_device.
*/
int
static int
lcs_probe_device(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
......@@ -1714,7 +1714,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
/**
* lcs_new_device will be called by setting the group device online.
*/
int
static int
lcs_new_device(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
......@@ -1794,7 +1794,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
/**
* lcs_shutdown_device, called when setting the group device offline.
*/
int
static int
lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
......@@ -1810,7 +1810,7 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
/**
* lcs_remove_device, free buffers and card
*/
int
static int
lcs_remove_device(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
......@@ -1828,7 +1828,7 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
/**
* LCS ccwgroup driver registration
*/
struct ccwgroup_driver lcs_group_driver = {
static struct ccwgroup_driver lcs_group_driver = {
.name = "lcs",
.max_slaves = 2,
.driver_id = 0xD3C3E2,
......
......@@ -53,7 +53,7 @@ extern const char _sb_findmap[];
/*
* SMP save set_bit routine based on compare and swap (CS)
*/
static inline void set_bit_cs(int nr, volatile void *ptr)
static inline void set_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -78,7 +78,7 @@ static inline void set_bit_cs(int nr, volatile void *ptr)
/*
* SMP save clear_bit routine based on compare and swap (CS)
*/
static inline void clear_bit_cs(int nr, volatile void *ptr)
static inline void clear_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -103,7 +103,7 @@ static inline void clear_bit_cs(int nr, volatile void *ptr)
/*
* SMP save change_bit routine based on compare and swap (CS)
*/
static inline void change_bit_cs(int nr, volatile void *ptr)
static inline void change_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -128,7 +128,8 @@ static inline void change_bit_cs(int nr, volatile void *ptr)
/*
* SMP save test_and_set_bit routine based on compare and swap (CS)
*/
static inline int test_and_set_bit_cs(int nr, volatile void *ptr)
static inline int
test_and_set_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -154,7 +155,8 @@ static inline int test_and_set_bit_cs(int nr, volatile void *ptr)
/*
* SMP save test_and_clear_bit routine based on compare and swap (CS)
*/
static inline int test_and_clear_bit_cs(int nr, volatile void *ptr)
static inline int
test_and_clear_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -180,7 +182,8 @@ static inline int test_and_clear_bit_cs(int nr, volatile void *ptr)
/*
* SMP save test_and_change_bit routine based on compare and swap (CS)
*/
static inline int test_and_change_bit_cs(int nr, volatile void *ptr)
static inline int
test_and_change_bit_cs(int nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -207,7 +210,7 @@ static inline int test_and_change_bit_cs(int nr, volatile void *ptr)
/*
* fast, non-SMP set_bit routine
*/
static inline void __set_bit(int nr, volatile void *ptr)
static inline void __set_bit(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -219,7 +222,7 @@ static inline void __set_bit(int nr, volatile void *ptr)
}
static inline void
__constant_set_bit(const int nr, volatile void *ptr)
__constant_set_bit(const int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -269,7 +272,7 @@ __constant_set_bit(const int nr, volatile void *ptr)
* fast, non-SMP clear_bit routine
*/
static inline void
__clear_bit(int nr, volatile void *ptr)
__clear_bit(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -281,7 +284,7 @@ __clear_bit(int nr, volatile void *ptr)
}
static inline void
__constant_clear_bit(const int nr, volatile void *ptr)
__constant_clear_bit(const int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -330,7 +333,7 @@ __constant_clear_bit(const int nr, volatile void *ptr)
/*
* fast, non-SMP change_bit routine
*/
static inline void __change_bit(int nr, volatile void *ptr)
static inline void __change_bit(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -342,7 +345,7 @@ static inline void __change_bit(int nr, volatile void *ptr)
}
static inline void
__constant_change_bit(const int nr, volatile void *ptr)
__constant_change_bit(const int nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -391,7 +394,8 @@ __constant_change_bit(const int nr, volatile void *ptr)
/*
* fast, non-SMP test_and_set_bit routine
*/
static inline int test_and_set_bit_simple(int nr, volatile void *ptr)
static inline int
test_and_set_bit_simple(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -409,7 +413,8 @@ static inline int test_and_set_bit_simple(int nr, volatile void *ptr)
/*
* fast, non-SMP test_and_clear_bit routine
*/
static inline int test_and_clear_bit_simple(int nr, volatile void *ptr)
static inline int
test_and_clear_bit_simple(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -427,7 +432,8 @@ static inline int test_and_clear_bit_simple(int nr, volatile void *ptr)
/*
* fast, non-SMP test_and_change_bit routine
*/
static inline int test_and_change_bit_simple(int nr, volatile void *ptr)
static inline int
test_and_change_bit_simple(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -463,7 +469,7 @@ static inline int test_and_change_bit_simple(int nr, volatile void *ptr)
* This routine doesn't need to be atomic.
*/
static inline int __test_bit(int nr, volatile void *ptr)
static inline int __test_bit(int nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -473,7 +479,8 @@ static inline int __test_bit(int nr, volatile void *ptr)
return (ch >> (nr & 7)) & 1;
}
static inline int __constant_test_bit(int nr, volatile void * addr) {
static inline int
__constant_test_bit(int nr, volatile unsigned long * addr) {
return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
}
......@@ -485,7 +492,8 @@ static inline int __constant_test_bit(int nr, volatile void * addr) {
/*
* Find-bit routines..
*/
static inline int find_first_zero_bit(void * addr, unsigned size)
static inline int
find_first_zero_bit(unsigned long * addr, unsigned size)
{
unsigned long cmp, count;
int res;
......@@ -523,7 +531,8 @@ static inline int find_first_zero_bit(void * addr, unsigned size)
return (res < size) ? res : size;
}
static inline int find_first_bit(void * addr, unsigned size)
static inline int
find_first_bit(unsigned long * addr, unsigned size)
{
unsigned long cmp, count;
int res;
......@@ -561,7 +570,8 @@ static inline int find_first_bit(void * addr, unsigned size)
return (res < size) ? res : size;
}
static inline int find_next_zero_bit (void * addr, int size, int offset)
static inline int
find_next_zero_bit (unsigned long * addr, int size, int offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
unsigned long bitvec, reg;
......@@ -599,7 +609,8 @@ static inline int find_next_zero_bit (void * addr, int size, int offset)
return (offset + res);
}
static inline int find_next_bit (void * addr, int size, int offset)
static inline int
find_next_bit (unsigned long * addr, int size, int offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
unsigned long bitvec, reg;
......@@ -668,7 +679,7 @@ static inline unsigned long ffz(unsigned long word)
* __ffs = find first bit in word. Undefined if no bit exists,
* so code should check against 0UL first..
*/
static inline unsigned long __ffs(unsigned long word)
static inline unsigned long __ffs (unsigned long word)
{
unsigned long reg, result;
......@@ -707,7 +718,7 @@ static inline int sched_find_first_bit(unsigned long *b)
* differs in spirit from the above ffz (man ffs).
*/
extern int inline ffs (int x)
extern inline int ffs (int x)
{
int r = 1;
......@@ -792,10 +803,15 @@ extern __inline__ int fls(int x)
* 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
*/
#define ext2_set_bit(nr, addr) test_and_set_bit((nr)^24, addr)
#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr)^24, addr)
#define ext2_test_bit(nr, addr) test_bit((nr)^24, addr)
static inline int ext2_find_first_zero_bit(void *vaddr, unsigned size)
#define ext2_set_bit(nr, addr) \
test_and_set_bit((nr)^24, (unsigned long *)addr)
#define ext2_clear_bit(nr, addr) \
test_and_clear_bit((nr)^24, (unsigned long *)addr)
#define ext2_test_bit(nr, addr) \
test_bit((nr)^24, (unsigned long *)addr)
static inline int
ext2_find_first_zero_bit(void *vaddr, unsigned size)
{
unsigned long cmp, count;
int res;
......
......@@ -262,8 +262,6 @@ struct diag210 {
extern int diag210(struct diag210 *addr);
extern int chsc(void *data);
extern void wait_cons_dev(void);
#endif
......
......@@ -13,7 +13,7 @@
#ifdef __KERNEL__
#include <asm/thread_info.h>
#include <linux/thread_info.h>
struct task_struct;
......
......@@ -64,7 +64,7 @@ static inline void copy_page(void *to, void *from)
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
__asm__ __volatile__(".word 0x0000"); \
__asm__ __volatile__(".long 0"); \
} while (0)
#define PAGE_BUG(page) do { \
......
......@@ -60,13 +60,13 @@ typedef struct {
#endif
#undef __FD_SET
#define __FD_SET(fd,fdsetp) set_bit(fd,fdsetp)
#define __FD_SET(fd,fdsetp) set_bit(fd,fdsetp->fds_bits)
#undef __FD_CLR
#define __FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp)
#define __FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp->fds_bits)
#undef __FD_ISSET
#define __FD_ISSET(fd,fdsetp) test_bit(fd,fdsetp)
#define __FD_ISSET(fd,fdsetp) test_bit(fd,fdsetp->fds_bits)
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
......
......@@ -228,7 +228,7 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
: "=&d" (old), "=&d" (new)
: "a" (&sem->count), "m" (tmp)
: "cc", "memory" );
if (new > 1) // FIXME: is this correct ?!?
if (new > 1)
rwsem_downgrade_wake(sem);
}
......
......@@ -26,6 +26,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
struct restart_block restart_block;
};
/*
......@@ -33,10 +34,13 @@ struct thread_info {
*/
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
flags: 0, \
cpu: 0, \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}
#define init_thread_info (init_thread_union.thread_info)
......@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
......@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
......@@ -84,7 +84,7 @@ extern inline int __put_user_asm_8(void *x, void *ptr)
{
int err;
__asm__ __volatile__ ( " sr %0,01\n"
__asm__ __volatile__ ( " sr %0,%0\n"
" lr 2,%1\n"
" lr 4,%2\n"
" sacf 512\n"
......
......@@ -19,6 +19,7 @@
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_restart_syscall 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
......
#ifndef _S390_BITOPS_H
#define _S390_BITOPS_H
/*
* include/asm-s390/bitops.h
*
......@@ -9,9 +12,7 @@
* Copyright (C) 1992, Linus Torvalds
*
*/
#ifndef _S390_BITOPS_H
#define _S390_BITOPS_H
#include <linux/config.h>
/*
* bit 0 is the LSB of *addr; bit 63 is the MSB of *addr;
......@@ -32,7 +33,6 @@
* of the form "flags |= (1 << bitnr)" are used INTERMIXED
* with operation of the form "set_bit(bitnr, flags)".
*/
#include <linux/config.h>
/* set ALIGN_CS to 1 if the SMP safe bit operations should
* align the address to 4 byte boundary. It seems to work
......@@ -57,7 +57,7 @@ extern const char _sb_findmap[];
/*
* SMP save set_bit routine based on compare and swap (CS)
*/
static inline void set_bit_cs(unsigned long nr, volatile void *ptr)
static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -82,7 +82,7 @@ static inline void set_bit_cs(unsigned long nr, volatile void *ptr)
/*
* SMP save clear_bit routine based on compare and swap (CS)
*/
static inline void clear_bit_cs(unsigned long nr, volatile void *ptr)
static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -107,7 +107,7 @@ static inline void clear_bit_cs(unsigned long nr, volatile void *ptr)
/*
* SMP save change_bit routine based on compare and swap (CS)
*/
static inline void change_bit_cs(unsigned long nr, volatile void *ptr)
static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -133,7 +133,7 @@ static inline void change_bit_cs(unsigned long nr, volatile void *ptr)
* SMP save test_and_set_bit routine based on compare and swap (CS)
*/
static inline int
test_and_set_bit_cs(unsigned long nr, volatile void *ptr)
test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -160,7 +160,7 @@ test_and_set_bit_cs(unsigned long nr, volatile void *ptr)
* SMP save test_and_clear_bit routine based on compare and swap (CS)
*/
static inline int
test_and_clear_bit_cs(unsigned long nr, volatile void *ptr)
test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -187,7 +187,7 @@ test_and_clear_bit_cs(unsigned long nr, volatile void *ptr)
* SMP save test_and_change_bit routine based on compare and swap (CS)
*/
static inline int
test_and_change_bit_cs(unsigned long nr, volatile void *ptr)
test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;
......@@ -214,7 +214,7 @@ test_and_change_bit_cs(unsigned long nr, volatile void *ptr)
/*
* fast, non-SMP set_bit routine
*/
static inline void __set_bit(unsigned long nr, volatile void *ptr)
static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -226,7 +226,7 @@ static inline void __set_bit(unsigned long nr, volatile void *ptr)
}
static inline void
__constant_set_bit(const unsigned long nr, volatile void *ptr)
__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -276,7 +276,7 @@ __constant_set_bit(const unsigned long nr, volatile void *ptr)
* fast, non-SMP clear_bit routine
*/
static inline void
__clear_bit(unsigned long nr, volatile void *ptr)
__clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -288,7 +288,7 @@ __clear_bit(unsigned long nr, volatile void *ptr)
}
static inline void
__constant_clear_bit(const unsigned long nr, volatile void *ptr)
__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -337,7 +337,7 @@ __constant_clear_bit(const unsigned long nr, volatile void *ptr)
/*
* fast, non-SMP change_bit routine
*/
static inline void __change_bit(unsigned long nr, volatile void *ptr)
static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -349,7 +349,7 @@ static inline void __change_bit(unsigned long nr, volatile void *ptr)
}
static inline void
__constant_change_bit(const unsigned long nr, volatile void *ptr)
__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
......@@ -399,7 +399,7 @@ __constant_change_bit(const unsigned long nr, volatile void *ptr)
* fast, non-SMP test_and_set_bit routine
*/
static inline int
test_and_set_bit_simple(unsigned long nr, volatile void *ptr)
test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -418,7 +418,7 @@ test_and_set_bit_simple(unsigned long nr, volatile void *ptr)
* fast, non-SMP test_and_clear_bit routine
*/
static inline int
test_and_clear_bit_simple(unsigned long nr, volatile void *ptr)
test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -437,7 +437,7 @@ test_and_clear_bit_simple(unsigned long nr, volatile void *ptr)
* fast, non-SMP test_and_change_bit routine
*/
static inline int
test_and_change_bit_simple(unsigned long nr, volatile void *ptr)
test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -473,7 +473,7 @@ test_and_change_bit_simple(unsigned long nr, volatile void *ptr)
* This routine doesn't need to be atomic.
*/
static inline int __test_bit(unsigned long nr, volatile void *ptr)
static inline int __test_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;
......@@ -484,7 +484,7 @@ static inline int __test_bit(unsigned long nr, volatile void *ptr)
}
static inline int
__constant_test_bit(unsigned long nr, volatile void *addr) {
__constant_test_bit(unsigned long nr, volatile unsigned long *addr) {
return (((volatile char *) addr)[(nr>>3)^7] & (1<<(nr&7))) != 0;
}
......@@ -497,7 +497,7 @@ __constant_test_bit(unsigned long nr, volatile void *addr) {
* Find-bit routines..
*/
static inline unsigned long
find_first_zero_bit(void * addr, unsigned long size)
find_first_zero_bit(unsigned long * addr, unsigned long size)
{
unsigned long res, cmp, count;
......@@ -539,7 +539,7 @@ find_first_zero_bit(void * addr, unsigned long size)
}
static inline unsigned long
find_first_bit(void * addr, unsigned long size)
find_first_bit(unsigned long * addr, unsigned long size)
{
unsigned long res, cmp, count;
......@@ -581,7 +581,7 @@ find_first_bit(void * addr, unsigned long size)
}
static inline unsigned long
find_next_zero_bit (void * addr, unsigned long size, unsigned long offset)
find_next_zero_bit (unsigned long * addr, unsigned long size, unsigned long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
unsigned long bitvec, reg;
......@@ -625,7 +625,7 @@ find_next_zero_bit (void * addr, unsigned long size, unsigned long offset)
}
static inline unsigned long
find_next_bit (void * addr, unsigned long size, unsigned long offset)
find_next_bit (unsigned long * addr, unsigned long size, unsigned long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
unsigned long bitvec, reg;
......@@ -744,7 +744,7 @@ static inline int sched_find_first_bit(unsigned long *b)
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
extern int inline ffs (int x)
extern inline int ffs (int x)
{
int r = 1;
......@@ -836,9 +836,13 @@ extern __inline__ int fls(int x)
* 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
*/
#define ext2_set_bit(nr, addr) test_and_set_bit((nr)^56, addr)
#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr)^56, addr)
#define ext2_test_bit(nr, addr) test_bit((nr)^56, addr)
#define ext2_set_bit(nr, addr) \
test_and_set_bit((nr)^56, (unsigned long *)addr)
#define ext2_clear_bit(nr, addr) \
test_and_clear_bit((nr)^56, (unsigned long *)addr)
#define ext2_test_bit(nr, addr) \
test_bit((nr)^56, (unsigned long *)addr)
static inline unsigned long
ext2_find_first_zero_bit(void *vaddr, unsigned long size)
{
......
......@@ -31,7 +31,7 @@ struct ccwgroup_driver {
extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver);
extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
extern int ccwgroup_create_dev (struct device *root,
extern int ccwgroup_create (struct device *root,
unsigned int creator_id,
struct ccw_driver *gdrv,
int argc, char *argv[]);
......
......@@ -262,8 +262,6 @@ struct diag210 {
extern int diag210(struct diag210 *addr);
extern int chsc(void *data);
extern void wait_cons_dev(void);
#endif
......
......@@ -13,7 +13,7 @@
#ifdef __KERNEL__
#include <asm/thread_info.h>
#include <linux/thread_info.h>
struct task_struct;
......
......@@ -58,13 +58,13 @@ typedef struct {
#endif
#undef __FD_SET
#define __FD_SET(fd,fdsetp) set_bit(fd,fdsetp)
#define __FD_SET(fd,fdsetp) set_bit(fd,fdsetp->fds_bits)
#undef __FD_CLR
#define __FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp)
#define __FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp->fds_bits)
#undef __FD_ISSET
#define __FD_ISSET(fd,fdsetp) test_bit(fd,fdsetp)
#define __FD_ISSET(fd,fdsetp) test_bit(fd,fdsetp->fds_bits)
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
......
......@@ -228,7 +228,7 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
: "=&d" (old), "=&d" (new)
: "a" (&sem->count), "m" (tmp)
: "cc", "memory" );
if (new > 1) // FIXME: is this correct ?!?
if (new > 1)
rwsem_downgrade_wake(sem);
}
......
......@@ -26,6 +26,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
unsigned int preempt_count; /* 0 => preemptable */
struct restart_block restart_block;
};
/*
......@@ -33,10 +34,13 @@ struct thread_info {
*/
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
flags: 0, \
cpu: 0, \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}
#define init_thread_info (init_thread_union.thread_info)
......@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
......@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
......@@ -19,6 +19,7 @@
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_restart_syscall 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment