From e018ba1fceee5bd306e31f6e3a60934d5f143ac5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 1 Feb 2006 03:06:31 -0800 Subject: [PATCH] s390: Remove CVS generated information - Remove all CVS generated information like e.g. revision IDs from drivers/s390 and include/asm-s390 (none present in arch/s390). - Add newline at end of arch/s390/lib/Makefile to avoid diff message. Acked-by: Andreas Herrmann Acked-by: Frank Pavlic Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 1 - drivers/s390/block/dasd_3370_erp.c | 1 - drivers/s390/block/dasd_3990_erp.c | 1 - drivers/s390/block/dasd_9336_erp.c | 1 - drivers/s390/block/dasd_9343_erp.c | 1 - drivers/s390/block/dasd_cmb.c | 2 -- drivers/s390/block/dasd_devmap.c | 1 - drivers/s390/block/dasd_diag.c | 1 - drivers/s390/block/dasd_diag.h | 1 - drivers/s390/block/dasd_eckd.c | 1 - drivers/s390/block/dasd_eckd.h | 1 - drivers/s390/block/dasd_erp.c | 1 - drivers/s390/block/dasd_fba.c | 1 - drivers/s390/block/dasd_fba.h | 1 - drivers/s390/block/dasd_genhd.c | 1 - drivers/s390/block/dasd_int.h | 1 - drivers/s390/block/dasd_ioctl.c | 2 -- drivers/s390/block/dasd_proc.c | 1 - drivers/s390/char/tape_34xx.c | 5 ++--- drivers/s390/char/tape_class.c | 4 ++-- drivers/s390/char/tape_class.h | 2 +- drivers/s390/char/tape_core.c | 5 ++--- drivers/s390/cio/airq.c | 2 -- drivers/s390/cio/blacklist.c | 1 - drivers/s390/cio/ccwgroup.c | 1 - drivers/s390/cio/chsc.c | 1 - drivers/s390/cio/cio.c | 1 - drivers/s390/cio/cmf.c | 2 +- drivers/s390/cio/css.c | 1 - drivers/s390/cio/device.c | 1 - drivers/s390/cio/device_ops.c | 2 -- drivers/s390/cio/qdio.c | 5 +---- drivers/s390/cio/qdio.h | 2 -- drivers/s390/crypto/z90common.h | 2 -- drivers/s390/crypto/z90crypt.h | 2 -- drivers/s390/crypto/z90hardware.c | 6 ------ drivers/s390/crypto/z90main.c | 10 ---------- drivers/s390/net/claw.c | 11 +---------- drivers/s390/net/claw.h | 2 +- drivers/s390/net/ctcdbug.c | 5 +---- drivers/s390/net/ctcdbug.h | 4 +--- drivers/s390/net/ctcmain.c | 19 ++----------------- drivers/s390/net/ctcmain.h | 4 ---- drivers/s390/net/ctctty.c | 2 -- drivers/s390/net/ctctty.h | 2 -- drivers/s390/net/cu3088.c | 2 -- drivers/s390/net/fsm.c | 2 -- drivers/s390/net/fsm.h | 2 -- drivers/s390/net/iucv.c | 16 +--------------- drivers/s390/net/lcs.c | 5 +---- drivers/s390/net/lcs.h | 2 -- drivers/s390/net/netiucv.c | 15 +-------------- drivers/s390/net/qeth.h | 2 -- drivers/s390/net/qeth_eddp.c | 5 +---- drivers/s390/net/qeth_eddp.h | 6 ++---- drivers/s390/net/qeth_fs.h | 5 ----- drivers/s390/net/qeth_main.c | 13 ++----------- drivers/s390/net/qeth_mpc.c | 2 -- drivers/s390/net/qeth_mpc.h | 4 ---- drivers/s390/net/qeth_proc.c | 4 +--- drivers/s390/net/qeth_sys.c | 4 +--- drivers/s390/net/qeth_tso.h | 4 +--- drivers/s390/s390_rdev.c | 1 - drivers/s390/scsi/zfcp_aux.c | 2 -- drivers/s390/scsi/zfcp_ccw.c | 2 -- drivers/s390/scsi/zfcp_dbf.c | 2 -- drivers/s390/scsi/zfcp_def.h | 2 -- drivers/s390/scsi/zfcp_erp.c | 2 -- drivers/s390/scsi/zfcp_ext.h | 2 -- drivers/s390/scsi/zfcp_fsf.c | 2 -- drivers/s390/scsi/zfcp_qdio.c | 2 -- drivers/s390/scsi/zfcp_scsi.c | 2 -- drivers/s390/scsi/zfcp_sysfs_adapter.c | 2 -- drivers/s390/scsi/zfcp_sysfs_driver.c | 2 -- drivers/s390/scsi/zfcp_sysfs_port.c | 2 -- drivers/s390/scsi/zfcp_sysfs_unit.c | 2 -- 76 files changed, 26 insertions(+), 218 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index ef4c687e7c01..953097c23d62 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.172 $ */ #include diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c index 84565c8f584e..1d11c2a9525d 100644 --- a/drivers/s390/block/dasd_3370_erp.c +++ b/drivers/s390/block/dasd_3370_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.9 $ */ #define PRINTK_HEADER "dasd_erp(3370)" diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c143ecb53d9d..4ee0f934e325 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -5,7 +5,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.36 $ */ #include diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c index 01e87170a3a2..dc861446d056 100644 --- a/drivers/s390/block/dasd_9336_erp.c +++ b/drivers/s390/block/dasd_9336_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.8 $ */ #define PRINTK_HEADER "dasd_erp(9336)" diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c index 2a23b74faf3f..4a5b79569aaa 100644 --- a/drivers/s390/block/dasd_9343_erp.c +++ b/drivers/s390/block/dasd_9343_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.13 $ */ #define PRINTK_HEADER "dasd_erp(9343)" diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c index 4f365bff275c..e88f73ee72ce 100644 --- a/drivers/s390/block/dasd_cmb.c +++ b/drivers/s390/block/dasd_cmb.c @@ -1,6 +1,4 @@ /* - * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $) - * * Linux on zSeries Channel Measurement Facility support * (dasd device driver interface) * diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index caee16a3dc62..1629b27c48ab 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -11,7 +11,6 @@ * functions may not be called from interrupt context. In particular * dasd_get_device is a no-no from interrupt context. * - * $Revision: 1.43 $ */ #include diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index ba80fdea7ebf..3f9d704d2657 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,7 +6,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.53 $ */ #include diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index a4f80bd735f1..38a4e55f8953 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -6,7 +6,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.9 $ */ #define MDSK_WRITE_REQ 0x01 diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 96eb48258580..822e2a265578 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -7,7 +7,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.74 $ */ #include diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index b6888c68b224..bc3823d35223 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -5,7 +5,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.10 $ */ #ifndef DASD_ECKD_H diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 7cb98d25f341..8fd71ab02ef0 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -7,7 +7,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.14 $ */ #include diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 8ec75dc08e2c..91145698f8e9 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -4,7 +4,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.41 $ */ #include diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h index 624f0402ee22..da1fa91fc01d 100644 --- a/drivers/s390/block/dasd_fba.h +++ b/drivers/s390/block/dasd_fba.h @@ -4,7 +4,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.6 $ */ #ifndef DASD_FBA_H diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index a601c9a33541..65dc844b975c 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -9,7 +9,6 @@ * * gendisk related functions for the dasd driver. * - * $Revision: 1.51 $ */ #include diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index e4b401500b01..c20af9874500 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.68 $ */ #ifndef DASD_INT_H diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 9396fcacb8f8..74ed5f4dd5e0 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -7,8 +7,6 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.50 $ - * * i/o controls for the dasd driver. */ #include diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index fff9020d4886..2d5da3c75ca7 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -9,7 +9,6 @@ * * /proc interface for the dasd driver. * - * $Revision: 1.33 $ */ #include diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 20be88e91fa1..682039cac15b 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1357,7 +1357,7 @@ tape_34xx_init (void) debug_set_level(TAPE_DBF_AREA, 6); #endif - DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n"); + DBF_EVENT(3, "34xx init\n"); /* Register driver for 3480/3490 tapes. */ rc = ccw_driver_register(&tape_34xx_driver); if (rc) @@ -1377,8 +1377,7 @@ tape_34xx_exit(void) MODULE_DEVICE_TABLE(ccw, tape_34xx_ids); MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH"); -MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape " - "device driver ($Revision: 1.23 $)"); +MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape device driver"); MODULE_LICENSE("GPL"); module_init(tape_34xx_init); diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index fcaee447d6fe..b3569c82bb16 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c @@ -1,6 +1,6 @@ /* * (C) Copyright IBM Corp. 2004 - * tape_class.c ($Revision: 1.8 $) + * tape_class.c * * Tape class device support * @@ -12,7 +12,7 @@ MODULE_AUTHOR("Stefan Bader "); MODULE_DESCRIPTION( "(C) Copyright IBM Corp. 2004 All Rights Reserved.\n" - "tape_class.c ($Revision: 1.8 $)" + "tape_class.c" ); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h index 33133ad00ba2..3d0ca054cdee 100644 --- a/drivers/s390/char/tape_class.h +++ b/drivers/s390/char/tape_class.h @@ -1,6 +1,6 @@ /* * (C) Copyright IBM Corp. 2004 All Rights Reserved. - * tape_class.h ($Revision: 1.4 $) + * tape_class.h * * Tape class device support * diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 8f486e1a8507..4ea438c749c9 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -1239,7 +1239,7 @@ tape_init (void) #ifdef DBF_LIKE_HELL debug_set_level(TAPE_DBF_AREA, 6); #endif - DBF_EVENT(3, "tape init: ($Revision: 1.54 $)\n"); + DBF_EVENT(3, "tape init\n"); tape_proc_init(); tapechar_init (); tapeblock_init (); @@ -1263,8 +1263,7 @@ tape_exit(void) MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); -MODULE_DESCRIPTION("Linux on zSeries channel attached " - "tape device driver ($Revision: 1.54 $)"); +MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver"); MODULE_LICENSE("GPL"); module_init(tape_init); diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index cd2cc28e16a7..5287631fbfc8 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -2,8 +2,6 @@ * drivers/s390/cio/airq.c * S/390 common I/O routines -- support for adapter interruptions * - * $Revision: 1.15 $ - * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 72f27c151c09..cb8e2e672b68 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.42 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 6c077ad71edc..8013c8eb76fe 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.35 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 2cbb724791a8..92be75d99a56 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.128 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 6223b06d27d5..cbb86fa5f293 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.140 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 0b03714e696a..07ef3f640f4a 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $) + * linux/drivers/s390/cio/cmf.c * * Linux on zSeries Channel Measurement Facility support * diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 516108779f60..1bbf231f8aaf 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.96 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a67e7e60e330..ceebf08e095b 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.140 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 8b0218949b62..3a50b1903287 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,8 +1,6 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.61 $ - * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 77be2c39bfe4..45ce032772f4 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,8 +56,6 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.117 $" - /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); MODULE_DESCRIPTION("QDIO base support version 2, " \ @@ -66,8 +64,7 @@ MODULE_LICENSE("GPL"); /******************** HERE WE GO ***********************************/ -static const char version[] = "QDIO base support version 2 (" - VERSION_QDIO_C "/" VERSION_QDIO_H "/" VERSION_CIO_QDIO_H ")"; +static const char version[] = "QDIO base support version 2"; #ifdef QDIO_PERFORMANCE_STATS static int proc_perf_file_registration; diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index fa385e761fe1..ceb3ab31ee08 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -5,8 +5,6 @@ #include "schid.h" -#define VERSION_CIO_QDIO_H "$Revision: 1.40 $" - #ifdef CONFIG_QDIO_DEBUG #define QDIO_VERBOSE_LEVEL 9 #else /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h index f87c785f2039..dbbcda3c846a 100644 --- a/drivers/s390/crypto/z90common.h +++ b/drivers/s390/crypto/z90common.h @@ -27,8 +27,6 @@ #ifndef _Z90COMMON_H_ #define _Z90COMMON_H_ -#define VERSION_Z90COMMON_H "$Revision: 1.17 $" - #define RESPBUFFSIZE 256 #define PCI_FUNC_KEY_DECRYPT 0x5044 diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index 3a18443fdfa7..5e6b1f535f62 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -29,8 +29,6 @@ #include -#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $" - #define z90crypt_VERSION 1 #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards #define z90crypt_VARIANT 3 // 3 = CEX2A support diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c index d7f7494a0cbe..4141919da805 100644 --- a/drivers/s390/crypto/z90hardware.c +++ b/drivers/s390/crypto/z90hardware.c @@ -32,12 +32,6 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $" - -char z90hardware_version[] __initdata = - "z90hardware.o (" VERSION_Z90HARDWARE_C "/" - VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; - struct cca_token_hdr { unsigned char token_identifier; unsigned char version; diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 2f54d033d7cf..7d6f19030ef9 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -38,14 +38,6 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90MAIN_C "$Revision: 1.62 $" - -static char z90main_version[] __initdata = - "z90main.o (" VERSION_Z90MAIN_C "/" - VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; - -extern char z90hardware_version[]; - /** * Defaults that may be modified. */ @@ -594,8 +586,6 @@ z90crypt_init_module(void) PRINTKN("Version %d.%d.%d loaded, built on %s %s\n", z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT, __DATE__, __TIME__); - PRINTKN("%s\n", z90main_version); - PRINTKN("%s\n", z90hardware_version); PDEBUG("create_z90crypt (domain index %d) successful.\n", domain); } else diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index e70af7f39946..a86436a7a606 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2,8 +2,6 @@ * drivers/s390/net/claw.c * ESCON CLAW network driver * - * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ - * * Linux for zSeries version * Copyright (C) 2002,2005 IBM Corporation * Author(s) Original code written by: @@ -4391,14 +4389,7 @@ static int __init claw_init(void) { int ret = 0; - printk(KERN_INFO "claw: starting driver " -#ifdef MODULE - "module " -#else - "compiled into kernel " -#endif - " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n"); - + printk(KERN_INFO "claw: starting driver\n"); #ifdef FUNCTRACE printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__); diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 3df71970f601..969be465309c 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -2,7 +2,7 @@ * Define constants * * * ********************************************************/ -#define VERSION_CLAW_H "$Revision: 1.6 $" + /*-----------------------------------------------------* * CCW command codes for CLAW protocol * *------------------------------------------------------*/ diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c index 0e2a8bb93032..e6e72deb36b5 100644 --- a/drivers/s390/net/ctcdbug.c +++ b/drivers/s390/net/ctcdbug.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $) + * linux/drivers/s390/net/ctcdbug.c * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,8 +9,6 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) @@ -80,4 +78,3 @@ ctc_register_dbf_views(void) return 0; } - diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h index 7d6afa1627c3..413925ee23d1 100644 --- a/drivers/s390/net/ctcdbug.h +++ b/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $) + * linux/drivers/s390/net/ctcdbug.h * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,8 +9,6 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 1901feef07d9..af9f212314b3 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,6 +1,4 @@ /* - * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $ - * * CTC / ESCON network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -37,8 +35,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $ - * */ #undef DEBUG #include @@ -248,22 +244,11 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.79 $"; - char *version = vbuf; if (printed) return; - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO "CTC driver Version%s" -#ifdef DEBUG - " (DEBUG-VERSION, " __DATE__ __TIME__ ")" -#endif - " initialized\n", version); + + printk(KERN_INFO "CTC driver initialized\n"); printed = 1; } diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h index ba3605f16335..d2e835c0c134 100644 --- a/drivers/s390/net/ctcmain.h +++ b/drivers/s390/net/ctcmain.h @@ -1,6 +1,4 @@ /* - * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $ - * * CTC / ESCON network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -29,8 +27,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $ - * */ #ifndef _CTCMAIN_H_ diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 93d1725eb79b..5cdcdbf92962 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -1,6 +1,4 @@ /* - * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $ - * * CTC / ESCON network driver, tty interface. * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h index 84b2f8f23ab3..7254dc006311 100644 --- a/drivers/s390/net/ctctty.h +++ b/drivers/s390/net/ctctty.h @@ -1,6 +1,4 @@ /* - * $Id: ctctty.h,v 1.4 2003/09/18 08:01:10 mschwide Exp $ - * * CTC / ESCON network driver, tty interface. * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 2014fb7a4881..b12533104c1f 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c @@ -1,6 +1,4 @@ /* - * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $ - * * CTC / LCS ccw_device driver * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 24029bd9c7d0..6caf5fa6a3b5 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c @@ -1,6 +1,4 @@ /** - * $Id: fsm.c,v 1.6 2003/10/15 11:37:29 mschwide Exp $ - * * A generic FSM based on fsm used in isdn4linux * */ diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index 5b98253be7aa..af679c10f1bd 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h @@ -1,5 +1,3 @@ -/* $Id: fsm.h,v 1.1.1.1 2002/03/13 19:33:09 mschwide Exp $ - */ #ifndef _FSM_H_ #define _FSM_H_ diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index ea8177392564..760e77ec5a11 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,6 +1,4 @@ /* - * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $ - * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -29,8 +27,6 @@ * 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.47 $ - * */ /* #define DEBUG */ @@ -355,17 +351,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.47 $"; - char *version = vbuf; - - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO - "IUCV lowlevel driver Version%s initialized\n", version); + printk(KERN_INFO "IUCV lowlevel driver initialized\n"); } /** diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index da8c515743e8..6229ba4995ad 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,8 +11,6 @@ * Frank Pavlic (fpavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) @@ -59,9 +57,8 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.99 $" -static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; +static char version[] __initdata = "LCS driver"; static char debug_buffer[255]; /** diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index a7f348ef1b08..08e60ad43916 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -6,8 +6,6 @@ #include #include -#define VERSION_LCS_H "$Revision: 1.19 $" - #define LCS_DBF_TEXT(level, name, text) \ do { \ debug_text_event(lcs_dbf_##name, level, text); \ diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index ac4c4b83fe17..71d3853e8682 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1,6 +1,4 @@ /* - * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $ - * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -31,8 +29,6 @@ * 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.69 $ - * */ #undef DEBUG @@ -2077,16 +2073,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write); static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.69 $"; - char *version = vbuf; - - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - PRINT_INFO("NETIUCV driver Version%s initialized\n", version); + PRINT_INFO("NETIUCV driver initialized\n"); } static void __exit diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index d238c7ed103b..9a064d4727ad 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -25,8 +25,6 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.152 $" - #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" #else diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index f94f1f25eec6..b02313127780 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -1,6 +1,5 @@ /* - * - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $) + * linux/drivers/s390/net/qeth_eddp.c * * Enhanced Device Driver Packing (EDDP) support for the qeth driver. * @@ -8,8 +7,6 @@ * * Author(s): Thomas Spatzier * - * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $ - * */ #include #include diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h index e1b51860bc57..cae9ba265056 100644 --- a/drivers/s390/net/qeth_eddp.h +++ b/drivers/s390/net/qeth_eddp.h @@ -1,14 +1,12 @@ /* - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.5 $) + * linux/drivers/s390/net/qeth_eddp.h * - * Header file for qeth enhanced device driver pakcing. + * Header file for qeth enhanced device driver packing. * * Copyright 2004 IBM Corporation * * Author(s): Thomas Spatzier * - * $Revision: 1.5 $ $Date: 2005/03/24 09:04:18 $ - * */ #ifndef __QETH_EDDP_H__ #define __QETH_EDDP_H__ diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h index c0b4c8d82c45..e422b41c656e 100644 --- a/drivers/s390/net/qeth_fs.h +++ b/drivers/s390/net/qeth_fs.h @@ -12,11 +12,6 @@ #ifndef __QETH_FS_H__ #define __QETH_FS_H__ -#define VERSION_QETH_FS_H "$Revision: 1.10 $" - -extern const char *VERSION_QETH_PROC_C; -extern const char *VERSION_QETH_SYS_C; - #ifdef CONFIG_PROC_FS extern int qeth_create_procfs_entries(void); diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 97f927c01a82..410abeada6c4 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,5 @@ /* - * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $) + * linux/drivers/s390/net/qeth_main.c * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,8 +11,6 @@ * Frank Pavlic (fpavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.251 $ $Date: 2005/05/04 20:19:18 $ - * * 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, or (at your option) @@ -73,7 +70,6 @@ #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.251 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -8626,12 +8622,7 @@ qeth_init(void) { int rc=0; - PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", - version, VERSION_QETH_C, VERSION_QETH_H, - VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, - VERSION_QETH_FS_H, VERSION_QETH_PROC_C, - VERSION_QETH_SYS_C, QETH_VERSION_IPV6, - QETH_VERSION_VLAN); + PRINT_INFO("loading %s\n", version); INIT_LIST_HEAD(&qeth_card_list.list); INIT_LIST_HEAD(&qeth_notify_list); diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c index 5f8754addc14..77c83209d70e 100644 --- a/drivers/s390/net/qeth_mpc.c +++ b/drivers/s390/net/qeth_mpc.c @@ -11,8 +11,6 @@ #include #include "qeth_mpc.h" -const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $"; - unsigned char IDX_ACTIVATE_READ[]={ 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, 0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00, diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 864cec5f6c62..011c41041029 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h @@ -14,10 +14,6 @@ #include -#define VERSION_QETH_MPC_H "$Revision: 1.46 $" - -extern const char *VERSION_QETH_MPC_C; - #define IPA_PDU_HEADER_SIZE 0x40 #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 7bf35098831e..3c6339df879d 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $) + * linux/drivers/s390/net/qeth_fs.c * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to procfs. @@ -21,8 +21,6 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $"; - /***** /proc/qeth *****/ #define QETH_PROCFILE_NAME "qeth" static struct proc_dir_entry *qeth_procfile; diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 0ea185f70f75..c1831f572585 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.60 $) + * linux/drivers/s390/net/qeth_sys.c * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,8 +20,6 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $"; - /*****************************************************************************/ /* */ /* /sys-fs stuff UNDER DEVELOPMENT !!! */ diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 3c50b6f24f51..1286ddea450b 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $) + * linux/drivers/s390/net/qeth_tso.h * * Header file for qeth TCP Segmentation Offload support. * @@ -7,8 +7,6 @@ * * Author(s): Frank Pavlic * - * $Revision: 1.8 $ $Date: 2005/05/04 20:19:18 $ - * */ #ifndef __QETH_TSO_H__ #define __QETH_TSO_H__ diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index 206518c7d332..e3f647169827 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c @@ -1,7 +1,6 @@ /* * drivers/s390/s390_rdev.c * s390 root device - * $Revision: 1.4 $ * * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 167fef39d8a7..95b92f317b6f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -29,8 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_AUX_REVISION "$Revision: 1.145 $" - #include "zfcp_ext.h" /* accumulated log level (module parameter) */ diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 0fc46381fc22..241136d0c6eb 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_CCW_C_REVISION "$Revision: 1.58 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 95599719f8ab..4d7d47cf2394 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -23,8 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_DBF_REVISION "$Revision$" - #include #include #include "zfcp_ext.h" diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9bb511083a26..e260d19fa717 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -34,8 +34,6 @@ #ifndef ZFCP_DEF_H #define ZFCP_DEF_H -#define ZFCP_DEF_REVISION "$Revision: 1.111 $" - /*************************** INCLUDES *****************************************/ #include diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c065cb836c97..da947e662031 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -31,8 +31,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP -#define ZFCP_ERP_REVISION "$Revision: 1.86 $" - #include "zfcp_ext.h" static int zfcp_erp_adisc(struct zfcp_port *); diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c3782261cb5c..c1ba7cf1b496 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -32,8 +32,6 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H -#define ZFCP_EXT_REVISION "$Revision: 1.62 $" - #include "zfcp_def.h" extern struct zfcp_data zfcp_data; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cbfab09899c8..9f0cb3d820c0 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -30,8 +30,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $" - #include "zfcp_ext.h" static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *); diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index d719f66a29a4..1c3275163c91 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -29,8 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_QDIO_C_REVISION "$Revision: 1.20 $" - #include "zfcp_ext.h" static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3c2cbcccbf54..e0803757c0fa 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -31,8 +31,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -#define ZFCP_SCSI_REVISION "$Revision: 1.74 $" - #include "zfcp_ext.h" static void zfcp_scsi_slave_destroy(struct scsi_device *sdp); diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index 9f262250043a..dfc07370f412 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.38 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c index 77a5e2dcc0ff..6622d55e0a45 100644 --- a/drivers/s390/scsi/zfcp_sysfs_driver.c +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.17 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index 3924eb38805c..f401d42db21c 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -28,8 +28,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 2f50815f65c7..ad5dfb889bee 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -28,8 +28,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -- cgit v1.2.2 From 3633b0475eb269dcb85923b23b321505f06b9488 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 1 Feb 2006 03:06:34 -0800 Subject: [PATCH] s390: hangcheck timer support Remove useless s390 define from hangcheck-timer, remove wrong definition of a TOD second and other s390 ifdefs. Use monotonic_clock instead. Add hangcheck-timer option, copied from drivers/char/Kconfig. This is ugly but unless we have a big Kconfig cleanup we cannot include drivers/char/Kconfig... Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/s390') diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index a86a650f3d6d..721787cc5a1c 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig @@ -51,6 +51,13 @@ config UNIX98_PTY_COUNT When not in use, each additional set of 256 PTYs occupy approximately 8 KB of kernel memory on 32-bit architectures. +config HANGCHECK_TIMER + tristate "Hangcheck timer" + help + The hangcheck-timer module detects when the system has gone + out to lunch past a certain margin. It can reboot the system + or merely print a warning. + source "drivers/char/watchdog/Kconfig" comment "S/390 character device drivers" -- cgit v1.2.2 From 600b5d163d7434332539cac7be00f649cbbfedcc Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 1 Feb 2006 03:06:35 -0800 Subject: [PATCH] s390: ccw_device_probe_console return value The return code of ccw_device_probe_console() is not properly handled. It should only return a valid ccw device pointer or a error value converted by ERR_PTR. Fix the console driver code to check with IS_ERR instead against NULL. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/con3215.c | 3 ++- drivers/s390/char/con3270.c | 3 ++- drivers/s390/cio/device.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 1f060914cfa4..606f6ad285a0 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -864,7 +865,7 @@ con3215_init(void) } cdev = ccw_device_probe_console(); - if (!cdev) + if (IS_ERR(cdev)) return -ENODEV; raw3215[0] = raw = (struct raw3215_info *) diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index c570a9f6ce9c..ef607a1de55a 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -597,7 +598,7 @@ con3270_init(void) } cdev = ccw_device_probe_console(); - if (!cdev) + if (IS_ERR(cdev)) return -ENODEV; rp = raw3270_setup_console(cdev); if (IS_ERR(rp)) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index ceebf08e095b..0b30921ce60d 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1012,7 +1012,7 @@ ccw_device_probe_console(void) int ret; if (xchg(&console_cdev_in_use, 1) != 0) - return NULL; + return ERR_PTR(-EBUSY); sch = cio_probe_console(); if (IS_ERR(sch)) { console_cdev_in_use = 0; -- cgit v1.2.2 From 57467195d1581e354998d5cc35dfd7a12d6e0a24 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Wed, 1 Feb 2006 03:06:36 -0800 Subject: [PATCH] s390: dasd open counter The open_count is increased for every opener, that includes the blkdev_get in dasd_scan_partitions. This tampers the open_count in BIODASDINFO. Hide the internal open from user-space. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_ioctl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 74ed5f4dd5e0..fafeeae52675 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -421,8 +421,15 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) dasd_info->cu_model = cdev->id.cu_model; dasd_info->dev_type = cdev->id.dev_type; dasd_info->dev_model = cdev->id.dev_model; - dasd_info->open_count = atomic_read(&device->open_count); dasd_info->status = device->state; + /* + * The open_count is increased for every opener, that includes + * the blkdev_get in dasd_scan_partitions. + * This must be hidden from user-space. + */ + dasd_info->open_count = atomic_read(&device->open_count); + if (!device->bdev) + dasd_info->open_count++; /* * check if device is really formatted -- cgit v1.2.2 From c2ba444d1d871d3f6cd3bc5e7d8e19c48c8c02a4 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Wed, 1 Feb 2006 03:06:37 -0800 Subject: [PATCH] s390: dasd wait for clear i/o interrupt The sleep_on function clears a running cqr without waiting for the related interrupt. This can lead to a panic at the time the interrupt is processed because the related memory might already be freed. Wait for clear-interrupt and de-queue cqr prior to return. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 953097c23d62..abdf1ee633e7 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -674,11 +674,8 @@ 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) { - cqr->retries--; - cqr->status = DASD_CQR_CLEAR; - } else - cqr->status = DASD_CQR_FAILED; + cqr->retries--; + cqr->status = DASD_CQR_CLEAR; cqr->stopclk = get_clock(); DBF_DEV_EVENT(DBF_DEBUG, device, "terminate cqr %p successful", @@ -1307,7 +1304,7 @@ dasd_tasklet(struct dasd_device * device) /* Now call the callback function of requests with final status */ list_for_each_safe(l, n, &final_queue) { cqr = list_entry(l, struct dasd_ccw_req, list); - list_del(&cqr->list); + list_del_init(&cqr->list); if (cqr->callback != NULL) (cqr->callback)(cqr, cqr->callback_data); } @@ -1392,7 +1389,9 @@ _wait_for_wakeup(struct dasd_ccw_req *cqr) device = cqr->device; spin_lock_irq(get_ccwdev_lock(device->cdev)); - rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED; + rc = ((cqr->status == DASD_CQR_DONE || + cqr->status == DASD_CQR_FAILED) && + list_empty(&cqr->list)); spin_unlock_irq(get_ccwdev_lock(device->cdev)); return rc; } @@ -1456,15 +1455,37 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr) while (!finished) { rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr)); if (rc != -ERESTARTSYS) { - /* Request status is either done or failed. */ - rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; + /* Request is final (done or failed) */ + rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; break; } spin_lock_irq(get_ccwdev_lock(device->cdev)); - if (cqr->status == DASD_CQR_IN_IO && - device->discipline->term_IO(cqr) == 0) { - list_del(&cqr->list); + switch (cqr->status) { + case DASD_CQR_IN_IO: + /* terminate runnig cqr */ + if (device->discipline->term_IO) { + cqr->retries = -1; + device->discipline->term_IO(cqr); + /*nished = + * wait (non-interruptible) for final status + * because signal ist still pending + */ + spin_unlock_irq(get_ccwdev_lock(device->cdev)); + wait_event(wait_q, _wait_for_wakeup(cqr)); + spin_lock_irq(get_ccwdev_lock(device->cdev)); + rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; + finished = 1; + } + break; + case DASD_CQR_QUEUED: + /* request */ + list_del_init(&cqr->list); + rc = -EIO; finished = 1; + break; + default: + /* cqr with 'non-interruptable' status - just wait */ + break; } spin_unlock_irq(get_ccwdev_lock(device->cdev)); } -- cgit v1.2.2 From b1969fa46d95efcdb0b84c540eca10db99665148 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 1 Feb 2006 03:06:39 -0800 Subject: [PATCH] s390: Fix modalias for ccw devices Fix modalias for ccw devices: cu_type should be in capitals as well. Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 0b30921ce60d..062fb100d94c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -254,7 +254,7 @@ modalias_show (struct device *dev, struct device_attribute *attr, char *buf) struct ccw_device_id *id = &(cdev->id); int ret; - ret = sprintf(buf, "ccw:t%04Xm%02x", + ret = sprintf(buf, "ccw:t%04Xm%02X", id->cu_type, id->cu_model); if (id->dev_type != 0) ret += sprintf(buf + ret, "dt%04Xdm%02X\n", -- cgit v1.2.2 From 46d0d2c811c8e9dd5cffdc3a5c03d988eb5a2996 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 1 Feb 2006 03:06:40 -0800 Subject: [PATCH] s390: Add missing memory constraint to stcrw() Add missing memory constraint to stcrw() inline assembly. Signed-off-by: Peter Oberparleiter Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/s390mach.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index d9ea7ed2e46e..7abb42a09ae2 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h @@ -90,15 +90,16 @@ struct crw { static inline int stcrw(struct crw *pcrw ) { - int ccode; + int ccode; - __asm__ __volatile__( - "STCRW 0(%1)\n\t" - "IPM %0\n\t" - "SRL %0,28\n\t" - : "=d" (ccode) : "a" (pcrw) - : "cc", "1" ); - return ccode; + __asm__ __volatile__( + "stcrw 0(%2)\n\t" + "ipm %0\n\t" + "srl %0,28\n\t" + : "=d" (ccode), "=m" (*pcrw) + : "a" (pcrw) + : "cc" ); + return ccode; } #endif /* __s390mach */ -- cgit v1.2.2 From 172411f10c25bbd81b19f67566af6a7f549f46a9 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 1 Feb 2006 03:06:40 -0800 Subject: [PATCH] ebcdic do_kdsk_ioctl off-by-one Add a missing return check from strnlen_user and fixes a off-by-one when terminating the string with zero. Signed-off-by: Davi Arnaut Cc: Heiko Carstens Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/keyboard.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 5bda2340a39d..a317a123daba 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -440,7 +440,11 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, return -EPERM; len = strnlen_user(u_kbs->kb_string, sizeof(u_kbs->kb_string) - 1); - p = kmalloc(len, GFP_KERNEL); + if (!len) + return -EFAULT; + if (len > sizeof(u_kbs->kb_string) - 1) + return -EINVAL; + p = kmalloc(len + 1, GFP_KERNEL); if (!p) return -ENOMEM; if (copy_from_user(p, u_kbs->kb_string, len)) { -- cgit v1.2.2 From 12c3a54848a6eba2b38cd92ba5925433d223332b Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Fri, 3 Feb 2006 03:03:49 -0800 Subject: [PATCH] s390: dasd extended error reporting module The DASD extended error reporting is a facility that allows to get detailed information about certain problems in the DASD I/O. This information can be used to implement fail-over applications that can recover these problems. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/Kconfig | 14 +- drivers/s390/block/Makefile | 2 + drivers/s390/block/dasd.c | 76 ++- drivers/s390/block/dasd_3990_erp.c | 3 + drivers/s390/block/dasd_eckd.h | 1 + drivers/s390/block/dasd_eer.c | 1090 ++++++++++++++++++++++++++++++++++++ drivers/s390/block/dasd_int.h | 37 ++ 7 files changed, 1219 insertions(+), 4 deletions(-) create mode 100644 drivers/s390/block/dasd_eer.c (limited to 'drivers/s390') diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 6f50cc9323d9..6912399d0937 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -55,13 +55,21 @@ config DASD_DIAG Disks under VM. If you are not running under VM or unsure what it is, say "N". +config DASD_EER + tristate "Extended error reporting (EER)" + depends on DASD + help + This driver provides a character device interface to the + DASD extended error reporting. This is only needed if you want to + use applications written for the EER facility. + config DASD_CMB tristate "Compatibility interface for DASD channel measurement blocks" depends on DASD help - This driver provides an additional interface to the channel measurement - facility, which is normally accessed though sysfs, with a set of - ioctl functions specific to the dasd driver. + This driver provides an additional interface to the channel + measurement facility, which is normally accessed though sysfs, with + a set of ioctl functions specific to the dasd driver. This is only needed if you want to use applications written for linux-2.4 dasd channel measurement facility interface. diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 58c6780134f7..0c0d871e8f51 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile @@ -5,6 +5,7 @@ dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o dasd_diag_mod-objs := dasd_diag.o +dasd_eer_mod-objs := dasd_eer.o dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ dasd_genhd.o dasd_erp.o @@ -13,5 +14,6 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o obj-$(CONFIG_DASD_CMB) += dasd_cmb.o +obj-$(CONFIG_DASD_EER) += dasd_eer.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o obj-$(CONFIG_DCSSBLK) += dcssblk.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index abdf1ee633e7..08c88fcd8963 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static void dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(void *data); +static void dasd_disable_eer(struct dasd_device *device); /* * SECTION: Operations on the device structure. @@ -151,6 +153,8 @@ dasd_state_new_to_known(struct dasd_device *device) static inline void dasd_state_known_to_new(struct dasd_device * device) { + /* disable extended error reporting for this device */ + dasd_disable_eer(device); /* Forget the discipline information. */ device->discipline = NULL; device->state = DASD_STATE_NEW; @@ -867,6 +871,9 @@ dasd_handle_state_change_pending(struct dasd_device *device) struct dasd_ccw_req *cqr; struct list_head *l, *n; + /* first of all call extended error reporting */ + dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL); + device->stopped &= ~DASD_STOPPED_PENDING; /* restart all 'running' IO on queue */ @@ -1086,6 +1093,19 @@ restart: } goto restart; } + + /* first of all call extended error reporting */ + if (device->eer && cqr->status == DASD_CQR_FAILED) { + dasd_write_eer_trigger(DASD_EER_FATALERROR, + device, cqr); + + /* restart request */ + cqr->status = DASD_CQR_QUEUED; + cqr->retries = 255; + device->stopped |= DASD_STOPPED_QUIESCE; + goto restart; + } + /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); @@ -1223,7 +1243,8 @@ __dasd_start_head(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); /* check FAILFAST */ if (device->stopped & ~DASD_STOPPED_PENDING && - test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && + (!device->eer)) { cqr->status = DASD_CQR_FAILED; dasd_schedule_bh(device); } @@ -1965,6 +1986,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: case CIO_NO_PATH: + /* first of all call extended error reporting */ + dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL); + if (device->state < DASD_STATE_BASIC) break; /* Device is active. We want to keep it. */ @@ -2022,6 +2046,51 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) put_driver(drv); } +/* + * notifications for extended error reports + */ +static struct notifier_block *dasd_eer_chain; + +int +dasd_register_eer_notifier(struct notifier_block *nb) +{ + return notifier_chain_register(&dasd_eer_chain, nb); +} + +int +dasd_unregister_eer_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&dasd_eer_chain, nb); +} + +/* + * Notify the registered error reporting module of a problem + */ +void +dasd_write_eer_trigger(unsigned int id, struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + if (device->eer) { + struct dasd_eer_trigger temp; + temp.id = id; + temp.device = device; + temp.cqr = cqr; + notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER, + (void *)&temp); + } +} + +/* + * Tell the registered error reporting module to disable error reporting for + * a given device and to cleanup any private data structures on that device. + */ +static void +dasd_disable_eer(struct dasd_device *device) +{ + notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device); +} + + static int __init dasd_init(void) { @@ -2103,6 +2172,11 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); EXPORT_SYMBOL_GPL(dasd_generic_auto_online); +EXPORT_SYMBOL(dasd_register_eer_notifier); +EXPORT_SYMBOL(dasd_unregister_eer_notifier); +EXPORT_SYMBOL(dasd_write_eer_trigger); + + /* * 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/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 4ee0f934e325..c811380b9079 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1108,6 +1108,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x0B: DEV_MESSAGE(KERN_WARNING, device, "%s", "FORMAT F - Volume is suspended duplex"); + /* call extended error reporting (EER) */ + dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device, + erp->refers); break; case 0x0C: DEV_MESSAGE(KERN_WARNING, device, "%s", diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index bc3823d35223..e15dd7978050 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -29,6 +29,7 @@ #define DASD_ECKD_CCW_PSF 0x27 #define DASD_ECKD_CCW_RSSD 0x3e #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 +#define DASD_ECKD_CCW_SNSS 0x54 #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 #define DASD_ECKD_CCW_WRITE_MT 0x85 #define DASD_ECKD_CCW_READ_MT 0x86 diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c new file mode 100644 index 000000000000..f70cd7716b24 --- /dev/null +++ b/drivers/s390/block/dasd_eer.c @@ -0,0 +1,1090 @@ +/* + * character device driver for extended error reporting + * + * + * Copyright (C) 2005 IBM Corporation + * extended error reporting for DASD ECKD devices + * Author(s): Stefan Weinhuber + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dasd_int.h" +#include "dasd_eckd.h" + + +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR("Stefan Weinhuber "); +MODULE_DESCRIPTION("DASD extended error reporting module"); + + +#ifdef PRINTK_HEADER +#undef PRINTK_HEADER +#endif /* PRINTK_HEADER */ +#define PRINTK_HEADER "dasd(eer):" + + + + + +/*****************************************************************************/ +/* the internal buffer */ +/*****************************************************************************/ + +/* + * The internal buffer is meant to store obaque blobs of data, so it doesn't + * know of higher level concepts like triggers. + * It consists of a number of pages that are used as a ringbuffer. Each data + * blob is stored in a simple record that consists of an integer, which + * contains the size of the following data, and the data bytes themselfes. + * + * To allow for multiple independent readers we create one internal buffer + * each time the device is opened and destroy the buffer when the file is + * closed again. + * + * One record can be written to a buffer by using the functions + * - dasd_eer_start_record (one time per record to write the size to the buffer + * and reserve the space for the data) + * - dasd_eer_write_buffer (one or more times per record to write the data) + * The data can be written in several steps but you will have to compute + * the total size up front for the invocation of dasd_eer_start_record. + * If the ringbuffer is full, dasd_eer_start_record will remove the required + * number of old records. + * + * A record is typically read in two steps, first read the integer that + * specifies the size of the following data, then read the data. + * Both can be done by + * - dasd_eer_read_buffer + * + * For all mentioned functions you need to get the bufferlock first and keep it + * until a complete record is written or read. + */ + + +/* + * Alle information necessary to keep track of an internal buffer is kept in + * a struct eerbuffer. The buffer specific to a file pointer is strored in + * the private_data field of that file. To be able to write data to all + * existing buffers, each buffer is also added to the bufferlist. + * If the user doesn't want to read a complete record in one go, we have to + * keep track of the rest of the record. residual stores the number of bytes + * that are still to deliver. If the rest of the record is invalidated between + * two reads then residual will be set to -1 so that the next read will fail. + * All entries in the eerbuffer structure are protected with the bufferlock. + * To avoid races between writing to a buffer on the one side and creating + * and destroying buffers on the other side, the bufferlock must also be used + * to protect the bufferlist. + */ + +struct eerbuffer { + struct list_head list; + char **buffer; + int buffersize; + int buffer_page_count; + int head; + int tail; + int residual; +}; + +LIST_HEAD(bufferlist); + +static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED; + +DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue); + +/* + * How many free bytes are available on the buffer. + * needs to be called with bufferlock held + */ +static int +dasd_eer_get_free_bytes(struct eerbuffer *eerb) +{ + if (eerb->head < eerb->tail) { + return eerb->tail - eerb->head - 1; + } else + return eerb->buffersize - eerb->head + eerb->tail -1; +} + +/* + * How many bytes of buffer space are used. + * needs to be called with bufferlock held + */ +static int +dasd_eer_get_filled_bytes(struct eerbuffer *eerb) +{ + + if (eerb->head >= eerb->tail) { + return eerb->head - eerb->tail; + } else + return eerb->buffersize - eerb->tail + eerb->head; +} + +/* + * The dasd_eer_write_buffer function just copies count bytes of data + * to the buffer. Make sure to call dasd_eer_start_record first, to + * make sure that enough free space is available. + * needs to be called with bufferlock held + */ +static void +dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data) +{ + + unsigned long headindex,localhead; + unsigned long rest, len; + char *nextdata; + + nextdata = data; + rest = count; + while (rest > 0) { + headindex = eerb->head / PAGE_SIZE; + localhead = eerb->head % PAGE_SIZE; + len = min(rest, (PAGE_SIZE - localhead)); + memcpy(eerb->buffer[headindex]+localhead, nextdata, len); + nextdata += len; + rest -= len; + eerb->head += len; + if ( eerb->head == eerb->buffersize ) + eerb->head = 0; /* wrap around */ + if (eerb->head > eerb->buffersize) { + MESSAGE(KERN_ERR, "%s", "runaway buffer head."); + BUG(); + } + } +} + +/* + * needs to be called with bufferlock held + */ +static int +dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data) +{ + + unsigned long tailindex,localtail; + unsigned long rest, len, finalcount; + char *nextdata; + + finalcount = min(count, dasd_eer_get_filled_bytes(eerb)); + nextdata = data; + rest = finalcount; + while (rest > 0) { + tailindex = eerb->tail / PAGE_SIZE; + localtail = eerb->tail % PAGE_SIZE; + len = min(rest, (PAGE_SIZE - localtail)); + memcpy(nextdata, eerb->buffer[tailindex]+localtail, len); + nextdata += len; + rest -= len; + eerb->tail += len; + if ( eerb->tail == eerb->buffersize ) + eerb->tail = 0; /* wrap around */ + if (eerb->tail > eerb->buffersize) { + MESSAGE(KERN_ERR, "%s", "runaway buffer tail."); + BUG(); + } + } + return finalcount; +} + +/* + * Whenever you want to write a blob of data to the internal buffer you + * have to start by using this function first. It will write the number + * of bytes that will be written to the buffer. If necessary it will remove + * old records to make room for the new one. + * needs to be called with bufferlock held + */ +static int +dasd_eer_start_record(struct eerbuffer *eerb, int count) +{ + int tailcount; + if (count + sizeof(count) > eerb->buffersize) + return -ENOMEM; + while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) { + if (eerb->residual > 0) { + eerb->tail += eerb->residual; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + eerb->residual = -1; + } + dasd_eer_read_buffer(eerb, sizeof(tailcount), + (char*)(&tailcount)); + eerb->tail += tailcount; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + } + dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count)); + + return 0; +}; + +/* + * release pages that are not used anymore + */ +static void +dasd_eer_free_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; ++i) { + free_page((unsigned long)buf[i]); + } +} + +/* + * allocate a new set of memory pages + */ +static int +dasd_eer_allocate_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; ++i) { + buf[i] = (char *) get_zeroed_page(GFP_KERNEL); + if (!buf[i]) { + dasd_eer_free_buffer_pages(buf, i); + return -ENOMEM; + } + } + return 0; +} + +/* + * empty the buffer by resetting head and tail + * In case there is a half read data blob in the buffer, we set residual + * to -1 to indicate that the remainder of the blob is lost. + */ +static void +dasd_eer_purge_buffer(struct eerbuffer *eerb) +{ + unsigned long flags; + + spin_lock_irqsave(&bufferlock, flags); + if (eerb->residual > 0) + eerb->residual = -1; + eerb->tail=0; + eerb->head=0; + spin_unlock_irqrestore(&bufferlock, flags); +} + +/* + * set the size of the buffer, newsize is the new number of pages to be used + * we don't try to copy any data back an forth, so any resize will also purge + * the buffer + */ +static int +dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize) +{ + int i, oldcount, reuse; + char **new; + char **old; + unsigned long flags; + + if (newsize < 1) + return -EINVAL; + if (eerb->buffer_page_count == newsize) { + /* documented behaviour is that any successfull invocation + * will purge all records */ + dasd_eer_purge_buffer(eerb); + return 0; + } + new = kmalloc(newsize*sizeof(char*), GFP_KERNEL); + if (!new) + return -ENOMEM; + + reuse=min(eerb->buffer_page_count, newsize); + for (i = 0; i < reuse; ++i) { + new[i] = eerb->buffer[i]; + } + if (eerb->buffer_page_count < newsize) { + if (dasd_eer_allocate_buffer_pages( + &new[eerb->buffer_page_count], + newsize - eerb->buffer_page_count)) { + kfree(new); + return -ENOMEM; + } + } + + spin_lock_irqsave(&bufferlock, flags); + old = eerb->buffer; + eerb->buffer = new; + if (eerb->residual > 0) + eerb->residual = -1; + eerb->tail = 0; + eerb->head = 0; + oldcount = eerb->buffer_page_count; + eerb->buffer_page_count = newsize; + spin_unlock_irqrestore(&bufferlock, flags); + + if (oldcount > newsize) { + for (i = newsize; i < oldcount; ++i) { + free_page((unsigned long)old[i]); + } + } + kfree(old); + + return 0; +} + + +/*****************************************************************************/ +/* The extended error reporting functionality */ +/*****************************************************************************/ + +/* + * When a DASD device driver wants to report an error, it calls the + * function dasd_eer_write_trigger (via a notifier mechanism) and gives the + * respective trigger ID as parameter. + * Currently there are four kinds of triggers: + * + * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems + * DASD_EER_PPRCSUSPEND: PPRC was suspended + * DASD_EER_NOPATH: There is no path to the device left. + * DASD_EER_STATECHANGE: The state of the device has changed. + * + * For the first three triggers all required information can be supplied by + * the caller. For these triggers a record is written by the function + * dasd_eer_write_standard_trigger. + * + * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE + * trigger, we have to gather the necessary sense data first. We cannot queue + * the necessary SNSS (sense subsystem status) request immediatly, since we + * are likely to run in a deadlock situation. Instead, we schedule a + * work_struct that calls the function dasd_eer_sense_subsystem_status to + * create and start an SNSS request asynchronously. + * + * To avoid memory allocations at runtime, the necessary memory is allocated + * when the extended error reporting is enabled for a device (by + * dasd_eer_probe). There is one private eer data structure for each eer + * enabled DASD device. It contains memory for the work_struct, one SNSS cqr + * and a flags field that is used to coordinate the use of the cqr. The call + * to write a state change trigger can come in at any time, so we have one flag + * CQR_IN_USE that protects the cqr itself. When this flag indicates that the + * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a + * second request but sets the SNSS_REQUESTED flag instead. + * + * When the request is finished, the callback function dasd_eer_SNSS_cb + * is called. This function will invoke the function + * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also + * check the SNSS_REQUESTED flag and if it is set it will call + * dasd_eer_sense_subsystem_status again. + * + * To avoid race conditions during the handling of the lock, the flags must + * be protected by the snsslock. + */ + +struct dasd_eer_private { + struct dasd_ccw_req *cqr; + unsigned long flags; + struct work_struct worker; +}; + +static void dasd_eer_destroy(struct dasd_device *device, + struct dasd_eer_private *eer); +static int +dasd_eer_write_trigger(struct dasd_eer_trigger *trigger); +static void dasd_eer_sense_subsystem_status(void *data); +static int dasd_eer_notify(struct notifier_block *self, + unsigned long action, void *data); + +struct workqueue_struct *dasd_eer_workqueue; + +#define SNSS_DATA_SIZE 44 +static spinlock_t snsslock = SPIN_LOCK_UNLOCKED; + +#define DASD_EER_BUSID_SIZE 10 +struct dasd_eer_header { + __u32 total_size; + __u32 trigger; + __u64 tv_sec; + __u64 tv_usec; + char busid[DASD_EER_BUSID_SIZE]; +} __attribute__ ((packed)); + +static struct notifier_block dasd_eer_nb = { + .notifier_call = dasd_eer_notify, +}; + +/* + * flags for use with dasd_eer_private + */ +#define CQR_IN_USE 0 +#define SNSS_REQUESTED 1 + +/* + * This function checks if extended error reporting is available for a given + * dasd_device. If yes, then it creates and returns a struct dasd_eer, + * otherwise it returns an -EPERM error pointer. + */ +struct dasd_eer_private * +dasd_eer_probe(struct dasd_device *device) +{ + struct dasd_eer_private *private; + + if (!(device && device->discipline + && !strcmp(device->discipline->name, "ECKD"))) { + return ERR_PTR(-EPERM); + } + /* allocate the private data structure */ + private = (struct dasd_eer_private *)kmalloc( + sizeof(struct dasd_eer_private), GFP_KERNEL); + if (!private) { + return ERR_PTR(-ENOMEM); + } + INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status, + (void *)device); + private->cqr = dasd_kmalloc_request("ECKD", + 1 /* SNSS */ , + SNSS_DATA_SIZE , + device); + if (!private->cqr) { + kfree(private); + return ERR_PTR(-ENOMEM); + } + private->flags = 0; + return private; +}; + +/* + * If our private SNSS request is queued, remove it from the + * dasd ccw queue so we can free the requests memory. + */ +static void +dasd_eer_dequeue_SNSS_request(struct dasd_device *device, + struct dasd_eer_private *eer) +{ + struct list_head *lst, *nxt; + struct dasd_ccw_req *cqr, *erpcqr; + dasd_erp_fn_t erp_fn; + + spin_lock_irq(get_ccwdev_lock(device->cdev)); + list_for_each_safe(lst, nxt, &device->ccw_queue) { + cqr = list_entry(lst, struct dasd_ccw_req, list); + /* we are looking for two kinds or requests */ + /* first kind: our SNSS request: */ + if (cqr == eer->cqr) { + if (cqr->status == DASD_CQR_IN_IO) + device->discipline->term_IO(cqr); + list_del(&cqr->list); + break; + } + /* second kind: ERP requests for our SNSS request */ + if (cqr->refers) { + /* If this erp request chain ends in our cqr, then */ + /* cal the erp_postaction to clean it up */ + erpcqr = cqr; + while (erpcqr->refers) { + erpcqr = erpcqr->refers; + } + if (erpcqr == eer->cqr) { + erp_fn = device->discipline->erp_postaction( + cqr); + erp_fn(cqr); + } + continue; + } + } + spin_unlock_irq(get_ccwdev_lock(device->cdev)); +} + +/* + * This function dismantles a struct dasd_eer that was created by + * dasd_eer_probe. Since we want to free our private data structure, + * we must make sure that the memory is not in use anymore. + * We have to flush the work queue and remove a possible SNSS request + * from the dasd queue. + */ +static void +dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer) +{ + flush_workqueue(dasd_eer_workqueue); + dasd_eer_dequeue_SNSS_request(device, eer); + dasd_kfree_request(eer->cqr, device); + kfree(eer); +}; + +/* + * enable the extended error reporting for a particular device + */ +static int +dasd_eer_enable_on_device(struct dasd_device *device) +{ + void *eer; + if (!device) + return -ENODEV; + if (device->eer) + return 0; + if (!try_module_get(THIS_MODULE)) { + return -EINVAL; + } + eer = (void *)dasd_eer_probe(device); + if (IS_ERR(eer)) { + module_put(THIS_MODULE); + return PTR_ERR(eer); + } + device->eer = eer; + return 0; +} + +/* + * enable the extended error reporting for a particular device + */ +static int +dasd_eer_disable_on_device(struct dasd_device *device) +{ + struct dasd_eer_private *eer = device->eer; + + if (!device) + return -ENODEV; + if (!device->eer) + return 0; + device->eer = NULL; + dasd_eer_destroy(device,eer); + module_put(THIS_MODULE); + + return 0; +} + +/* + * Set extended error reporting (eer) + * Note: This will be registered as a DASD ioctl, to be called on DASD devices. + */ +static int +dasd_ioctl_set_eer(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + int intval; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (bdev != bdev->bd_contains) + /* Error-reporting is not allowed for partitions */ + return -EINVAL; + if (get_user(intval, (int __user *) args)) + return -EFAULT; + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + + intval = (intval != 0); + DEV_MESSAGE (KERN_DEBUG, device, + "set eer on device to %d", intval); + if (intval) + return dasd_eer_enable_on_device(device); + else + return dasd_eer_disable_on_device(device); +} + +/* + * Get value of extended error reporting. + * Note: This will be registered as a DASD ioctl, to be called on DASD devices. + */ +static int +dasd_ioctl_get_eer(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + return put_user((device->eer != NULL), (int __user *) args); +} + +/* + * The following function can be used for those triggers that have + * all necessary data available when the function is called. + * If the parameter cqr is not NULL, the chain of requests will be searched + * for valid sense data, and all valid sense data sets will be added to + * the triggers data. + */ +static int +dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + struct dasd_ccw_req *temp_cqr; + int data_size; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + /* go through cqr chain and count the valid sense data sets */ + temp_cqr = cqr; + data_size = 0; + while (temp_cqr) { + if (temp_cqr->irb.esw.esw0.erw.cons) + data_size += 32; + temp_cqr = temp_cqr->refers; + } + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = trigger; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header)); + temp_cqr = cqr; + while (temp_cqr) { + if (temp_cqr->irb.esw.esw0.erw.cons) + dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw); + temp_cqr = temp_cqr->refers; + } + dasd_eer_write_buffer(eerb, 4,"EOR"); + } + spin_unlock_irqrestore(&bufferlock, flags); + + wake_up_interruptible(&dasd_eer_read_wait_queue); + + return 0; +} + +/* + * This function writes a DASD_EER_STATECHANGE trigger. + */ +static void +dasd_eer_write_SNSS_trigger(struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + int data_size; + int snss_rc; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; + if (snss_rc) + data_size = 0; + else + data_size = SNSS_DATA_SIZE; + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = DASD_EER_STATECHANGE; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header)); + if (!snss_rc) + dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data); + dasd_eer_write_buffer(eerb, 4,"EOR"); + } + spin_unlock_irqrestore(&bufferlock, flags); + + wake_up_interruptible(&dasd_eer_read_wait_queue); +} + +/* + * callback function for use with SNSS request + */ +static void +dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data) +{ + struct dasd_device *device; + struct dasd_eer_private *private; + unsigned long irqflags; + + device = (struct dasd_device *)data; + private = (struct dasd_eer_private *)device->eer; + dasd_eer_write_SNSS_trigger(device, cqr); + spin_lock_irqsave(&snsslock, irqflags); + if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) { + clear_bit(CQR_IN_USE, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + return; + }; + clear_bit(CQR_IN_USE, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + dasd_eer_sense_subsystem_status(device); + return; +} + +/* + * clean a used cqr before using it again + */ +static void +dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr) +{ + struct ccw1 *cpaddr = cqr->cpaddr; + void *data = cqr->data; + + memset(cqr, 0, sizeof(struct dasd_ccw_req)); + memset(cpaddr, 0, sizeof(struct ccw1)); + memset(data, 0, SNSS_DATA_SIZE); + cqr->cpaddr = cpaddr; + cqr->data = data; + strncpy((char *) &cqr->magic, "ECKD", 4); + ASCEBC((char *) &cqr->magic, 4); + set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); +} + +/* + * build and start an SNSS request + * This function is called from a work queue so we have to + * pass the dasd_device pointer as a void pointer. + */ +static void +dasd_eer_sense_subsystem_status(void *data) +{ + struct dasd_device *device; + struct dasd_eer_private *private; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + unsigned long irqflags; + + device = (struct dasd_device *)data; + private = (struct dasd_eer_private *)device->eer; + if (!private) /* device not eer enabled any more */ + return; + cqr = private->cqr; + spin_lock_irqsave(&snsslock, irqflags); + if(test_and_set_bit(CQR_IN_USE, &private->flags)) { + set_bit(SNSS_REQUESTED, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + return; + }; + spin_unlock_irqrestore(&snsslock, irqflags); + dasd_eer_clean_SNSS_request(cqr); + cqr->device = device; + cqr->retries = 255; + cqr->expires = 10 * HZ; + + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_SNSS; + ccw->count = SNSS_DATA_SIZE; + ccw->flags = 0; + ccw->cda = (__u32)(addr_t)cqr->data; + + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + cqr->callback = dasd_eer_SNSS_cb; + cqr->callback_data = (void *)device; + dasd_add_request_head(cqr); + + return; +} + +/* + * This function is called for all triggers. It calls the appropriate + * function that writes the actual trigger records. + */ +static int +dasd_eer_write_trigger(struct dasd_eer_trigger *trigger) +{ + int rc; + struct dasd_eer_private *private = trigger->device->eer; + + switch (trigger->id) { + case DASD_EER_FATALERROR: + case DASD_EER_PPRCSUSPEND: + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, trigger->cqr); + break; + case DASD_EER_NOPATH: + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, NULL); + break; + case DASD_EER_STATECHANGE: + if (queue_work(dasd_eer_workqueue, &private->worker)) { + rc=0; + } else { + /* If the work_struct was already queued, it can't + * be queued again. But this is OK since we don't + * need to have it queued twice. + */ + rc = -EBUSY; + } + break; + default: /* unknown trigger, so we write it without any sense data */ + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, NULL); + break; + } + return rc; +} + +/* + * This function is registered with the dasd device driver and gets called + * for all dasd eer notifications. + */ +static int dasd_eer_notify(struct notifier_block *self, + unsigned long action, void *data) +{ + switch (action) { + case DASD_EER_DISABLE: + dasd_eer_disable_on_device((struct dasd_device *)data); + break; + case DASD_EER_TRIGGER: + dasd_eer_write_trigger((struct dasd_eer_trigger *)data); + break; + } + return NOTIFY_OK; +} + + +/*****************************************************************************/ +/* the device operations */ +/*****************************************************************************/ + +/* + * On the one side we need a lock to access our internal buffer, on the + * other side a copy_to_user can sleep. So we need to copy the data we have + * to transfer in a readbuffer, which is protected by the readbuffer_mutex. + */ +static char readbuffer[PAGE_SIZE]; +DECLARE_MUTEX(readbuffer_mutex); + + +static int +dasd_eer_open(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL); + eerb->head = 0; + eerb->tail = 0; + eerb->residual = 0; + eerb->buffer_page_count = 1; + eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; + eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*), + GFP_KERNEL); + if (!eerb->buffer) + return -ENOMEM; + if (dasd_eer_allocate_buffer_pages(eerb->buffer, + eerb->buffer_page_count)) { + kfree(eerb->buffer); + return -ENOMEM; + } + filp->private_data = eerb; + spin_lock_irqsave(&bufferlock, flags); + list_add(&eerb->list, &bufferlist); + spin_unlock_irqrestore(&bufferlock, flags); + + return nonseekable_open(inp,filp); +} + +static int +dasd_eer_close(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = (struct eerbuffer *)filp->private_data; + spin_lock_irqsave(&bufferlock, flags); + list_del(&eerb->list); + spin_unlock_irqrestore(&bufferlock, flags); + dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count); + kfree(eerb->buffer); + kfree(eerb); + + return 0; +} + +static long +dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int intval; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + switch (cmd) { + case DASD_EER_PURGE: + dasd_eer_purge_buffer(eerb); + return 0; + case DASD_EER_SETBUFSIZE: + if (get_user(intval, (int __user *)arg)) + return -EFAULT; + return dasd_eer_resize_buffer(eerb, intval); + default: + return -ENOIOCTLCMD; + } +} + +static ssize_t +dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) +{ + int tc,rc; + int tailcount,effective_count; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + if(down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + + spin_lock_irqsave(&bufferlock, flags); + + if (eerb->residual < 0) { /* the remainder of this record */ + /* has been deleted */ + eerb->residual = 0; + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + return -EIO; + } else if (eerb->residual > 0) { + /* OK we still have a second half of a record to deliver */ + effective_count = min(eerb->residual, (int)count); + eerb->residual -= effective_count; + } else { + tc = 0; + while (!tc) { + tc = dasd_eer_read_buffer(eerb, + sizeof(tailcount), (char*)(&tailcount)); + if (!tc) { + /* no data available */ + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + rc = wait_event_interruptible( + dasd_eer_read_wait_queue, + eerb->head != eerb->tail); + if (rc) { + return rc; + } + if(down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + spin_lock_irqsave(&bufferlock, flags); + } + } + WARN_ON(tc != sizeof(tailcount)); + effective_count = min(tailcount,(int)count); + eerb->residual = tailcount - effective_count; + } + + tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer); + WARN_ON(tc != effective_count); + + spin_unlock_irqrestore(&bufferlock, flags); + + if (copy_to_user(buf, readbuffer, effective_count)) { + up(&readbuffer_mutex); + return -EFAULT; + } + + up(&readbuffer_mutex); + return effective_count; +} + +static unsigned int +dasd_eer_poll (struct file *filp, poll_table *ptable) +{ + unsigned int mask; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + poll_wait(filp, &dasd_eer_read_wait_queue, ptable); + spin_lock_irqsave(&bufferlock, flags); + if (eerb->head != eerb->tail) + mask = POLLIN | POLLRDNORM ; + else + mask = 0; + spin_unlock_irqrestore(&bufferlock, flags); + return mask; +} + +static struct file_operations dasd_eer_fops = { + .open = &dasd_eer_open, + .release = &dasd_eer_close, + .unlocked_ioctl = &dasd_eer_ioctl, + .compat_ioctl = &dasd_eer_ioctl, + .read = &dasd_eer_read, + .poll = &dasd_eer_poll, + .owner = THIS_MODULE, +}; + +static struct miscdevice dasd_eer_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dasd_eer", + .fops = &dasd_eer_fops, +}; + + +/*****************************************************************************/ +/* Init and exit */ +/*****************************************************************************/ + +static int +__init dasd_eer_init(void) +{ + int rc; + + dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer"); + if (!dasd_eer_workqueue) { + MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not " + "create workqueue \n"); + rc = -ENOMEM; + goto out; + } + + rc = dasd_register_eer_notifier(&dasd_eer_nb); + if (rc) { + MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + "register error reporting"); + goto queue; + } + + dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer); + dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer); + + /* we don't need our own character device, + * so we just register as misc device */ + rc = misc_register(&dasd_eer_dev); + if (rc) { + MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + "register misc device"); + goto unregister; + } + + return 0; + +unregister: + dasd_unregister_eer_notifier(&dasd_eer_nb); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, + dasd_ioctl_set_eer); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, + dasd_ioctl_get_eer); +queue: + destroy_workqueue(dasd_eer_workqueue); +out: + return rc; + +} +module_init(dasd_eer_init); + +static void +__exit dasd_eer_exit(void) +{ + dasd_unregister_eer_notifier(&dasd_eer_nb); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, + dasd_ioctl_set_eer); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, + dasd_ioctl_get_eer); + destroy_workqueue(dasd_eer_workqueue); + + WARN_ON(misc_deregister(&dasd_eer_dev) != 0); +} +module_exit(dasd_eer_exit); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index c20af9874500..d1b08fa13fd2 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -275,6 +275,34 @@ struct dasd_discipline { extern struct dasd_discipline *dasd_diag_discipline_pointer; + +/* + * Notification numbers for extended error reporting notifications: + * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's + * eer pointer) is freed. The error reporting module needs to do all necessary + * cleanup steps. + * The DASD_EER_TRIGGER notification sends the actual error reports (triggers). + */ +#define DASD_EER_DISABLE 0 +#define DASD_EER_TRIGGER 1 + +/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */ +#define DASD_EER_FATALERROR 1 +#define DASD_EER_NOPATH 2 +#define DASD_EER_STATECHANGE 3 +#define DASD_EER_PPRCSUSPEND 4 + +/* + * The dasd_eer_trigger structure contains all data that we need to send + * along with an DASD_EER_TRIGGER notification. + */ +struct dasd_eer_trigger { + unsigned int id; + struct dasd_device *device; + struct dasd_ccw_req *cqr; +}; + + struct dasd_device { /* Block device stuff. */ struct gendisk *gdp; @@ -288,6 +316,9 @@ struct dasd_device { unsigned long flags; /* per device flags */ unsigned short features; /* copy of devmap-features (read-only!) */ + /* extended error reporting stuff (eer) */ + void *eer; + /* Device discipline stuff. */ struct dasd_discipline *discipline; char *private; @@ -488,6 +519,12 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); int dasd_generic_set_offline (struct ccw_device *cdev); int dasd_generic_notify(struct ccw_device *, int); void dasd_generic_auto_online (struct ccw_driver *); +int dasd_register_eer_notifier(struct notifier_block *); +int dasd_unregister_eer_notifier(struct notifier_block *); +void dasd_write_eer_trigger(unsigned int , struct dasd_device *, + struct dasd_ccw_req *); + + /* externals in dasd_devmap.c */ extern int dasd_max_devindex; -- cgit v1.2.2 From 501fe31df4bb94999fbe9bb42f05527df5525683 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 3 Feb 2006 03:03:52 -0800 Subject: [PATCH] s390: fix to_channelpath macro Fix broken to_channelpath macro (fortunately worked in all current cases...). Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chsc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 44e4b4bb1c5a..3e75095f35d0 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -68,6 +68,6 @@ extern void *chsc_get_chp_desc(struct subchannel*, int); extern int chsc_enable_facility(int); -#define to_channelpath(dev) container_of(dev, struct channel_path, dev) +#define to_channelpath(device) container_of(device, struct channel_path, dev) #endif -- cgit v1.2.2 From c48d865c50e8626372a52094385fb1f5a2d2a7fd Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Sat, 11 Feb 2006 17:55:57 -0800 Subject: [PATCH] s390: fix locking in __chp_add() and s390_subchannel_remove_chpid() Fix locking in __chp_add() and s390_subchannel_remove_chpid(): Need to disable/enable because they are always called from a thread (and not directly from a machine check...) Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 92be75d99a56..8cf9905d484b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -232,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) return 0; mask = 0x80 >> j; - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); stsch(sch->schid, &schib); if (!schib.pmcw.dnv) @@ -281,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); out_unlock: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); return 0; out_unreg: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); sch->lpm = 0; if (css_enqueue_subchannel_slow(sch->schid)) { css_clear_subchannel_slow_list(); @@ -652,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data) if (!sch) /* Check if the subchannel is now available. */ return __chp_add_new_sch(schid); - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); for (i=0; i<8; i++) if (sch->schib.pmcw.chpid[i] == chp->id) { if (stsch(sch->schid, &sch->schib) != 0) { @@ -674,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); put_device(&sch->dev); return 0; } -- cgit v1.2.2 From 25fab9ebac445d57b656f5faabac5a195bed2f82 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Sat, 11 Feb 2006 17:55:59 -0800 Subject: [PATCH] s390: fix sclp memory corruption in tty pages list When the sclp interface takes very long to serve a request, the sclp core driver will report a failed request to the sclp tty driver even though the request is still being processed by the sclp interface. Eventually the sclp interface completes the request and updates some fields in the request buffer which leads to a corrupted tty pages list. The next time function sclp_tty_write_room is called, the corrupted list will be traversed, resulting in an oops. To avoid this remove the busy retry limit and increase retry intervals. Signed-off-by: Peter Oberparleiter Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/sclp.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index ceb0e474fde4..4138564402b8 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t { /* Maximum retry counts */ #define SCLP_INIT_RETRY 3 #define SCLP_MASK_RETRY 3 -#define SCLP_REQUEST_RETRY 3 /* Timeout intervals in seconds.*/ -#define SCLP_BUSY_INTERVAL 2 -#define SCLP_RETRY_INTERVAL 5 +#define SCLP_BUSY_INTERVAL 10 +#define SCLP_RETRY_INTERVAL 15 static void sclp_process_queue(void); static int sclp_init_mask(int calculate); @@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; del_timer(&sclp_request_timer); - if (req->start_count <= SCLP_REQUEST_RETRY) { - rc = service_call(req->command, req->sccb); - req->start_count++; - } else - rc = -EIO; + rc = service_call(req->command, req->sccb); + req->start_count++; + if (rc == 0) { /* Sucessfully started request */ req->status = SCLP_REQ_RUNNING; -- cgit v1.2.2 From c8024eb549f0c701e6d1c46c32e997f06f05d76d Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:40:11 +0100 Subject: [SCSI] zfcp: get rid of physical_wwpn and physical_s_id Remove all remainders of obsolete zfcp adapter attributes physical_wwpn and physical_s_id. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 2 -- drivers/s390/scsi/zfcp_sysfs_adapter.c | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index e260d19fa717..7dac56c49ade 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -915,8 +915,6 @@ struct zfcp_adapter { wwn_t peer_wwnn; /* P2P peer WWNN */ wwn_t peer_wwpn; /* P2P peer WWPN */ u32 peer_d_id; /* P2P peer D_ID */ - wwn_t physical_wwpn; /* WWPN of physical port */ - u32 physical_s_id; /* local FC port ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u8 fc_service_class; u32 hydra_version; /* Hydra version */ diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index dfc07370f412..b29ac25e07f3 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -55,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); -ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); -ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", @@ -241,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_peer_wwnn.attr, &dev_attr_peer_wwpn.attr, &dev_attr_peer_d_id.attr, - &dev_attr_physical_wwpn.attr, - &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, &dev_attr_status.attr, -- cgit v1.2.2 From 2f8f3ed5fc566700cf45d422f4cf1624bd123d93 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:41:50 +0100 Subject: [SCSI] zfcp: fix adapter erp when link is unplugged Remove endless polling for replug of the local link. Just wait for link up notification. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 5 --- drivers/s390/scsi/zfcp_erp.c | 80 ++++++++++++++++---------------------------- drivers/s390/scsi/zfcp_fsf.c | 74 ++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 90 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 7dac56c49ade..f031199c7414 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -152,11 +152,6 @@ typedef u32 scsi_lun_t; #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 -/* Retry 5 times every 2 second, then every minute */ -#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5 -#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200 -#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000 - /* timeout value for "default timer" for fsf requests */ #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index da947e662031..8ed6fcb41653 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) { int retval; - if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &erp_action->adapter->status)) && - (erp_action->adapter->adapter_features & - FSF_FEATURE_HBAAPI_MANAGEMENT)) { - zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); - atomic_set(&erp_action->adapter->erp_counter, 0); - return ZFCP_ERP_FAILED; - } - retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); if (retval == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; @@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) { @@ -2350,48 +2334,40 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) { int ret; - int retries; - int sleep; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_adapter *adapter; + adapter = erp_action->adapter; atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - retries = 0; - do { - write_lock(&adapter->erp_lock); - zfcp_erp_action_to_running(erp_action); - write_unlock(&adapter->erp_lock); - zfcp_erp_timeout_init(erp_action); - ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); - if (ret == -EOPNOTSUPP) { - debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); - return ZFCP_ERP_SUCCEEDED; - } else if (ret) { - debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); - return ZFCP_ERP_FAILED; - } - debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); + write_lock(&adapter->erp_lock); + zfcp_erp_action_to_running(erp_action); + write_unlock(&adapter->erp_lock); - down(&adapter->erp_ready_sem); - if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { - ZFCP_LOG_INFO("error: exchange of port data " - "for adapter %s timed out\n", - zfcp_get_busid_by_adapter(adapter)); - break; - } - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status)) - break; + zfcp_erp_timeout_init(erp_action); + ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); + if (ret == -EOPNOTSUPP) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); + return ZFCP_ERP_SUCCEEDED; + } else if (ret) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); + return ZFCP_ERP_FAILED; + } + debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); - if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { - sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; - retries++; - } else - sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; - schedule_timeout(sleep); - } while (1); + ret = ZFCP_ERP_SUCCEEDED; + down(&adapter->erp_ready_sem); + if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { + ZFCP_LOG_INFO("error: exchange port data timed out (adapter " + "%s)\n", zfcp_get_busid_by_adapter(adapter)); + ret = ZFCP_ERP_FAILED; + } + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) { + ZFCP_LOG_INFO("error: exchange port data failed (adapter " + "%s\n", zfcp_get_busid_by_adapter(adapter)); + ret = ZFCP_ERP_FAILED; + } - return ZFCP_ERP_SUCCEEDED; + return ret; } /* diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9f0cb3d820c0..bd8cd4d46134 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) case FSF_PROT_LINK_DOWN: zfcp_fsf_link_down_info_eval(adapter, &prot_status_qual->link_down_info); + zfcp_erp_adapter_reopen(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); - if (link_down == NULL) { - zfcp_erp_adapter_reopen(adapter, 0); - return; - } + if (link_down == NULL) + goto out; switch (link_down->error_code) { case FSF_PSQ_LINK_NO_LIGHT: @@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, link_down->explanation_code, link_down->vendor_specific_code); - switch (link_down->error_code) { - case FSF_PSQ_LINK_NO_LIGHT: - case FSF_PSQ_LINK_WRAP_PLUG: - case FSF_PSQ_LINK_NO_FCP: - case FSF_PSQ_LINK_FIRMWARE_UPDATE: - zfcp_erp_adapter_reopen(adapter, 0); - break; - default: - zfcp_erp_adapter_failed(adapter); - } + out: + zfcp_erp_adapter_failed(adapter); } /* @@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, return retval; } +/** + * zfcp_fsf_exchange_port_evaluate + * @fsf_req: fsf_req which belongs to xchg port data request + * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1) + */ +static void +zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) +{ + struct zfcp_adapter *adapter; + struct fsf_qtcb *qtcb; + struct fsf_qtcb_bottom_port *bottom, *data; + struct Scsi_Host *shost; + + adapter = fsf_req->adapter; + qtcb = fsf_req->qtcb; + bottom = &qtcb->bottom.port; + shost = adapter->scsi_host; + + data = (struct fsf_qtcb_bottom_port*) fsf_req->data; + if (data) + memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); + + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) + fc_host_permanent_port_name(shost) = bottom->wwpn; + else + fc_host_permanent_port_name(shost) = fc_host_port_name(shost); + fc_host_maxframe_size(shost) = bottom->maximum_frame_size; + fc_host_supported_speeds(shost) = bottom->supported_speed; +} /** * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request @@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) { - struct zfcp_adapter *adapter = fsf_req->adapter; - struct Scsi_Host *shost = adapter->scsi_host; - struct fsf_qtcb *qtcb = fsf_req->qtcb; - struct fsf_qtcb_bottom_port *bottom, *data; + struct zfcp_adapter *adapter; + struct fsf_qtcb *qtcb; + + adapter = fsf_req->adapter; + qtcb = fsf_req->qtcb; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) return; switch (qtcb->header.fsf_status) { case FSF_GOOD: + zfcp_fsf_exchange_port_evaluate(fsf_req, 1); atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - - bottom = &qtcb->bottom.port; - data = (struct fsf_qtcb_bottom_port*) fsf_req->data; - if (data) - memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) - fc_host_permanent_port_name(shost) = bottom->wwpn; - else - fc_host_permanent_port_name(shost) = - fc_host_port_name(shost); - fc_host_maxframe_size(shost) = bottom->maximum_frame_size; - fc_host_supported_speeds(shost) = bottom->supported_speed; break; - case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + zfcp_fsf_exchange_port_evaluate(fsf_req, 0); atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - zfcp_fsf_link_down_info_eval(adapter, &qtcb->header.fsf_status_qual.link_down_info); break; - default: debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); debug_event(adapter->erp_dbf, 0, -- cgit v1.2.2 From ed829ad607a9c334cea490d3a8c0f874153fb42d Mon Sep 17 00:00:00 2001 From: Maxim Shchetynin Date: Sat, 11 Feb 2006 01:42:58 +0100 Subject: [SCSI] zfcp: fix logging during device reset Avoid access to old fsf_requests if device reset is logged. Signed-off-by: Maxim Shchetynin Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 76 +++++++++++++++++-------------------------- drivers/s390/scsi/zfcp_def.h | 6 +--- drivers/s390/scsi/zfcp_ext.h | 5 +-- drivers/s390/scsi/zfcp_fsf.c | 6 ++-- drivers/s390/scsi/zfcp_scsi.c | 15 ++++++--- 5 files changed, 47 insertions(+), 61 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 4d7d47cf2394..a5f2ba9a8fdb 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -710,10 +710,9 @@ static inline void _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, - struct zfcp_fsf_req *new_fsf_req) + struct zfcp_fsf_req *fsf_req, + struct zfcp_fsf_req *old_fsf_req) { - struct zfcp_fsf_req *fsf_req = - (struct zfcp_fsf_req *)scsi_cmnd->host_scribble; struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; unsigned long flags; @@ -727,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, if (offset == 0) { strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); - if (scsi_cmnd->device) { - rec->scsi_id = scsi_cmnd->device->id; - rec->scsi_lun = scsi_cmnd->device->lun; + if (scsi_cmnd != NULL) { + if (scsi_cmnd->device) { + rec->scsi_id = scsi_cmnd->device->id; + rec->scsi_lun = scsi_cmnd->device->lun; + } + rec->scsi_result = scsi_cmnd->result; + rec->scsi_cmnd = (unsigned long)scsi_cmnd; + rec->scsi_serial = scsi_cmnd->serial_number; + memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, + min((int)scsi_cmnd->cmd_len, + ZFCP_DBF_SCSI_OPCODE)); + rec->scsi_retries = scsi_cmnd->retries; + rec->scsi_allowed = scsi_cmnd->allowed; } - rec->scsi_result = scsi_cmnd->result; - rec->scsi_cmnd = (unsigned long)scsi_cmnd; - rec->scsi_serial = scsi_cmnd->serial_number; - memcpy(rec->scsi_opcode, - &scsi_cmnd->cmnd, - min((int)scsi_cmnd->cmd_len, - ZFCP_DBF_SCSI_OPCODE)); - rec->scsi_retries = scsi_cmnd->retries; - rec->scsi_allowed = scsi_cmnd->allowed; if (fsf_req != NULL) { fcp_rsp = (struct fcp_rsp_iu *) &(fsf_req->qtcb->bottom.io.fcp_rsp); @@ -772,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, rec->fsf_seqno = fsf_req->seq_no; rec->fsf_issued = fsf_req->issued; } - if (new_fsf_req != NULL) { - rec->type.new_fsf_req.fsf_reqid = - (unsigned long) - new_fsf_req; - rec->type.new_fsf_req.fsf_seqno = - new_fsf_req->seq_no; - rec->type.new_fsf_req.fsf_issued = - new_fsf_req->issued; - } + rec->type.old_fsf_reqid = + (unsigned long) old_fsf_req; } else { strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); dump->total_size = buflen; @@ -801,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, inline void zfcp_scsi_dbf_event_result(const char *tag, int level, struct zfcp_adapter *adapter, - struct scsi_cmnd *scsi_cmnd) + struct scsi_cmnd *scsi_cmnd, + struct zfcp_fsf_req *fsf_req) { - _zfcp_scsi_dbf_event_common("rslt", - tag, level, adapter, scsi_cmnd, NULL); + _zfcp_scsi_dbf_event_common("rslt", tag, level, + adapter, scsi_cmnd, fsf_req, NULL); } inline void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, - struct zfcp_fsf_req *new_fsf_req) + struct zfcp_fsf_req *new_fsf_req, + struct zfcp_fsf_req *old_fsf_req) { - _zfcp_scsi_dbf_event_common("abrt", - tag, 1, adapter, scsi_cmnd, new_fsf_req); + _zfcp_scsi_dbf_event_common("abrt", tag, 1, + adapter, scsi_cmnd, new_fsf_req, old_fsf_req); } inline void @@ -823,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, struct zfcp_adapter *adapter = unit->port->adapter; _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", - tag, 1, adapter, scsi_cmnd, NULL); + tag, 1, adapter, scsi_cmnd, NULL, NULL); } static int @@ -856,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, rec->scsi_retries); len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x", rec->scsi_allowed); + if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx", + rec->type.old_fsf_reqid); + } len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", rec->fsf_reqid); len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", @@ -883,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, min((int)rec->type.fcp.sns_info_len, ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, rec->type.fcp.sns_info_len); - } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { - len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx", - rec->type.new_fsf_req.fsf_reqid); - len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x", - rec->type.new_fsf_req.fsf_seqno); - len += zfcp_dbf_stck(out_buf + len, "fsf_issued", - rec->type.new_fsf_req.fsf_issued); - } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) || - (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) { - len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx", - rec->type.new_fsf_req.fsf_reqid); - len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x", - rec->type.new_fsf_req.fsf_seqno); - len += zfcp_dbf_stck(out_buf + len, "fsf_issued", - rec->type.new_fsf_req.fsf_issued); } len += sprintf(out_buf + len, "\n"); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index f031199c7414..7f551d66f47f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -424,11 +424,7 @@ struct zfcp_scsi_dbf_record { u32 fsf_seqno; u64 fsf_issued; union { - struct { - u64 fsf_reqid; - u32 fsf_seqno; - u64 fsf_issued; - } new_fsf_req; + u64 old_fsf_reqid; struct { u8 rsp_validity; u8 rsp_scsi_status; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c1ba7cf1b496..700f5402a978 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -194,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *); extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *, - struct scsi_cmnd *); + struct scsi_cmnd *, + struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, - struct scsi_cmnd *, + struct scsi_cmnd *, struct zfcp_fsf_req *, struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, struct scsi_cmnd *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index bd8cd4d46134..662ec571d73b 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4211,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); if (scpnt->result != 0) - zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req); else if (scpnt->retries > 0) - zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req); else - zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req); /* cleanup pointer (need this especially for abort) */ scpnt->host_scribble = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e0803757c0fa..9f6b4d7a46f3 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -242,7 +242,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) zfcp_scsi_dbf_event_result("fail", 4, (struct zfcp_adapter*) scpnt->device->host->hostdata[0], - scpnt); + scpnt, NULL); /* return directly */ scpnt->scsi_done(scpnt); } @@ -446,7 +446,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; if (!old_fsf_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); - zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL); retval = SUCCESS; goto out; } @@ -460,6 +460,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) adapter, unit, 0); if (!new_fsf_req) { ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); + zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, + old_fsf_req); retval = FAILED; goto out; } @@ -470,13 +472,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) /* status should be valid since signals were not permitted */ if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { - zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req, + NULL); retval = SUCCESS; } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { - zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req, + NULL); retval = SUCCESS; } else { - zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req, + NULL); retval = FAILED; } zfcp_fsf_req_free(new_fsf_req); -- cgit v1.2.2 From 61c41823c50302ca6cd455c48a1395f944c61f8f Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:43:55 +0100 Subject: [SCSI] zfcp: fix: avoid race between fc_remote_port_add and scsi_add_device Flush workqueue of a scsi host after a remote port for that host is registered at the fc transport class. Otherwise immediate registration of a scsi device on that host is racy. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8ed6fcb41653..e3c4bdd29a60 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3415,6 +3415,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, "(adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), port->wwpn); + else + scsi_flush_work(adapter->scsi_host); } zfcp_port_put(port); break; -- cgit v1.2.2 From 0d613a27cc753bfacd20e6eaa2183bb7fef4c76e Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Tue, 7 Feb 2006 17:04:36 +0100 Subject: [PATCH] s390: lcs performance enhancements [patch 1/2] s390: lcs performance enhancements From: Klaus Wacker - When flood pinging (with large packet size) an LCS device, about 90 % of all packets are dropped by driver. - increased number of lcs IO buffers to 32. - use netif_stop_queue/netif_wake_queue in lcs_start_xmit routine - don't lock the whole xmit routine but just the piece of code where tx_buffer is touched. Signed-off-by: Frank Pavlic diffstat: lcs.c | 31 +++++++++++++++++-------------- lcs.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/lcs.c | 31 +++++++++++++++++-------------- drivers/s390/net/lcs.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 6229ba4995ad..9cf88d7201d3 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -98,9 +98,9 @@ lcs_register_debug_facility(void) return -ENOMEM; } debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_setup, 4); + debug_set_level(lcs_dbf_setup, 2); debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_trace, 4); + debug_set_level(lcs_dbf_trace, 2); return 0; } @@ -1292,9 +1292,8 @@ lcs_set_multicast_list(struct net_device *dev) LCS_DBF_TEXT(4, trace, "setmulti"); card = (struct lcs_card *) dev->priv; - if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) { + if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) schedule_work(&card->kernel_thread_starter); - } } #endif /* CONFIG_IP_MULTICAST */ @@ -1459,6 +1458,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer) lcs_release_buffer(channel, buffer); card = (struct lcs_card *) ((char *) channel - offsetof(struct lcs_card, write)); + if (netif_queue_stopped(card->dev)) + netif_wake_queue(card->dev); spin_lock(&card->lock); card->tx_emitted--; if (card->tx_emitted <= 0 && card->tx_buffer != NULL) @@ -1478,6 +1479,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, struct net_device *dev) { struct lcs_header *header; + int rc = 0; LCS_DBF_TEXT(5, trace, "hardxmit"); if (skb == NULL) { @@ -1492,10 +1494,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, card->stats.tx_carrier_errors++; return 0; } - if (netif_queue_stopped(dev) ) { - card->stats.tx_dropped++; - return -EBUSY; - } + netif_stop_queue(card->dev); + spin_lock(&card->lock); if (card->tx_buffer != NULL && card->tx_buffer->count + sizeof(struct lcs_header) + skb->len + sizeof(u16) > LCS_IOBUFFERSIZE) @@ -1506,7 +1506,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, card->tx_buffer = lcs_get_buffer(&card->write); if (card->tx_buffer == NULL) { card->stats.tx_dropped++; - return -EBUSY; + rc = -EBUSY; + goto out; } card->tx_buffer->callback = lcs_txbuffer_cb; card->tx_buffer->count = 0; @@ -1518,13 +1519,18 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, header->type = card->lan_type; header->slot = card->portno; memcpy(header + 1, skb->data, skb->len); + spin_unlock(&card->lock); card->stats.tx_bytes += skb->len; card->stats.tx_packets++; dev_kfree_skb(skb); - if (card->tx_emitted <= 0) + netif_wake_queue(card->dev); + spin_lock(&card->lock); + if (card->tx_emitted <= 0 && card->tx_buffer != NULL) /* If this is the first tx buffer emit it immediately. */ __lcs_emit_txbuffer(card); - return 0; +out: + spin_unlock(&card->lock); + return rc; } static int @@ -1535,9 +1541,7 @@ lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) LCS_DBF_TEXT(5, trace, "pktxmit"); card = (struct lcs_card *) dev->priv; - spin_lock(&card->lock); rc = __lcs_start_xmit(card, skb, dev); - spin_unlock(&card->lock); return rc; } @@ -2319,7 +2323,6 @@ __init lcs_init_module(void) PRINT_ERR("Initialization failed\n"); return rc; } - return 0; } diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 08e60ad43916..2fad5e40c2e4 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -95,7 +95,7 @@ do { \ */ #define LCS_ILLEGAL_OFFSET 0xffff #define LCS_IOBUFFERSIZE 0x5000 -#define LCS_NUM_BUFFS 8 /* needs to be power of 2 */ +#define LCS_NUM_BUFFS 32 /* needs to be power of 2 */ #define LCS_MAC_LENGTH 6 #define LCS_INVALID_PORT_NO -1 #define LCS_LANCMD_TIMEOUT_DEFAULT 5 -- cgit v1.2.2 From 66cc5d5aee1ea427b3aeacdabd006a4195c81eee Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Tue, 7 Feb 2006 17:04:38 +0100 Subject: [PATCH] s390: some qeth driver fixes [patch 2/2] s390: some qeth driver fixes From: Frank Pavlic - fixed kernel panic when using EDDP support in Layer 2 mode - NULL pointer exception in qeth_set_offline fixed. - setting EDDP in Layer 2 mode did not set NETIF_F_(SG/TSO) flags when device became online. - use sscanf for parsing and converting IPv4 addresses from string to __u8 values. - qeth_string_to_ipaddr6 fixed. in case of double colon the converted IPv6 address out from the string was not correct in previous implementation. Signed-off-by: Frank Pavlic diffstat: qeth.h | 112 +++++++++++++++++++++++++----------------------------------- qeth_eddp.c | 11 ++++- qeth_main.c | 17 +++------ 3 files changed, 63 insertions(+), 77 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth.h | 112 ++++++++++++++++++------------------------- drivers/s390/net/qeth_eddp.c | 11 ++++- drivers/s390/net/qeth_main.c | 17 +++---- 3 files changed, 63 insertions(+), 77 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 9a064d4727ad..4df0fcd7b10b 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -1075,16 +1075,6 @@ qeth_get_qdio_q_format(struct qeth_card *card) } } -static inline int -qeth_isdigit(char * buf) -{ - while (*buf) { - if (!isdigit(*buf++)) - return 0; - } - return 1; -} - static inline int qeth_isxdigit(char * buf) { @@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf) static inline int qeth_string_to_ipaddr4(const char *buf, __u8 *addr) { - const char *start, *end; - char abuf[4]; - char *tmp; - int len; - int i; - - start = buf; - for (i = 0; i < 4; i++) { - if (i == 3) { - end = strchr(start,0xa); - if (end) - len = end - start; - else - len = strlen(start); - } - else { - end = strchr(start, '.'); - len = end - start; - } - if ((len <= 0) || (len > 3)) - return -EINVAL; - memset(abuf, 0, 4); - strncpy(abuf, start, len); - if (!qeth_isdigit(abuf)) + int count = 0, rc = 0; + int in[4]; + + rc = sscanf(buf, "%d.%d.%d.%d%n", + &in[0], &in[1], &in[2], &in[3], &count); + if (rc != 4 || count) + return -EINVAL; + for (count = 0; count < 4; count++) { + if (in[count] > 255) return -EINVAL; - addr[i] = simple_strtoul(abuf, &tmp, 10); - start = end + 1; + addr[count] = in[count]; } return 0; } @@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf) static inline int qeth_string_to_ipaddr6(const char *buf, __u8 *addr) { - const char *start, *end; - u16 *tmp_addr; - char abuf[5]; - char *tmp; - int len; - int i; - - tmp_addr = (u16 *)addr; - start = buf; - for (i = 0; i < 8; i++) { - if (i == 7) { - end = strchr(start,0xa); - if (end) - len = end - start; - else - len = strlen(start); - } - else { - end = strchr(start, ':'); - len = end - start; + char *end, *start; + __u16 *in; + char num[5]; + int num2, cnt, out, found, save_cnt; + unsigned short in_tmp[8] = {0, }; + + cnt = out = found = save_cnt = num2 = 0; + end = start = (char *) buf; + in = (__u16 *) addr; + memset(in, 0, 16); + while (end) { + end = strchr(end,':'); + if (end == NULL) { + end = (char *)buf + (strlen(buf)); + out = 1; + } + if ((end - start)) { + memset(num, 0, 5); + memcpy(num, start, end - start); + if (!qeth_isxdigit(num)) + return -EINVAL; + sscanf(start, "%x", &num2); + if (found) + in_tmp[save_cnt++] = num2; + else + in[cnt++] = num2; + if (out) + break; + } else { + if (found) + return -EINVAL; + found = 1; } - if ((len <= 0) || (len > 4)) - return -EINVAL; - memset(abuf, 0, 5); - strncpy(abuf, start, len); - if (!qeth_isxdigit(abuf)) - return -EINVAL; - tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); - start = end + 1; - } + start = ++end; + } + cnt = 7; + while (save_cnt) + in[cnt--] = in_tmp[--save_cnt]; return 0; } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index b02313127780..82cb4af2f0e7 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) for (i = 0; i < ctx->num_pages; ++i) free_page((unsigned long)ctx->pages[i]); kfree(ctx->pages); - if (ctx->elements != NULL) - kfree(ctx->elements); + kfree(ctx->elements); kfree(ctx); } @@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, QETH_DBF_TEXT(trace, 5, "eddpftcp"); eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; + if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { + eddp->skb_offset += sizeof(struct ethhdr); +#ifdef CONFIG_QETH_VLAN + if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) + eddp->skb_offset += VLAN_HLEN; +#endif /* CONFIG_QETH_VLAN */ + } tcph = eddp->skb->h.th; while (eddp->skb_offset < eddp->skb->len) { data_len = min((int)skb_shinfo(eddp->skb)->tso_size, @@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, return -ENOMEM; } if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { + skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr); memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); #ifdef CONFIG_QETH_VLAN if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 410abeada6c4..dba7f7f02e79 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) QETH_DBF_TEXT(setup, 3, "setoffl"); QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); - netif_carrier_off(card->dev); + if (card->dev && netif_carrier_ok(card->dev)) + netif_carrier_off(card->dev); recover_flag = card->state; if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ PRINT_WARN("Stopping card %s interrupted by user!\n", @@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data) spin_unlock_irqrestore(&reply->card->lock, flags); } + static struct qeth_ipa_cmd * qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) { @@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) QETH_CARD_IFNAME(card), card->info.chpid); card->lan_online = 0; - netif_carrier_off(card->dev); + if (card->dev && netif_carrier_ok(card->dev)) + netif_carrier_off(card->dev); return NULL; case IPA_CMD_STARTLAN: PRINT_INFO("Link reestablished on %s " @@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev) if (card->info.type == QETH_CARD_TYPE_OSN) return ; - QETH_DBF_TEXT(trace,3,"setmulti"); + QETH_DBF_TEXT(trace, 3, "setmulti"); qeth_delete_mc_addresses(card); if (card->options.layer2) { qeth_layer2_add_multicast(card); @@ -5579,7 +5582,6 @@ out: return; if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) schedule_work(&card->kernel_thread_starter); - } static int @@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card) card->lan_online = 1; if (card->info.type==QETH_CARD_TYPE_OSN) goto out; + qeth_set_large_send(card, card->options.large_send); if (card->options.layer2) { card->dev->features |= NETIF_F_HW_VLAN_FILTER | @@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card) #endif goto out; } - if ((card->options.large_send == QETH_LARGE_SEND_EDDP) || - (card->options.large_send == QETH_LARGE_SEND_TSO)) - card->dev->features |= NETIF_F_TSO | NETIF_F_SG; - else - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); - if ((rc = qeth_setadapter_parms(card))) QETH_DBF_TEXT_(setup, 2, "2err%d", rc); if ((rc = qeth_start_ipassists(card))) -- cgit v1.2.2 From 6d751c43b29deb1d990fb9644c13ca941c9d1305 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 17 Feb 2006 13:52:45 -0800 Subject: [PATCH] s390: ccw device disbanding If __ccw_device_disband_start() fails to initiate disbanding, it should finish with ccw_device_disband_done() (which leaves the device in offline state) instead of ccw_device_verify_done() (which leaves the device in online state). Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/device_pgid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index d2a5b04d7cba..85b1020a1fcc 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -405,7 +405,7 @@ __ccw_device_disband_start(struct ccw_device *cdev) cdev->private->iretry = 5; cdev->private->imask >>= 1; } - ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV); + ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV); } /* -- cgit v1.2.2 From 6cadb78b3bec0a439a99db8fb550dc568e924ae6 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 17 Feb 2006 13:52:49 -0800 Subject: [PATCH] s390: fix assignment instead of check in ccw_device_set_online() Fix assignment instead of check in ccw_device_set_online(). Also remove unneeded assignment in ccw_device_do_sense(). Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/device.c | 2 +- drivers/s390/cio/device_status.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 062fb100d94c..afc4e88551ad 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -359,7 +359,7 @@ ccw_device_set_online(struct ccw_device *cdev) else pr_debug("ccw_device_offline returned %d, device %s\n", ret, cdev->dev.bus_id); - return (ret = 0) ? -ENODEV : ret; + return (ret == 0) ? -ENODEV : ret; } static ssize_t diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index dad4dd9887c9..6c762b43f921 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c @@ -317,7 +317,6 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb) /* * We have ending status but no sense information. Do a basic sense. */ - sch = to_subchannel(cdev->dev.parent); sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE; sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw); sch->sense_ccw.count = SENSE_MAX_COUNT; -- cgit v1.2.2 From 15c73691780252a5571bfa7902b4dc227ec66c84 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Mon, 20 Feb 2006 18:28:12 -0800 Subject: [PATCH] s390: V=V qdio fixes Using FCP devices with V=V support, the input queue stalled when CCQ 97 had been returned in qdio_do_eqbs. When this happen we have to reissue the eqbs instruction. Another bug was when V=V was enabled we checked if hardware has SIGA-sync support. If not we returned with 0 from tiqdio_is_inbound_q_done. Thus qdio lost initiative on FCP devices and input queue stalled. Running devices in V=V there is no SIGA-sync support but nevertheless we have to process tiqdio_is_inbound_q_done either. Signed-off-by: Frank Pavlic Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/qdio.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 45ce032772f4..9ed37dc9a1b0 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -165,8 +165,13 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, q_no = q->q_no; if(!q->is_input_q) q_no += irq->no_input_qs; +again: ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); rc = qdio_check_ccq(q, ccq); + if (rc == 1) { + QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); + goto again; + } if (rc < 0) { QDIO_DBF_TEXT2(1,trace,"eqberr"); sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no); @@ -195,8 +200,13 @@ qdio_do_sqbs(struct qdio_q *q, unsigned char state, q_no = q->q_no; if(!q->is_input_q) q_no += irq->no_input_qs; +again: ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt); rc = qdio_check_ccq(q, ccq); + if (rc == 1) { + QDIO_DBF_TEXT5(1,trace,"sqAGAIN"); + goto again; + } if (rc < 0) { QDIO_DBF_TEXT3(1,trace,"sqberr"); sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no); @@ -1187,8 +1197,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) if (!no_used) return 1; - - if (!q->siga_sync) + if (!q->siga_sync && !irq->is_qebsm) /* we'll check for more primed buffers in qeth_stop_polling */ return 0; if (irq->is_qebsm) { -- cgit v1.2.2 From aa88861fc3184a7d830954661dd281de4ae8d2ba Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 20 Feb 2006 18:28:13 -0800 Subject: [PATCH] s390: dasd reference counting When using the dasd diag discipline, the base discipline module (eckd or fba) can be unloaded, even though the dasd driver requires both discipline modules (base and diag) to work correctly. Implement reference counting for both base and diag discipline modules in order to fix this. Signed-off-by: Peter Oberparleiter Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 21 ++++++++++++++++++++- drivers/s390/block/dasd_int.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 08c88fcd8963..06bb992a4c6c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -156,7 +156,12 @@ dasd_state_known_to_new(struct dasd_device * device) /* disable extended error reporting for this device */ dasd_disable_eer(device); /* Forget the discipline information. */ + if (device->discipline) + module_put(device->discipline->owner); device->discipline = NULL; + if (device->base_discipline) + module_put(device->base_discipline->owner); + device->base_discipline = NULL; device->state = DASD_STATE_NEW; dasd_free_queue(device); @@ -1880,9 +1885,10 @@ dasd_generic_remove (struct ccw_device *cdev) */ int dasd_generic_set_online (struct ccw_device *cdev, - struct dasd_discipline *discipline) + struct dasd_discipline *base_discipline) { + struct dasd_discipline *discipline; struct dasd_device *device; int rc; @@ -1890,6 +1896,7 @@ dasd_generic_set_online (struct ccw_device *cdev, if (IS_ERR(device)) return PTR_ERR(device); + discipline = base_discipline; if (device->features & DASD_FEATURE_USEDIAG) { if (!dasd_diag_discipline_pointer) { printk (KERN_WARNING @@ -1901,6 +1908,16 @@ dasd_generic_set_online (struct ccw_device *cdev, } discipline = dasd_diag_discipline_pointer; } + if (!try_module_get(base_discipline->owner)) { + dasd_delete_device(device); + return -EINVAL; + } + if (!try_module_get(discipline->owner)) { + module_put(base_discipline->owner); + dasd_delete_device(device); + return -EINVAL; + } + device->base_discipline = base_discipline; device->discipline = discipline; rc = discipline->check_device(device); @@ -1909,6 +1926,8 @@ dasd_generic_set_online (struct ccw_device *cdev, "dasd_generic couldn't online device %s " "with discipline %s rc=%i\n", cdev->dev.bus_id, discipline->name, rc); + module_put(discipline->owner); + module_put(base_discipline->owner); dasd_delete_device(device); return rc; } diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index d1b08fa13fd2..5efac1b97ece 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -321,6 +321,7 @@ struct dasd_device { /* Device discipline stuff. */ struct dasd_discipline *discipline; + struct dasd_discipline *base_discipline; char *private; /* Device state and target state. */ -- cgit v1.2.2 From 49d9c81a699b57a5b6488f3a761669d05e116588 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 20 Feb 2006 18:28:14 -0800 Subject: [PATCH] s390: revert dasd eer module Revert dasd eer module until we have a common understanding of how the interface should be. Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/Kconfig | 14 +- drivers/s390/block/Makefile | 2 - drivers/s390/block/dasd.c | 76 +-- drivers/s390/block/dasd_3990_erp.c | 3 - drivers/s390/block/dasd_eckd.h | 1 - drivers/s390/block/dasd_eer.c | 1090 ------------------------------------ drivers/s390/block/dasd_int.h | 37 -- 7 files changed, 4 insertions(+), 1219 deletions(-) delete mode 100644 drivers/s390/block/dasd_eer.c (limited to 'drivers/s390') diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 6912399d0937..6f50cc9323d9 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -55,21 +55,13 @@ config DASD_DIAG Disks under VM. If you are not running under VM or unsure what it is, say "N". -config DASD_EER - tristate "Extended error reporting (EER)" - depends on DASD - help - This driver provides a character device interface to the - DASD extended error reporting. This is only needed if you want to - use applications written for the EER facility. - config DASD_CMB tristate "Compatibility interface for DASD channel measurement blocks" depends on DASD help - This driver provides an additional interface to the channel - measurement facility, which is normally accessed though sysfs, with - a set of ioctl functions specific to the dasd driver. + This driver provides an additional interface to the channel measurement + facility, which is normally accessed though sysfs, with a set of + ioctl functions specific to the dasd driver. This is only needed if you want to use applications written for linux-2.4 dasd channel measurement facility interface. diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 0c0d871e8f51..58c6780134f7 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile @@ -5,7 +5,6 @@ dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o dasd_diag_mod-objs := dasd_diag.o -dasd_eer_mod-objs := dasd_eer.o dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ dasd_genhd.o dasd_erp.o @@ -14,6 +13,5 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o obj-$(CONFIG_DASD_CMB) += dasd_cmb.o -obj-$(CONFIG_DASD_EER) += dasd_eer.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o obj-$(CONFIG_DCSSBLK) += dcssblk.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 06bb992a4c6c..af1d5b404cee 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -58,7 +57,6 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static void dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(void *data); -static void dasd_disable_eer(struct dasd_device *device); /* * SECTION: Operations on the device structure. @@ -153,8 +151,6 @@ dasd_state_new_to_known(struct dasd_device *device) static inline void dasd_state_known_to_new(struct dasd_device * device) { - /* disable extended error reporting for this device */ - dasd_disable_eer(device); /* Forget the discipline information. */ if (device->discipline) module_put(device->discipline->owner); @@ -876,9 +872,6 @@ dasd_handle_state_change_pending(struct dasd_device *device) struct dasd_ccw_req *cqr; struct list_head *l, *n; - /* first of all call extended error reporting */ - dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL); - device->stopped &= ~DASD_STOPPED_PENDING; /* restart all 'running' IO on queue */ @@ -1098,19 +1091,6 @@ restart: } goto restart; } - - /* first of all call extended error reporting */ - if (device->eer && cqr->status == DASD_CQR_FAILED) { - dasd_write_eer_trigger(DASD_EER_FATALERROR, - device, cqr); - - /* restart request */ - cqr->status = DASD_CQR_QUEUED; - cqr->retries = 255; - device->stopped |= DASD_STOPPED_QUIESCE; - goto restart; - } - /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); @@ -1248,8 +1228,7 @@ __dasd_start_head(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); /* check FAILFAST */ if (device->stopped & ~DASD_STOPPED_PENDING && - test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && - (!device->eer)) { + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { cqr->status = DASD_CQR_FAILED; dasd_schedule_bh(device); } @@ -2005,9 +1984,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: case CIO_NO_PATH: - /* first of all call extended error reporting */ - dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL); - if (device->state < DASD_STATE_BASIC) break; /* Device is active. We want to keep it. */ @@ -2065,51 +2041,6 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) put_driver(drv); } -/* - * notifications for extended error reports - */ -static struct notifier_block *dasd_eer_chain; - -int -dasd_register_eer_notifier(struct notifier_block *nb) -{ - return notifier_chain_register(&dasd_eer_chain, nb); -} - -int -dasd_unregister_eer_notifier(struct notifier_block *nb) -{ - return notifier_chain_unregister(&dasd_eer_chain, nb); -} - -/* - * Notify the registered error reporting module of a problem - */ -void -dasd_write_eer_trigger(unsigned int id, struct dasd_device *device, - struct dasd_ccw_req *cqr) -{ - if (device->eer) { - struct dasd_eer_trigger temp; - temp.id = id; - temp.device = device; - temp.cqr = cqr; - notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER, - (void *)&temp); - } -} - -/* - * Tell the registered error reporting module to disable error reporting for - * a given device and to cleanup any private data structures on that device. - */ -static void -dasd_disable_eer(struct dasd_device *device) -{ - notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device); -} - - static int __init dasd_init(void) { @@ -2191,11 +2122,6 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); EXPORT_SYMBOL_GPL(dasd_generic_auto_online); -EXPORT_SYMBOL(dasd_register_eer_notifier); -EXPORT_SYMBOL(dasd_unregister_eer_notifier); -EXPORT_SYMBOL(dasd_write_eer_trigger); - - /* * 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/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c811380b9079..4ee0f934e325 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1108,9 +1108,6 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x0B: DEV_MESSAGE(KERN_WARNING, device, "%s", "FORMAT F - Volume is suspended duplex"); - /* call extended error reporting (EER) */ - dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device, - erp->refers); break; case 0x0C: DEV_MESSAGE(KERN_WARNING, device, "%s", diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index e15dd7978050..bc3823d35223 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -29,7 +29,6 @@ #define DASD_ECKD_CCW_PSF 0x27 #define DASD_ECKD_CCW_RSSD 0x3e #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 -#define DASD_ECKD_CCW_SNSS 0x54 #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 #define DASD_ECKD_CCW_WRITE_MT 0x85 #define DASD_ECKD_CCW_READ_MT 0x86 diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c deleted file mode 100644 index f70cd7716b24..000000000000 --- a/drivers/s390/block/dasd_eer.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * character device driver for extended error reporting - * - * - * Copyright (C) 2005 IBM Corporation - * extended error reporting for DASD ECKD devices - * Author(s): Stefan Weinhuber - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "dasd_int.h" -#include "dasd_eckd.h" - - -MODULE_LICENSE("GPL"); - -MODULE_AUTHOR("Stefan Weinhuber "); -MODULE_DESCRIPTION("DASD extended error reporting module"); - - -#ifdef PRINTK_HEADER -#undef PRINTK_HEADER -#endif /* PRINTK_HEADER */ -#define PRINTK_HEADER "dasd(eer):" - - - - - -/*****************************************************************************/ -/* the internal buffer */ -/*****************************************************************************/ - -/* - * The internal buffer is meant to store obaque blobs of data, so it doesn't - * know of higher level concepts like triggers. - * It consists of a number of pages that are used as a ringbuffer. Each data - * blob is stored in a simple record that consists of an integer, which - * contains the size of the following data, and the data bytes themselfes. - * - * To allow for multiple independent readers we create one internal buffer - * each time the device is opened and destroy the buffer when the file is - * closed again. - * - * One record can be written to a buffer by using the functions - * - dasd_eer_start_record (one time per record to write the size to the buffer - * and reserve the space for the data) - * - dasd_eer_write_buffer (one or more times per record to write the data) - * The data can be written in several steps but you will have to compute - * the total size up front for the invocation of dasd_eer_start_record. - * If the ringbuffer is full, dasd_eer_start_record will remove the required - * number of old records. - * - * A record is typically read in two steps, first read the integer that - * specifies the size of the following data, then read the data. - * Both can be done by - * - dasd_eer_read_buffer - * - * For all mentioned functions you need to get the bufferlock first and keep it - * until a complete record is written or read. - */ - - -/* - * Alle information necessary to keep track of an internal buffer is kept in - * a struct eerbuffer. The buffer specific to a file pointer is strored in - * the private_data field of that file. To be able to write data to all - * existing buffers, each buffer is also added to the bufferlist. - * If the user doesn't want to read a complete record in one go, we have to - * keep track of the rest of the record. residual stores the number of bytes - * that are still to deliver. If the rest of the record is invalidated between - * two reads then residual will be set to -1 so that the next read will fail. - * All entries in the eerbuffer structure are protected with the bufferlock. - * To avoid races between writing to a buffer on the one side and creating - * and destroying buffers on the other side, the bufferlock must also be used - * to protect the bufferlist. - */ - -struct eerbuffer { - struct list_head list; - char **buffer; - int buffersize; - int buffer_page_count; - int head; - int tail; - int residual; -}; - -LIST_HEAD(bufferlist); - -static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED; - -DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue); - -/* - * How many free bytes are available on the buffer. - * needs to be called with bufferlock held - */ -static int -dasd_eer_get_free_bytes(struct eerbuffer *eerb) -{ - if (eerb->head < eerb->tail) { - return eerb->tail - eerb->head - 1; - } else - return eerb->buffersize - eerb->head + eerb->tail -1; -} - -/* - * How many bytes of buffer space are used. - * needs to be called with bufferlock held - */ -static int -dasd_eer_get_filled_bytes(struct eerbuffer *eerb) -{ - - if (eerb->head >= eerb->tail) { - return eerb->head - eerb->tail; - } else - return eerb->buffersize - eerb->tail + eerb->head; -} - -/* - * The dasd_eer_write_buffer function just copies count bytes of data - * to the buffer. Make sure to call dasd_eer_start_record first, to - * make sure that enough free space is available. - * needs to be called with bufferlock held - */ -static void -dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data) -{ - - unsigned long headindex,localhead; - unsigned long rest, len; - char *nextdata; - - nextdata = data; - rest = count; - while (rest > 0) { - headindex = eerb->head / PAGE_SIZE; - localhead = eerb->head % PAGE_SIZE; - len = min(rest, (PAGE_SIZE - localhead)); - memcpy(eerb->buffer[headindex]+localhead, nextdata, len); - nextdata += len; - rest -= len; - eerb->head += len; - if ( eerb->head == eerb->buffersize ) - eerb->head = 0; /* wrap around */ - if (eerb->head > eerb->buffersize) { - MESSAGE(KERN_ERR, "%s", "runaway buffer head."); - BUG(); - } - } -} - -/* - * needs to be called with bufferlock held - */ -static int -dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data) -{ - - unsigned long tailindex,localtail; - unsigned long rest, len, finalcount; - char *nextdata; - - finalcount = min(count, dasd_eer_get_filled_bytes(eerb)); - nextdata = data; - rest = finalcount; - while (rest > 0) { - tailindex = eerb->tail / PAGE_SIZE; - localtail = eerb->tail % PAGE_SIZE; - len = min(rest, (PAGE_SIZE - localtail)); - memcpy(nextdata, eerb->buffer[tailindex]+localtail, len); - nextdata += len; - rest -= len; - eerb->tail += len; - if ( eerb->tail == eerb->buffersize ) - eerb->tail = 0; /* wrap around */ - if (eerb->tail > eerb->buffersize) { - MESSAGE(KERN_ERR, "%s", "runaway buffer tail."); - BUG(); - } - } - return finalcount; -} - -/* - * Whenever you want to write a blob of data to the internal buffer you - * have to start by using this function first. It will write the number - * of bytes that will be written to the buffer. If necessary it will remove - * old records to make room for the new one. - * needs to be called with bufferlock held - */ -static int -dasd_eer_start_record(struct eerbuffer *eerb, int count) -{ - int tailcount; - if (count + sizeof(count) > eerb->buffersize) - return -ENOMEM; - while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) { - if (eerb->residual > 0) { - eerb->tail += eerb->residual; - if (eerb->tail >= eerb->buffersize) - eerb->tail -= eerb->buffersize; - eerb->residual = -1; - } - dasd_eer_read_buffer(eerb, sizeof(tailcount), - (char*)(&tailcount)); - eerb->tail += tailcount; - if (eerb->tail >= eerb->buffersize) - eerb->tail -= eerb->buffersize; - } - dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count)); - - return 0; -}; - -/* - * release pages that are not used anymore - */ -static void -dasd_eer_free_buffer_pages(char **buf, int no_pages) -{ - int i; - - for (i = 0; i < no_pages; ++i) { - free_page((unsigned long)buf[i]); - } -} - -/* - * allocate a new set of memory pages - */ -static int -dasd_eer_allocate_buffer_pages(char **buf, int no_pages) -{ - int i; - - for (i = 0; i < no_pages; ++i) { - buf[i] = (char *) get_zeroed_page(GFP_KERNEL); - if (!buf[i]) { - dasd_eer_free_buffer_pages(buf, i); - return -ENOMEM; - } - } - return 0; -} - -/* - * empty the buffer by resetting head and tail - * In case there is a half read data blob in the buffer, we set residual - * to -1 to indicate that the remainder of the blob is lost. - */ -static void -dasd_eer_purge_buffer(struct eerbuffer *eerb) -{ - unsigned long flags; - - spin_lock_irqsave(&bufferlock, flags); - if (eerb->residual > 0) - eerb->residual = -1; - eerb->tail=0; - eerb->head=0; - spin_unlock_irqrestore(&bufferlock, flags); -} - -/* - * set the size of the buffer, newsize is the new number of pages to be used - * we don't try to copy any data back an forth, so any resize will also purge - * the buffer - */ -static int -dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize) -{ - int i, oldcount, reuse; - char **new; - char **old; - unsigned long flags; - - if (newsize < 1) - return -EINVAL; - if (eerb->buffer_page_count == newsize) { - /* documented behaviour is that any successfull invocation - * will purge all records */ - dasd_eer_purge_buffer(eerb); - return 0; - } - new = kmalloc(newsize*sizeof(char*), GFP_KERNEL); - if (!new) - return -ENOMEM; - - reuse=min(eerb->buffer_page_count, newsize); - for (i = 0; i < reuse; ++i) { - new[i] = eerb->buffer[i]; - } - if (eerb->buffer_page_count < newsize) { - if (dasd_eer_allocate_buffer_pages( - &new[eerb->buffer_page_count], - newsize - eerb->buffer_page_count)) { - kfree(new); - return -ENOMEM; - } - } - - spin_lock_irqsave(&bufferlock, flags); - old = eerb->buffer; - eerb->buffer = new; - if (eerb->residual > 0) - eerb->residual = -1; - eerb->tail = 0; - eerb->head = 0; - oldcount = eerb->buffer_page_count; - eerb->buffer_page_count = newsize; - spin_unlock_irqrestore(&bufferlock, flags); - - if (oldcount > newsize) { - for (i = newsize; i < oldcount; ++i) { - free_page((unsigned long)old[i]); - } - } - kfree(old); - - return 0; -} - - -/*****************************************************************************/ -/* The extended error reporting functionality */ -/*****************************************************************************/ - -/* - * When a DASD device driver wants to report an error, it calls the - * function dasd_eer_write_trigger (via a notifier mechanism) and gives the - * respective trigger ID as parameter. - * Currently there are four kinds of triggers: - * - * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems - * DASD_EER_PPRCSUSPEND: PPRC was suspended - * DASD_EER_NOPATH: There is no path to the device left. - * DASD_EER_STATECHANGE: The state of the device has changed. - * - * For the first three triggers all required information can be supplied by - * the caller. For these triggers a record is written by the function - * dasd_eer_write_standard_trigger. - * - * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE - * trigger, we have to gather the necessary sense data first. We cannot queue - * the necessary SNSS (sense subsystem status) request immediatly, since we - * are likely to run in a deadlock situation. Instead, we schedule a - * work_struct that calls the function dasd_eer_sense_subsystem_status to - * create and start an SNSS request asynchronously. - * - * To avoid memory allocations at runtime, the necessary memory is allocated - * when the extended error reporting is enabled for a device (by - * dasd_eer_probe). There is one private eer data structure for each eer - * enabled DASD device. It contains memory for the work_struct, one SNSS cqr - * and a flags field that is used to coordinate the use of the cqr. The call - * to write a state change trigger can come in at any time, so we have one flag - * CQR_IN_USE that protects the cqr itself. When this flag indicates that the - * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a - * second request but sets the SNSS_REQUESTED flag instead. - * - * When the request is finished, the callback function dasd_eer_SNSS_cb - * is called. This function will invoke the function - * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also - * check the SNSS_REQUESTED flag and if it is set it will call - * dasd_eer_sense_subsystem_status again. - * - * To avoid race conditions during the handling of the lock, the flags must - * be protected by the snsslock. - */ - -struct dasd_eer_private { - struct dasd_ccw_req *cqr; - unsigned long flags; - struct work_struct worker; -}; - -static void dasd_eer_destroy(struct dasd_device *device, - struct dasd_eer_private *eer); -static int -dasd_eer_write_trigger(struct dasd_eer_trigger *trigger); -static void dasd_eer_sense_subsystem_status(void *data); -static int dasd_eer_notify(struct notifier_block *self, - unsigned long action, void *data); - -struct workqueue_struct *dasd_eer_workqueue; - -#define SNSS_DATA_SIZE 44 -static spinlock_t snsslock = SPIN_LOCK_UNLOCKED; - -#define DASD_EER_BUSID_SIZE 10 -struct dasd_eer_header { - __u32 total_size; - __u32 trigger; - __u64 tv_sec; - __u64 tv_usec; - char busid[DASD_EER_BUSID_SIZE]; -} __attribute__ ((packed)); - -static struct notifier_block dasd_eer_nb = { - .notifier_call = dasd_eer_notify, -}; - -/* - * flags for use with dasd_eer_private - */ -#define CQR_IN_USE 0 -#define SNSS_REQUESTED 1 - -/* - * This function checks if extended error reporting is available for a given - * dasd_device. If yes, then it creates and returns a struct dasd_eer, - * otherwise it returns an -EPERM error pointer. - */ -struct dasd_eer_private * -dasd_eer_probe(struct dasd_device *device) -{ - struct dasd_eer_private *private; - - if (!(device && device->discipline - && !strcmp(device->discipline->name, "ECKD"))) { - return ERR_PTR(-EPERM); - } - /* allocate the private data structure */ - private = (struct dasd_eer_private *)kmalloc( - sizeof(struct dasd_eer_private), GFP_KERNEL); - if (!private) { - return ERR_PTR(-ENOMEM); - } - INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status, - (void *)device); - private->cqr = dasd_kmalloc_request("ECKD", - 1 /* SNSS */ , - SNSS_DATA_SIZE , - device); - if (!private->cqr) { - kfree(private); - return ERR_PTR(-ENOMEM); - } - private->flags = 0; - return private; -}; - -/* - * If our private SNSS request is queued, remove it from the - * dasd ccw queue so we can free the requests memory. - */ -static void -dasd_eer_dequeue_SNSS_request(struct dasd_device *device, - struct dasd_eer_private *eer) -{ - struct list_head *lst, *nxt; - struct dasd_ccw_req *cqr, *erpcqr; - dasd_erp_fn_t erp_fn; - - spin_lock_irq(get_ccwdev_lock(device->cdev)); - list_for_each_safe(lst, nxt, &device->ccw_queue) { - cqr = list_entry(lst, struct dasd_ccw_req, list); - /* we are looking for two kinds or requests */ - /* first kind: our SNSS request: */ - if (cqr == eer->cqr) { - if (cqr->status == DASD_CQR_IN_IO) - device->discipline->term_IO(cqr); - list_del(&cqr->list); - break; - } - /* second kind: ERP requests for our SNSS request */ - if (cqr->refers) { - /* If this erp request chain ends in our cqr, then */ - /* cal the erp_postaction to clean it up */ - erpcqr = cqr; - while (erpcqr->refers) { - erpcqr = erpcqr->refers; - } - if (erpcqr == eer->cqr) { - erp_fn = device->discipline->erp_postaction( - cqr); - erp_fn(cqr); - } - continue; - } - } - spin_unlock_irq(get_ccwdev_lock(device->cdev)); -} - -/* - * This function dismantles a struct dasd_eer that was created by - * dasd_eer_probe. Since we want to free our private data structure, - * we must make sure that the memory is not in use anymore. - * We have to flush the work queue and remove a possible SNSS request - * from the dasd queue. - */ -static void -dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer) -{ - flush_workqueue(dasd_eer_workqueue); - dasd_eer_dequeue_SNSS_request(device, eer); - dasd_kfree_request(eer->cqr, device); - kfree(eer); -}; - -/* - * enable the extended error reporting for a particular device - */ -static int -dasd_eer_enable_on_device(struct dasd_device *device) -{ - void *eer; - if (!device) - return -ENODEV; - if (device->eer) - return 0; - if (!try_module_get(THIS_MODULE)) { - return -EINVAL; - } - eer = (void *)dasd_eer_probe(device); - if (IS_ERR(eer)) { - module_put(THIS_MODULE); - return PTR_ERR(eer); - } - device->eer = eer; - return 0; -} - -/* - * enable the extended error reporting for a particular device - */ -static int -dasd_eer_disable_on_device(struct dasd_device *device) -{ - struct dasd_eer_private *eer = device->eer; - - if (!device) - return -ENODEV; - if (!device->eer) - return 0; - device->eer = NULL; - dasd_eer_destroy(device,eer); - module_put(THIS_MODULE); - - return 0; -} - -/* - * Set extended error reporting (eer) - * Note: This will be registered as a DASD ioctl, to be called on DASD devices. - */ -static int -dasd_ioctl_set_eer(struct block_device *bdev, int no, long args) -{ - struct dasd_device *device; - int intval; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (bdev != bdev->bd_contains) - /* Error-reporting is not allowed for partitions */ - return -EINVAL; - if (get_user(intval, (int __user *) args)) - return -EFAULT; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - - intval = (intval != 0); - DEV_MESSAGE (KERN_DEBUG, device, - "set eer on device to %d", intval); - if (intval) - return dasd_eer_enable_on_device(device); - else - return dasd_eer_disable_on_device(device); -} - -/* - * Get value of extended error reporting. - * Note: This will be registered as a DASD ioctl, to be called on DASD devices. - */ -static int -dasd_ioctl_get_eer(struct block_device *bdev, int no, long args) -{ - struct dasd_device *device; - - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - return put_user((device->eer != NULL), (int __user *) args); -} - -/* - * The following function can be used for those triggers that have - * all necessary data available when the function is called. - * If the parameter cqr is not NULL, the chain of requests will be searched - * for valid sense data, and all valid sense data sets will be added to - * the triggers data. - */ -static int -dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device, - struct dasd_ccw_req *cqr) -{ - struct dasd_ccw_req *temp_cqr; - int data_size; - struct timeval tv; - struct dasd_eer_header header; - unsigned long flags; - struct eerbuffer *eerb; - - /* go through cqr chain and count the valid sense data sets */ - temp_cqr = cqr; - data_size = 0; - while (temp_cqr) { - if (temp_cqr->irb.esw.esw0.erw.cons) - data_size += 32; - temp_cqr = temp_cqr->refers; - } - - header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ - header.trigger = trigger; - do_gettimeofday(&tv); - header.tv_sec = tv.tv_sec; - header.tv_usec = tv.tv_usec; - strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); - - spin_lock_irqsave(&bufferlock, flags); - list_for_each_entry(eerb, &bufferlist, list) { - dasd_eer_start_record(eerb, header.total_size); - dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header)); - temp_cqr = cqr; - while (temp_cqr) { - if (temp_cqr->irb.esw.esw0.erw.cons) - dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw); - temp_cqr = temp_cqr->refers; - } - dasd_eer_write_buffer(eerb, 4,"EOR"); - } - spin_unlock_irqrestore(&bufferlock, flags); - - wake_up_interruptible(&dasd_eer_read_wait_queue); - - return 0; -} - -/* - * This function writes a DASD_EER_STATECHANGE trigger. - */ -static void -dasd_eer_write_SNSS_trigger(struct dasd_device *device, - struct dasd_ccw_req *cqr) -{ - int data_size; - int snss_rc; - struct timeval tv; - struct dasd_eer_header header; - unsigned long flags; - struct eerbuffer *eerb; - - snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; - if (snss_rc) - data_size = 0; - else - data_size = SNSS_DATA_SIZE; - - header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ - header.trigger = DASD_EER_STATECHANGE; - do_gettimeofday(&tv); - header.tv_sec = tv.tv_sec; - header.tv_usec = tv.tv_usec; - strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); - - spin_lock_irqsave(&bufferlock, flags); - list_for_each_entry(eerb, &bufferlist, list) { - dasd_eer_start_record(eerb, header.total_size); - dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header)); - if (!snss_rc) - dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data); - dasd_eer_write_buffer(eerb, 4,"EOR"); - } - spin_unlock_irqrestore(&bufferlock, flags); - - wake_up_interruptible(&dasd_eer_read_wait_queue); -} - -/* - * callback function for use with SNSS request - */ -static void -dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data) -{ - struct dasd_device *device; - struct dasd_eer_private *private; - unsigned long irqflags; - - device = (struct dasd_device *)data; - private = (struct dasd_eer_private *)device->eer; - dasd_eer_write_SNSS_trigger(device, cqr); - spin_lock_irqsave(&snsslock, irqflags); - if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) { - clear_bit(CQR_IN_USE, &private->flags); - spin_unlock_irqrestore(&snsslock, irqflags); - return; - }; - clear_bit(CQR_IN_USE, &private->flags); - spin_unlock_irqrestore(&snsslock, irqflags); - dasd_eer_sense_subsystem_status(device); - return; -} - -/* - * clean a used cqr before using it again - */ -static void -dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr) -{ - struct ccw1 *cpaddr = cqr->cpaddr; - void *data = cqr->data; - - memset(cqr, 0, sizeof(struct dasd_ccw_req)); - memset(cpaddr, 0, sizeof(struct ccw1)); - memset(data, 0, SNSS_DATA_SIZE); - cqr->cpaddr = cpaddr; - cqr->data = data; - strncpy((char *) &cqr->magic, "ECKD", 4); - ASCEBC((char *) &cqr->magic, 4); - set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); -} - -/* - * build and start an SNSS request - * This function is called from a work queue so we have to - * pass the dasd_device pointer as a void pointer. - */ -static void -dasd_eer_sense_subsystem_status(void *data) -{ - struct dasd_device *device; - struct dasd_eer_private *private; - struct dasd_ccw_req *cqr; - struct ccw1 *ccw; - unsigned long irqflags; - - device = (struct dasd_device *)data; - private = (struct dasd_eer_private *)device->eer; - if (!private) /* device not eer enabled any more */ - return; - cqr = private->cqr; - spin_lock_irqsave(&snsslock, irqflags); - if(test_and_set_bit(CQR_IN_USE, &private->flags)) { - set_bit(SNSS_REQUESTED, &private->flags); - spin_unlock_irqrestore(&snsslock, irqflags); - return; - }; - spin_unlock_irqrestore(&snsslock, irqflags); - dasd_eer_clean_SNSS_request(cqr); - cqr->device = device; - cqr->retries = 255; - cqr->expires = 10 * HZ; - - ccw = cqr->cpaddr; - ccw->cmd_code = DASD_ECKD_CCW_SNSS; - ccw->count = SNSS_DATA_SIZE; - ccw->flags = 0; - ccw->cda = (__u32)(addr_t)cqr->data; - - cqr->buildclk = get_clock(); - cqr->status = DASD_CQR_FILLED; - cqr->callback = dasd_eer_SNSS_cb; - cqr->callback_data = (void *)device; - dasd_add_request_head(cqr); - - return; -} - -/* - * This function is called for all triggers. It calls the appropriate - * function that writes the actual trigger records. - */ -static int -dasd_eer_write_trigger(struct dasd_eer_trigger *trigger) -{ - int rc; - struct dasd_eer_private *private = trigger->device->eer; - - switch (trigger->id) { - case DASD_EER_FATALERROR: - case DASD_EER_PPRCSUSPEND: - rc = dasd_eer_write_standard_trigger( - trigger->id, trigger->device, trigger->cqr); - break; - case DASD_EER_NOPATH: - rc = dasd_eer_write_standard_trigger( - trigger->id, trigger->device, NULL); - break; - case DASD_EER_STATECHANGE: - if (queue_work(dasd_eer_workqueue, &private->worker)) { - rc=0; - } else { - /* If the work_struct was already queued, it can't - * be queued again. But this is OK since we don't - * need to have it queued twice. - */ - rc = -EBUSY; - } - break; - default: /* unknown trigger, so we write it without any sense data */ - rc = dasd_eer_write_standard_trigger( - trigger->id, trigger->device, NULL); - break; - } - return rc; -} - -/* - * This function is registered with the dasd device driver and gets called - * for all dasd eer notifications. - */ -static int dasd_eer_notify(struct notifier_block *self, - unsigned long action, void *data) -{ - switch (action) { - case DASD_EER_DISABLE: - dasd_eer_disable_on_device((struct dasd_device *)data); - break; - case DASD_EER_TRIGGER: - dasd_eer_write_trigger((struct dasd_eer_trigger *)data); - break; - } - return NOTIFY_OK; -} - - -/*****************************************************************************/ -/* the device operations */ -/*****************************************************************************/ - -/* - * On the one side we need a lock to access our internal buffer, on the - * other side a copy_to_user can sleep. So we need to copy the data we have - * to transfer in a readbuffer, which is protected by the readbuffer_mutex. - */ -static char readbuffer[PAGE_SIZE]; -DECLARE_MUTEX(readbuffer_mutex); - - -static int -dasd_eer_open(struct inode *inp, struct file *filp) -{ - struct eerbuffer *eerb; - unsigned long flags; - - eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL); - eerb->head = 0; - eerb->tail = 0; - eerb->residual = 0; - eerb->buffer_page_count = 1; - eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; - eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*), - GFP_KERNEL); - if (!eerb->buffer) - return -ENOMEM; - if (dasd_eer_allocate_buffer_pages(eerb->buffer, - eerb->buffer_page_count)) { - kfree(eerb->buffer); - return -ENOMEM; - } - filp->private_data = eerb; - spin_lock_irqsave(&bufferlock, flags); - list_add(&eerb->list, &bufferlist); - spin_unlock_irqrestore(&bufferlock, flags); - - return nonseekable_open(inp,filp); -} - -static int -dasd_eer_close(struct inode *inp, struct file *filp) -{ - struct eerbuffer *eerb; - unsigned long flags; - - eerb = (struct eerbuffer *)filp->private_data; - spin_lock_irqsave(&bufferlock, flags); - list_del(&eerb->list); - spin_unlock_irqrestore(&bufferlock, flags); - dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count); - kfree(eerb->buffer); - kfree(eerb); - - return 0; -} - -static long -dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int intval; - struct eerbuffer *eerb; - - eerb = (struct eerbuffer *)filp->private_data; - switch (cmd) { - case DASD_EER_PURGE: - dasd_eer_purge_buffer(eerb); - return 0; - case DASD_EER_SETBUFSIZE: - if (get_user(intval, (int __user *)arg)) - return -EFAULT; - return dasd_eer_resize_buffer(eerb, intval); - default: - return -ENOIOCTLCMD; - } -} - -static ssize_t -dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) -{ - int tc,rc; - int tailcount,effective_count; - unsigned long flags; - struct eerbuffer *eerb; - - eerb = (struct eerbuffer *)filp->private_data; - if(down_interruptible(&readbuffer_mutex)) - return -ERESTARTSYS; - - spin_lock_irqsave(&bufferlock, flags); - - if (eerb->residual < 0) { /* the remainder of this record */ - /* has been deleted */ - eerb->residual = 0; - spin_unlock_irqrestore(&bufferlock, flags); - up(&readbuffer_mutex); - return -EIO; - } else if (eerb->residual > 0) { - /* OK we still have a second half of a record to deliver */ - effective_count = min(eerb->residual, (int)count); - eerb->residual -= effective_count; - } else { - tc = 0; - while (!tc) { - tc = dasd_eer_read_buffer(eerb, - sizeof(tailcount), (char*)(&tailcount)); - if (!tc) { - /* no data available */ - spin_unlock_irqrestore(&bufferlock, flags); - up(&readbuffer_mutex); - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - rc = wait_event_interruptible( - dasd_eer_read_wait_queue, - eerb->head != eerb->tail); - if (rc) { - return rc; - } - if(down_interruptible(&readbuffer_mutex)) - return -ERESTARTSYS; - spin_lock_irqsave(&bufferlock, flags); - } - } - WARN_ON(tc != sizeof(tailcount)); - effective_count = min(tailcount,(int)count); - eerb->residual = tailcount - effective_count; - } - - tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer); - WARN_ON(tc != effective_count); - - spin_unlock_irqrestore(&bufferlock, flags); - - if (copy_to_user(buf, readbuffer, effective_count)) { - up(&readbuffer_mutex); - return -EFAULT; - } - - up(&readbuffer_mutex); - return effective_count; -} - -static unsigned int -dasd_eer_poll (struct file *filp, poll_table *ptable) -{ - unsigned int mask; - unsigned long flags; - struct eerbuffer *eerb; - - eerb = (struct eerbuffer *)filp->private_data; - poll_wait(filp, &dasd_eer_read_wait_queue, ptable); - spin_lock_irqsave(&bufferlock, flags); - if (eerb->head != eerb->tail) - mask = POLLIN | POLLRDNORM ; - else - mask = 0; - spin_unlock_irqrestore(&bufferlock, flags); - return mask; -} - -static struct file_operations dasd_eer_fops = { - .open = &dasd_eer_open, - .release = &dasd_eer_close, - .unlocked_ioctl = &dasd_eer_ioctl, - .compat_ioctl = &dasd_eer_ioctl, - .read = &dasd_eer_read, - .poll = &dasd_eer_poll, - .owner = THIS_MODULE, -}; - -static struct miscdevice dasd_eer_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "dasd_eer", - .fops = &dasd_eer_fops, -}; - - -/*****************************************************************************/ -/* Init and exit */ -/*****************************************************************************/ - -static int -__init dasd_eer_init(void) -{ - int rc; - - dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer"); - if (!dasd_eer_workqueue) { - MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not " - "create workqueue \n"); - rc = -ENOMEM; - goto out; - } - - rc = dasd_register_eer_notifier(&dasd_eer_nb); - if (rc) { - MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " - "register error reporting"); - goto queue; - } - - dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer); - dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer); - - /* we don't need our own character device, - * so we just register as misc device */ - rc = misc_register(&dasd_eer_dev); - if (rc) { - MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " - "register misc device"); - goto unregister; - } - - return 0; - -unregister: - dasd_unregister_eer_notifier(&dasd_eer_nb); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, - dasd_ioctl_set_eer); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, - dasd_ioctl_get_eer); -queue: - destroy_workqueue(dasd_eer_workqueue); -out: - return rc; - -} -module_init(dasd_eer_init); - -static void -__exit dasd_eer_exit(void) -{ - dasd_unregister_eer_notifier(&dasd_eer_nb); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, - dasd_ioctl_set_eer); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, - dasd_ioctl_get_eer); - destroy_workqueue(dasd_eer_workqueue); - - WARN_ON(misc_deregister(&dasd_eer_dev) != 0); -} -module_exit(dasd_eer_exit); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 5efac1b97ece..0592354cc604 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -275,34 +275,6 @@ struct dasd_discipline { extern struct dasd_discipline *dasd_diag_discipline_pointer; - -/* - * Notification numbers for extended error reporting notifications: - * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's - * eer pointer) is freed. The error reporting module needs to do all necessary - * cleanup steps. - * The DASD_EER_TRIGGER notification sends the actual error reports (triggers). - */ -#define DASD_EER_DISABLE 0 -#define DASD_EER_TRIGGER 1 - -/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */ -#define DASD_EER_FATALERROR 1 -#define DASD_EER_NOPATH 2 -#define DASD_EER_STATECHANGE 3 -#define DASD_EER_PPRCSUSPEND 4 - -/* - * The dasd_eer_trigger structure contains all data that we need to send - * along with an DASD_EER_TRIGGER notification. - */ -struct dasd_eer_trigger { - unsigned int id; - struct dasd_device *device; - struct dasd_ccw_req *cqr; -}; - - struct dasd_device { /* Block device stuff. */ struct gendisk *gdp; @@ -316,9 +288,6 @@ struct dasd_device { unsigned long flags; /* per device flags */ unsigned short features; /* copy of devmap-features (read-only!) */ - /* extended error reporting stuff (eer) */ - void *eer; - /* Device discipline stuff. */ struct dasd_discipline *discipline; struct dasd_discipline *base_discipline; @@ -520,12 +489,6 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); int dasd_generic_set_offline (struct ccw_device *cdev); int dasd_generic_notify(struct ccw_device *, int); void dasd_generic_auto_online (struct ccw_driver *); -int dasd_register_eer_notifier(struct notifier_block *); -int dasd_unregister_eer_notifier(struct notifier_block *); -void dasd_write_eer_trigger(unsigned int , struct dasd_device *, - struct dasd_ccw_req *); - - /* externals in dasd_devmap.c */ extern int dasd_max_devindex; -- cgit v1.2.2 From 35dc2585fa32a2b300307ffa9f17122b13ccef97 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 2 Mar 2006 21:28:54 +0100 Subject: [SCSI] zfcp: correctly set this_id for hosts It fixes a bug in zfcp which provokes a race in scsi_scan.c. Finally this can lead to an Oops like: kernel BUG at fs/sysfs/symlink.c:87! Correctly set this_id for the host. Otherwise we provoke a race between scsi_target_reap_work and concurrent scsi_add_device. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9f6b4d7a46f3..a2de3c9afe49 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -68,7 +68,7 @@ struct zfcp_data zfcp_data = { eh_host_reset_handler: zfcp_scsi_eh_host_reset_handler, /* FIXME(openfcp): Tune */ can_queue: 4096, - this_id: 0, + this_id: -1, /* * FIXME: * one less? can zfcp_create_sbale cope with it? -- cgit v1.2.2 From 15730ddbf745fbda9001b8bbd71977ac66bf5f41 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 6 Mar 2006 15:43:02 -0800 Subject: [PATCH] s390: improve response code handling in chsc_enable_facility() Rather than checking for some known failures, check positively for the success response code 0x0001 and return -EIO for unrecognized failure response codes. Signed-off-by: Cornelia Huck Cc: Greg Smith Cc: Heiko Carstens Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chsc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 8cf9905d484b..f4183d660258 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1115,6 +1115,9 @@ chsc_enable_facility(int operation_code) goto out; } switch (sda_area->response.code) { + case 0x0001: /* everything ok */ + ret = 0; + break; case 0x0003: /* invalid request block */ case 0x0007: ret = -EINVAL; @@ -1123,6 +1126,8 @@ chsc_enable_facility(int operation_code) case 0x0101: /* facility not provided */ ret = -EOPNOTSUPP; break; + default: /* something went wrong */ + ret = -EIO; } out: free_page((unsigned long)sda_area); -- cgit v1.2.2 From fbcae7eafcf7dfb315602de935d7ca85574e5c11 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 7 Mar 2006 21:55:38 -0800 Subject: [PATCH] s390: iucv message limit for smsg The message limit on the iucv connect call for the smsg module is too low. Therefore increase the smsg message limit to 255. Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/net/smsgiucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index d6469baa7e16..72118ee68954 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -168,7 +168,7 @@ smsg_init(void) driver_unregister(&smsg_driver); return -EIO; /* better errno ? */ } - rc = iucv_connect (&smsg_pathid, 1, 0, "*MSG ", 0, 0, 0, 0, + rc = iucv_connect (&smsg_pathid, 255, 0, "*MSG ", 0, 0, 0, 0, smsg_handle, 0); if (rc) { printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG"); -- cgit v1.2.2 From 90f0094dc607abe384a412bfb7199fb667ab0735 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Tue, 7 Mar 2006 21:55:39 -0800 Subject: [PATCH] s390: dasd partition detection DASD allows to open a device as soon as gendisk is registered, which means the device is a fake device (capacity=0) and we do know nothing about blocksize and partitions at that point of time. In case the device is opened by someone, the bdev and inode creation is done with the fake device info and the following partition detection code is just using the wrong data. To avoid this modify the DASD state machine to make sure that the open is rejected until the device analysis is either finished or an unformatted device was detected. Signed-off-by: Horst Hummel Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 38 +++++++++++++++++++++++++++++--------- drivers/s390/block/dasd_genhd.c | 2 -- drivers/s390/block/dasd_int.h | 7 ++++--- drivers/s390/block/dasd_proc.c | 3 +++ 4 files changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index af1d5b404cee..33157c84d1d3 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -215,9 +215,10 @@ dasd_state_basic_to_known(struct dasd_device * device) * interrupt for this detection ccw uses the kernel event daemon to * trigger the call to dasd_change_state. All this is done in the * discipline code, see dasd_eckd.c. - * After the analysis ccw is done (do_analysis returned 0 or error) - * the block device is setup. Either a fake disk is added to allow - * formatting or a proper device request queue is created. + * After the analysis ccw is done (do_analysis returned 0) the block + * device is setup. + * In case the analysis returns an error, the device setup is stopped + * (a fake disk was already added to allow formatting). */ static inline int dasd_state_basic_to_ready(struct dasd_device * device) @@ -227,13 +228,19 @@ dasd_state_basic_to_ready(struct dasd_device * device) rc = 0; if (device->discipline->do_analysis != NULL) rc = device->discipline->do_analysis(device); - if (rc) + if (rc) { + if (rc != -EAGAIN) + device->state = DASD_STATE_UNFMT; return rc; + } + /* make disk known with correct capacity */ dasd_setup_queue(device); + set_capacity(device->gdp, device->blocks << device->s2b_shift); device->state = DASD_STATE_READY; - if (dasd_scan_partitions(device) != 0) + rc = dasd_scan_partitions(device); + if (rc) device->state = DASD_STATE_BASIC; - return 0; + return rc; } /* @@ -253,6 +260,15 @@ dasd_state_ready_to_basic(struct dasd_device * device) device->state = DASD_STATE_BASIC; } +/* + * Back to basic. + */ +static inline void +dasd_state_unfmt_to_basic(struct dasd_device * device) +{ + device->state = DASD_STATE_BASIC; +} + /* * Make the device online and schedule the bottom half to start * the requeueing of requests from the linux request queue to the @@ -319,8 +335,12 @@ dasd_decrease_state(struct dasd_device *device) if (device->state == DASD_STATE_READY && device->target <= DASD_STATE_BASIC) dasd_state_ready_to_basic(device); - - if (device->state == DASD_STATE_BASIC && + + if (device->state == DASD_STATE_UNFMT && + device->target <= DASD_STATE_BASIC) + dasd_state_unfmt_to_basic(device); + + if (device->state == DASD_STATE_BASIC && device->target <= DASD_STATE_KNOWN) dasd_state_basic_to_known(device); @@ -1722,7 +1742,7 @@ dasd_open(struct inode *inp, struct file *filp) goto out; } - if (device->state < DASD_STATE_BASIC) { + if (device->state <= DASD_STATE_BASIC) { DBF_DEV_EVENT(DBF_ERR, device, " %s", " Cannot open unrecognized device"); rc = -ENODEV; diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 65dc844b975c..fce2835e7d19 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -100,8 +100,6 @@ dasd_scan_partitions(struct dasd_device * device) { struct block_device *bdev; - /* Make the disk known. */ - set_capacity(device->gdp, device->blocks << device->s2b_shift); bdev = bdget_disk(device->gdp, 0); if (!bdev || blkdev_get(bdev, FMODE_READ, 1) < 0) return -ENODEV; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 0592354cc604..7cb0b9e78a6a 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -26,7 +26,7 @@ * new: the dasd_device structure is allocated. * known: the discipline for the device is identified. * basic: the device can do basic i/o. - * accept: the device is analysed (format is known). + * unfmt: the device could not be analyzed (format is unknown). * ready: partition detection is done and the device is can do block io. * online: the device accepts requests from the block device queue. * @@ -47,8 +47,9 @@ #define DASD_STATE_NEW 0 #define DASD_STATE_KNOWN 1 #define DASD_STATE_BASIC 2 -#define DASD_STATE_READY 3 -#define DASD_STATE_ONLINE 4 +#define DASD_STATE_UNFMT 3 +#define DASD_STATE_READY 4 +#define DASD_STATE_ONLINE 5 #include #include diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 2d5da3c75ca7..4c1acc8daa82 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -93,6 +93,9 @@ dasd_devices_show(struct seq_file *m, void *v) case DASD_STATE_BASIC: seq_printf(m, "basic"); break; + case DASD_STATE_UNFMT: + seq_printf(m, "unnformatted"); + break; case DASD_STATE_READY: case DASD_STATE_ONLINE: seq_printf(m, "active "); -- cgit v1.2.2 From ad58f7dbeb6f5ea82679962f18985f16b660a2d9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 10 Mar 2006 00:56:16 +0100 Subject: [SCSI] zfcp: fix device registration issues The patch fixes following issues: (1) Replace scsi_add_device with scsi_scan_target. (Thus the rport instead of the scsi_host becomes parent of a scsi_target again.) (2) Avoid scsi_device allocation during registration of an remote port. (Would be done during fc_scsi_scan_rport.) (3) Fix queuecommand behaviour when an zfcp unit is blocked. (Call scsi_done with DID_NO_CONNECT instead of returning SCSI_MLQUEUE_DEVICE_BUSY otherwise we might end up waiting for completion in blk_execute_rq for ever.) Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_erp.c | 11 +++++++---- drivers/s390/scsi/zfcp_scsi.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 7f551d66f47f..6eba56cd89ba 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -664,6 +664,7 @@ do { \ #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 +#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 /* FSF request status (this does not have a common part) */ #define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e3c4bdd29a60..57cb628a05aa 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3391,10 +3391,13 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, &unit->status)) && !unit->device - && port->rport) - scsi_add_device(port->adapter->scsi_host, 0, - port->rport->scsi_target_id, - unit->scsi_lun); + && port->rport) { + atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, + &unit->status); + scsi_scan_target(&port->rport->dev, 0, + port->rport->scsi_target_id, + unit->scsi_lun, 0); + } zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index a2de3c9afe49..9e6d07d7b3c8 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -183,7 +183,8 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) read_lock_irqsave(&zfcp_data.config_lock, flags); unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); - if (unit) { + if (unit && atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, + &unit->status)) { sdp->hostdata = unit; unit->device = sdp; zfcp_unit_get(unit); @@ -208,6 +209,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; if (unit) { + atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); sdpnt->hostdata = NULL; unit->device = NULL; zfcp_unit_put(unit); @@ -291,7 +293,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, "on port 0x%016Lx in recovery\n", zfcp_get_busid_by_unit(unit), unit->fcp_lun, unit->port->wwpn); - retval = SCSI_MLQUEUE_DEVICE_BUSY; + zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); goto out; } -- cgit v1.2.2 From b707dbe6c52e143a9afea06aa8f84103135ca873 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Thu, 9 Mar 2006 17:33:52 -0800 Subject: [PATCH] s390: dasd proc interface typo This fixes a typo introduced with 90f0094dc607abe384a412bfb7199fb667ab0735. Signed-off-by: Horst Hummel Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 4c1acc8daa82..1aa3c261718a 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -94,7 +94,7 @@ dasd_devices_show(struct seq_file *m, void *v) seq_printf(m, "basic"); break; case DASD_STATE_UNFMT: - seq_printf(m, "unnformatted"); + seq_printf(m, "unformatted"); break; case DASD_STATE_READY: case DASD_STATE_ONLINE: -- cgit v1.2.2 From e843e280cbe218fc8387339806d344708dee348a Mon Sep 17 00:00:00 2001 From: Greg Smith Date: Tue, 14 Mar 2006 19:50:17 -0800 Subject: [PATCH] "s390: multiple subchannel sets support" fix It seems this patch got dropped (it was in addition to the `s390: improve response code handling in chsc_enable_facility()' patch). Acked-by: Cornelia Huck Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/css.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 1bbf231f8aaf..3c77d65960db 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -409,6 +409,9 @@ __init_channel_subsystem(struct subchannel_id schid, void *data) /* -ENXIO: no more subchannels. */ case -ENXIO: return ret; + /* -EIO: this subchannel set not supported. */ + case -EIO: + return ret; default: return 0; } -- cgit v1.2.2