diff options
76 files changed, 1997 insertions, 561 deletions
@@ -1944,6 +1944,12 @@ S: 8786 Niwot Road S: Niwot, Colorado 80503 S: USA +N: Pete Popov +E: pete_popov@yahoo.com +D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging +S: San Jose, CA 95134 +S: USA + N: Robert M. Love E: rml@tech9.net E: rml@ufl.edu diff --git a/Documentation/s390/crypto/crypto-API.txt b/Documentation/s390/crypto/crypto-API.txt new file mode 100644 index 000000000000..78a77624a716 --- /dev/null +++ b/Documentation/s390/crypto/crypto-API.txt @@ -0,0 +1,83 @@ +crypto-API support for z990 Message Security Assist (MSA) instructions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +AUTHOR: Thomas Spatzier (tspat@de.ibm.com) + + +1. Introduction crypto-API +~~~~~~~~~~~~~~~~~~~~~~~~~~ +See Documentation/crypto/api-intro.txt for an introduction/description of the +kernel crypto API. +According to api-intro.txt support for z990 crypto instructions has been added +in the algorithm api layer of the crypto API. Several files containing z990 +optimized implementations of crypto algorithms are placed in the +arch/s390/crypto directory. + + +2. Probing for availability of MSA +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It should be possible to use Kernels with the z990 crypto implementations both +on machines with MSA available an on those without MSA (pre z990 or z990 +without MSA). Therefore a simple probing mechanisms has been implemented: +In the init function of each crypto module the availability of MSA and of the +respective crypto algorithm in particular will be tested. If the algorithm is +available the module will load and register its algorithm with the crypto API. + +If the respective crypto algorithm is not available, the init function will +return -ENOSYS. In that case a fallback to the standard software implementation +of the crypto algorithm must be taken ( -> the standard crypto modules are +also build when compiling the kernel). + + +3. Ensuring z990 crypto module preference +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If z990 crypto instructions are available the optimized modules should be +preferred instead of standard modules. + +3.1. compiled-in modules +~~~~~~~~~~~~~~~~~~~~~~~~ +For compiled-in modules it has to be ensured that the z990 modules are linked +before the standard crypto modules. Then, on system startup the init functions +of z990 crypto modules will be called first and query for availability of z990 +crypto instructions. If instruction is available, the z990 module will register +its crypto algorithm implementation -> the load of the standard module will fail +since the algorithm is already registered. +If z990 crypto instruction is not available the load of the z990 module will +fail -> the standard module will load and register its algorithm. + +3.2. dynamic modules +~~~~~~~~~~~~~~~~~~~~ +A system administrator has to take care of giving preference to z990 crypto +modules. If MSA is available appropriate lines have to be added to +/etc/modprobe.conf. + +Example: z990 crypto instruction for SHA1 algorithm is available + + add the following line to /etc/modprobe.conf (assuming the + z990 crypto modules for SHA1 is called sha1_z990): + + alias sha1 sha1_z990 + + -> when the sha1 algorithm is requested through the crypto API + (which has a module autoloader) the z990 module will be loaded. + +TBD: a userspace module probin mechanism + something like 'probe sha1 sha1_z990 sha1' in modprobe.conf + -> try module sha1_z990, if it fails to load load standard module sha1 + the 'probe' statement is currently not supported in modprobe.conf + + +4. Currently implemented z990 crypto algorithms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following crypto algorithms with z990 MSA support are currently implemented. +The name of each algorithm under which it is registered in crypto API and the +name of the respective module is given in square brackets. + +- SHA1 Digest Algorithm [sha1 -> sha1_z990] +- DES Encrypt/Decrypt Algorithm (64bit key) [des -> des_z990] +- Tripple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990] +- Tripple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990] + +In order to load, for example, the sha1_z990 module when the sha1 algorithm is +requested (see 3.2.) add 'alias sha1 sha1_z990' to /etc/modprobe.conf. + diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 0e317230f81e..c51bf8dbfc8a 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -415,16 +415,12 @@ init_irq_proc (void) #endif /* - * Create entries for all existing IRQs. If the number of IRQs - * is greater the 1/4 the total dynamic inode space for /proc, - * don't pollute the inode space + * Create entries for all existing IRQs. */ - if (ACTUAL_NR_IRQS < (PROC_NDYNAMIC / 4)) { - for (i = 0; i < ACTUAL_NR_IRQS; i++) { - if (irq_desc[i].handler == &no_irq_type) - continue; - register_irq_proc(i); - } + for (i = 0; i < ACTUAL_NR_IRQS; i++) { + if (irq_desc[i].handler == &no_irq_type) + continue; + register_irq_proc(i); } } diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 8906f66b65e7..52348791ce1e 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -137,18 +137,6 @@ dik_show_trace(unsigned long *sp) printk("\n"); } -void show_trace_task(struct task_struct * tsk) -{ - struct thread_info *ti = tsk->thread_info; - unsigned long fp, sp = ti->pcb.ksp, base = (unsigned long) ti; - - if (sp > base && sp+6*8 < base + 16*1024) { - fp = ((unsigned long*)sp)[6]; - if (fp > sp && fp < base + 16*1024) - dik_show_trace((unsigned long *)fp); - } -} - static int kstack_depth_to_print = 24; void show_stack(struct task_struct *task, unsigned long *sp) diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index d2ffd9016c07..f0a49fec0d9e 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c @@ -165,18 +165,6 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) c_backtrace(fp, processor_mode(regs)); } -/* - * This is called from SysRq-T (show_task) to display the current - * call trace for each process. Very useful. - */ -void show_trace_task(struct task_struct *tsk) -{ - if (tsk != current) { - unsigned int fp = thread_saved_fp(tsk); - c_backtrace(fp, 0x10); - } -} - /* FIXME - this is probably wrong.. */ void show_stack(struct task_struct *task, unsigned long *sp) { dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info); diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c index 2a757b825c44..d9e6565655f4 100644 --- a/arch/cris/kernel/traps.c +++ b/arch/cris/kernel/traps.c @@ -60,14 +60,6 @@ void show_trace(unsigned long * stack) } } -void show_trace_task(struct task_struct *tsk) -{ - /* TODO, this is not really useful since its called from - * SysRq-T and we don't have a keyboard.. :) - */ -} - - /* * These constants are for searching for possible module text * segments. MODULE_RANGE is a guess of how much space is likely diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c index 300e3279ca5a..253c87bc5b32 100644 --- a/arch/h8300/kernel/traps.c +++ b/arch/h8300/kernel/traps.c @@ -156,14 +156,8 @@ void show_stack(struct task_struct *task, unsigned long *esp) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - show_stack(tsk,(unsigned long *)tsk->thread.esp0); -} - void dump_stack(void) { show_stack(NULL,NULL); } - EXPORT_SYMBOL(dump_stack); diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index f424fc369fb1..0be8d6b87cf7 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -445,5 +445,5 @@ void __init init_IRQ(void) if (boot_cpu_data.hard_math && !cpu_has_fpu) setup_irq(FPU_IRQ, &fpu_irq); - irq_ctx_init(current_thread_info()->cpu); + irq_ctx_init(smp_processor_id()); } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index d74fb46abd31..574ae5814333 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -462,8 +462,7 @@ void nmi_watchdog_tick (struct pt_regs * regs) /* Only P6 based Pentium M need to re-unmask * the apic vector but it doesn't hurt * other P6 variant */ - apic_write(APIC_LVTPC, - apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); + apic_write(APIC_LVTPC, APIC_DM_NMI); } wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index cf8da7ba4cdb..c770d878cbcf 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -123,16 +123,6 @@ void show_trace(struct task_struct *task, unsigned long * stack) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - unsigned long esp = tsk->thread.esp; - - /* User space on another CPU? */ - if ((esp ^ (unsigned long)tsk->thread_info) & ~(THREAD_SIZE - 1)) - return; - show_trace(tsk, (unsigned long *)esp); -} - void show_stack(struct task_struct *task, unsigned long *esp) { unsigned long *stack; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index d72026927fec..752dbd3e93fb 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -126,11 +126,6 @@ void show_trace(struct task_struct *task, unsigned long *stack) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - show_trace(tsk, (long *)tsk->thread.reg29); -} - /* * The architecture-independent dump_stack generator */ diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f83053a37644..6f1f6f738d6c 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -202,11 +202,6 @@ void show_trace(struct task_struct *task, unsigned long *stack) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - show_trace(tsk, (unsigned long *)tsk->thread.regs.ksp); -} - void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (user_mode(regs)) { diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index f74b14d7e58e..7c153dc24895 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c @@ -536,10 +536,4 @@ void dump_stack(void) { show_stack(current, (unsigned long *)__get_SP()); } - EXPORT_SYMBOL(dump_stack); - -void show_trace_task(struct task_struct *tsk) -{ - show_stack(tsk, (unsigned long *)tsk->thread.ksp); -} diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 9525ee20aa0e..a4a727aab6f7 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -44,7 +44,7 @@ head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o head-y += arch/$(ARCH)/kernel/init_task.o -core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ \ +core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \ arch/$(ARCH)/appldata/ libs-y += arch/$(ARCH)/lib/ drivers-y += drivers/s390/ diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile new file mode 100644 index 000000000000..96a05e6b51e0 --- /dev/null +++ b/arch/s390/crypto/Makefile @@ -0,0 +1,8 @@ +# +# Cryptographic API +# + +obj-$(CONFIG_CRYPTO_SHA1_Z990) += sha1_z990.o +obj-$(CONFIG_CRYPTO_DES_Z990) += des_z990.o des_check_key.o + +obj-$(CONFIG_CRYPTO_TEST) += crypt_z990_query.o diff --git a/arch/s390/crypto/crypt_z990.h b/arch/s390/crypto/crypt_z990.h new file mode 100644 index 000000000000..4df660b99e5a --- /dev/null +++ b/arch/s390/crypto/crypt_z990.h @@ -0,0 +1,374 @@ +/* + * Cryptographic API. + * + * Support for z990 cryptographic instructions. + * + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_ARCH_S390_CRYPT_Z990_H +#define _CRYPTO_ARCH_S390_CRYPT_Z990_H + +#include <asm/errno.h> + +#define CRYPT_Z990_OP_MASK 0xFF00 +#define CRYPT_Z990_FUNC_MASK 0x00FF + + +/*z990 cryptographic operations*/ +enum crypt_z990_operations { + CRYPT_Z990_KM = 0x0100, + CRYPT_Z990_KMC = 0x0200, + CRYPT_Z990_KIMD = 0x0300, + CRYPT_Z990_KLMD = 0x0400, + CRYPT_Z990_KMAC = 0x0500 +}; + +/*function codes for KM (CIPHER MESSAGE) instruction*/ +enum crypt_z990_km_func { + KM_QUERY = CRYPT_Z990_KM | 0, + KM_DEA_ENCRYPT = CRYPT_Z990_KM | 1, + KM_DEA_DECRYPT = CRYPT_Z990_KM | 1 | 0x80, //modifier bit->decipher + KM_TDEA_128_ENCRYPT = CRYPT_Z990_KM | 2, + KM_TDEA_128_DECRYPT = CRYPT_Z990_KM | 2 | 0x80, + KM_TDEA_192_ENCRYPT = CRYPT_Z990_KM | 3, + KM_TDEA_192_DECRYPT = CRYPT_Z990_KM | 3 | 0x80, +}; + +/*function codes for KMC (CIPHER MESSAGE WITH CHAINING) instruction*/ +enum crypt_z990_kmc_func { + KMC_QUERY = CRYPT_Z990_KMC | 0, + KMC_DEA_ENCRYPT = CRYPT_Z990_KMC | 1, + KMC_DEA_DECRYPT = CRYPT_Z990_KMC | 1 | 0x80, //modifier bit->decipher + KMC_TDEA_128_ENCRYPT = CRYPT_Z990_KMC | 2, + KMC_TDEA_128_DECRYPT = CRYPT_Z990_KMC | 2 | 0x80, + KMC_TDEA_192_ENCRYPT = CRYPT_Z990_KMC | 3, + KMC_TDEA_192_DECRYPT = CRYPT_Z990_KMC | 3 | 0x80, +}; + +/*function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) instruction*/ +enum crypt_z990_kimd_func { + KIMD_QUERY = CRYPT_Z990_KIMD | 0, + KIMD_SHA_1 = CRYPT_Z990_KIMD | 1, +}; + +/*function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) instruction*/ +enum crypt_z990_klmd_func { + KLMD_QUERY = CRYPT_Z990_KLMD | 0, + KLMD_SHA_1 = CRYPT_Z990_KLMD | 1, +}; + +/*function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) instruction*/ +enum crypt_z990_kmac_func { + KMAC_QUERY = CRYPT_Z990_KMAC | 0, + KMAC_DEA = CRYPT_Z990_KMAC | 1, + KMAC_TDEA_128 = CRYPT_Z990_KMAC | 2, + KMAC_TDEA_192 = CRYPT_Z990_KMAC | 3 +}; + +/*status word for z990 crypto instructions' QUERY functions*/ +struct crypt_z990_query_status { + u64 high; + u64 low; +}; + +/* + * Standard fixup and ex_table sections for crypt_z990 inline functions. + * label 0: the z990 crypto operation + * label 1: just after 1 to catch illegal operation exception on non-z990 + * label 6: the return point after fixup + * label 7: set error value if exception _in_ crypto operation + * label 8: set error value if illegal operation exception + * [ret] is the variable to receive the error code + * [ERR] is the error code value + */ +#ifndef __s390x__ +#define __crypt_z990_fixup \ + ".section .fixup,\"ax\" \n" \ + "7: lhi %0,%h[e1] \n" \ + " bras 1,9f \n" \ + " .long 6b \n" \ + "8: lhi %0,%h[e2] \n" \ + " bras 1,9f \n" \ + " .long 6b \n" \ + "9: l 1,0(1) \n" \ + " br 1 \n" \ + ".previous \n" \ + ".section __ex_table,\"a\" \n" \ + " .align 4 \n" \ + " .long 0b,7b \n" \ + " .long 1b,8b \n" \ + ".previous" +#else /* __s390x__ */ +#define __crypt_z990_fixup \ + ".section .fixup,\"ax\" \n" \ + "7: lhi %0,%h[e1] \n" \ + " jg 6b \n" \ + "8: lhi %0,%h[e2] \n" \ + " jg 6b \n" \ + ".previous\n" \ + ".section __ex_table,\"a\" \n" \ + " .align 8 \n" \ + " .quad 0b,7b \n" \ + " .quad 1b,8b \n" \ + ".previous" +#endif /* __s390x__ */ + +/* + * Standard code for setting the result of z990 crypto instructions. + * %0: the register which will receive the result + * [result]: the register containing the result (e.g. second operand length + * to compute number of processed bytes]. + */ +#ifndef __s390x__ +#define __crypt_z990_set_result \ + " lr %0,%[result] \n" +#else /* __s390x__ */ +#define __crypt_z990_set_result \ + " lgr %0,%[result] \n" +#endif + +/* + * Executes the KM (CIPHER MESSAGE) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_km_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs + */ +static inline int +crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; + register void* __param asm("1") = param; + register u8* __dest asm("4") = dest; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB92E0000,%1,%2 \n" //KM opcode + "1: brc 1,0b \n" //handle partial completion + __crypt_z990_set_result + "6: \n" + __crypt_z990_fixup + : "+d" (ret), "+a" (__dest), "+a" (__src), + [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_kmc_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs + */ +static inline int +crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; + register void* __param asm("1") = param; + register u8* __dest asm("4") = dest; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB92F0000,%1,%2 \n" //KMC opcode + "1: brc 1,0b \n" //handle partial completion + __crypt_z990_set_result + "6: \n" + __crypt_z990_fixup + : "+d" (ret), "+a" (__dest), "+a" (__src), + [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation + * of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_kimd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_z990_kimd(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB93E0000,%1,%1 \n" //KIMD opcode + "1: brc 1,0b \n" /*handle partical completion of kimd*/ + __crypt_z990_set_result + "6: \n" + __crypt_z990_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && (func & CRYPT_Z990_FUNC_MASK)){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_z990_klmd(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB93F0000,%1,%1 \n" //KLMD opcode + "1: brc 1,0b \n" /*handle partical completion of klmd*/ + __crypt_z990_set_result + "6: \n" + __crypt_z990_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation + * of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_z990_kmac(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB91E0000,%5,%5 \n" //KMAC opcode + "1: brc 1,0b \n" /*handle partical completion of klmd*/ + __crypt_z990_set_result + "6: \n" + __crypt_z990_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/** + * Tests if a specific z990 crypto function is implemented on the machine. + * @param func: the function code of the specific function; 0 if op in general + * @return 1 if func available; 0 if func or op in general not available + */ +static inline int +crypt_z990_func_available(int func) +{ + int ret; + + struct crypt_z990_query_status status = { + .high = 0, + .low = 0 + }; + switch (func & CRYPT_Z990_OP_MASK){ + case CRYPT_Z990_KM: + ret = crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_Z990_KMC: + ret = crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_Z990_KIMD: + ret = crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); + break; + case CRYPT_Z990_KLMD: + ret = crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); + break; + case CRYPT_Z990_KMAC: + ret = crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); + break; + default: + ret = 0; + return ret; + } + if (ret >= 0){ + func &= CRYPT_Z990_FUNC_MASK; + func &= 0x7f; //mask modifier bit + if (func < 64){ + ret = (status.high >> (64 - func - 1)) & 0x1; + } else { + ret = (status.low >> (128 - func - 1)) & 0x1; + } + } else { + ret = 0; + } + return ret; +} + + +#endif // _CRYPTO_ARCH_S390_CRYPT_Z990_H diff --git a/arch/s390/crypto/crypt_z990_query.c b/arch/s390/crypto/crypt_z990_query.c new file mode 100644 index 000000000000..7133983d1384 --- /dev/null +++ b/arch/s390/crypto/crypt_z990_query.c @@ -0,0 +1,111 @@ +/* + * Cryptographic API. + * + * Support for z990 cryptographic instructions. + * Testing module for querying processor crypto capabilities. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/errno.h> +#include "crypt_z990.h" + +static void +query_available_functions(void) +{ + printk(KERN_INFO "#####################\n"); + //query available KM functions + printk(KERN_INFO "KM_QUERY: %d\n", + crypt_z990_func_available(KM_QUERY)); + printk(KERN_INFO "KM_DEA: %d\n", + crypt_z990_func_available(KM_DEA_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_128: %d\n", + crypt_z990_func_available(KM_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_192: %d\n", + crypt_z990_func_available(KM_TDEA_192_ENCRYPT)); + //query available KMC functions + printk(KERN_INFO "KMC_QUERY: %d\n", + crypt_z990_func_available(KMC_QUERY)); + printk(KERN_INFO "KMC_DEA: %d\n", + crypt_z990_func_available(KMC_DEA_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_128: %d\n", + crypt_z990_func_available(KMC_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_192: %d\n", + crypt_z990_func_available(KMC_TDEA_192_ENCRYPT)); + //query available KIMD fucntions + printk(KERN_INFO "KIMD_QUERY: %d\n", + crypt_z990_func_available(KIMD_QUERY)); + printk(KERN_INFO "KIMD_SHA_1: %d\n", + crypt_z990_func_available(KIMD_SHA_1)); + //query available KLMD functions + printk(KERN_INFO "KLMD_QUERY: %d\n", + crypt_z990_func_available(KLMD_QUERY)); + printk(KERN_INFO "KLMD_SHA_1: %d\n", + crypt_z990_func_available(KLMD_SHA_1)); + //query available KMAC functions + printk(KERN_INFO "KMAC_QUERY: %d\n", + crypt_z990_func_available(KMAC_QUERY)); + printk(KERN_INFO "KMAC_DEA: %d\n", + crypt_z990_func_available(KMAC_DEA)); + printk(KERN_INFO "KMAC_TDEA_128: %d\n", + crypt_z990_func_available(KMAC_TDEA_128)); + printk(KERN_INFO "KMAC_TDEA_192: %d\n", + crypt_z990_func_available(KMAC_TDEA_192)); +} + +static int +init(void) +{ + struct crypt_z990_query_status status = { + .high = 0, + .low = 0 + }; + + printk(KERN_INFO "crypt_z990: querying available crypto functions\n"); + crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KM: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KMC: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KIMD: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KLMD: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); + printk(KERN_INFO "KMAC: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + + query_available_functions(); + return -1; +} + +static void __exit +cleanup(void) +{ +} + +module_init(init); +module_exit(cleanup); + +MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/crypto_des.h b/arch/s390/crypto/crypto_des.h new file mode 100644 index 000000000000..c964b64111dd --- /dev/null +++ b/arch/s390/crypto/crypto_des.h @@ -0,0 +1,18 @@ +/* + * Cryptographic API. + * + * Function for checking keys for the DES and Tripple DES Encryption + * algorithms. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#ifndef __CRYPTO_DES_H__ +#define __CRYPTO_DES_H__ + +extern int crypto_des_check_key(const u8*, unsigned int, u32*); + +#endif //__CRYPTO_DES_H__ diff --git a/arch/s390/crypto/des_check_key.c b/arch/s390/crypto/des_check_key.c new file mode 100644 index 000000000000..e3f5c5f238fe --- /dev/null +++ b/arch/s390/crypto/des_check_key.c @@ -0,0 +1,130 @@ +/* + * Cryptographic API. + * + * Function for checking keys for the DES and Tripple DES Encryption + * algorithms. + * + * Originally released as descore by Dana L. How <how@isl.stanford.edu>. + * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel. + * Derived from Cryptoapi and Nettle implementations, adapted for in-place + * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL. + * + * s390 Version: + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * Derived from "crypto/des.c" + * Copyright (c) 1992 Dana L. How. + * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de> + * Copyright (c) Gisle Sflensminde <gisle@ii.uib.no> + * Copyright (C) 2001 Niels Mvller. + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/crypto.h> + +#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o)) + +static const u8 parity[] = { + 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, +}; + +/* + * RFC2451: Weak key checks SHOULD be performed. + */ +int +crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags) +{ + u32 n, w; + + n = parity[key[0]]; n <<= 4; + n |= parity[key[1]]; n <<= 4; + n |= parity[key[2]]; n <<= 4; + n |= parity[key[3]]; n <<= 4; + n |= parity[key[4]]; n <<= 4; + n |= parity[key[5]]; n <<= 4; + n |= parity[key[6]]; n <<= 4; + n |= parity[key[7]]; + w = 0x88888888L; + + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) + && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */ + if (n < 0x41415151) { + if (n < 0x31312121) { + if (n < 0x14141515) { + /* 01 01 01 01 01 01 01 01 */ + if (n == 0x11111111) goto weak; + /* 01 1F 01 1F 01 0E 01 0E */ + if (n == 0x13131212) goto weak; + } else { + /* 01 E0 01 E0 01 F1 01 F1 */ + if (n == 0x14141515) goto weak; + /* 01 FE 01 FE 01 FE 01 FE */ + if (n == 0x16161616) goto weak; + } + } else { + if (n < 0x34342525) { + /* 1F 01 1F 01 0E 01 0E 01 */ + if (n == 0x31312121) goto weak; + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ + if (n == 0x33332222) goto weak; + } else { + /* 1F E0 1F E0 0E F1 0E F1 */ + if (n == 0x34342525) goto weak; + /* 1F FE 1F FE 0E FE 0E FE */ + if (n == 0x36362626) goto weak; + } + } + } else { + if (n < 0x61616161) { + if (n < 0x44445555) { + /* E0 01 E0 01 F1 01 F1 01 */ + if (n == 0x41415151) goto weak; + /* E0 1F E0 1F F1 0E F1 0E */ + if (n == 0x43435252) goto weak; + } else { + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ + if (n == 0x44445555) goto weak; + /* E0 FE E0 FE F1 FE F1 FE */ + if (n == 0x46465656) goto weak; + } + } else { + if (n < 0x64646565) { + /* FE 01 FE 01 FE 01 FE 01 */ + if (n == 0x61616161) goto weak; + /* FE 1F FE 1F FE 0E FE 0E */ + if (n == 0x63636262) goto weak; + } else { + /* FE E0 FE E0 FE F1 FE F1 */ + if (n == 0x64646565) goto weak; + /* FE FE FE FE FE FE FE FE */ + if (n == 0x66666666) goto weak; + } + } + } + } + return 0; +weak: + *flags |= CRYPTO_TFM_RES_WEAK_KEY; + return -EINVAL; +} + +EXPORT_SYMBOL(crypto_des_check_key); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Key Check function for DES & DES3 Cipher Algorithms"); diff --git a/arch/s390/crypto/des_z990.c b/arch/s390/crypto/des_z990.c new file mode 100644 index 000000000000..813cf37b1177 --- /dev/null +++ b/arch/s390/crypto/des_z990.c @@ -0,0 +1,284 @@ +/* + * Cryptographic API. + * + * z990 implementation of the DES Cipher Algorithm. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <asm/scatterlist.h> +#include <linux/crypto.h> +#include "crypt_z990.h" +#include "crypto_des.h" + +#define DES_BLOCK_SIZE 8 +#define DES_KEY_SIZE 8 + +#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE) +#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE + +#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) +#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE + +struct crypt_z990_des_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES_KEY_SIZE]; +}; + +struct crypt_z990_des3_128_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES3_128_KEY_SIZE]; +}; + +struct crypt_z990_des3_192_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES3_192_KEY_SIZE]; +}; + +static int +des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + struct crypt_z990_des_ctx *dctx; + int ret; + + dctx = ctx; + //test if key is valid (not a weak key) + ret = crypto_des_check_key(key, keylen, flags); + if (ret == 0){ + memcpy(dctx->key, key, keylen); + } + return ret; +} + + +static void +des_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); +} + +static void +des_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); +} + +static struct crypto_alg des_alg = { + .cra_name = "des", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_z990_des_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt } } +}; + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the two independent 64-bit keys are equal, + * then the DES3 operation is simply the same as DES. + * Implementers MUST reject keys that exhibit this property. + * + */ +static int +des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + int i, ret; + struct crypt_z990_des3_128_ctx *dctx; + const u8* temp_key = key; + + dctx = ctx; + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); + if (ret < 0) + return ret; + } + memcpy(dctx->key, key, keylen); + return 0; +} + +static void +des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des3_128_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, + DES3_128_BLOCK_SIZE); +} + +static void +des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des3_128_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, + DES3_128_BLOCK_SIZE); +} + +static struct crypto_alg des3_128_alg = { + .cra_name = "des3_ede128", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_128_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_z990_des3_128_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_128_KEY_SIZE, + .cia_max_keysize = DES3_128_KEY_SIZE, + .cia_setkey = des3_128_setkey, + .cia_encrypt = des3_128_encrypt, + .cia_decrypt = des3_128_decrypt } } +}; + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + * + */ +static int +des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + int i, ret; + struct crypt_z990_des3_192_ctx *dctx; + const u8* temp_key; + + dctx = ctx; + temp_key = key; + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], + DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); + if (ret < 0){ + return ret; + } + } + memcpy(dctx->key, key, keylen); + return 0; +} + +static void +des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des3_192_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, + DES3_192_BLOCK_SIZE); +} + +static void +des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_z990_des3_192_ctx *dctx; + + dctx = ctx; + crypt_z990_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, + DES3_192_BLOCK_SIZE); +} + +static struct crypto_alg des3_192_alg = { + .cra_name = "des3_ede", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_192_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_z990_des3_192_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_192_KEY_SIZE, + .cia_max_keysize = DES3_192_KEY_SIZE, + .cia_setkey = des3_192_setkey, + .cia_encrypt = des3_192_encrypt, + .cia_decrypt = des3_192_decrypt } } +}; + + + +static int +init(void) +{ + int ret; + + if (!crypt_z990_func_available(KM_DEA_ENCRYPT) || + !crypt_z990_func_available(KM_TDEA_128_ENCRYPT) || + !crypt_z990_func_available(KM_TDEA_192_ENCRYPT)){ + return -ENOSYS; + } + + ret = 0; + ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; + ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; + ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; + if (ret){ + crypto_unregister_alg(&des3_192_alg); + crypto_unregister_alg(&des3_128_alg); + crypto_unregister_alg(&des_alg); + return -EEXIST; + } + + printk(KERN_INFO "crypt_z990: des_z990 loaded.\n"); + return 0; +} + +static void __exit +fini(void) +{ + crypto_unregister_alg(&des3_192_alg); + crypto_unregister_alg(&des3_128_alg); + crypto_unregister_alg(&des_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("des"); +MODULE_ALIAS("des3_ede"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); diff --git a/arch/s390/crypto/sha1_z990.c b/arch/s390/crypto/sha1_z990.c new file mode 100644 index 000000000000..298174ddf5b1 --- /dev/null +++ b/arch/s390/crypto/sha1_z990.c @@ -0,0 +1,167 @@ +/* + * Cryptographic API. + * + * z990 implementation of the SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * s390 Version: + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * Derived from "crypto/sha1.c" + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> + * + * 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 the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/crypto.h> +#include <asm/scatterlist.h> +#include <asm/byteorder.h> +#include "crypt_z990.h" + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +struct crypt_z990_sha1_ctx { + u64 count; + u32 state[5]; + u32 buf_len; + u8 buffer[2 * SHA1_BLOCK_SIZE]; +}; + +static void +sha1_init(void *ctx) +{ + static const struct crypt_z990_sha1_ctx initstate = { + .state = { + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0 + }, + }; + memcpy(ctx, &initstate, sizeof(initstate)); +} + +static void +sha1_update(void *ctx, const u8 *data, unsigned int len) +{ + struct crypt_z990_sha1_ctx *sctx; + long imd_len; + + sctx = ctx; + sctx->count += len * 8; //message bit length + + //anything in buffer yet? -> must be completed + if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { + //complete full block and hash + memcpy(sctx->buffer + sctx->buf_len, data, + SHA1_BLOCK_SIZE - sctx->buf_len); + crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, + SHA1_BLOCK_SIZE); + data += SHA1_BLOCK_SIZE - sctx->buf_len; + len -= SHA1_BLOCK_SIZE - sctx->buf_len; + sctx->buf_len = 0; + } + + //rest of data contains full blocks? + imd_len = len & ~0x3ful; + if (imd_len){ + crypt_z990_kimd(KIMD_SHA_1, sctx->state, data, imd_len); + data += imd_len; + len -= imd_len; + } + //anything left? store in buffer + if (len){ + memcpy(sctx->buffer + sctx->buf_len , data, len); + sctx->buf_len += len; + } +} + + +static void +pad_message(struct crypt_z990_sha1_ctx* sctx) +{ + int index; + + index = sctx->buf_len; + sctx->buf_len = (sctx->buf_len < 56)? + SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; + //start pad with 1 + sctx->buffer[index] = 0x80; + //pad with zeros + index++; + memset(sctx->buffer + index, 0x00, sctx->buf_len - index); + //append length + memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, + sizeof sctx->count); +} + +/* Add padding and return the message digest. */ +static void +sha1_final(void* ctx, u8 *out) +{ + struct crypt_z990_sha1_ctx *sctx = ctx; + + //must perform manual padding + pad_message(sctx); + crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); + //copy digest to out + memcpy(out, sctx->state, SHA1_DIGEST_SIZE); + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha1", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_z990_sha1_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA1_DIGEST_SIZE, + .dia_init = sha1_init, + .dia_update = sha1_update, + .dia_final = sha1_final } } +}; + +static int +init(void) +{ + int ret = -ENOSYS; + + if (crypt_z990_func_available(KIMD_SHA_1)){ + ret = crypto_register_alg(&alg); + if (ret == 0){ + printk(KERN_INFO "crypt_z990: sha1_z990 loaded.\n"); + } + } + return ret; +} + +static void __exit +fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("sha1"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 574c1b2a9d06..8e95f1a00b11 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -18,8 +18,10 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=17 CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y @@ -31,6 +33,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -231,8 +234,6 @@ CONFIG_IPV6=y # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set # CONFIG_IPV6_TUNNEL is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -242,7 +243,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -286,6 +289,11 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=m CONFIG_BONDING=m @@ -305,20 +313,16 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces @@ -341,23 +345,10 @@ CONFIG_QETH=y # CONFIG_QETH_IPV6 is not set # CONFIG_QETH_PERF_STATS is not set CONFIG_CCWGROUP=y - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # File systems @@ -397,6 +388,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y @@ -493,9 +485,11 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_Z990 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DES_Z990 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 0cc8e5be48ba..b68ace7e2e4f 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -33,6 +33,8 @@ #define NUM_ACRS 16 #define TASK31_SIZE (0x80000000UL) +#undef TASK_SIZE +#define TASK_SIZE TASK31_SIZE /* For SVR4/S390 the function pointer to be registered with `atexit` is passed in R14. */ diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 566277b9409c..df06185d54c2 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -297,64 +297,46 @@ static inline long put_tv32(struct compat_timeval *o, struct timeval *i) */ asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) { - if(call >> 16) /* hack for backward compatibility */ + if (call >> 16) /* hack for backward compatibility */ return -EINVAL; call &= 0xffff; - if (call <= SEMTIMEDOP) - switch (call) { - case SEMTIMEDOP: - if (third) - return compat_sys_semtimedop(first, - compat_ptr(ptr), second, - compat_ptr(third)); - /* else fall through for normal semop() */ - case SEMOP: - /* struct sembuf is the same on 32 and 64bit :)) */ - return sys_semtimedop (first, compat_ptr(ptr), - second, NULL); - case SEMGET: - return sys_semget (first, second, third); - case SEMCTL: - return compat_sys_semctl (first, second, third, - compat_ptr(ptr)); - default: - return -EINVAL; - }; - if (call <= MSGCTL) - switch (call) { - case MSGSND: - return compat_sys_msgsnd (first, second, third, - compat_ptr(ptr)); - case MSGRCV: - return compat_sys_msgrcv (first, second, 0, third, - 0, compat_ptr(ptr)); - case MSGGET: - return sys_msgget ((key_t) first, second); - case MSGCTL: - return compat_sys_msgctl (first, second, - compat_ptr(ptr)); - default: - return -EINVAL; - } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - return compat_sys_shmat (first, second, third, - 0, compat_ptr(ptr)); - case SHMDT: - return sys_shmdt(compat_ptr(ptr)); - case SHMGET: - return sys_shmget(first, second, third); - case SHMCTL: - return compat_sys_shmctl(first, second, - compat_ptr(ptr)); - default: - return -EINVAL; - } + switch (call) { + case SEMTIMEDOP: + return compat_sys_semtimedop(first, compat_ptr(ptr), + second, compat_ptr(third)); + case SEMOP: + /* struct sembuf is the same on 32 and 64bit :)) */ + return sys_semtimedop(first, compat_ptr(ptr), + second, NULL); + case SEMGET: + return sys_semget(first, second, third); + case SEMCTL: + return compat_sys_semctl(first, second, third, + compat_ptr(ptr)); + case MSGSND: + return compat_sys_msgsnd(first, second, third, + compat_ptr(ptr)); + case MSGRCV: + return compat_sys_msgrcv(first, second, 0, third, + 0, compat_ptr(ptr)); + case MSGGET: + return sys_msgget((key_t) first, second); + case MSGCTL: + return compat_sys_msgctl(first, second, compat_ptr(ptr)); + case SHMAT: + return compat_sys_shmat(first, second, third, + 0, compat_ptr(ptr)); + case SHMDT: + return sys_shmdt(compat_ptr(ptr)); + case SHMGET: + return sys_shmget(first, second, third); + case SHMCTL: + return compat_sys_shmctl(first, second, compat_ptr(ptr)); + } - return -EINVAL; + return -ENOSYS; } asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low) diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 043c25b7b8f9..66861b95da68 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1361,7 +1361,7 @@ compat_sys_mq_open_wrapper: llgtr %r5,%r5 # struct compat_mq_attr * jg compat_sys_mq_open - .globl sys_mq_unlink_wrapper + .globl sys32_mq_unlink_wrapper sys32_mq_unlink_wrapper: llgtr %r2,%r2 # const char * jg sys_mq_unlink diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 37520c7e71be..d5a9e1cdac09 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -198,7 +198,8 @@ __switch_to_noper: */ .global do_call_softirq do_call_softirq: - stm %r12,%r15,24(%r15) + stnsm 24(%r15),0xfc + stm %r12,%r15,28(%r15) lr %r12,%r15 basr %r13,0 do_call_base: @@ -211,7 +212,8 @@ do_call_base: st %r12,0(%r15) # store backchain l %r1,.Ldo_softirq-do_call_base(%r13) basr %r14,%r1 - lm %r12,%r15,24(%r12) + lm %r12,%r15,28(%r12) + ssm 24(%r15) br %r14 __critical_start: diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 89c52f6b35fe..e94e694d512c 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -186,7 +186,8 @@ __switch_to_noper: */ .global do_call_softirq do_call_softirq: - stmg %r12,%r15,48(%r15) + stnsm 48(%r15),0xfc + stmg %r12,%r15,56(%r15) lgr %r12,%r15 lg %r0,__LC_ASYNC_STACK slgr %r0,%r15 @@ -196,7 +197,8 @@ do_call_softirq: 0: aghi %r15,-STACK_FRAME_OVERHEAD stg %r12,0(%r15) # store back chain brasl %r14,do_softirq - lmg %r12,%r15,48(%r12) + lmg %r12,%r15,56(%r12) + ssm 48(%r15) br %r14 __critical_start: diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 7f0e45e001f0..7ca8a8706cca 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -254,13 +254,13 @@ void (*_machine_power_off)(void) = machine_power_off_smp; /* * Reboot, halt and power_off routines for non SMP. */ -extern void do_reipl(unsigned long devno); +extern void reipl(unsigned long devno); static void do_machine_restart_nonsmp(char * __unused) { if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0); else - do_reipl (0x10000 | S390_lowcore.ipl_device); + reipl (0x10000 | S390_lowcore.ipl_device); } static void do_machine_halt_nonsmp(void) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 2ee07a475716..de99f63ec951 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -64,7 +64,7 @@ EXPORT_SYMBOL(cpu_online_map); extern char vmhalt_cmd[]; extern char vmpoff_cmd[]; -extern void do_reipl(unsigned long devno); +extern void reipl(unsigned long devno); static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); @@ -278,7 +278,7 @@ static void do_machine_restart(void * __unused) if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0); else - do_reipl (0x10000 | S390_lowcore.ipl_device); + reipl (0x10000 | S390_lowcore.ipl_device); } signal_processor(smp_processor_id(), sigp_stop); } diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index d778f98a2c7c..016eb6cd48c9 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -105,17 +105,6 @@ void show_trace(struct task_struct *task, unsigned long * stack) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - /* - * We can't print the backtrace of a running process. It is - * unreliable at best and can cause kernel oopses. - */ - if (tsk->state == TASK_RUNNING) - return; - show_trace(tsk, (unsigned long *) tsk->thread.ksp); -} - void show_stack(struct task_struct *task, unsigned long *sp) { unsigned long *stack; diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 5211a375afa8..3e63d8a70ed3 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -705,14 +705,8 @@ void show_task(unsigned long *sp) show_stack(NULL, sp); } -void show_trace_task(struct task_struct *tsk) -{ - show_task((unsigned long *)tsk->thread.sp); -} - void dump_stack(void) { show_stack(NULL, NULL); } - EXPORT_SYMBOL(dump_stack); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3cf8af39ac95..47d685193ade 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1760,13 +1760,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) #endif } -void show_trace_task(struct task_struct *tsk) -{ - if (tsk) - show_stack(tsk, - (unsigned long *) tsk->thread_info->ksp); -} - void dump_stack(void) { unsigned long *ksp; diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 078dc11132d3..ce108f7d6971 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -42,19 +42,8 @@ void dump_stack(void) show_trace(&stack); } - EXPORT_SYMBOL(dump_stack); -void show_trace_task(struct task_struct *tsk) -{ - unsigned long esp = PT_REGS_SP(&tsk->thread.regs); - - /* User space on another CPU? */ - if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) - return; - show_trace((unsigned long *)esp); -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c index 977d75772d81..2fccb4cc7b82 100644 --- a/arch/v850/kernel/process.c +++ b/arch/v850/kernel/process.c @@ -234,10 +234,3 @@ unsigned long get_wchan (struct task_struct *p) return 0; } - -void show_trace_task (struct task_struct *t) -{ - /* blarg XXX */ - printk ("show_trace_task: KSP = 0x%lx, USP = 0x%lx, UPC = 0x%lx\n", - t->thread.ksp, KSTK_ESP (t), KSTK_EIP (t)); -} diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 5afe235c0474..2efdbaa1ecfa 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -197,16 +197,6 @@ void show_trace(unsigned long *stack) printk("\n"); } -void show_trace_task(struct task_struct *tsk) -{ - unsigned long rsp = tsk->thread.rsp; - - /* User space on another CPU? */ - if ((rsp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1)) - return; - show_trace((unsigned long *)rsp); -} - void show_stack(struct task_struct *tsk, unsigned long * rsp) { unsigned long *stack; diff --git a/crypto/Kconfig b/crypto/Kconfig index 4b0925ea142b..d7c9d552fd8b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -40,6 +40,12 @@ config CRYPTO_SHA1 help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). +config CRYPTO_SHA1_Z990 + tristate "SHA1 digest algorithm for IBM zSeries z990" + depends on CRYPTO && ARCH_S390 + help + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). + config CRYPTO_SHA256 tristate "SHA256 digest algorithm" depends on CRYPTO @@ -67,6 +73,12 @@ config CRYPTO_DES help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). +config CRYPTO_DES_Z990 + tristate "DES and Triple DES cipher algorithms for IBM zSeries z990" + depends on CRYPTO && ARCH_S390 + help + DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). + config CRYPTO_BLOWFISH tristate "Blowfish cipher algorithm" depends on CRYPTO diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index b1d5dfa351ff..9d2759d8aa92 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -39,6 +39,8 @@ #include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/completion.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <asm/bug.h> @@ -132,7 +134,12 @@ struct cdrom_info { char type[4]; char model[3]; }; -static struct cdrom_info viocd_unitinfo[VIOCD_MAX_CD]; +/* + * This needs to be allocated since it is passed to the + * Hypervisor and we may be a module. + */ +static struct cdrom_info *viocd_unitinfo; +static dma_addr_t unitinfo_dmaaddr; struct disk_info { struct gendisk *viocd_disk; @@ -141,13 +148,39 @@ struct disk_info { static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; #define DEVICE_NR(di) ((di) - &viocd_diskinfo[0]) -#define VIOCDI viocd_diskinfo[deviceno].viocd_info static request_queue_t *viocd_queue; static spinlock_t viocd_reqlock; #define MAX_CD_REQ 1 +/* procfs support */ +static int proc_viocd_show(struct seq_file *m, void *v) +{ + int i; + + for (i = 0; i < viocd_numdev; i++) { + seq_printf(m, "viocd device %d is iSeries resource %10.10s" + "type %4.4s, model %3.3s\n", + i, viocd_unitinfo[i].rsrcname, + viocd_unitinfo[i].type, + viocd_unitinfo[i].model); + } + return 0; +} + +static int proc_viocd_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_viocd_show, NULL); +} + +static struct file_operations proc_viocd_operations = { + .open = proc_viocd_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int viocd_blk_open(struct inode *inode, struct file *file) { struct disk_info *di = inode->i_bdev->bd_disk->private_data; @@ -184,18 +217,20 @@ struct block_device_operations viocd_fops = { /* Get info on CD devices from OS/400 */ static void __init get_viocd_info(void) { - dma_addr_t dmaaddr; HvLpEvent_Rc hvrc; int i; struct viocd_waitevent we; - dmaaddr = dma_map_single(iSeries_vio_dev, viocd_unitinfo, - sizeof(viocd_unitinfo), DMA_FROM_DEVICE); - if (dmaaddr == (dma_addr_t)-1) { - printk(VIOCD_KERN_WARNING "error allocating tce\n"); + viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev, + sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, + &unitinfo_dmaaddr, GFP_ATOMIC); + if (viocd_unitinfo == NULL) { + printk(VIOCD_KERN_WARNING "error allocating unitinfo\n"); return; } + memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD); + init_completion(&we.com); hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -204,29 +239,34 @@ static void __init get_viocd_info(void) HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, viopath_sourceinst(viopath_hostLp), viopath_targetinst(viopath_hostLp), - (u64)&we, VIOVERSION << 16, dmaaddr, 0, - sizeof(viocd_unitinfo), 0); + (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, + sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0); if (hvrc != HvLpEvent_Rc_Good) { printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", (int)hvrc); - return; + goto error_ret; } wait_for_completion(&we.com); - dma_unmap_single(iSeries_vio_dev, dmaaddr, sizeof(viocd_unitinfo), - DMA_FROM_DEVICE); - if (we.rc) { const struct vio_error_entry *err = vio_lookup_rc(viocd_err_table, we.sub_result); printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", we.rc, we.sub_result, err->msg); - return; + goto error_ret; } for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) viocd_numdev++; + + return; + +error_ret: + dma_free_coherent(iSeries_vio_dev, + sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, + viocd_unitinfo, unitinfo_dmaaddr); + viocd_unitinfo = NULL; } static int viocd_open(struct cdrom_device_info *cdi, int purpose) @@ -307,10 +347,6 @@ static int send_request(struct request *req) } dmaaddr = sg_dma_address(&sg); len = sg_dma_len(&sg); - if (dmaaddr == (dma_addr_t)-1) { - printk(VIOCD_KERN_WARNING "error allocating tce\n"); - return -1; - } hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, HvLpEvent_Type_VirtualIo, @@ -534,6 +570,7 @@ static int __init viocd_init(void) struct gendisk *gendisk; int deviceno; int ret = 0; + struct proc_dir_entry *e; if (viopath_hostLp == HvLpIndexInvalid) { vio_set_hostlp(); @@ -604,7 +641,7 @@ static int __init viocd_init(void) printk(VIOCD_KERN_WARNING "Cannot create gendisk for %s!\n", c->name); - unregister_cdrom(&VIOCDI); + unregister_cdrom(c); continue; } gendisk->major = VIOCD_MAJOR; @@ -622,6 +659,12 @@ static int __init viocd_init(void) add_disk(gendisk); } + e = create_proc_entry("iSeries/viocd", S_IFREG|S_IRUGO, NULL); + if (e) { + e->owner = THIS_MODULE; + e->proc_fops = &proc_viocd_operations; + } + return 0; out_undo_vio: @@ -636,6 +679,7 @@ static void __exit viocd_exit(void) { int deviceno; + remove_proc_entry("iSeries/viocd", NULL); for (deviceno = 0; deviceno < viocd_numdev; deviceno++) { struct disk_info *d = &viocd_diskinfo[deviceno]; if (unregister_cdrom(&d->viocd_info) != 0) @@ -646,7 +690,10 @@ static void __exit viocd_exit(void) put_disk(d->viocd_disk); } blk_cleanup_queue(viocd_queue); - + if (viocd_unitinfo != NULL) + dma_free_coherent(iSeries_vio_dev, + sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, + viocd_unitinfo, unitinfo_dmaaddr); viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); vio_clearHandler(viomajorsubtype_cdio); unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 3f2b43fe4ac6..a5915c1e764b 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -47,6 +47,8 @@ #include <linux/devfs_fs_kernel.h> #include <linux/major.h> #include <linux/completion.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <asm/uaccess.h> #include <asm/ioctls.h> @@ -56,7 +58,7 @@ #include <asm/iSeries/HvCallEvent.h> #include <asm/iSeries/HvLpConfig.h> -#define VIOTAPE_VERSION "1.1" +#define VIOTAPE_VERSION "1.2" #define VIOTAPE_MAXREQ 1 #define VIOTAPE_KERN_WARN KERN_WARNING "viotape: " @@ -269,6 +271,34 @@ static struct op_struct *op_struct_list; /* forward declaration to resolve interdependence */ static int chg_state(int index, unsigned char new_state, struct file *file); +/* procfs support */ +static int proc_viotape_show(struct seq_file *m, void *v) +{ + int i; + + seq_printf(m, "viotape driver version " VIOTAPE_VERSION "\n"); + for (i = 0; i < viotape_numdev; i++) { + seq_printf(m, "viotape device %d is iSeries resource %10.10s" + "type %4.4s, model %3.3s\n", + i, viotape_unitinfo[i].rsrcname, + viotape_unitinfo[i].type, + viotape_unitinfo[i].model); + } + return 0; +} + +static int proc_viotape_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_viotape_show, NULL); +} + +static struct file_operations proc_viotape_operations = { + .open = proc_viotape_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* Decode the device minor number into its parts */ void get_dev_info(struct inode *ino, struct viot_devinfo_struct *devi) { @@ -912,6 +942,7 @@ int __init viotap_init(void) int ret; char tapename[32]; int i; + struct proc_dir_entry *e; op_struct_list = NULL; if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) { @@ -988,6 +1019,12 @@ int __init viotap_init(void) viotape_unitinfo[i].model); } + e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL); + if (e) { + e->owner = THIS_MODULE; + e->proc_fops = &proc_viotape_operations; + } + return 0; unreg_class: @@ -1029,6 +1066,8 @@ static void __exit viotap_exit(void) { int i, ret; + remove_proc_entry("iSeries/viotape", NULL); + for (i = 0; i < viotape_numdev; ++i) { devfs_remove("iseries/nvt%d", i); devfs_remove("iseries/vt%d", i); diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 79c9cb80fd0a..ac2246dd7646 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -86,7 +86,7 @@ static struct edd_device *edd_devices[EDDMAXNR]; #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ struct edd_attribute edd_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ + .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ .show = _show, \ .test = _test, \ }; diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 10a54ddd2540..cacd1f20ea5f 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -130,3 +130,13 @@ config SERIO_PCIPS2 To compile this driver as a module, choose M here: the module will be called pcips2. + +config SERIO_MACEPS2 + tristate "SGI O2 MACE PS/2 controller" + depends on SGI_IP32 && SERIO + help + Say Y here if you have SGI O2 workstation and want to use its + PS/2 ports. + + To compile this driver as a module, choose M here: the + module will be called maceps2. diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 2eb86eba6ed9..a47dec2556e8 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o +obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 6b434f8b62f1..9b36485fc605 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -69,7 +69,7 @@ static inline int i8042_platform_init(void) * On ix86 platforms touching the i8042 data register region can do really * bad things. Because of this the region is always reserved on ix86 boxes. */ -#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) +#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) if (!request_region(I8042_DATA_REG, 16, "i8042")) return -1; #endif diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h new file mode 100644 index 000000000000..863b9c95fbb8 --- /dev/null +++ b/drivers/input/serio/i8042-ip22io.h @@ -0,0 +1,76 @@ +#ifndef _I8042_IP22_H +#define _I8042_IP22_H + +#include <asm/sgi/ioc.h> +#include <asm/sgi/ip22.h> + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * Names. + */ + +#define I8042_KBD_PHYS_DESC "hpc3ps2/serio0" +#define I8042_AUX_PHYS_DESC "hpc3ps2/serio1" +#define I8042_MUX_PHYS_DESC "hpc3ps2/serio%d" + +/* + * IRQs. + */ + +#define I8042_KBD_IRQ SGI_KEYBD_IRQ +#define I8042_AUX_IRQ SGI_KEYBD_IRQ + +/* + * Register numbers. + */ + +#define I8042_COMMAND_REG ((unsigned long)&sgioc->kbdmouse.command) +#define I8042_STATUS_REG ((unsigned long)&sgioc->kbdmouse.command) +#define I8042_DATA_REG ((unsigned long)&sgioc->kbdmouse.data) + +static inline int i8042_read_data(void) +{ + return sgioc->kbdmouse.data; +} + +static inline int i8042_read_status(void) +{ + return sgioc->kbdmouse.command; +} + +static inline void i8042_write_data(int val) +{ + sgioc->kbdmouse.data = val; +} + +static inline void i8042_write_command(int val) +{ + sgioc->kbdmouse.command = val; +} + +static inline int i8042_platform_init(void) +{ +#if 0 + /* XXX sgi_kh is a virtual address */ + if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042")) + return 1; +#endif + + i8042_reset = 1; + + return 0; +} + +static inline void i8042_platform_exit(void) +{ +#if 0 + release_mem_region(JAZZ_KEYBOARD_ADDRESS, sizeof(struct hpc_keyb)); +#endif +} + +#endif /* _I8042_IP22_H */ diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h new file mode 100644 index 000000000000..5c20ab131488 --- /dev/null +++ b/drivers/input/serio/i8042-jazzio.h @@ -0,0 +1,69 @@ +#ifndef _I8042_JAZZ_H +#define _I8042_JAZZ_H + +#include <asm/jazz.h> + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * Names. + */ + +#define I8042_KBD_PHYS_DESC "R4030/serio0" +#define I8042_AUX_PHYS_DESC "R4030/serio1" +#define I8042_MUX_PHYS_DESC "R4030/serio%d" + +/* + * IRQs. + */ + +#define I8042_KBD_IRQ JAZZ_KEYBOARD_IRQ +#define I8042_AUX_IRQ JAZZ_MOUSE_IRQ + +#define I8042_COMMAND_REG ((unsigned long)&jazz_kh->command) +#define I8042_STATUS_REG ((unsigned long)&jazz_kh->command) +#define I8042_DATA_REG ((unsigned long)&jazz_kh->data) + +static inline int i8042_read_data(void) +{ + return jazz_kh->data; +} + +static inline int i8042_read_status(void) +{ + return jazz_kh->command; +} + +static inline void i8042_write_data(int val) +{ + jazz_kh->data = val; +} + +static inline void i8042_write_command(int val) +{ + jazz_kh->command = val; +} + +static inline int i8042_platform_init(void) +{ +#if 0 + /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */ + if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042")) + return 1; +#endif + + return 0; +} + +static inline void i8042_platform_exit(void) +{ +#if 0 + release_mem_region(JAZZ_KEYBOARD_ADDRESS, 2); +#endif +} + +#endif /* _I8042_JAZZ_H */ diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index 3d59eb2e05a7..f0f637483233 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h @@ -1,6 +1,8 @@ #ifndef _I8042_H #define _I8042_H +#include <linux/config.h> + /* * Copyright (c) 1999-2002 Vojtech Pavlik * @@ -13,7 +15,11 @@ * Arch-dependent inline functions and defines. */ -#if defined(CONFIG_PPC) +#if defined(CONFIG_MIPS_JAZZ) +#include "i8042-jazzio.h" +#elif defined(CONFIG_SGI_IP22) +#include "i8042-ip22io.h" +#elif defined(CONFIG_PPC) #include "i8042-ppcio.h" #elif defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) #include "i8042-sparcio.h" diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c new file mode 100644 index 000000000000..c7db1de49cfc --- /dev/null +++ b/drivers/input/serio/maceps2.c @@ -0,0 +1,160 @@ +/* + * SGI O2 MACE PS2 controller driver for linux + * + * Copyright (C) 2002 Vivien Chappelier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/serio.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/ip32/mace.h> +#include <asm/ip32/ip32_ints.h> + +MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org"); +MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver"); +MODULE_LICENSE("GPL"); + +#define MACE_PS2_TIMEOUT 10000 /* in 50us unit */ + +#define PS2_STATUS_CLOCK_SIGNAL BIT(0) /* external clock signal */ +#define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */ +#define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */ +#define PS2_STATUS_TX_EMPTY BIT(3) /* empty transmit buffer */ +#define PS2_STATUS_RX_FULL BIT(4) /* full receive buffer */ +#define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */ +#define PS2_STATUS_ERROR_PARITY BIT(6) /* parity error */ +#define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */ + +#define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */ +#define PS2_CONTROL_TX_ENABLE BIT(1) /* transmit enable */ +#define PS2_CONTROL_TX_INT_ENABLE BIT(2) /* enable transmit interrupt */ +#define PS2_CONTROL_RX_INT_ENABLE BIT(3) /* enable receive interrupt */ +#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */ +#define PS2_CONTROL_RESET BIT(5) /* reset */ + + +struct maceps2_data { + struct mace_ps2port *port; + int irq; +}; + +static int maceps2_write(struct serio *dev, unsigned char val) +{ + struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port; + unsigned int timeout = MACE_PS2_TIMEOUT; + + do { + if (mace_read(port->status) & PS2_STATUS_TX_EMPTY) { + mace_write(val, port->tx); + return 0; + } + udelay(50); + } while (timeout--); + + return -1; +} + +static irqreturn_t maceps2_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct serio *dev = dev_id; + struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port; + unsigned int byte; + + if (mace_read(port->status) & PS2_STATUS_RX_FULL) { + byte = mace_read(port->rx); + serio_interrupt(dev, byte & 0xff, 0, regs); + } + + return IRQ_HANDLED; +} + +static int maceps2_open(struct serio *dev) +{ + struct maceps2_data *data = (struct maceps2_data *)dev->driver; + + if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) { + printk(KERN_ERR "Could not allocate PS/2 IRQ\n"); + return -EBUSY; + } + + /* Reset port */ + mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET, + data->port->control); + udelay(100); + + /* Enable interrupts */ + mace_write(PS2_CONTROL_RX_CLOCK_ENABLE | PS2_CONTROL_TX_ENABLE | + PS2_CONTROL_RX_INT_ENABLE, data->port->control); + + return 0; +} + +static void maceps2_close(struct serio *dev) +{ + struct maceps2_data *data = (struct maceps2_data *)dev->driver; + + mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET, + data->port->control); + udelay(100); + free_irq(data->irq, dev); +} + +static struct maceps2_data port0_data, port1_data; + +static struct serio maceps2_port0 = +{ + .type = SERIO_8042, + .open = maceps2_open, + .close = maceps2_close, + .write = maceps2_write, + .name = "MACE PS/2 port0", + .phys = "mace/serio0", + .driver = &port0_data, +}; + +static struct serio maceps2_port1 = +{ + .type = SERIO_8042, + .open = maceps2_open, + .close = maceps2_close, + .write = maceps2_write, + .name = "MACE PS/2 port1", + .phys = "mace/serio1", + .driver = &port1_data, +}; + +static int __init maceps2_init(void) +{ + port0_data.port = &mace->perif.ps2.keyb; + port0_data.irq = MACEISA_KEYB_IRQ; + port1_data.port = &mace->perif.ps2.mouse; + port1_data.irq = MACEISA_MOUSE_IRQ; + serio_register_port(&maceps2_port0); + serio_register_port(&maceps2_port1); + + return 0; +} + +static void __exit maceps2_exit(void) +{ + serio_unregister_port(&maceps2_port0); + serio_unregister_port(&maceps2_port1); +} + +module_init(maceps2_init); +module_exit(maceps2_exit); diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 87fa182a06b3..260b12b34779 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -24,8 +24,7 @@ obj-$(CONFIG_PARISC) += setup-bus.o obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o obj-$(CONFIG_PPC32) += setup-irq.o obj-$(CONFIG_PPC64) += setup-bus.o -obj-$(CONFIG_SGI_IP27) += setup-irq.o -obj-$(CONFIG_SGI_IP32) += setup-irq.o +obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_PCI_USE_VECTOR) += msi.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d0ab034fa0c1..ab9f28443436 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.136 $ + * $Revision: 1.139 $ */ #include <linux/config.h> @@ -74,6 +74,8 @@ dasd_alloc_device(void) if (device == NULL) return ERR_PTR(-ENOMEM); memset(device, 0, sizeof (struct dasd_device)); + /* open_count = 0 means device online but not in use */ + atomic_set(&device->open_count, -1); /* Get two pages for normal block device operations. */ device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1); @@ -549,6 +551,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize, } strncpy((char *) &cqr->magic, magic, 4); ASCEBC((char *) &cqr->magic, 4); + set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); dasd_get_device(device); return cqr; } @@ -597,6 +600,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize, } strncpy((char *) &cqr->magic, magic, 4); ASCEBC((char *) &cqr->magic, 4); + set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); dasd_get_device(device); return cqr; } @@ -688,9 +692,10 @@ dasd_term_IO(struct dasd_ccw_req * cqr) rc = ccw_device_clear(device->cdev, (long) cqr); switch (rc) { case 0: /* termination successful */ - if (cqr->retries > 0) + if (cqr->retries > 0) { + cqr->retries--; cqr->status = DASD_CQR_QUEUED; - else + } else cqr->status = DASD_CQR_FAILED; cqr->stopclk = get_clock(); break; @@ -982,6 +987,8 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, irb->scsw.cstat == 0 && !irb->esw.esw0.erw.cons) era = dasd_era_none; + else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) + era = dasd_era_fatal; /* don't recover this request */ else if (irb->esw.esw0.erw.cons) era = device->discipline->examine_error(cqr, irb); else @@ -1875,7 +1882,7 @@ dasd_generic_set_offline (struct ccw_device *cdev) * the blkdev_get in dasd_scan_partitions. We are only interested * in the other openers. */ - max_count = device->bdev ? 1 : 0; + max_count = device->bdev ? 0 : -1; if (atomic_read(&device->open_count) > max_count) { printk (KERN_WARNING "Can't offline dasd device with open" " count = %i.\n", diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c6b26e729aaa..e90c1c93e19a 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -5,7 +5,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.28 $ + * $Revision: 1.30 $ */ #include <linux/timer.h> @@ -1763,6 +1763,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) erp->magic = default_erp->magic; erp->expires = 0; erp->retries = 256; + cqr->buildclk = get_clock(); erp->status = DASD_CQR_FILLED; /* remove the default erp */ diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1490f1e4a4ec..e7afb426b539 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -7,7 +7,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.53 $ + * $Revision: 1.54 $ */ #include <linux/config.h> @@ -1130,6 +1130,7 @@ dasd_eckd_release(struct block_device *bdev, int no, long args) cqr->cpaddr->count = 32; cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; + clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); @@ -1173,6 +1174,7 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args) cqr->cpaddr->count = 32; cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; + clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); @@ -1215,6 +1217,7 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) cqr->cpaddr->count = 32; cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; + clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 70ccb1110d07..9967c082c0ad 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,7 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.56 $ + * $Revision: 1.57 $ */ #ifndef DASD_INT_H @@ -159,6 +159,7 @@ struct dasd_ccw_req { struct ccw1 *cpaddr; /* address of channel program */ char status; /* status of this request */ short retries; /* A retry counter */ + unsigned long flags; /* flags of this request */ /* ... and how */ unsigned long starttime; /* jiffies time of request start */ @@ -192,6 +193,9 @@ struct dasd_ccw_req { #define DASD_CQR_ERROR 0x04 /* request is completed with error */ #define DASD_CQR_FAILED 0x05 /* request is finally failed */ +/* per dasd_ccw_req flags */ +#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ + /* Signature for error recovery functions. */ typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index ef0f996fa798..ecba07756cbb 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -381,6 +381,8 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) return; /* Sucessfully restarted. */ break; case RAW3270_IO_STOP: + if (!rq) + break; raw3270_halt_io_nolock(rp, rq); rq->rc = -EIO; break; @@ -881,7 +883,7 @@ raw3270_activate_view(struct raw3270_view *view) if (rc) { /* Didn't work. Try to reactivate the old view. */ rp->view = oldview; - if (oldview->fn->activate(oldview) != 0) { + if (!oldview || oldview->fn->activate(oldview) != 0) { /* Didn't work as well. Try any other view. */ list_for_each_entry(nv, &rp->view_list, list) if (nv != view && nv != oldview) { diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index cffeda66520e..ccdf053b3dfd 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.117 $ + * $Revision: 1.121 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -783,3 +783,68 @@ cio_get_console_subchannel(void) } #endif +static inline int +__disable_subchannel_easy(unsigned int schid, struct schib *schib) +{ + int retry, cc; + + cc = 0; + for (retry=0;retry<3;retry++) { + schib->pmcw.ena = 0; + cc = msch(schid, schib); + if (cc) + return (cc==3?-ENODEV:-EBUSY); + stsch(schid, schib); + if (!schib->pmcw.ena) + return 0; + } + return -EBUSY; /* uhm... */ +} + +static inline int +__clear_subchannel_easy(unsigned int schid) +{ + int retry; + + if (csch(schid)) + return -ENODEV; + for (retry=0;retry<20;retry++) { + struct tpi_info ti; + + if (tpi(&ti)) { + tsch(schid, (struct irb *)__LC_IRB); + return 0; + } + udelay(100); + } + return -EBUSY; +} + +extern void do_reipl(unsigned long devno); +/* Make sure all subchannels are quiet before we re-ipl an lpar. */ +void +reipl(unsigned long devno) +{ + unsigned int schid; + + local_irq_disable(); + for (schid=0;schid<=highest_subchannel;schid++) { + struct schib schib; + if (stsch(schid, &schib)) + goto out; + if (!schib.pmcw.ena) + continue; + switch(__disable_subchannel_easy(schid, &schib)) { + case 0: + case -ENODEV: + break; + default: /* -EBUSY */ + if (__clear_subchannel_easy(schid)) + break; /* give up... */ + stsch(schid, &schib); + __disable_subchannel_easy(schid, &schib); + } + } +out: + do_reipl(devno); +} diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index eac048a1991c..763056eede77 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -440,12 +440,14 @@ ccw_device_nopath_notify(void *data) if (!ret) { if (get_device(&sch->dev)) { /* Driver doesn't want to keep device. */ + cio_disable_subchannel(sch); device_unregister(&sch->dev); sch->schib.pmcw.intparm = 0; cio_modify(sch); put_device(&sch->dev); } } else { + cio_disable_subchannel(sch); ccw_device_set_timeout(cdev, 0); cdev->private->state = DEV_STATE_DISCONNECTED; wake_up(&cdev->private->wait_q); @@ -787,6 +789,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); + ccw_device_set_timeout(cdev, 0); /* OK, i/o is dead now. Call interrupt handler. */ cdev->private->state = DEV_STATE_ONLINE; if (cdev->handler) diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 3188cde89326..f4c9779d2d4a 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.79 $" +#define VERSION_QDIO_C "$Revision: 1.80 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); @@ -461,12 +461,12 @@ check_next: switch(slsb[f_mod_no]) { - /* the hydra has not fetched the output yet */ + /* the adapter has not fetched the output yet */ case SLSB_CU_OUTPUT_PRIMED: QDIO_DBF_TEXT5(0,trace,"outpprim"); break; - /* the hydra got it */ + /* the adapter got it */ case SLSB_P_OUTPUT_EMPTY: atomic_dec(&q->number_of_buffers_used); f++; @@ -919,7 +919,7 @@ qdio_is_inbound_q_done(struct qdio_q *q) no_used=atomic_read(&q->number_of_buffers_used); /* - * we need that one for synchronization with Hydra, as Hydra + * we need that one for synchronization with the adapter, as it * does a kind of PCI avoidance */ SYNC_MEMORY; @@ -1069,7 +1069,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) } /* * maybe we have to do work on our outbound queues... at least - * we have to check Hydra outbound-int-capable thinint-capable + * we have to check the outbound-int-capable thinint-capable * queues */ if (q->hydra_gives_outbound_pcis) { @@ -2027,7 +2027,7 @@ tiqdio_check_chsc_availability(void) goto exit; } - /* Check for hydra thin interrupts (bit 67). */ + /* Check for OSA/FCP thin interrupts (bit 67). */ hydra_thinints = ((scsc_area->general_char[2] & 0x10000000) == 0x10000000); sprintf(dbf_text,"hydrati%1x", hydra_thinints); diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index 601453f1a6b9..5771fb36360f 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.27 2004/03/22 07:43:43 braunu Exp $ + * $Id: iucv.c,v 1.28 2004/04/15 06:34:58 braunu Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.27 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.28 $ * */ @@ -351,7 +351,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.27 $"; + char vbuf[] = "$Revision: 1.28 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -800,6 +800,7 @@ iucv_register_program (__u8 pgmname[16], if (iucv_pathid_table == NULL) { printk(KERN_WARNING "%s: iucv_pathid_table storage " "allocation failed\n", __FUNCTION__); + kfree(new_handler); return NULL; } memset (iucv_pathid_table, 0, max_connections * sizeof(handler *)); diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index fb30461252ab..a65ef7677beb 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1,5 +1,5 @@ /* - * $Id: netiucv.c,v 1.48 2004/04/01 13:42:09 braunu Exp $ + * $Id: netiucv.c,v 1.49 2004/04/15 06:37:54 braunu Exp $ * * IUCV network driver * @@ -30,7 +30,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.48 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.49 $ * */ @@ -601,11 +601,12 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) if ((skb = skb_dequeue(&conn->commit_queue))) { atomic_dec(&skb->users); dev_kfree_skb_any(skb); - } - if (privptr) { - privptr->stats.tx_packets++; - privptr->stats.tx_bytes += - (skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN); + if (privptr) { + privptr->stats.tx_packets++; + privptr->stats.tx_bytes += + (skb->len - NETIUCV_HDRLEN + - NETIUCV_HDRLEN); + } } } conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head; @@ -1078,6 +1079,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { "%s: Could not allocate tx_skb\n", conn->netdev->name); rc = -ENOMEM; + return rc; } else { skb_reserve(nskb, NETIUCV_HDRLEN); memcpy(skb_put(nskb, skb->len), @@ -1880,7 +1882,7 @@ static struct device_driver netiucv_driver = { static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.48 $"; + char vbuf[] = "$Revision: 1.49 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 1175c1e8deac..74b167b0f29a 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -23,7 +23,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.98 $" +#define VERSION_QETH_H "$Revision: 1.100 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -423,14 +423,12 @@ struct qeth_qdio_out_q { struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q]; int queue_no; struct qeth_card *card; - struct tasklet_struct tasklet; spinlock_t lock; volatile int do_pack; /* * index of buffer to be filled by driver; state EMPTY or PACKING */ volatile int next_buf_to_fill; - volatile int next_buf_to_flush; /* * number of buffers that are currently filled (PRIMED) * -> these buffers are hardware-owned @@ -447,7 +445,6 @@ struct qeth_qdio_info { struct qeth_qdio_buffer_pool in_buf_pool; struct qeth_qdio_buffer_pool init_pool; int in_buf_size; - struct tasklet_struct in_tasklet; /* output */ int no_out_queues; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 414d9c3de0d5..4ee0592f21d0 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.77 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.82 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.77 $ $Date: 2004/04/06 14:38:19 $ + * $Revision: 1.82 $ $Date: 2004/04/21 08:27:21 $ * * 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 @@ -78,7 +78,7 @@ qeth_eyecatcher(void) #include "qeth_mpc.h" #include "qeth_fs.h" -#define VERSION_QETH_C "$Revision: 1.77 $" +#define VERSION_QETH_C "$Revision: 1.82 $" static const char *version = "qeth S/390 OSA-Express driver (" VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H QETH_VERSION_IPV6 QETH_VERSION_VLAN ")"; @@ -486,6 +486,7 @@ qeth_remove_device(struct ccwgroup_device *cgdev) list_del(&card->list); write_unlock_irqrestore(&qeth_card_list.rwlock, flags); unregister_netdev(card->dev); + qeth_remove_device_attributes(&cgdev->dev); qeth_free_card(card); cgdev->dev.driver_data = NULL; put_device(&cgdev->dev); @@ -822,7 +823,7 @@ qeth_register_mc_addresses(void *ptr) struct qeth_card *card; card = (struct qeth_card *) ptr; - daemonize("getmcaddr"); + daemonize("qeth_reg_mcaddrs"); QETH_DBF_TEXT(trace,4,"regmcth1"); if (!qeth_do_run_thread(card, QETH_SET_MC_THREAD)) return 0; @@ -843,7 +844,7 @@ qeth_register_ip_address(void *ptr) struct qeth_card *card; card = (struct qeth_card *) ptr; - daemonize("regip"); + daemonize("qeth_reg_ip"); QETH_DBF_TEXT(trace,4,"regipth1"); if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD)) return 0; @@ -860,7 +861,7 @@ qeth_recover(void *ptr) int rc = 0; card = (struct qeth_card *) ptr; - daemonize("recover"); + daemonize("qeth_recover"); QETH_DBF_TEXT(trace,2,"recover1"); QETH_DBF_HEX(trace, 2, &card, sizeof(void *)); if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD)) @@ -1969,45 +1970,6 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf, return rc; } -static void -qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, - unsigned int qdio_err, unsigned int siga_err, - unsigned int queue, int first_element, int count, - unsigned long card_ptr) -{ - struct net_device *net_dev; - struct qeth_card *card; - struct qeth_qdio_buffer *buffer; - int i; - - QETH_DBF_TEXT(trace, 6, "qdinput"); - card = (struct qeth_card *) card_ptr; - net_dev = card->dev; -#ifdef CONFIG_QETH_PERF_STATS - card->perf_stats.inbound_start_time = qeth_get_micros(); -#endif - if (status & QDIO_STATUS_LOOK_FOR_ERROR) { - if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ - QETH_DBF_TEXT(trace, 1,"qdinchk"); - QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); - QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count); - QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status); - qeth_schedule_recovery(card); - return; - } - } - for (i = first_element; i < (first_element + count); ++i) { - buffer = &card->qdio.in_q->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - if ((status == QDIO_STATUS_LOOK_FOR_ERROR) && - qeth_check_for_inbound_error(buffer, qdio_err, siga_err)) - buffer->state = QETH_QDIO_BUF_ERROR; - else - buffer->state = QETH_QDIO_BUF_PRIMED; - } - - tasklet_schedule(&card->qdio.in_tasklet); -} - static inline struct sk_buff * qeth_get_skb(unsigned int length) { @@ -2127,7 +2089,6 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_802_2); } - static inline void qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) @@ -2193,7 +2154,6 @@ qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, #endif /* CONFIG_QETH_VLAN */ } - static inline void qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) @@ -2241,6 +2201,38 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, qeth_rebuild_skb_vlan(card, skb, hdr); } +static inline void +qeth_process_inbound_buffer(struct qeth_card *card, + struct qeth_qdio_buffer *buf, int index) +{ + struct qdio_buffer_element *element; + int offset; + struct sk_buff *skb; + struct qeth_hdr *hdr; + int rxrc; + + /* get first element of current buffer */ + element = (struct qdio_buffer_element *)&buf->buffer->element[0]; + offset = 0; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.bufs_rec++; +#endif + while((skb = qeth_get_next_skb(card, buf->buffer, &element, + &offset, &hdr))){ + qeth_rebuild_skb(card, skb, hdr); + +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.inbound_time += qeth_get_micros() - + card->perf_stats.inbound_start_time; + card->perf_stats.inbound_cnt++; +#endif + skb->dev = card->dev; + rxrc = netif_rx(skb); + card->dev->last_rx = jiffies; + card->stats.rx_packets++; + card->stats.rx_bytes += skb->len; + } +} static inline struct qeth_buffer_pool_entry * qeth_get_buffer_pool_entry(struct qeth_card *card) @@ -2284,7 +2276,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) buf->state = QETH_QDIO_BUF_EMPTY; } -static void +static inline void qeth_clear_output_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf) { @@ -2355,61 +2347,43 @@ qeth_put_buffer_pool_entry(struct qeth_card *card, } static void -qeth_qdio_input_tasklet(unsigned long data) +qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, + unsigned int qdio_err, unsigned int siga_err, + unsigned int queue, int first_element, int count, + unsigned long card_ptr) { - struct qeth_card *card = (struct qeth_card *) data; - int current_buf = card->qdio.in_q->next_buf_to_process; - struct qeth_qdio_buffer *buf; - struct qdio_buffer_element *element; - int offset; - struct sk_buff *skb; - struct qeth_hdr *hdr; - int rxrc; - - QETH_DBF_TEXT(trace,6,"qdintlet"); - buf = &card->qdio.in_q->bufs[current_buf]; - while((buf->state == QETH_QDIO_BUF_PRIMED) || - (buf->state == QETH_QDIO_BUF_ERROR)){ - if (buf->state == QETH_QDIO_BUF_ERROR) - goto clear_buffer; - if (netif_queue_stopped(card->dev)) - goto clear_buffer; - /* get first element of current buffer */ - element = (struct qdio_buffer_element *) - &buf->buffer->element[0]; - offset = 0; -#ifdef CONFIG_QETH_PERF_STATS - card->perf_stats.bufs_rec++; -#endif - while((skb = qeth_get_next_skb(card, buf->buffer, &element, - &offset, &hdr))){ + struct net_device *net_dev; + struct qeth_card *card; + struct qeth_qdio_buffer *buffer; + int index; + int i; - qeth_rebuild_skb(card, skb, hdr); + QETH_DBF_TEXT(trace, 6, "qdinput"); + card = (struct qeth_card *) card_ptr; + net_dev = card->dev; #ifdef CONFIG_QETH_PERF_STATS - card->perf_stats.inbound_time += qeth_get_micros() - - card->perf_stats.inbound_start_time; - card->perf_stats.inbound_cnt++; + card->perf_stats.inbound_start_time = qeth_get_micros(); #endif - skb->dev = card->dev; - if (netif_queue_stopped(card->dev)) { - dev_kfree_skb_irq(skb); - card->stats.rx_dropped++; - } else { - rxrc = netif_rx(skb); - card->dev->last_rx = jiffies; - card->stats.rx_packets++; - card->stats.rx_bytes += skb->len; - } + if (status & QDIO_STATUS_LOOK_FOR_ERROR) { + if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ + QETH_DBF_TEXT(trace, 1,"qdinchk"); + QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); + QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count); + QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status); + qeth_schedule_recovery(card); + return; } -clear_buffer: - qeth_put_buffer_pool_entry(card, buf->pool_entry); - /* give buffer back to hardware */ - qeth_queue_input_buffer(card, current_buf); - current_buf = (current_buf + 1) % QDIO_MAX_BUFFERS_PER_Q; - buf = &card->qdio.in_q->bufs[current_buf]; } - /* set index for next time the tasklet is scheduled */ - card->qdio.in_q->next_buf_to_process = current_buf; + for (i = first_element; i < (first_element + count); ++i) { + index = i % QDIO_MAX_BUFFERS_PER_Q; + buffer = &card->qdio.in_q->bufs[index]; + if (!((status == QDIO_STATUS_LOOK_FOR_ERROR) && + qeth_check_for_inbound_error(buffer, qdio_err, siga_err))) + qeth_process_inbound_buffer(card, buffer, index); + /* clear buffer and give back to hardware */ + qeth_put_buffer_pool_entry(card, buffer->pool_entry); + qeth_queue_input_buffer(card, index); + } } static inline int @@ -2524,10 +2498,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, * switches between PACKING and non-PACKING state if needed. * has to be called holding queue->lock */ -static inline void +static inline int qeth_switch_packing_state(struct qeth_qdio_out_q *queue) { struct qeth_qdio_out_buffer *buffer; + int flush_count = 0; QETH_DBF_TEXT(trace, 6, "swipack"); if (!queue->do_pack) { @@ -2554,6 +2529,7 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue) BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED); if (buffer->next_element_to_fill > 0) { buffer->state = QETH_QDIO_BUF_PRIMED; + flush_count++; atomic_inc(&queue->used_buffers); queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % @@ -2561,6 +2537,25 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue) } } } + return flush_count; +} + +static inline void +qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue, int under_int) +{ + struct qeth_qdio_out_buffer *buffer; + + buffer = &queue->bufs[queue->next_buf_to_fill]; + BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED); + if (buffer->next_element_to_fill > 0){ + /* it's a packing buffer */ + buffer->state = QETH_QDIO_BUF_PRIMED; + atomic_inc(&queue->used_buffers); + qeth_flush_buffers(queue, under_int, queue->next_buf_to_fill, + 1); + queue->next_buf_to_fill = + (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; + } } static void @@ -2603,58 +2598,12 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, atomic_dec(&queue->set_pci_flags_count); qeth_clear_output_buffer(card, buffer); + atomic_dec(&queue->used_buffers); } - atomic_sub(count, &queue->used_buffers); - - //if (!atomic_read(&queue->set_pci_flags_count)) - tasklet_schedule(&queue->tasklet); netif_wake_queue(card->dev); } -static void -qeth_qdio_output_tasklet(unsigned long data) -{ - struct qeth_qdio_out_q *queue = (struct qeth_qdio_out_q *) data; - struct qeth_qdio_out_buffer *buffer; - int index; - int count; - - QETH_DBF_TEXT(trace, 6, "outtlet"); - - /* flush all PRIMED buffers */ - index = queue->next_buf_to_flush; - count = 0; - while (queue->bufs[index].state == QETH_QDIO_BUF_PRIMED) { - count++; - index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; - } - qeth_flush_buffers(queue, 0, queue->next_buf_to_flush, count); - queue->next_buf_to_flush = index; - - /* flush a buffer with data, if no more PCIs are - * outstanding */ - if (!atomic_read(&queue->set_pci_flags_count)){ - spin_lock(&queue->lock); - buffer = &queue->bufs[index]; - if (buffer->state == QETH_QDIO_BUF_PRIMED){ - qeth_flush_buffers(queue, 0, index, 1); - index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; - queue->next_buf_to_flush = index; - } else if (buffer->next_element_to_fill > 0){ - /* it's a packing buffer */ - BUG_ON(index != queue->next_buf_to_fill); - buffer->state = QETH_QDIO_BUF_PRIMED; - atomic_inc(&queue->used_buffers); - qeth_flush_buffers(queue, 0, index, 1); - index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; - queue->next_buf_to_flush = index; - queue->next_buf_to_fill = index; - } - spin_unlock(&queue->lock); - } -} - static char* qeth_create_qib_param_field(struct qeth_card *card) { @@ -2858,8 +2807,6 @@ qeth_init_qdio_info(struct qeth_card *card) card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); - card->qdio.in_tasklet.data = (unsigned long) card; - card->qdio.in_tasklet.func = qeth_qdio_input_tasklet; /* outbound */ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; @@ -2903,13 +2850,9 @@ qeth_init_qdio_queues(struct qeth_card *card) } card->qdio.out_qs[i]->card = card; card->qdio.out_qs[i]->next_buf_to_fill = 0; - card->qdio.out_qs[i]->next_buf_to_flush = 0; card->qdio.out_qs[i]->do_pack = 0; atomic_set(&card->qdio.out_qs[i]->used_buffers,0); atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0); - card->qdio.out_qs[i]->tasklet.data = - (unsigned long) card->qdio.out_qs[i]; - card->qdio.out_qs[i]->tasklet.func = qeth_qdio_output_tasklet; spin_lock_init(&card->qdio.out_qs[i]->lock); } return 0; @@ -3653,6 +3596,8 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr; struct qeth_qdio_out_buffer *buffer; int elements_needed; + int start_index; + int flush_count = 0; int rc; QETH_DBF_TEXT(trace, 6, "dosndpkt"); @@ -3671,9 +3616,7 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, } spin_lock(&queue->lock); - /* check if we need to switch packing state of this queue */ - if (card->info.type != QETH_CARD_TYPE_IQD) - qeth_switch_packing_state(queue); + start_index = queue->next_buf_to_fill; buffer = &queue->bufs[queue->next_buf_to_fill]; BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED); if (queue->do_pack){ @@ -3682,6 +3625,7 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, < elements_needed){ /* ... no -> set state PRIMED */ buffer->state = QETH_QDIO_BUF_PRIMED; + flush_count++; atomic_inc(&queue->used_buffers); queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % @@ -3695,18 +3639,24 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, PRINT_WARN("qeth_do_send_packet: error during " "qeth_fill_buffer."); card->stats.tx_dropped++; - spin_unlock(&queue->lock); - return rc; - } - if (buffer->state == QETH_QDIO_BUF_PRIMED){ + } else if (buffer->state == QETH_QDIO_BUF_PRIMED){ /* next time fill the next buffer */ + flush_count++; atomic_inc(&queue->used_buffers); queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; } - spin_unlock(&queue->lock); + /* check if we need to switch packing state of this queue */ + if (card->info.type != QETH_CARD_TYPE_IQD) + flush_count += qeth_switch_packing_state(queue); + + if (flush_count) + qeth_flush_buffers(queue, 0, start_index, flush_count); - tasklet_schedule(&queue->tasklet); + if (!atomic_read(&queue->set_pci_flags_count)) + qeth_flush_buffers_on_no_pci(queue, 0); + + spin_unlock(&queue->lock); return rc; } @@ -4424,6 +4374,10 @@ qeth_delete_mc_addresses(struct qeth_card *card) if (!ipm->is_multicast) continue; iptodo = qeth_get_addr_buffer(ipm->proto); + if (!iptodo) { + QETH_DBF_TEXT(trace, 2, "dmcnomem"); + continue; + } memcpy(iptodo, ipm, sizeof(struct qeth_ipaddr)); iptodo->users = iptodo->users * -1; if (!__qeth_insert_ip_todo(card, iptodo, 0)) @@ -4694,14 +4648,14 @@ qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) if (addr->proto == QETH_PROT_IPV4) { QETH_DBF_TEXT(trace, 2,"setaddr4"); - QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, sizeof(int)); + QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int)); } else if (addr->proto == QETH_PROT_IPV6) { QETH_DBF_TEXT(trace, 2, "setaddr6"); - QETH_DBF_HEX(trace,4,&addr->u.a6.addr,4); - QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+4,4); + QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8); + QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8); } else { QETH_DBF_TEXT(trace, 2, "setaddr?"); - QETH_DBF_HEX(trace, 4, addr, sizeof(struct qeth_ipaddr)); + QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr)); } do { if (addr->is_multicast) @@ -4732,14 +4686,14 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) if (addr->proto == QETH_PROT_IPV4) { QETH_DBF_TEXT(trace, 2,"deladdr4"); - QETH_DBF_HEX(trace, 2, &addr->u.a4.addr, sizeof(int)); + QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int)); } else if (addr->proto == QETH_PROT_IPV6) { QETH_DBF_TEXT(trace, 2, "deladdr6"); - QETH_DBF_HEX(trace, 2, &addr->u.a6.addr, - sizeof(struct in6_addr)); + QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8); + QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8); } else { QETH_DBF_TEXT(trace, 2, "deladdr?"); - QETH_DBF_HEX(trace, 2, addr, sizeof(struct qeth_ipaddr)); + QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr)); } if (addr->is_multicast) rc = qeth_send_setdelmc(card, addr, IPA_CMD_DELIPM); @@ -6515,26 +6469,24 @@ qeth_ip_event(struct notifier_block *this, addr->u.a4.addr = ifa->ifa_address; addr->u.a4.mask = ifa->ifa_mask; addr->type = QETH_IP_TYPE_NORMAL; - } + } else + goto out; + switch(event) { case NETDEV_UP: - if (addr) { - if (!qeth_add_ip(card, addr)) - kfree(addr); - } + if (!qeth_add_ip(card, addr)) + kfree(addr); break; case NETDEV_DOWN: - if (addr) { - if (!qeth_delete_ip(card, addr)) - kfree(addr); - } + if (!qeth_delete_ip(card, addr)) + kfree(addr); break; default: break; } qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD); schedule_work(&card->kernel_thread_starter); - +out: return NOTIFY_DONE; } @@ -6570,26 +6522,24 @@ qeth_ip6_event(struct notifier_block *this, memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr)); addr->u.a6.pfxlen = ifa->prefix_len; addr->type = QETH_IP_TYPE_NORMAL; - } + } else + goto out; + switch(event) { case NETDEV_UP: - if (addr){ - if (!qeth_add_ip(card, addr)) - kfree(addr); - } + if (!qeth_add_ip(card, addr)) + kfree(addr); break; case NETDEV_DOWN: - if (addr){ - if (!qeth_delete_ip(card, addr)) - kfree(addr); - } + if (!qeth_delete_ip(card, addr)) + kfree(addr); break; default: break; } qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD); schedule_work(&card->kernel_thread_starter); - +out: return NOTIFY_DONE; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 31eb79a84c58..a6f1156440bf 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_AUX_REVISION "$Revision: 1.105 $" +#define ZFCP_AUX_REVISION "$Revision: 1.107 $" #include "zfcp_ext.h" @@ -1078,17 +1078,6 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter) { char dbf_name[20]; - /* debug feature area which records fsf request sequence numbers */ - sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s", - zfcp_get_busid_by_adapter(adapter)); - adapter->req_dbf = debug_register(dbf_name, - ZFCP_REQ_DBF_INDEX, - ZFCP_REQ_DBF_AREAS, - ZFCP_REQ_DBF_LENGTH); - debug_register_view(adapter->req_dbf, &debug_hex_ascii_view); - debug_set_level(adapter->req_dbf, ZFCP_REQ_DBF_LEVEL); - debug_text_event(adapter->req_dbf, 1, "zzz"); - /* debug feature area which records SCSI command failures (hostbyte) */ rwlock_init(&adapter->cmd_dbf_lock); sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s", @@ -1131,7 +1120,7 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter) debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL); - if (adapter->req_dbf && adapter->cmd_dbf && adapter->abort_dbf && + if (adapter->cmd_dbf && adapter->abort_dbf && adapter->in_els_dbf && adapter->erp_dbf) return 0; @@ -1147,7 +1136,6 @@ void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) { debug_unregister(adapter->erp_dbf); - debug_unregister(adapter->req_dbf); debug_unregister(adapter->cmd_dbf); debug_unregister(adapter->abort_dbf); debug_unregister(adapter->in_els_dbf); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 00de5d6f0733..e4bc663cea4a 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -33,7 +33,7 @@ #define ZFCP_DEF_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.71 $" +#define ZFCP_DEF_REVISION "$Revision: 1.72 $" /*************************** INCLUDES *****************************************/ @@ -450,19 +450,12 @@ struct zfcp_ls_rnid_acc { #define ZFCP_ERP_DBF_LEVEL 3 #define ZFCP_ERP_DBF_NAME "zfcperp" -#define ZFCP_REQ_DBF_INDEX 1 -#define ZFCP_REQ_DBF_AREAS 1 -#define ZFCP_REQ_DBF_LENGTH 8 -#define ZFCP_REQ_DBF_LEVEL 1 -#define ZFCP_REQ_DBF_NAME "zfcpreq" - #define ZFCP_CMD_DBF_INDEX 2 #define ZFCP_CMD_DBF_AREAS 1 #define ZFCP_CMD_DBF_LENGTH 8 #define ZFCP_CMD_DBF_LEVEL 3 #define ZFCP_CMD_DBF_NAME "zfcpcmd" - #define ZFCP_ABORT_DBF_INDEX 2 #define ZFCP_ABORT_DBF_AREAS 1 #define ZFCP_ABORT_DBF_LENGTH 8 @@ -475,11 +468,6 @@ struct zfcp_ls_rnid_acc { #define ZFCP_IN_ELS_DBF_LEVEL 6 #define ZFCP_IN_ELS_DBF_NAME "zfcpels" -#define ZFCP_ADAPTER_REQ_DBF_INDEX 4 -#define ZFCP_ADAPTER_REQ_DBF_AREAS 1 -#define ZFCP_ADAPTER_REQ_DBF_LENGTH 8 -#define ZFCP_ADAPTER_REQ_DBF_LEVEL 6 - /******************** LOGGING MACROS AND DEFINES *****************************/ /* @@ -986,7 +974,6 @@ struct zfcp_adapter { struct zfcp_port *nameserver_port; /* adapter's nameserver */ debug_info_t *erp_dbf; /* S/390 debug features */ debug_info_t *abort_dbf; - debug_info_t *req_dbf; debug_info_t *in_els_dbf; debug_info_t *cmd_dbf; rwlock_t cmd_dbf_lock; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index ccac73ed538f..045d04ba8497 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -31,7 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.49 $" +#define ZFCP_ERP_REVISION "$Revision: 1.51 $" #include "zfcp_ext.h" @@ -1865,6 +1865,7 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) case ZFCP_ERP_FAILED : atomic_inc(&port->erp_counter); if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) + zfcp_erp_port_failed(port); break; case ZFCP_ERP_EXIT : /* nothing */ @@ -1874,7 +1875,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ result = ZFCP_ERP_EXIT; - zfcp_erp_port_failed(port); } return result; @@ -2397,8 +2397,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) ZFCP_LOG_NORMAL("bug: shutdown of QDIO queues failed " "(retval=%d)\n", retval_cleanup); } - else - debug_text_event(adapter->req_dbf, 1, "q_clean"); failed_qdio_establish: atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); @@ -2468,10 +2466,8 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) ZFCP_LOG_NORMAL("bug: shutdown of QDIO queues failed on " "adapter %s\n", zfcp_get_busid_by_adapter(adapter)); - } else { + } else ZFCP_LOG_DEBUG("queues cleaned up\n"); - debug_text_event(adapter->req_dbf, 1, "q_clean"); - } /* * First we had to stop QDIO operation. @@ -2834,9 +2830,10 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) /* nameserver port may live again */ atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &adapter->nameserver_port->status); - zfcp_erp_port_reopen(adapter->nameserver_port, 0); - erp_action->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; - retval = ZFCP_ERP_CONTINUES; + if (zfcp_erp_port_reopen(adapter->nameserver_port, 0) >= 0) { + erp_action->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; + retval = ZFCP_ERP_CONTINUES; + } else retval = ZFCP_ERP_FAILED; break; } /* else nameserver port is already open, fall through */ @@ -2972,6 +2969,10 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w"); debug_event(adapter->erp_dbf, 3, &erp_action->port->wwpn, sizeof (wwn_t)); + if (atomic_test_mask( + ZFCP_STATUS_COMMON_ERP_FAILED, + &adapter->nameserver_port->status)) + zfcp_erp_port_failed(erp_action->port); zfcp_erp_action_ready(erp_action); } } @@ -3357,7 +3358,7 @@ zfcp_erp_action_enqueue(int action, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit) { - int retval = -1; + int retval = 1; struct zfcp_erp_action *erp_action = NULL; int stronger_action = 0; u32 status = 0; @@ -3376,7 +3377,7 @@ zfcp_erp_action_enqueue(int action, if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status)) - goto out; + return -EIO; debug_event(adapter->erp_dbf, 4, &action, sizeof (int)); /* check whether we really need this */ diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c4faf9ec2b89..79bb0bab483f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.43 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.45 $" #include "zfcp_ext.h" @@ -379,13 +379,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) zfcp_get_busid_by_adapter(adapter), fsf_req->qtcb->prefix.prot_status_qual. sequence_error.exp_req_seq_no); - debug_text_event(adapter->req_dbf, 1, "exp_seq!"); - debug_event(adapter->req_dbf, 1, - &fsf_req->qtcb->prefix.prot_status_qual. - sequence_error.exp_req_seq_no, 4); - debug_text_event(adapter->req_dbf, 1, "qtcb_seq!"); - debug_exception(adapter->req_dbf, 1, - &fsf_req->qtcb->prefix.req_seq_no, 4); debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err"); /* restart operation on this adapter */ zfcp_erp_adapter_reopen(adapter, 0); @@ -891,7 +884,6 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) ZFCP_LOG_TRACE("Status Read request initiated (adapter%s)\n", zfcp_get_busid_by_adapter(adapter)); - debug_text_event(adapter->req_dbf, 1, "unso"); goto out; failed_req_send: @@ -1277,10 +1269,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) case FSF_FCP_COMMAND_DOES_NOT_EXIST: ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n"); retval = 0; - debug_text_event(new_fsf_req->adapter->req_dbf, 3, "no_exist"); - debug_event(new_fsf_req->adapter->req_dbf, 3, - &new_fsf_req->qtcb->bottom.support.req_handle, - sizeof (unsigned long)); debug_text_event(new_fsf_req->adapter->erp_dbf, 3, "fsf_s_no_exist"); new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; @@ -3373,10 +3361,6 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, * (need this for look up on normal command completion) */ fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd; - debug_text_event(adapter->req_dbf, 3, "fsf/sc"); - debug_event(adapter->req_dbf, 3, &fsf_req, sizeof (unsigned long)); - debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long)); - fsf_req->data.send_fcp_command_task.start_jiffies = jiffies; fsf_req->data.send_fcp_command_task.unit = unit; ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun); @@ -3517,12 +3501,9 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, send_failed: no_fit: failed_scsi_cmnd: - /* dequeue new FSF request previously enqueued */ - debug_text_event(adapter->req_dbf, 3, "fail_sc"); - debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long)); - zfcp_fsf_req_free(fsf_req); fsf_req = NULL; + scsi_cmnd->host_scribble = NULL; success: failed_req_create: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); @@ -4267,14 +4248,9 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) * the new eh */ /* always call back */ - debug_text_event(fsf_req->adapter->req_dbf, 2, "ok_done:"); - debug_event(fsf_req->adapter->req_dbf, 2, &scpnt, - sizeof (unsigned long)); - debug_event(fsf_req->adapter->req_dbf, 2, &scpnt->scsi_done, - sizeof (unsigned long)); - debug_event(fsf_req->adapter->req_dbf, 2, &fsf_req, - sizeof (unsigned long)); + (scpnt->scsi_done) (scpnt); + /* * We must hold this lock until scsi_done has been called. * Otherwise we may call scsi_done after abort regarding this @@ -4954,15 +4930,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) "to request queue.\n"); } else { req_queue->distance_from_int = new_distance_from_int; - debug_text_event(adapter->req_dbf, 1, "o:a/seq"); - debug_event(adapter->req_dbf, 1, &fsf_req, - sizeof (unsigned long)); - if (likely(inc_seq_no)) { - debug_event(adapter->req_dbf, 1, - &adapter->fsf_req_seq_no, sizeof (u32)); - } else { - debug_text_event(adapter->req_dbf, 1, "nocb"); - } /* * increase FSF sequence counter - * this must only be done for request successfully enqueued to diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 1e72bd18796b..ca238c054d5d 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -28,7 +28,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_QDIO_C_REVISION "$Revision: 1.16 $" +#define ZFCP_QDIO_C_REVISION "$Revision: 1.18 $" #include "zfcp_ext.h" @@ -485,10 +485,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) struct zfcp_fsf_req *fsf_req; int retval = 0; - /* Note: seq is entered later */ - debug_text_event(adapter->req_dbf, 1, "i:a/seq"); - debug_event(adapter->req_dbf, 1, &sbale_addr, sizeof (unsigned long)); - /* invalid (per convention used in this driver) */ if (unlikely(!sbale_addr)) { ZFCP_LOG_NORMAL("bug: invalid reqid\n"); @@ -506,11 +502,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) retval = -EINVAL; goto out; } - /* debug feature stuff (test for QTCB: remember new unsol. status!) */ - if (likely(fsf_req->qtcb)) { - debug_event(adapter->req_dbf, 1, - &fsf_req->qtcb->prefix.req_seq_no, sizeof (u32)); - } ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb); if (likely(fsf_req->qtcb)) { diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 071007e0f181..ed9ebd166acc 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -31,7 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.59 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.60 $" #include <linux/blkdev.h> @@ -297,10 +297,6 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, if (unlikely(tmp < 0)) { ZFCP_LOG_DEBUG("error: initiation of Send FCP Cmnd failed\n"); retval = SCSI_MLQUEUE_HOST_BUSY; - } else { - debug_text_event(adapter->req_dbf, 3, "q_scpnt"); - debug_event(adapter->req_dbf, 3, &scpnt, - sizeof (unsigned long)); } out: diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index daee75c13a46..482693db18a0 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -207,7 +207,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) /** * fb_set_cmap - set the colormap * @cmap: frame buffer colormap structure - * @kspc: boolean, 0 copy local, 1 get_user() function + * @kspc: boolean, 1 copy local, 0 get_user() function * @info: frame buffer info structure * * Sets the colormap @cmap for a screen of device @info. diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index bd6eb4940d3c..9875025aa650 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -44,7 +44,7 @@ config BINFMT_SHARED_FLAT config BINFMT_AOUT tristate "Kernel support for a.out and ECOFF binaries" - depends on (X86 && !X86_64) || ALPHA || ARM || M68K || MIPS || SPARC32 + depends on (X86 && !X86_64) || ALPHA || ARM || M68K || SPARC32 ---help--- A.out (Assembler.OUTput) is a set of formats for libraries and executables used in the earliest versions of UNIX. Linux used diff --git a/fs/compat.c b/fs/compat.c index 40023e684520..b628d2e315f1 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -235,7 +235,7 @@ out: return error; } -/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64 */ +/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */ #define IOCTL_HASHSIZE 256 struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index e7c7fd2265cd..0439ec64301c 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -121,6 +121,8 @@ struct thread_struct { #endif /* CONFIG_ALTIVEC */ }; +#define ARCH_MIN_TASKALIGN 16 + #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #define INIT_THREAD { \ diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index ea8bf67f7007..d3e83108c064 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -553,6 +553,8 @@ struct thread_struct { #endif /* CONFIG_ALTIVEC */ }; +#define ARCH_MIN_TASKALIGN 16 + #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #define INIT_THREAD { \ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0b12bd800fd1..2d439a8390c0 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -24,8 +24,6 @@ enum { PROC_ROOT_INO = 1, }; -/* Finally, the dynamically allocatable proc entries are reserved: */ - #define PROC_SUPER_MAGIC 0x9fa0 /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 428b48964fc8..e414003e872b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -151,7 +151,6 @@ extern void init_idle(task_t *idle, int cpu); extern void show_state(void); extern void show_regs(struct pt_regs *); -extern void show_trace_task(task_t *tsk); /* * TASK is a pointer to the task whose backtrace we want to see (or NULL for current diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h index a444c9edb9e9..3a2206f61de0 100644 --- a/include/linux/sunrpc/svcauth_gss.h +++ b/include/linux/sunrpc/svcauth_gss.h @@ -20,6 +20,7 @@ #include <linux/sunrpc/auth_gss.h> int gss_svc_init(void); +void gss_svc_shutdown(void); int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name); #endif /* __KERNEL__ */ diff --git a/init/Kconfig b/init/Kconfig index 55261afdc3bf..337feb1026ea 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -149,7 +149,7 @@ config AUDIT config AUDITSYSCALL bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC64) + depends on AUDIT && (X86 || PPC64 || ARCH_S390) default y if SECURITY_SELINUX default n help diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index b1b922f09257..971124109c8c 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -984,6 +984,7 @@ out: static void __exit exit_rpcsec_gss(void) { + gss_svc_shutdown(); gss_mech_unregister_all(); rpcauth_unregister(&authgss_ops); } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index a60a541e9f5e..dae18e9792a6 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1063,3 +1063,10 @@ gss_svc_init(void) svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); return 0; } + +void +gss_svc_shutdown(void) +{ + cache_unregister(&rsc_cache); + cache_unregister(&rsi_cache); +} |
