GIT e659fa8b4647c083e48ff6b213bfe13c116b39bb git://git390.osdl.marist.edu/pub/scm/linux-2.6.git#for-andrew commit e659fa8b4647c083e48ff6b213bfe13c116b39bb Author: Satyam Sharma Date: Fri Aug 24 10:40:08 2007 +0200 [S390] appldata_base: Remove module_exit function and modular stuff arch/s390/Kconfig tells us that CONFIG_APPLDATA_BASE is bool and hence can never be built modular. Given this, defining appldata_exit() function is pointless (and wasteful, actually). Remove all that. Previous patch annotated appldata_offline_cpu() as __cpuexit, but now with the __exit function appldata_exit() gone, the only callsite that references it is __cpuinit, so this function can also be __cpuinit, thereby saving space when HOTPLUG_CPU=n. Signed-off-by: Satyam Sharma Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Martin Schwidefsky commit 107e7e44182e92e3af0f2c4a13c2c2a2262a9f27 Author: Satyam Sharma Date: Fri Aug 24 10:40:07 2007 +0200 [S390] appldata_base: Misc cpuinit annotations and bugfix appldata_offline_cpu() is only called from __cpuinit-marked hotplug notifier callback and from the __exit-marked module_exit function, therefore candidate for __cpuexit. BTW the __exit module_exit function appldata_exit() of this driver fails to unregister_hotcpu_notifier() the notifier_block that was registered by appldata_init() during module startup. This will lead to oops if hotplug notification comes after module has been unloaded. Let's fix this by unregistering the notifier appropriately (before appldata_offline_cpu()'ing the CPUs). Signed-off-by: Satyam Sharma Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Martin Schwidefsky commit a18ec9adc94a2afc9d9ea169f8246d2102762984 Author: Heiko Carstens Date: Fri Aug 24 10:40:06 2007 +0200 [S390] Force link error if xchg/cmpxchg gets called with unsupported size. Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit c7be48651a2cff49c9265b30aad7cb36e48083cb Author: Ursula Braun Date: Fri Aug 24 10:40:05 2007 +0200 [S390] qdio: change QDIO performance_stats error message priority Signed-off-by: Ursula Braun Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 2b93bab99983c52dd9f830c7e753beb06f5a1f7c Author: vignesh babu Date: Fri Aug 24 10:40:04 2007 +0200 [S390] is_power_of_2 in drivers/s390/block/dasd_int.h Replacing n & (n - 1) for power of 2 check by is_power_of_2(n) Signed-off-by: vignesh babu Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 949d1a8a607de215c7e08fc6a937bbf15031184b Author: Heiko Carstens Date: Fri Aug 24 10:40:03 2007 +0200 [S390] qdio: dont cast function pointers and use them to call functions. According to C99 6.3.2.3 it's undefined what happens if a converted pointer is used to call a function whose type is not compatible with the pointed-to type. That's what the qdio code is doing, so fix it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit a9d81069d3e5acca5033878bc9f52c1db19e1bc5 Author: Heiko Carstens Date: Fri Aug 24 10:40:02 2007 +0200 [S390] Get rid of ARCH_KMALLOC_MINALIGN. slab cache debugging code has been changed so that we always get a minimum alignment of the alignment of a 64-integer. Since this is 8 on s390/s390x there is no need of ARCH_KMALLOC_MINALIGN anymore. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit d2b3c266febf4fba660fcad1163116bfe3ee2e43 Author: Christian Borntraeger Date: Fri Aug 24 10:40:01 2007 +0200 [S390] remove packed attribute from ext_int_info_t. ext_int_info_t is no longer used in entry(64).S Instead do_extint is a C function that handles the hash search. As the structure is handled in C code, we can also remove the packed attribute to avoid alignment issues. (Currently there is no alignment problem in ext_int_info_t, even if packet) Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 84699705e1596ed0af56db91ea0dc4bca01c31b1 Author: Heiko Carstens Date: Fri Aug 24 10:40:00 2007 +0200 [S390] Get rid of a bunch of sparse warnings again. Also removes a bunch of ^L in drivers/s390/cio/cmf.c Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit a0d9e6ef6a919e077e040a30574351714211e8c6 Author: Heiko Carstens Date: Fri Aug 24 10:39:59 2007 +0200 [S390] zcrypt: make init/exit functions static. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit 57028f0efa8e8d776be4be9d6c308cafcbfff41e Author: Cornelia Huck Date: Fri Aug 24 10:39:58 2007 +0200 [S390] cio: Add s390-drivers book. s390-drivers is generated using the docbook comments. It should eventually supersede Documentation/s390/cds.txt. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 17a69fe0ea0d198ec45e5380f491b7312f8af764 Author: Cornelia Huck Date: Fri Aug 24 10:39:57 2007 +0200 [S390] cio: Add docbook comments. Comment a bunch of function in docbook style and convert existing comments on structures to docbook. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 4db6d9f644e75e9a7ae0c3df0ad7161cfa400cbd Author: Cornelia Huck Date: Fri Aug 24 10:39:56 2007 +0200 [S390] cio: Kerneldoc comments for cmf. - Fix existing kerneldoc-style comments. - Move descriptions of functions from cmb.h to cmf.c. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit f49ce303afcd2138d31a79379d3e89c8a7a8efd9 Author: Cornelia Huck Date: Fri Aug 24 10:39:55 2007 +0200 [S390] cio: Fix some coding style issues in cmf. Fix some formatting and correct a comment. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit f2b3e5163a3ed11ccd19579e30126902fc7756c5 Author: Cornelia Huck Date: Fri Aug 24 10:39:54 2007 +0200 [S390] cio: remove subchannel_add_files() subchannel_add_files() no longer exists, remove from header. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit dc5c1fb7b5e4d37b76d72f86a3d177cb71825a82 Author: Cornelia Huck Date: Fri Aug 24 10:39:53 2007 +0200 [S390] cio: rename css to channel_subsystems Rename css[] to channel_subsystems[] to avoid name clashes. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens commit 3d36af1e899fb3b7e70cda524c75849342d894fd Author: Heiko Carstens Date: Fri Aug 24 10:39:14 2007 +0200 [S390] etr: force read of etr_sync_word in get_sync_clock(). The compiler might optimize the two atomic_read() so that only a single memory access happens. To force two reads add a barrier(). Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit 3e611bf1e8c58e571838d172d52c5ab769f37585 Author: Heiko Carstens Date: Fri Aug 24 10:39:13 2007 +0200 [S390] Remove barrier() from atomic_read/set again. After all adding a barrier() to atomic_read/set won't help. If e.g. cpu 1 does something like while(atomic_read(&v)); and then cpu 2 changes v cpu 1 will see the changed value only if cpu serializiation happens on cpu 1. Therefore the barrier() in atomic_read() won't help since it forces gcc to generate code that rereads the already fetched value from the cache of cpu 1. In order to force cpu 1 to fetch the value again from memory an explicit smp barrier must be added. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton --- Documentation/DocBook/Makefile | 2 Documentation/DocBook/s390-drivers.tmpl | 149 +++++++++++ arch/s390/appldata/appldata_base.c | 53 ---- arch/s390/kernel/audit.c | 7 arch/s390/kernel/audit.h | 15 + arch/s390/kernel/compat_audit.c | 1 arch/s390/kernel/time.c | 2 drivers/s390/block/dasd_int.h | 3 drivers/s390/char/con3270.c | 3 drivers/s390/char/sclp.c | 5 drivers/s390/char/tty3270.c | 9 drivers/s390/char/tty3270.h | 16 + drivers/s390/cio/ccwgroup.c | 67 +++-- drivers/s390/cio/chp.c | 22 - drivers/s390/cio/cmf.c | 232 +++++++++++------ drivers/s390/cio/css.c | 69 ++--- drivers/s390/cio/css.h | 3 drivers/s390/cio/device.c | 64 ++++ drivers/s390/cio/device_fsm.c | 3 drivers/s390/cio/device_ops.c | 241 ++++++++++++++++-- drivers/s390/cio/qdio.c | 39 +- drivers/s390/crypto/zcrypt_mono.c | 4 drivers/s390/scsi/zfcp_dbf.c | 10 drivers/s390/scsi/zfcp_erp.c | 18 - include/asm-s390/atomic.h | 4 include/asm-s390/cache.h | 2 include/asm-s390/ccwdev.h | 75 ++--- include/asm-s390/ccwgroup.h | 32 ++ include/asm-s390/cio.h | 288 +++++++++++++++------- include/asm-s390/cmb.h | 73 +---- include/asm-s390/s390_ext.h | 8 include/asm-s390/system.h | 24 - 32 files changed, 1051 insertions(+), 492 deletions(-) diff -puN Documentation/DocBook/Makefile~git-s390 Documentation/DocBook/Makefile --- a/Documentation/DocBook/Makefile~git-s390 +++ a/Documentation/DocBook/Makefile @@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mc procfs-guide.xml writing_usb_driver.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ - genericirq.xml + genericirq.xml s390-drivers.xml ### # The build process is as follows (targets): diff -puN /dev/null Documentation/DocBook/s390-drivers.tmpl --- /dev/null +++ a/Documentation/DocBook/s390-drivers.tmpl @@ -0,0 +1,149 @@ + + + + + + Writing s390 channel device drivers + + + + Cornelia + Huck + +
+ cornelia.huck@de.ibm.com +
+
+
+
+ + + 2007 + IBM Corp. + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + This document describes the interfaces available for device drivers that + drive s390 based channel attached devices. This includes interfaces for + interaction with the hardware and interfaces for interacting with the + common driver core. Those interfaces are provided by the s390 common I/O + layer. + + + The document assumes a familarity with the technical terms associated + with the s390 channel I/O architecture. For a description of this + architecture, please refer to the "z/Architecture: Principles of + Operation", IBM publication no. SA22-7832. + + + While most I/O devices on a s390 system are typically driven through the + channel I/O mechanism described here, there are various other methods + (like the diag interface). These are out of the scope of this document. + + + Some additional information can also be found in the kernel source + under Documentation/s390/driver-model.txt. + + + + The ccw bus + + The ccw bus typically contains the majority of devices available to + a s390 system. Named after the channel command word (ccw), the basic + command structure used to address its devices, the ccw bus contains + so-called channel attached devices. They are addressed via subchannels, + visible on the css bus. A device driver, however, will never interact + with the subchannel directly, but only via the device on the ccw bus, + the ccw device. + + + I/O functions for channel-attached devices + + Some hardware structures have been translated into C structures for use + by the common I/O layer and device drivers. For more information on + the hardware structures represented here, please consult the Principles + of Operation. + +!Iinclude/asm-s390/cio.h + + + ccw devices + + Devices that want to initiate channel I/O need to attach to the ccw bus. + Interaction with the driver core is done via the common I/O layer, which + provides the abstractions of ccw devices and ccw device drivers. + + + The functions that initiate or terminate channel I/O all act upon a + ccw device structure. Device drivers must not bypass those functions + or strange side effects may happen. + +!Iinclude/asm-s390/ccwdev.h +!Edrivers/s390/cio/device.c +!Edrivers/s390/cio/device_ops.c + + + The channel-measurement facility + + The channel-measurement facility provides a means to collect + measurement data which is made available by the channel subsystem + for each channel attached device. + +!Iinclude/asm-s390/cmb.h +!Edrivers/s390/cio/cmf.c + + + + + The ccwgroup bus + + The ccwgroup bus only contains artificial devices, created by the user. + Many networking devices (e.g. qeth) are in fact composed of several + ccw devices (like read, write and data channel for qeth). The + ccwgroup bus provides a mechanism to create a meta-device which + contains those ccw devices as slave devices and can be associated + with the netdevice. + + + ccw group devices +!Iinclude/asm-s390/ccwgroup.h +!Edrivers/s390/cio/ccwgroup.c + + + +
diff -puN arch/s390/appldata/appldata_base.c~git-s390 arch/s390/appldata/appldata_base.c --- a/arch/s390/appldata/appldata_base.c~git-s390 +++ a/arch/s390/appldata/appldata_base.c @@ -547,8 +547,7 @@ static void __cpuinit appldata_online_cp spin_unlock(&appldata_timer_lock); } -static void -appldata_offline_cpu(int cpu) +static void __cpuinit appldata_offline_cpu(int cpu) { del_virt_timer(&per_cpu(appldata_timer, cpu)); if (atomic_dec_and_test(&appldata_expire_count)) { @@ -560,9 +559,9 @@ appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -static int __cpuinit -appldata_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int __cpuinit appldata_cpu_notify(struct notifier_block *self, + unsigned long action, + void *hcpu) { switch (action) { case CPU_ONLINE: @@ -608,59 +607,15 @@ static int __init appldata_init(void) register_hotcpu_notifier(&appldata_nb); appldata_sysctl_header = register_sysctl_table(appldata_dir_table); -#ifdef MODULE - appldata_dir_table[0].de->owner = THIS_MODULE; - appldata_table[0].de->owner = THIS_MODULE; - appldata_table[1].de->owner = THIS_MODULE; -#endif P_DEBUG("Base interface initialized.\n"); return 0; } -/* - * appldata_exit() - * - * stop timer, unregister /proc entries - */ -static void __exit appldata_exit(void) -{ - struct list_head *lh; - struct appldata_ops *ops; - int rc, i; - - P_DEBUG("Unloading module ...\n"); - /* - * ops list should be empty, but just in case something went wrong... - */ - spin_lock(&appldata_ops_lock); - list_for_each(lh, &appldata_ops_list) { - ops = list_entry(lh, struct appldata_ops, list); - rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, - (unsigned long) ops->data, ops->size, - ops->mod_lvl); - if (rc != 0) { - P_ERROR("STOP DIAG 0xDC for %s failed, " - "return code: %d\n", ops->name, rc); - } - } - spin_unlock(&appldata_ops_lock); - - for_each_online_cpu(i) - appldata_offline_cpu(i); - - appldata_timer_active = 0; - - unregister_sysctl_table(appldata_sysctl_header); - - destroy_workqueue(appldata_wq); - P_DEBUG("... module unloaded!\n"); -} /**************************** init / exit ******************************/ module_init(appldata_init); -module_exit(appldata_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gerald Schaefer"); MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure"); diff -puN arch/s390/kernel/audit.c~git-s390 arch/s390/kernel/audit.c --- a/arch/s390/kernel/audit.c~git-s390 +++ a/arch/s390/kernel/audit.c @@ -2,6 +2,7 @@ #include #include #include +#include "audit.h" static unsigned dir_class[] = { #include @@ -40,7 +41,6 @@ int audit_classify_arch(int arch) int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_COMPAT - extern int s390_classify_syscall(unsigned); if (abi == AUDIT_ARCH_S390) return s390_classify_syscall(syscall); #endif @@ -61,11 +61,6 @@ int audit_classify_syscall(int abi, unsi static int __init audit_classes_init(void) { #ifdef CONFIG_COMPAT - extern __u32 s390_dir_class[]; - extern __u32 s390_write_class[]; - extern __u32 s390_read_class[]; - extern __u32 s390_chattr_class[]; - extern __u32 s390_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); diff -puN /dev/null arch/s390/kernel/audit.h --- /dev/null +++ a/arch/s390/kernel/audit.h @@ -0,0 +1,15 @@ +#ifndef __ARCH_S390_KERNEL_AUDIT_H +#define __ARCH_S390_KERNEL_AUDIT_H + +#include + +#ifdef CONFIG_COMPAT +extern int s390_classify_syscall(unsigned); +extern __u32 s390_dir_class[]; +extern __u32 s390_write_class[]; +extern __u32 s390_read_class[]; +extern __u32 s390_chattr_class[]; +extern __u32 s390_signal_class[]; +#endif /* CONFIG_COMPAT */ + +#endif /* __ARCH_S390_KERNEL_AUDIT_H */ diff -puN arch/s390/kernel/compat_audit.c~git-s390 arch/s390/kernel/compat_audit.c --- a/arch/s390/kernel/compat_audit.c~git-s390 +++ a/arch/s390/kernel/compat_audit.c @@ -1,5 +1,6 @@ #undef __s390x__ #include +#include "audit.h" unsigned s390_dir_class[] = { #include diff -puN arch/s390/kernel/time.c~git-s390 arch/s390/kernel/time.c --- a/arch/s390/kernel/time.c~git-s390 +++ a/arch/s390/kernel/time.c @@ -446,6 +446,8 @@ int get_sync_clock(unsigned long long *c sw_ptr = &get_cpu_var(etr_sync_word); sw0 = atomic_read(sw_ptr); *clock = get_clock(); + /* Force read of local etr_sync_word. */ + barrier(); sw1 = atomic_read(sw_ptr); put_cpu_var(etr_sync_sync); if (sw0 == sw1 && (sw0 & 0x80000000U)) diff -puN drivers/s390/block/dasd_int.h~git-s390 drivers/s390/block/dasd_int.h --- a/drivers/s390/block/dasd_int.h~git-s390 +++ a/drivers/s390/block/dasd_int.h @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -456,7 +457,7 @@ dasd_free_chunk(struct list_head *chunk_ static inline int dasd_check_blocksize(int bsize) { - if (bsize < 512 || bsize > 4096 || (bsize & (bsize - 1)) != 0) + if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize)) return -EMEDIUMTYPE; return 0; } diff -puN drivers/s390/char/con3270.c~git-s390 drivers/s390/char/con3270.c --- a/drivers/s390/char/con3270.c~git-s390 +++ a/drivers/s390/char/con3270.c @@ -22,6 +22,7 @@ #include #include "raw3270.h" +#include "tty3270.h" #include "ctrlchar.h" #define CON3270_OUTPUT_BUFFER_SIZE 1024 @@ -507,8 +508,6 @@ con3270_write(struct console *co, const spin_unlock_irqrestore(&cp->view.lock,flags); } -extern struct tty_driver *tty3270_driver; - static struct tty_driver * con3270_device(struct console *c, int *index) { diff -puN drivers/s390/char/sclp.c~git-s390 drivers/s390/char/sclp.c --- a/drivers/s390/char/sclp.c~git-s390 +++ a/drivers/s390/char/sclp.c @@ -93,6 +93,7 @@ static volatile enum sclp_mask_state_t { #define SCLP_RETRY_INTERVAL 30 static void sclp_process_queue(void); +static void __sclp_make_read_req(void); static int sclp_init_mask(int calculate); static int sclp_init(void); @@ -115,7 +116,6 @@ sclp_service_call(sclp_cmdw_t command, v return 0; } -static inline void __sclp_make_read_req(void); static void __sclp_queue_read_req(void) @@ -318,8 +318,7 @@ sclp_read_cb(struct sclp_req *req, void } /* Prepare read event data request. Called while sclp_lock is locked. */ -static inline void -__sclp_make_read_req(void) +static void __sclp_make_read_req(void) { struct sccb_header *sccb; diff -puN drivers/s390/char/tty3270.c~git-s390 drivers/s390/char/tty3270.c --- a/drivers/s390/char/tty3270.c~git-s390 +++ a/drivers/s390/char/tty3270.c @@ -25,8 +25,8 @@ #include #include - #include "raw3270.h" +#include "tty3270.h" #include "keyboard.h" #define TTY3270_CHAR_BUF_SIZE 256 @@ -1338,8 +1338,11 @@ tty3270_getpar(struct tty3270 *tp, int i static void tty3270_goto_xy(struct tty3270 *tp, int cx, int cy) { - tp->cx = min_t(int, tp->view.cols - 1, max_t(int, 0, cx)); - cy = min_t(int, tp->view.rows - 3, max_t(int, 0, cy)); + int max_cx = max(0, cx); + int max_cy = max(0, cy); + + tp->cx = min_t(int, tp->view.cols - 1, max_cx); + cy = min_t(int, tp->view.rows - 3, max_cy); if (cy != tp->cy) { tty3270_convert_line(tp, tp->cy); tp->cy = cy; diff -puN /dev/null drivers/s390/char/tty3270.h --- /dev/null +++ a/drivers/s390/char/tty3270.h @@ -0,0 +1,16 @@ +/* + * drivers/s390/char/tty3270.h + * + * Copyright IBM Corp. 2007 + * + */ + +#ifndef __DRIVERS_S390_CHAR_TTY3270_H +#define __DRIVERS_S390_CHAR_TTY3270_H + +#include +#include + +extern struct tty_driver *tty3270_driver; + +#endif /* __DRIVERS_S390_CHAR_TTY3270_H */ diff -puN drivers/s390/cio/ccwgroup.c~git-s390 drivers/s390/cio/ccwgroup.c --- a/drivers/s390/cio/ccwgroup.c~git-s390 +++ a/drivers/s390/cio/ccwgroup.c @@ -151,16 +151,24 @@ __ccwgroup_create_symlinks(struct ccwgro return 0; } -/* - * try to add a new ccwgroup device for one driver - * argc and argv[] are a list of bus_id's of devices - * belonging to the driver. +/** + * ccwgroup_create() - create and register a ccw group device + * @root: parent device for the new device + * @creator_id: identifier of creating driver + * @cdrv: ccw driver of slave devices + * @argc: number of slave devices + * @argv: bus ids of slave devices + * + * Create and register a new ccw group device as a child of @root. Slave + * devices are obtained from the list of bus ids given in @argv[] and must all + * belong to @cdrv. + * Returns: + * %0 on success and an error code on failure. + * Context: + * non-atomic */ -int -ccwgroup_create(struct device *root, - unsigned int creator_id, - struct ccw_driver *cdrv, - int argc, char *argv[]) +int ccwgroup_create(struct device *root, unsigned int creator_id, + struct ccw_driver *cdrv, int argc, char *argv[]) { struct ccwgroup_device *gdev; int i; @@ -389,8 +397,13 @@ static struct bus_type ccwgroup_bus_type .remove = ccwgroup_remove, }; -int -ccwgroup_driver_register (struct ccwgroup_driver *cdriver) +/** + * ccwgroup_driver_register() - register a ccw group driver + * @cdriver: driver to be registered + * + * This function is mainly a wrapper around driver_register(). + */ +int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ cdriver->driver.bus = &ccwgroup_bus_type; @@ -405,8 +418,13 @@ __ccwgroup_match_all(struct device *dev, return 1; } -void -ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) +/** + * ccwgroup_driver_unregister() - deregister a ccw group driver + * @cdriver: driver to be deregistered + * + * This function is mainly a wrapper around driver_unregister(). + */ +void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) { struct device *dev; @@ -426,8 +444,16 @@ ccwgroup_driver_unregister (struct ccwgr driver_unregister(&cdriver->driver); } -int -ccwgroup_probe_ccwdev(struct ccw_device *cdev) +/** + * ccwgroup_probe_ccwdev() - probe function for slave devices + * @cdev: ccw device to be probed + * + * This is a dummy probe function for ccw devices that are slave devices in + * a ccw group device. + * Returns: + * always %0 + */ +int ccwgroup_probe_ccwdev(struct ccw_device *cdev) { return 0; } @@ -451,8 +477,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_d return NULL; } -void -ccwgroup_remove_ccwdev(struct ccw_device *cdev) +/** + * ccwgroup_remove_ccwdev() - remove function for slave devices + * @cdev: ccw device to be removed + * + * This is a remove function for ccw devices that are slave devices in a ccw + * group device. It sets the ccw device offline and also deregisters the + * embedding ccw group device. + */ +void ccwgroup_remove_ccwdev(struct ccw_device *cdev) { struct ccwgroup_device *gdev; diff -puN drivers/s390/cio/chp.c~git-s390 drivers/s390/cio/chp.c --- a/drivers/s390/cio/chp.c~git-s390 +++ a/drivers/s390/cio/chp.c @@ -55,7 +55,7 @@ static wait_queue_head_t cfg_wait_queue; /* Return channel_path struct for given chpid. */ static inline struct channel_path *chpid_to_chp(struct chp_id chpid) { - return css[chpid.cssid]->chps[chpid.id]; + return channel_subsystems[chpid.cssid]->chps[chpid.id]; } /* Set vary state for given chpid. */ @@ -140,9 +140,11 @@ static ssize_t chp_measurement_chars_rea char *buf, loff_t off, size_t count) { struct channel_path *chp; + struct device *device; unsigned int size; - chp = to_channelpath(container_of(kobj, struct device, kobj)); + device = container_of(kobj, struct device, kobj); + chp = to_channelpath(device); if (!chp->cmg_chars) return 0; @@ -193,9 +195,11 @@ static ssize_t chp_measurement_read(stru { struct channel_path *chp; struct channel_subsystem *css; + struct device *device; unsigned int size; - chp = to_channelpath(container_of(kobj, struct device, kobj)); + device = container_of(kobj, struct device, kobj); + chp = to_channelpath(device); css = to_css(chp->dev.parent); size = sizeof(struct cmg_entry); @@ -395,7 +399,7 @@ int chp_new(struct chp_id chpid) /* fill in status, etc. */ chp->chpid = chpid; chp->state = 1; - chp->dev.parent = &css[chpid.cssid]->device; + chp->dev.parent = &channel_subsystems[chpid.cssid]->device; chp->dev.release = chp_release; snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, chpid.id); @@ -430,18 +434,18 @@ int chp_new(struct chp_id chpid) device_unregister(&chp->dev); goto out_free; } - mutex_lock(&css[chpid.cssid]->mutex); - if (css[chpid.cssid]->cm_enabled) { + mutex_lock(&channel_subsystems[chpid.cssid]->mutex); + if (channel_subsystems[chpid.cssid]->cm_enabled) { ret = chp_add_cmg_attr(chp); if (ret) { sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); device_unregister(&chp->dev); - mutex_unlock(&css[chpid.cssid]->mutex); + mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); goto out_free; } } - css[chpid.cssid]->chps[chpid.id] = chp; - mutex_unlock(&css[chpid.cssid]->mutex); + channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; + mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); return ret; out_free: kfree(chp); diff -puN drivers/s390/cio/cmf.c~git-s390 drivers/s390/cio/cmf.c --- a/drivers/s390/cio/cmf.c~git-s390 +++ a/drivers/s390/cio/cmf.c @@ -45,7 +45,8 @@ #include "ioasm.h" #include "chsc.h" -/* parameter to enable cmf during boot, possible uses are: +/* + * parameter to enable cmf during boot, possible uses are: * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be * used on any subchannel * "s390cmf=" -- enable cmf and allocate enough memory to measure @@ -73,18 +74,20 @@ enum cmb_index { * enum cmb_format - types of supported measurement block formats * * @CMF_BASIC: traditional channel measurement blocks supported - * by all machines that we run on + * by all machines that we run on * @CMF_EXTENDED: improved format that was introduced with the z990 - * machine - * @CMF_AUTODETECT: default: use extended format when running on a z990 - * or later machine, otherwise fall back to basic format - **/ + * machine + * @CMF_AUTODETECT: default: use extended format when running on a machine + * supporting extended format, otherwise fall back to + * basic format + */ enum cmb_format { CMF_BASIC, CMF_EXTENDED, CMF_AUTODETECT = -1, }; -/** + +/* * format - actual format for all measurement blocks * * The format module parameter can be set to a value of 0 (zero) @@ -105,20 +108,21 @@ module_param(format, bool, 0444); * either with the help of a special pool or with kmalloc * @free: free memory allocated with @alloc * @set: enable or disable measurement + * @read: read a measurement entry at an index * @readall: read a measurement block in a common format * @reset: clear the data in the associated measurement block and * reset its time stamp * @align: align an allocated block so that the hardware can use it */ struct cmb_operations { - int (*alloc) (struct ccw_device*); - void(*free) (struct ccw_device*); - int (*set) (struct ccw_device*, u32); - u64 (*read) (struct ccw_device*, int); - int (*readall)(struct ccw_device*, struct cmbdata *); - void (*reset) (struct ccw_device*); - void * (*align) (void *); - + int (*alloc) (struct ccw_device *); + void (*free) (struct ccw_device *); + int (*set) (struct ccw_device *, u32); + u64 (*read) (struct ccw_device *, int); + int (*readall)(struct ccw_device *, struct cmbdata *); + void (*reset) (struct ccw_device *); + void *(*align) (void *); +/* private: */ struct attribute_group *attr_group; }; static struct cmb_operations *cmbops; @@ -130,9 +134,11 @@ struct cmb_data { unsigned long long last_update; /* when last_block was updated */ }; -/* our user interface is designed in terms of nanoseconds, +/* + * Our user interface is designed in terms of nanoseconds, * while the hardware measures total times in its own - * unit.*/ + * unit. + */ static inline u64 time_to_nsec(u32 value) { return ((u64)value) * 128000ull; @@ -159,12 +165,13 @@ static inline u64 time_to_avg_nsec(u32 v return ret; } -/* activate or deactivate the channel monitor. When area is NULL, +/* + * Activate or deactivate the channel monitor. When area is NULL, * the monitor is deactivated. The channel monitor needs to * be active in order to measure subchannels, which also need - * to be enabled. */ -static inline void -cmf_activate(void *area, unsigned int onoff) + * to be enabled. + */ +static inline void cmf_activate(void *area, unsigned int onoff) { register void * __gpr2 asm("2"); register long __gpr1 asm("1"); @@ -175,8 +182,8 @@ cmf_activate(void *area, unsigned int on asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); } -static int -set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) +static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, + unsigned long address) { int ret; int retry; @@ -466,6 +473,7 @@ static void cmf_generic_reset(struct ccw * * @mem: pointer to CMBs (only in basic measurement mode) * @list: contains a linked list of all subchannels + * @num_channels: number of channels to be measured * @lock: protect concurrent access to @mem and @list */ struct cmb_area { @@ -481,28 +489,36 @@ static struct cmb_area cmb_area = { .num_channels = 1024, }; - /* ****** old style CMB handling ********/ -/** int maxchannels - * +/* * Basic channel measurement blocks are allocated in one contiguous * block of memory, which can not be moved as long as any channel * is active. Therefore, a maximum number of subchannels needs to * be defined somewhere. This is a module parameter, defaulting to * a resonable value of 1024, or 32 kb of memory. * Current kernels don't allow kmalloc with more than 128kb, so the - * maximum is 4096 + * maximum is 4096. */ module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); /** * struct cmb - basic channel measurement block + * @ssch_rsch_count: number of ssch and rsch + * @sample_count: number of samples + * @device_connect_time: time of device connect + * @function_pending_time: time of function pending + * @device_disconnect_time: time of device disconnect + * @control_unit_queuing_time: time of control unit queuing + * @device_active_only_time: time of device active only + * @reserved: unused in basic measurement mode + * + * The measurement block as used by the hardware. The fields are described + * further in z/Architecture Principles of Operation, chapter 17. * - * cmb as used by the hardware the fields are described in z/Architecture - * Principles of Operation, chapter 17. - * The area to be a contiguous array and may not be reallocated or freed. + * The cmb area made up from these blocks must be a contiguous array and may + * not be reallocated or freed. * Only one cmb area can be present in the system. */ struct cmb { @@ -516,8 +532,9 @@ struct cmb { u32 reserved[2]; }; -/* insert a single device into the cmb_area list - * called with cmb_area.lock held from alloc_cmb +/* + * Insert a single device into the cmb_area list. + * Called with cmb_area.lock held from alloc_cmb. */ static int alloc_cmb_single(struct ccw_device *cdev, struct cmb_data *cmb_data) @@ -532,9 +549,11 @@ static int alloc_cmb_single(struct ccw_d goto out; } - /* find first unused cmb in cmb_area.mem. - * this is a little tricky: cmb_area.list - * remains sorted by ->cmb->hw_data pointers */ + /* + * Find first unused cmb in cmb_area.mem. + * This is a little tricky: cmb_area.list + * remains sorted by ->cmb->hw_data pointers. + */ cmb = cmb_area.mem; list_for_each_entry(node, &cmb_area.list, cmb_list) { struct cmb_data *data; @@ -558,8 +577,7 @@ out: return ret; } -static int -alloc_cmb (struct ccw_device *cdev) +static int alloc_cmb(struct ccw_device *cdev) { int ret; struct cmb *mem; @@ -670,7 +688,7 @@ static int set_cmb(struct ccw_device *cd return set_schib_wait(cdev, mme, 0, offset); } -static u64 read_cmb (struct ccw_device *cdev, int index) +static u64 read_cmb(struct ccw_device *cdev, int index) { struct cmb *cmb; u32 val; @@ -720,7 +738,7 @@ out: return ret; } -static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data) +static int readall_cmb(struct ccw_device *cdev, struct cmbdata *data) { struct cmb *cmb; struct cmb_data *cmb_data; @@ -793,14 +811,25 @@ static struct cmb_operations cmbops_basi .align = align_cmb, .attr_group = &cmf_attr_group, }; - + /* ******** extended cmb handling ********/ /** * struct cmbe - extended channel measurement block + * @ssch_rsch_count: number of ssch and rsch + * @sample_count: number of samples + * @device_connect_time: time of device connect + * @function_pending_time: time of function pending + * @device_disconnect_time: time of device disconnect + * @control_unit_queuing_time: time of control unit queuing + * @device_active_only_time: time of device active only + * @device_busy_time: time of device busy + * @initial_command_response_time: initial command response time + * @reserved: unused * - * cmb as used by the hardware, may be in any 64 bit physical location, - * the fields are described in z/Architecture Principles of Operation, + * The measurement block as used by the hardware. May be in any 64 bit physical + * location. + * The fields are described further in z/Architecture Principles of Operation, * third edition, chapter 17. */ struct cmbe { @@ -816,10 +845,12 @@ struct cmbe { u32 reserved[7]; }; -/* kmalloc only guarantees 8 byte alignment, but we need cmbe +/* + * kmalloc only guarantees 8 byte alignment, but we need cmbe * pointers to be naturally aligned. Make sure to allocate - * enough space for two cmbes */ -static inline struct cmbe* cmbe_align(struct cmbe *c) + * enough space for two cmbes. + */ +static inline struct cmbe *cmbe_align(struct cmbe *c) { unsigned long addr; addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & @@ -827,7 +858,7 @@ static inline struct cmbe* cmbe_align(st return (struct cmbe*)addr; } -static int alloc_cmbe (struct ccw_device *cdev) +static int alloc_cmbe(struct ccw_device *cdev) { struct cmbe *cmbe; struct cmb_data *cmb_data; @@ -873,7 +904,7 @@ out_free: return ret; } -static void free_cmbe (struct ccw_device *cdev) +static void free_cmbe(struct ccw_device *cdev) { struct cmb_data *cmb_data; @@ -912,7 +943,7 @@ static int set_cmbe(struct ccw_device *c } -static u64 read_cmbe (struct ccw_device *cdev, int index) +static u64 read_cmbe(struct ccw_device *cdev, int index) { struct cmbe *cmb; struct cmb_data *cmb_data; @@ -970,7 +1001,7 @@ out: return ret; } -static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) +static int readall_cmbe(struct ccw_device *cdev, struct cmbdata *data) { struct cmbe *cmb; struct cmb_data *cmb_data; @@ -1047,17 +1078,16 @@ static struct cmb_operations cmbops_exte .align = align_cmbe, .attr_group = &cmf_attr_group_ext, }; - -static ssize_t -cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) +static ssize_t cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) { return sprintf(buf, "%lld\n", (unsigned long long) cmf_read(to_ccwdev(dev), idx)); } -static ssize_t -cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t cmb_show_avg_sample_interval(struct device *dev, + struct device_attribute *attr, + char *buf) { struct ccw_device *cdev; long interval; @@ -1079,8 +1109,9 @@ cmb_show_avg_sample_interval(struct devi return sprintf(buf, "%ld\n", interval); } -static ssize_t -cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t cmb_show_avg_utilization(struct device *dev, + struct device_attribute *attr, + char *buf) { struct cmbdata data; u64 utilization; @@ -1112,14 +1143,16 @@ cmb_show_avg_utilization(struct device * } #define cmf_attr(name) \ -static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ -{ return cmb_show_attr((dev), buf, cmb_ ## name); } \ -static DEVICE_ATTR(name, 0444, show_ ## name, NULL); +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ return cmb_show_attr((dev), buf, cmb_##name); } \ +static DEVICE_ATTR(name, 0444, show_##name, NULL); #define cmf_attr_avg(name) \ -static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ -{ return cmb_show_attr((dev), buf, cmb_ ## name); } \ -static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL); +static ssize_t show_avg_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ return cmb_show_attr((dev), buf, cmb_##name); } \ +static DEVICE_ATTR(avg_##name, 0444, show_avg_##name, NULL); cmf_attr(ssch_rsch_count); cmf_attr(sample_count); @@ -1131,7 +1164,8 @@ cmf_attr_avg(device_active_only_time); cmf_attr_avg(device_busy_time); cmf_attr_avg(initial_command_response_time); -static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL); +static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, + NULL); static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); static struct attribute *cmf_attributes[] = { @@ -1172,12 +1206,16 @@ static struct attribute_group cmf_attr_g .attrs = cmf_attributes_ext, }; -static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t cmb_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); } -static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c) +static ssize_t cmb_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t c) { struct ccw_device *cdev; int ret; @@ -1202,9 +1240,16 @@ static ssize_t cmb_enable_store(struct d DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); -/* enable_cmf/disable_cmf: module interface for cmf (de)activation */ -int -enable_cmf(struct ccw_device *cdev) +/** + * enable_cmf() - switch on the channel measurement for a specific device + * @cdev: The ccw device to be enabled + * + * Returns %0 for success or a negative error value. + * + * Context: + * non-atomic + */ +int enable_cmf(struct ccw_device *cdev) { int ret; @@ -1225,8 +1270,16 @@ enable_cmf(struct ccw_device *cdev) return ret; } -int -disable_cmf(struct ccw_device *cdev) +/** + * disable_cmf() - switch off the channel measurement for a specific device + * @cdev: The ccw device to be disabled + * + * Returns %0 for success or a negative error value. + * + * Context: + * non-atomic + */ +int disable_cmf(struct ccw_device *cdev) { int ret; @@ -1238,14 +1291,32 @@ disable_cmf(struct ccw_device *cdev) return ret; } -u64 -cmf_read(struct ccw_device *cdev, int index) +/** + * cmf_read() - read one value from the current channel measurement block + * @cdev: the channel to be read + * @index: the index of the value to be read + * + * Returns the value read or %0 if the value cannot be read. + * + * Context: + * any + */ +u64 cmf_read(struct ccw_device *cdev, int index) { return cmbops->read(cdev, index); } -int -cmf_readall(struct ccw_device *cdev, struct cmbdata *data) +/** + * cmf_readall() - read the current channel measurement block + * @cdev: the channel to be read + * @data: a pointer to a data block that will be filled + * + * Returns %0 on success, a negative error value otherwise. + * + * Context: + * any + */ +int cmf_readall(struct ccw_device *cdev, struct cmbdata *data) { return cmbops->readall(cdev, data); } @@ -1257,15 +1328,16 @@ int cmf_reenable(struct ccw_device *cdev return cmbops->set(cdev, 2); } -static int __init -init_cmf(void) +static int __init init_cmf(void) { char *format_string; char *detect_string = "parameter"; - /* We cannot really autoprobe this. If the user did not give a parameter, - see if we are running on z990 or up, otherwise fall back to basic mode. */ - + /* + * If the user did not give a parameter, see if we are running on a + * machine supporting extended measurement blocks, otherwise fall back + * to basic mode. + */ if (format == CMF_AUTODETECT) { if (!css_characteristics_avail || !css_general_characteristics.ext_mb) { @@ -1284,7 +1356,7 @@ init_cmf(void) cmbops = &cmbops_basic; break; case CMF_EXTENDED: - format_string = "extended"; + format_string = "extended"; cmbops = &cmbops_extended; break; default: diff -puN drivers/s390/cio/css.c~git-s390 drivers/s390/cio/css.c --- a/drivers/s390/cio/css.c~git-s390 +++ a/drivers/s390/cio/css.c @@ -27,7 +27,7 @@ int css_init_done = 0; static int need_reprobe = 0; static int max_ssid = 0; -struct channel_subsystem *css[__MAX_CSSID + 1]; +struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; int css_characteristics_avail = 0; @@ -177,7 +177,7 @@ static int css_register_subchannel(struc int ret; /* Initialize the subchannel structure */ - sch->dev.parent = &css[0]->device; + sch->dev.parent = &channel_subsystems[0]->device; sch->dev.bus = &css_bus_type; sch->dev.release = &css_subchannel_release; sch->dev.groups = subch_attr_groups; @@ -606,27 +606,29 @@ static int __init setup_css(int nr) { u32 tod_high; int ret; + struct channel_subsystem *css; - memset(css[nr], 0, sizeof(struct channel_subsystem)); - css[nr]->pseudo_subchannel = - kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL); - if (!css[nr]->pseudo_subchannel) + css = channel_subsystems[nr]; + memset(css, 0, sizeof(struct channel_subsystem)); + css->pseudo_subchannel = + kzalloc(sizeof(*css->pseudo_subchannel), GFP_KERNEL); + if (!css->pseudo_subchannel) return -ENOMEM; - css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device; - css[nr]->pseudo_subchannel->dev.release = css_subchannel_release; - sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct"); - ret = cio_create_sch_lock(css[nr]->pseudo_subchannel); + css->pseudo_subchannel->dev.parent = &css->device; + css->pseudo_subchannel->dev.release = css_subchannel_release; + sprintf(css->pseudo_subchannel->dev.bus_id, "defunct"); + ret = cio_create_sch_lock(css->pseudo_subchannel); if (ret) { - kfree(css[nr]->pseudo_subchannel); + kfree(css->pseudo_subchannel); return ret; } - mutex_init(&css[nr]->mutex); - css[nr]->valid = 1; - css[nr]->cssid = nr; - sprintf(css[nr]->device.bus_id, "css%x", nr); - css[nr]->device.release = channel_subsystem_release; + mutex_init(&css->mutex); + css->valid = 1; + css->cssid = nr; + sprintf(css->device.bus_id, "css%x", nr); + css->device.release = channel_subsystem_release; tod_high = (u32) (get_clock() >> 32); - css_generate_pgid(css[nr], tod_high); + css_generate_pgid(css, tod_high); return 0; } @@ -670,25 +672,28 @@ init_channel_subsystem (void) } /* Setup css structure. */ for (i = 0; i <= __MAX_CSSID; i++) { - css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); - if (!css[i]) { + struct channel_subsystem *css; + + css = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); + if (!css) { ret = -ENOMEM; goto out_unregister; } + channel_subsystems[i] = css; ret = setup_css(i); if (ret) goto out_free; - ret = device_register(&css[i]->device); + ret = device_register(&css->device); if (ret) goto out_free_all; if (css_characteristics_avail && css_chsc_characteristics.secm) { - ret = device_create_file(&css[i]->device, + ret = device_create_file(&css->device, &dev_attr_cm_enable); if (ret) goto out_device; } - ret = device_register(&css[i]->pseudo_subchannel->dev); + ret = device_register(&css->pseudo_subchannel->dev); if (ret) goto out_file; } @@ -699,22 +704,26 @@ init_channel_subsystem (void) for_each_subchannel(__init_channel_subsystem, NULL); return 0; out_file: - device_remove_file(&css[i]->device, &dev_attr_cm_enable); + device_remove_file(&channel_subsystems[i]->device, + &dev_attr_cm_enable); out_device: - device_unregister(&css[i]->device); + device_unregister(&channel_subsystems[i]->device); out_free_all: - kfree(css[i]->pseudo_subchannel->lock); - kfree(css[i]->pseudo_subchannel); + kfree(channel_subsystems[i]->pseudo_subchannel->lock); + kfree(channel_subsystems[i]->pseudo_subchannel); out_free: - kfree(css[i]); + kfree(channel_subsystems[i]); out_unregister: while (i > 0) { + struct channel_subsystem *css; + i--; - device_unregister(&css[i]->pseudo_subchannel->dev); + css = channel_subsystems[i]; + device_unregister(&css->pseudo_subchannel->dev); if (css_characteristics_avail && css_chsc_characteristics.secm) - device_remove_file(&css[i]->device, + device_remove_file(&css->device, &dev_attr_cm_enable); - device_unregister(&css[i]->device); + device_unregister(&css->device); } out_bus: bus_unregister(&css_bus_type); diff -puN drivers/s390/cio/css.h~git-s390 drivers/s390/cio/css.h --- a/drivers/s390/cio/css.h~git-s390 +++ a/drivers/s390/cio/css.h @@ -167,7 +167,7 @@ struct channel_subsystem { #define to_css(dev) container_of(dev, struct channel_subsystem, device) extern struct bus_type css_bus_type; -extern struct channel_subsystem *css[]; +extern struct channel_subsystem *channel_subsystems[]; /* Some helper functions for disconnected state. */ int device_is_disconnected(struct subchannel *); @@ -191,6 +191,5 @@ int sch_is_pseudo_sch(struct subchannel extern struct workqueue_struct *slow_path_wq; -int subchannel_add_files (struct device *); extern struct attribute_group *subch_attr_groups[]; #endif diff -puN drivers/s390/cio/device.c~git-s390 drivers/s390/cio/device.c --- a/drivers/s390/cio/device.c~git-s390 +++ a/drivers/s390/cio/device.c @@ -346,8 +346,18 @@ ccw_device_remove_disconnected(struct cc cdev->private->dev_id.devno); } -int -ccw_device_set_offline(struct ccw_device *cdev) +/** + * ccw_device_set_offline() - disable a ccw device for I/O + * @cdev: target ccw device + * + * This function calls the driver's set_offline() function for @cdev, if + * given, and then disables @cdev. + * Returns: + * %0 on success and a negative error value on failure. + * Context: + * enabled, ccw device lock not held + */ +int ccw_device_set_offline(struct ccw_device *cdev) { int ret; @@ -385,8 +395,19 @@ ccw_device_set_offline(struct ccw_device return ret; } -int -ccw_device_set_online(struct ccw_device *cdev) +/** + * ccw_device_set_online() - enable a ccw device for I/O + * @cdev: target ccw device + * + * This function first enables @cdev and then calls the driver's set_online() + * function for @cdev, if given. If set_online() returns an error, @cdev is + * disabled again. + * Returns: + * %0 on success and a negative error value on failure. + * Context: + * enabled, ccw device lock not held + */ +int ccw_device_set_online(struct ccw_device *cdev) { int ret; @@ -1315,8 +1336,19 @@ __ccwdev_check_busid(struct device *dev, } -struct ccw_device * -get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) +/** + * get_ccwdev_by_busid() - obtain device from a bus id + * @cdrv: driver the device is owned by + * @bus_id: bus id of the device to be searched + * + * This function searches all devices owned by @cdrv for a device with a bus + * id matching @bus_id. + * Returns: + * If a match is found, its reference count of the found device is increased + * and it is returned; else %NULL is returned. + */ +struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, + const char *bus_id) { struct device *dev; struct device_driver *drv; @@ -1398,8 +1430,15 @@ struct bus_type ccw_bus_type = { .remove = ccw_device_remove, }; -int -ccw_driver_register (struct ccw_driver *cdriver) +/** + * ccw_driver_register() - register a ccw driver + * @cdriver: driver to be registered + * + * This function is mainly a wrapper around driver_register(). + * Returns: + * %0 on success and a negative error value on failure. + */ +int ccw_driver_register(struct ccw_driver *cdriver) { struct device_driver *drv = &cdriver->driver; @@ -1409,8 +1448,13 @@ ccw_driver_register (struct ccw_driver * return driver_register(drv); } -void -ccw_driver_unregister (struct ccw_driver *cdriver) +/** + * ccw_driver_unregister() - deregister a ccw driver + * @cdriver: driver to be deregistered + * + * This function is mainly a wrapper around driver_unregister(). + */ +void ccw_driver_unregister(struct ccw_driver *cdriver) { driver_unregister(&cdriver->driver); } diff -puN drivers/s390/cio/device_fsm.c~git-s390 drivers/s390/cio/device_fsm.c --- a/drivers/s390/cio/device_fsm.c~git-s390 +++ a/drivers/s390/cio/device_fsm.c @@ -446,7 +446,8 @@ static void __ccw_device_get_common_pgid if (cdev->private->pgid[last].inf.ps.state1 == SNID_STATE1_RESET) /* No previous pgid found */ - memcpy(&cdev->private->pgid[0], &css[0]->global_pgid, + memcpy(&cdev->private->pgid[0], + &channel_subsystems[0]->global_pgid, sizeof(struct pgid)); else /* Use existing pgid */ diff -puN drivers/s390/cio/device_ops.c~git-s390 drivers/s390/cio/device_ops.c --- a/drivers/s390/cio/device_ops.c~git-s390 +++ a/drivers/s390/cio/device_ops.c @@ -25,6 +25,16 @@ #include "device.h" #include "chp.h" +/** + * ccw_device_set_options_mask() - set some options and unset the rest + * @cdev: device for which the options are to be set + * @flags: options to be set + * + * All flags specified in @flags are set, all flags not specified in @flags + * are cleared. + * Returns: + * %0 on success, -%EINVAL on an invalid flag combination. + */ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) { /* @@ -40,6 +50,15 @@ int ccw_device_set_options_mask(struct c return 0; } +/** + * ccw_device_set_options() - set some options + * @cdev: device for which the options are to be set + * @flags: options to be set + * + * All flags specified in @flags are set, the remainder is left untouched. + * Returns: + * %0 on success, -%EINVAL if an invalid flag combination would ensue. + */ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) { /* @@ -59,6 +78,13 @@ int ccw_device_set_options(struct ccw_de return 0; } +/** + * ccw_device_clear_options() - clear some options + * @cdev: device for which the options are to be cleared + * @flags: options to be cleared + * + * All flags specified in @flags are cleared, the remainder is left untouched. + */ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) { cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; @@ -67,8 +93,22 @@ void ccw_device_clear_options(struct ccw cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; } -int -ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) +/** + * ccw_device_clear() - terminate I/O request processing + * @cdev: target ccw device + * @intparm: interruption parameter; value is only used if no I/O is + * outstanding, otherwise the intparm associated with the I/O request + * is returned + * + * ccw_device_clear() calls csch on @cdev's subchannel. + * Returns: + * %0 on success, + * -%ENODEV on device not operational, + * -%EINVAL on invalid device state. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) { struct subchannel *sch; int ret; @@ -89,10 +129,33 @@ ccw_device_clear(struct ccw_device *cdev return ret; } -int -ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, - unsigned long intparm, __u8 lpm, __u8 key, - unsigned long flags) +/** + * ccw_device_start_key() - start a s390 channel program with key + * @cdev: target ccw device + * @cpa: logical start address of channel program + * @intparm: user specific interruption parameter; will be presented back to + * @cdev's interrupt handler. Allows a device driver to associate + * the interrupt with a particular I/O request. + * @lpm: defines the channel path to be used for a specific I/O request. A + * value of 0 will make cio use the opm. + * @key: storage key to be used for the I/O + * @flags: additional flags; defines the action to be performed for I/O + * processing. + * + * Start a S/390 channel program. When the interrupt arrives, the + * IRQ handler is called, either immediately, delayed (dev-end missing, + * or sense required) or never (no IRQ handler registered). + * Returns: + * %0, if the operation was successful; + * -%EBUSY, if the device is busy, or status pending; + * -%EACCES, if no path specified in @lpm is operational; + * -%ENODEV, if the device is not operational. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, + unsigned long intparm, __u8 lpm, __u8 key, + unsigned long flags) { struct subchannel *sch; int ret; @@ -135,11 +198,38 @@ ccw_device_start_key(struct ccw_device * return ret; } - -int -ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, - unsigned long intparm, __u8 lpm, __u8 key, - unsigned long flags, int expires) +/** + * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key + * @cdev: target ccw device + * @cpa: logical start address of channel program + * @intparm: user specific interruption parameter; will be presented back to + * @cdev's interrupt handler. Allows a device driver to associate + * the interrupt with a particular I/O request. + * @lpm: defines the channel path to be used for a specific I/O request. A + * value of 0 will make cio use the opm. + * @key: storage key to be used for the I/O + * @flags: additional flags; defines the action to be performed for I/O + * processing. + * @expires: timeout value in jiffies + * + * Start a S/390 channel program. When the interrupt arrives, the + * IRQ handler is called, either immediately, delayed (dev-end missing, + * or sense required) or never (no IRQ handler registered). + * This function notifies the device driver if the channel program has not + * completed during the time specified by @expires. If a timeout occurs, the + * channel program is terminated via xsch, hsch or csch, and the device's + * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). + * Returns: + * %0, if the operation was successful; + * -%EBUSY, if the device is busy, or status pending; + * -%EACCES, if no path specified in @lpm is operational; + * -%ENODEV, if the device is not operational. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, + unsigned long intparm, __u8 lpm, __u8 key, + unsigned long flags, int expires) { int ret; @@ -152,18 +242,67 @@ ccw_device_start_timeout_key(struct ccw_ return ret; } -int -ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, - unsigned long intparm, __u8 lpm, unsigned long flags) +/** + * ccw_device_start() - start a s390 channel program + * @cdev: target ccw device + * @cpa: logical start address of channel program + * @intparm: user specific interruption parameter; will be presented back to + * @cdev's interrupt handler. Allows a device driver to associate + * the interrupt with a particular I/O request. + * @lpm: defines the channel path to be used for a specific I/O request. A + * value of 0 will make cio use the opm. + * @flags: additional flags; defines the action to be performed for I/O + * processing. + * + * Start a S/390 channel program. When the interrupt arrives, the + * IRQ handler is called, either immediately, delayed (dev-end missing, + * or sense required) or never (no IRQ handler registered). + * Returns: + * %0, if the operation was successful; + * -%EBUSY, if the device is busy, or status pending; + * -%EACCES, if no path specified in @lpm is operational; + * -%ENODEV, if the device is not operational. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, + unsigned long intparm, __u8 lpm, unsigned long flags) { return ccw_device_start_key(cdev, cpa, intparm, lpm, PAGE_DEFAULT_KEY, flags); } -int -ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, - unsigned long intparm, __u8 lpm, unsigned long flags, - int expires) +/** + * ccw_device_start_timeout() - start a s390 channel program with timeout + * @cdev: target ccw device + * @cpa: logical start address of channel program + * @intparm: user specific interruption parameter; will be presented back to + * @cdev's interrupt handler. Allows a device driver to associate + * the interrupt with a particular I/O request. + * @lpm: defines the channel path to be used for a specific I/O request. A + * value of 0 will make cio use the opm. + * @flags: additional flags; defines the action to be performed for I/O + * processing. + * @expires: timeout value in jiffies + * + * Start a S/390 channel program. When the interrupt arrives, the + * IRQ handler is called, either immediately, delayed (dev-end missing, + * or sense required) or never (no IRQ handler registered). + * This function notifies the device driver if the channel program has not + * completed during the time specified by @expires. If a timeout occurs, the + * channel program is terminated via xsch, hsch or csch, and the device's + * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). + * Returns: + * %0, if the operation was successful; + * -%EBUSY, if the device is busy, or status pending; + * -%EACCES, if no path specified in @lpm is operational; + * -%ENODEV, if the device is not operational. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, + unsigned long intparm, __u8 lpm, + unsigned long flags, int expires) { return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, PAGE_DEFAULT_KEY, flags, @@ -171,8 +310,23 @@ ccw_device_start_timeout(struct ccw_devi } -int -ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) +/** + * ccw_device_halt() - halt I/O request processing + * @cdev: target ccw device + * @intparm: interruption parameter; value is only used if no I/O is + * outstanding, otherwise the intparm associated with the I/O request + * is returned + * + * ccw_device_halt() calls hsch on @cdev's subchannel. + * Returns: + * %0 on success, + * -%ENODEV on device not operational, + * -%EINVAL on invalid device state, + * -%EBUSY on device busy or interrupt pending. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) { struct subchannel *sch; int ret; @@ -193,8 +347,20 @@ ccw_device_halt(struct ccw_device *cdev, return ret; } -int -ccw_device_resume(struct ccw_device *cdev) +/** + * ccw_device_resume() - resume channel program execution + * @cdev: target ccw device + * + * ccw_device_resume() calls rsch on @cdev's subchannel. + * Returns: + * %0 on success, + * -%ENODEV on device not operational, + * -%EINVAL on invalid device state, + * -%EBUSY on device busy or interrupt pending. + * Context: + * Interrupts disabled, ccw device lock held + */ +int ccw_device_resume(struct ccw_device *cdev) { struct subchannel *sch; @@ -260,11 +426,21 @@ ccw_device_call_handler(struct ccw_devic return 1; } -/* - * Search for CIW command in extended sense data. +/** + * ccw_device_get_ciw() - Search for CIW command in extended sense data. + * @cdev: ccw device to inspect + * @ct: command type to look for + * + * During SenseID, command information words (CIWs) describing special + * commands available to the device may have been stored in the extended + * sense data. This function searches for CIWs of a specified command + * type in the extended sense data. + * Returns: + * %NULL if no extended sense data has been stored or if no CIW of the + * specified command type could be found, + * else a pointer to the CIW of the specified command type. */ -struct ciw * -ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) +struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) { int ciw_cnt; @@ -276,8 +452,14 @@ ccw_device_get_ciw(struct ccw_device *cd return NULL; } -__u8 -ccw_device_get_path_mask(struct ccw_device *cdev) +/** + * ccw_device_get_path_mask() - get currently available paths + * @cdev: ccw device to be queried + * Returns: + * %0 if no subchannel for the device is available, + * else the mask of currently available paths for the ccw device's subchannel. + */ +__u8 ccw_device_get_path_mask(struct ccw_device *cdev) { struct subchannel *sch; @@ -357,8 +539,7 @@ out_unlock: return ret; } -void * -ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) +void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) { struct subchannel *sch; struct chp_id chpid; diff -puN drivers/s390/cio/qdio.c~git-s390 drivers/s390/cio/qdio.c --- a/drivers/s390/cio/qdio.c~git-s390 +++ a/drivers/s390/cio/qdio.c @@ -1024,9 +1024,9 @@ __qdio_outbound_processing(struct qdio_q } static void -qdio_outbound_processing(struct qdio_q *q) +qdio_outbound_processing(unsigned long q) { - __qdio_outbound_processing(q); + __qdio_outbound_processing((struct qdio_q *) q); } /************************* INBOUND ROUTINES *******************************/ @@ -1449,9 +1449,10 @@ out: } static void -tiqdio_inbound_processing(struct qdio_q *q) +tiqdio_inbound_processing(unsigned long q) { - __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); + __tiqdio_inbound_processing((struct qdio_q *) q, + atomic_read(&spare_indicator_usecount)); } static void @@ -1494,9 +1495,9 @@ again: } static void -qdio_inbound_processing(struct qdio_q *q) +qdio_inbound_processing(unsigned long q) { - __qdio_inbound_processing(q); + __qdio_inbound_processing((struct qdio_q *) q); } /************************* MAIN ROUTINES *******************************/ @@ -1760,12 +1761,15 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, s q->handler=input_handler; q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; - q->tasklet.data=(unsigned long)q; /* q->is_thinint_q isn't valid at this time, but - * irq_ptr->is_thinint_irq is */ - q->tasklet.func=(void(*)(unsigned long)) - ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing: - &qdio_inbound_processing); + * irq_ptr->is_thinint_irq is + */ + if (irq_ptr->is_thinint_irq) + tasklet_init(&q->tasklet, tiqdio_inbound_processing, + (unsigned long) q); + else + tasklet_init(&q->tasklet, qdio_inbound_processing, + (unsigned long) q); /* actually this is not used for inbound queues. yet. */ atomic_set(&q->busy_siga_counter,0); @@ -1836,13 +1840,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, s q->last_move_ftc=0; q->handler=output_handler; - q->tasklet.data=(unsigned long)q; - q->tasklet.func=(void(*)(unsigned long)) - &qdio_outbound_processing; - q->timer.function=(void(*)(unsigned long)) - &qdio_outbound_processing; - q->timer.data = (long)q; - init_timer(&q->timer); + tasklet_init(&q->tasklet, qdio_outbound_processing, + (unsigned long) q); + setup_timer(&q->timer, qdio_outbound_processing, + (unsigned long) q); atomic_set(&q->busy_siga_counter,0); q->timing.busy_start=0; @@ -3726,7 +3727,7 @@ qdio_performance_stats_store(struct bus_ #endif /* CONFIG_64BIT */ } } else { - QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n"); + QDIO_PRINT_ERR("QDIO performance_stats: write 0 or 1 to this file!\n"); return -EINVAL; } return count; diff -puN drivers/s390/crypto/zcrypt_mono.c~git-s390 drivers/s390/crypto/zcrypt_mono.c --- a/drivers/s390/crypto/zcrypt_mono.c~git-s390 +++ a/drivers/s390/crypto/zcrypt_mono.c @@ -45,7 +45,7 @@ /** * The module initialization code. */ -int __init zcrypt_init(void) +static int __init zcrypt_init(void) { int rc; @@ -86,7 +86,7 @@ out: /** * The module termination code. */ -void __exit zcrypt_exit(void) +static void __exit zcrypt_exit(void) { zcrypt_cex2a_exit(); zcrypt_pcixcc_exit(); diff -puN drivers/s390/scsi/zfcp_dbf.c~git-s390 drivers/s390/scsi/zfcp_dbf.c --- a/drivers/s390/scsi/zfcp_dbf.c~git-s390 +++ a/drivers/s390/scsi/zfcp_dbf.c @@ -19,8 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include +#include #include "zfcp_ext.h" static u32 dbfsize = 4; @@ -35,17 +35,17 @@ static int zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) { unsigned long long sec; - struct timespec xtime; + struct timespec dbftime; int len = 0; stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); sec = stck >> 12; do_div(sec, 1000000); - xtime.tv_sec = sec; + dbftime.tv_sec = sec; stck -= (sec * 1000000) << 12; - xtime.tv_nsec = ((stck * 1000) >> 12); + dbftime.tv_nsec = ((stck * 1000) >> 12); len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", - label, xtime.tv_sec, xtime.tv_nsec); + label, dbftime.tv_sec, dbftime.tv_nsec); return len; } diff -puN drivers/s390/scsi/zfcp_erp.c~git-s390 drivers/s390/scsi/zfcp_erp.c --- a/drivers/s390/scsi/zfcp_erp.c~git-s390 +++ a/drivers/s390/scsi/zfcp_erp.c @@ -54,7 +54,7 @@ static int zfcp_erp_strategy_check_adapt static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, struct zfcp_port *, struct zfcp_unit *, int); -static inline int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); +static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, struct zfcp_port *, struct zfcp_unit *, int); @@ -106,8 +106,8 @@ static void zfcp_erp_action_cleanup(int, static void zfcp_erp_action_ready(struct zfcp_erp_action *); static int zfcp_erp_action_exists(struct zfcp_erp_action *); -static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *); -static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *); +static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); +static void zfcp_erp_action_to_running(struct zfcp_erp_action *); static void zfcp_erp_memwait_handler(unsigned long); @@ -952,7 +952,7 @@ zfcp_erp_memwait_handler(unsigned long d * action gets an appropriate flag and will be processed * accordingly */ -void zfcp_erp_timeout_handler(unsigned long data) +static void zfcp_erp_timeout_handler(unsigned long data) { struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; struct zfcp_adapter *adapter = erp_action->adapter; @@ -1491,7 +1491,7 @@ zfcp_erp_strategy_statechange(int action return retval; } -static inline int +static int zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) { return @@ -2001,7 +2001,7 @@ zfcp_erp_adapter_strategy_generic(struct * returns: 0 - successful setup * !0 - failed setup */ -int +static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) { int retval; @@ -3248,8 +3248,7 @@ static void zfcp_erp_action_dismiss_unit zfcp_erp_action_dismiss(&unit->erp_action); } -static inline void -zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) +static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) { struct zfcp_adapter *adapter = erp_action->adapter; @@ -3258,8 +3257,7 @@ zfcp_erp_action_to_running(struct zfcp_e list_move(&erp_action->list, &erp_action->adapter->erp_running_head); } -static inline void -zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) +static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) { struct zfcp_adapter *adapter = erp_action->adapter; diff -puN include/asm-s390/atomic.h~git-s390 include/asm-s390/atomic.h --- a/include/asm-s390/atomic.h~git-s390 +++ a/include/asm-s390/atomic.h @@ -69,14 +69,12 @@ typedef struct { static inline int atomic_read(const atomic_t *v) { - barrier(); return v->counter; } static inline void atomic_set(atomic_t *v, int i) { v->counter = i; - barrier(); } static __inline__ int atomic_add_return(int i, atomic_t * v) @@ -193,14 +191,12 @@ typedef struct { static inline long long atomic64_read(const atomic64_t *v) { - barrier(); return v->counter; } static inline void atomic64_set(atomic64_t *v, long long i) { v->counter = i; - barrier(); } static __inline__ long long atomic64_add_return(long long i, atomic64_t * v) diff -puN include/asm-s390/cache.h~git-s390 include/asm-s390/cache.h --- a/include/asm-s390/cache.h~git-s390 +++ a/include/asm-s390/cache.h @@ -14,8 +14,6 @@ #define L1_CACHE_BYTES 256 #define L1_CACHE_SHIFT 8 -#define ARCH_KMALLOC_MINALIGN 8 - #define __read_mostly __attribute__((__section__(".data.read_mostly"))) #endif diff -puN include/asm-s390/ccwdev.h~git-s390 include/asm-s390/ccwdev.h --- a/include/asm-s390/ccwdev.h~git-s390 +++ a/include/asm-s390/ccwdev.h @@ -67,36 +67,53 @@ ccw_device_id_match(const struct ccw_dev return NULL; } -/* The struct ccw device is our replacement for the globally accessible - * ioinfo array. ioinfo will mutate into a subchannel device later. +/** + * struct ccw_device - channel attached device + * @ccwlock: pointer to device lock + * @id: id of this device + * @drv: ccw driver for this device + * @dev: embedded device structure + * @online: online status of device + * @handler: interrupt handler * - * Reference: Documentation/s390/driver-model.txt */ + * @handler is a member of the device rather than the driver since a driver + * can have different interrupt handlers for different ccw devices + * (multi-subchannel drivers). + */ struct ccw_device { spinlock_t *ccwlock; +/* private: */ struct ccw_device_private *private; /* cio private information */ - struct ccw_device_id id; /* id of this device, driver_info is - set by ccw_find_driver */ - struct ccw_driver *drv; /* */ - struct device dev; /* */ +/* public: */ + struct ccw_device_id id; + struct ccw_driver *drv; + struct device dev; int online; - /* This is sick, but a driver can have different interrupt handlers - for different ccw_devices (multi-subchannel drivers)... */ void (*handler) (struct ccw_device *, unsigned long, struct irb *); }; -/* Each ccw driver registers with the ccw root bus */ +/** + * struct ccw driver - device driver for channel attached devices + * @owner: owning module + * @ids: ids supported by this driver + * @probe: function called on probe + * @remove: function called on remove + * @set_online: called when setting device online + * @set_offline: called when setting device offline + * @notify: notify driver of device state changes + * @driver: embedded device driver structure + * @name: device driver name + */ struct ccw_driver { - struct module *owner; /* for automatic MOD_INC_USE_COUNT */ - struct ccw_device_id *ids; /* probe driver with these devs */ - int (*probe) (struct ccw_device *); /* ask driver to probe dev */ + struct module *owner; + struct ccw_device_id *ids; + int (*probe) (struct ccw_device *); void (*remove) (struct ccw_device *); - /* device is no longer available */ int (*set_online) (struct ccw_device *); int (*set_offline) (struct ccw_device *); int (*notify) (struct ccw_device *, int); - struct device_driver driver; /* higher level structure, don't init - this from your driver */ + struct device_driver driver; char *name; }; @@ -124,36 +141,10 @@ extern void ccw_device_clear_options(str /* Allow forced onlining of boxed devices. */ #define CCWDEV_ALLOW_FORCE 0x0008 -/* - * ccw_device_start() - * - * Start a S/390 channel program. When the interrupt arrives, the - * IRQ handler is called, either immediately, delayed (dev-end missing, - * or sense required) or never (no IRQ handler registered). - * Depending on the action taken, ccw_device_start() returns: - * 0 - Success - * -EBUSY - Device busy, or status pending - * -ENODEV - Device not operational - * -EINVAL - Device invalid for operation - */ extern int ccw_device_start(struct ccw_device *, struct ccw1 *, unsigned long, __u8, unsigned long); -/* - * ccw_device_start_timeout() - * - * This function notifies the device driver if the channel program has not - * completed during the specified time. If a timeout occurs, the channel - * program is terminated via xsch(), hsch() or csch(). - */ extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *, unsigned long, __u8, unsigned long, int); -/* - * ccw_device_start_key() - * ccw_device_start_key_timeout() - * - * Same as ccw_device_start() and ccw_device_start_timeout(), except a - * storage key != default key can be provided for the I/O. - */ extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *, unsigned long, __u8, __u8, unsigned long); extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *, diff -puN include/asm-s390/ccwgroup.h~git-s390 include/asm-s390/ccwgroup.h --- a/include/asm-s390/ccwgroup.h~git-s390 +++ a/include/asm-s390/ccwgroup.h @@ -4,19 +4,41 @@ struct ccw_device; struct ccw_driver; +/** + * struct ccwgroup_device - ccw group device + * @creator_id: unique number of the driver + * @state: online/offline state + * @count: number of attached slave devices + * @dev: embedded device structure + * @cdev: variable number of slave devices, allocated as needed + */ struct ccwgroup_device { - unsigned long creator_id; /* unique number of the driver */ + unsigned long creator_id; enum { CCWGROUP_OFFLINE, CCWGROUP_ONLINE, } state; +/* private: */ atomic_t onoff; struct mutex reg_mutex; - unsigned int count; /* number of attached slave devices */ - struct device dev; /* master device */ - struct ccw_device *cdev[0]; /* variable number, allocate as needed */ +/* public: */ + unsigned int count; + struct device dev; + struct ccw_device *cdev[0]; }; +/** + * struct ccwgroup_driver - driver for ccw group devices + * @owner: driver owner + * @name: driver name + * @max_slaves: maximum number of slave devices + * @driver_id: unique id + * @probe: function called on probe + * @remove: function called on remove + * @set_online: function called when device is set online + * @set_offline: function called when device is set offline + * @driver: embedded driver structure + */ struct ccwgroup_driver { struct module *owner; char *name; @@ -28,7 +50,7 @@ struct ccwgroup_driver { int (*set_online) (struct ccwgroup_device *); int (*set_offline) (struct ccwgroup_device *); - struct device_driver driver; /* this driver */ + struct device_driver driver; }; extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); diff -puN include/asm-s390/cio.h~git-s390 include/asm-s390/cio.h --- a/include/asm-s390/cio.h~git-s390 +++ a/include/asm-s390/cio.h @@ -15,30 +15,50 @@ #define LPM_ANYPATH 0xff #define __MAX_CSSID 0 -/* - * subchannel status word +/** + * struct scsw - subchannel status word + * @key: subchannel key + * @sctl: suspend control + * @eswf: esw format + * @cc: deferred condition code + * @fmt: format + * @pfch: prefetch + * @isic: initial-status interruption control + * @alcc: adress-limit checking control + * @ssi: supress-suspended interruption + * @zcc: zero condition code + * @ectl: extended control + * @pno: path not operational + * @res: reserved + * @fctl: function control + * @actl: activity control + * @stctl: status control + * @cpa: channel program address + * @dstat: device status + * @cstat: subchannel status + * @count: residual count */ struct scsw { - __u32 key : 4; /* subchannel key */ - __u32 sctl : 1; /* suspend control */ - __u32 eswf : 1; /* ESW format */ - __u32 cc : 2; /* deferred condition code */ - __u32 fmt : 1; /* format */ - __u32 pfch : 1; /* prefetch */ - __u32 isic : 1; /* initial-status interruption control */ - __u32 alcc : 1; /* address-limit checking control */ - __u32 ssi : 1; /* supress-suspended interruption */ - __u32 zcc : 1; /* zero condition code */ - __u32 ectl : 1; /* extended control */ - __u32 pno : 1; /* path not operational */ - __u32 res : 1; /* reserved */ - __u32 fctl : 3; /* function control */ - __u32 actl : 7; /* activity control */ - __u32 stctl : 5; /* status control */ - __u32 cpa; /* channel program address */ - __u32 dstat : 8; /* device status */ - __u32 cstat : 8; /* subchannel status */ - __u32 count : 16; /* residual count */ + __u32 key : 4; + __u32 sctl : 1; + __u32 eswf : 1; + __u32 cc : 2; + __u32 fmt : 1; + __u32 pfch : 1; + __u32 isic : 1; + __u32 alcc : 1; + __u32 ssi : 1; + __u32 zcc : 1; + __u32 ectl : 1; + __u32 pno : 1; + __u32 res : 1; + __u32 fctl : 3; + __u32 actl : 7; + __u32 stctl : 5; + __u32 cpa; + __u32 dstat : 8; + __u32 cstat : 8; + __u32 count : 16; } __attribute__ ((packed)); #define SCSW_FCTL_CLEAR_FUNC 0x1 @@ -110,11 +130,22 @@ struct scsw { #define SNS2_ENV_DATA_PRESENT 0x10 #define SNS2_INPRECISE_END 0x04 +/** + * struct ccw1 - channel command word + * @cmd_code: command code + * @flags: flags, like IDA adressing, etc. + * @count: byte count + * @cda: data address + * + * The ccw is the basic structure to build channel programs that perform + * operations with the device or the control unit. Only Format-1 channel + * command words are supported. + */ struct ccw1 { - __u8 cmd_code; /* command code */ - __u8 flags; /* flags, like IDA addressing, etc. */ - __u16 count; /* byte count */ - __u32 cda; /* data address */ + __u8 cmd_code; + __u8 flags; + __u16 count; + __u32 cda; } __attribute__ ((packed,aligned(8))); #define CCW_FLAG_DC 0x80 @@ -140,102 +171,162 @@ struct ccw1 { #define SENSE_MAX_COUNT 0x20 +/** + * struct erw - extended report word + * @res0: reserved + * @auth: authorization check + * @pvrf: path-verification-required flag + * @cpt: channel-path timeout + * @fsavf: failing storage address validity flag + * @cons: concurrent sense + * @scavf: secondary ccw address validity flag + * @fsaf: failing storage address format + * @scnt: sense count, if @cons == %1 + * @res16: reserved + */ struct erw { - __u32 res0 : 3; /* reserved */ - __u32 auth : 1; /* Authorization check */ - __u32 pvrf : 1; /* path-verification-required flag */ - __u32 cpt : 1; /* channel-path timeout */ - __u32 fsavf : 1; /* Failing storage address validity flag */ - __u32 cons : 1; /* concurrent-sense */ - __u32 scavf : 1; /* Secondary ccw address validity flag */ - __u32 fsaf : 1; /* Failing storage address format */ - __u32 scnt : 6; /* sense count if cons == 1 */ - __u32 res16 : 16; /* reserved */ + __u32 res0 : 3; + __u32 auth : 1; + __u32 pvrf : 1; + __u32 cpt : 1; + __u32 fsavf : 1; + __u32 cons : 1; + __u32 scavf : 1; + __u32 fsaf : 1; + __u32 scnt : 6; + __u32 res16 : 16; } __attribute__ ((packed)); -/* - * subchannel logout area +/** + * struct sublog - subchannel logout area + * @res0: reserved + * @esf: extended status flags + * @lpum: last path used mask + * @arep: ancillary report + * @fvf: field-validity flags + * @sacc: storage access code + * @termc: termination code + * @devsc: device-status check + * @serr: secondary error + * @ioerr: i/o-error alert + * @seqc: sequence code */ struct sublog { - __u32 res0 : 1; /* reserved */ - __u32 esf : 7; /* extended status flags */ - __u32 lpum : 8; /* last path used mask */ - __u32 arep : 1; /* ancillary report */ - __u32 fvf : 5; /* field-validity flags */ - __u32 sacc : 2; /* storage access code */ - __u32 termc : 2; /* termination code */ - __u32 devsc : 1; /* device-status check */ - __u32 serr : 1; /* secondary error */ - __u32 ioerr : 1; /* i/o-error alert */ - __u32 seqc : 3; /* sequence code */ + __u32 res0 : 1; + __u32 esf : 7; + __u32 lpum : 8; + __u32 arep : 1; + __u32 fvf : 5; + __u32 sacc : 2; + __u32 termc : 2; + __u32 devsc : 1; + __u32 serr : 1; + __u32 ioerr : 1; + __u32 seqc : 3; } __attribute__ ((packed)); -/* - * Format 0 Extended Status Word (ESW) +/** + * struct esw0 - Format 0 Extended Status Word (ESW) + * @sublog: subchannel logout + * @erw: extended report word + * @faddr: failing storage address + * @saddr: secondary ccw address */ struct esw0 { - struct sublog sublog; /* subchannel logout */ - struct erw erw; /* extended report word */ - __u32 faddr[2]; /* failing storage address */ - __u32 saddr; /* secondary ccw address */ + struct sublog sublog; + struct erw erw; + __u32 faddr[2]; + __u32 saddr; } __attribute__ ((packed)); -/* - * Format 1 Extended Status Word (ESW) +/** + * struct esw1 - Format 1 Extended Status Word (ESW) + * @zero0: reserved zeros + * @lpum: last path used mask + * @zero16: reserved zeros + * @erw: extended report word + * @zeros: three fullwords of zeros */ struct esw1 { - __u8 zero0; /* reserved zeros */ - __u8 lpum; /* last path used mask */ - __u16 zero16; /* reserved zeros */ - struct erw erw; /* extended report word */ - __u32 zeros[3]; /* 2 fullwords of zeros */ + __u8 zero0; + __u8 lpum; + __u16 zero16; + struct erw erw; + __u32 zeros[3]; } __attribute__ ((packed)); -/* - * Format 2 Extended Status Word (ESW) +/** + * struct esw2 - Format 2 Extended Status Word (ESW) + * @zero0: reserved zeros + * @lpum: last path used mask + * @dcti: device-connect-time interval + * @erw: extended report word + * @zeros: three fullwords of zeros */ struct esw2 { - __u8 zero0; /* reserved zeros */ - __u8 lpum; /* last path used mask */ - __u16 dcti; /* device-connect-time interval */ - struct erw erw; /* extended report word */ - __u32 zeros[3]; /* 2 fullwords of zeros */ + __u8 zero0; + __u8 lpum; + __u16 dcti; + struct erw erw; + __u32 zeros[3]; } __attribute__ ((packed)); -/* - * Format 3 Extended Status Word (ESW) +/** + * struct esw3 - Format 3 Extended Status Word (ESW) + * @zero0: reserved zeros + * @lpum: last path used mask + * @res: reserved + * @erw: extended report word + * @zeros: three fullwords of zeros */ struct esw3 { - __u8 zero0; /* reserved zeros */ - __u8 lpum; /* last path used mask */ - __u16 res; /* reserved */ - struct erw erw; /* extended report word */ - __u32 zeros[3]; /* 2 fullwords of zeros */ + __u8 zero0; + __u8 lpum; + __u16 res; + struct erw erw; + __u32 zeros[3]; } __attribute__ ((packed)); -/* - * interruption response block +/** + * struct irb - interruption response block + * @scsw: subchannel status word + * @esw: extened status word, 4 formats + * @ecw: extended control word + * + * The irb that is handed to the device driver when an interrupt occurs. For + * solicited interrupts, the common I/O layer already performs checks whether + * a field is valid; a field not being valid is always passed as %0. + * If a unit check occured, @ecw may contain sense data; this is retrieved + * by the common I/O layer itself if the device doesn't support concurrent + * sense (so that the device driver never needs to perform basic sene itself). + * For unsolicited interrupts, the irb is passed as-is (expect for sense data, + * if applicable). */ struct irb { - struct scsw scsw; /* subchannel status word */ - union { /* extended status word, 4 formats */ + struct scsw scsw; + union { struct esw0 esw0; struct esw1 esw1; struct esw2 esw2; struct esw3 esw3; } esw; - __u8 ecw[32]; /* extended control word */ + __u8 ecw[32]; } __attribute__ ((packed,aligned(4))); -/* - * command information word (CIW) layout +/** + * struct ciw - command information word (CIW) layout + * @et: entry type + * @reserved: reserved bits + * @ct: command type + * @cmd: command code + * @count: command count */ struct ciw { - __u32 et : 2; /* entry type */ - __u32 reserved : 2; /* reserved */ - __u32 ct : 4; /* command type */ - __u32 cmd : 8; /* command */ - __u32 count : 16; /* coun */ + __u32 et : 2; + __u32 reserved : 2; + __u32 ct : 4; + __u32 cmd : 8; + __u32 count : 16; } __attribute__ ((packed)); #define CIW_TYPE_RCD 0x0 /* read configuration data */ @@ -258,11 +349,32 @@ struct ciw { /* Sick revalidation of device. */ #define CIO_REVALIDATE 0x0008 +/** + * struct ccw_dev_id - unique identifier for ccw devices + * @ssid: subchannel set id + * @devno: device number + * + * This structure is not directly based on any hardware structure. The + * hardware identifies a device by its device number and its subchannel, + * which is in turn identified by its id. In order to get a unique identifier + * for ccw devices across subchannel sets, @struct ccw_dev_id has been + * introduced. + */ struct ccw_dev_id { u8 ssid; u16 devno; }; +/** + * ccw_device_id_is_equal() - compare two ccw_dev_ids + * @dev_id1: a ccw_dev_id + * @dev_id2: another ccw_dev_id + * Returns: + * %1 if the two structures are equal field-by-field, + * %0 if not. + * Context: + * any + */ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, struct ccw_dev_id *dev_id2) { diff -puN include/asm-s390/cmb.h~git-s390 include/asm-s390/cmb.h --- a/include/asm-s390/cmb.h~git-s390 +++ a/include/asm-s390/cmb.h @@ -1,29 +1,29 @@ #ifndef S390_CMB_H #define S390_CMB_H /** - * struct cmbdata -- channel measurement block data for user space + * struct cmbdata - channel measurement block data for user space + * @size: size of the stored data + * @elapsed_time: time since last sampling + * @ssch_rsch_count: number of ssch and rsch + * @sample_count: number of samples + * @device_connect_time: time of device connect + * @function_pending_time: time of function pending + * @device_disconnect_time: time of device disconnect + * @control_unit_queuing_time: time of control unit queuing + * @device_active_only_time: time of device active only + * @device_busy_time: time of device busy (ext. format) + * @initial_command_response_time: initial command response time (ext. format) * - * @size: size of the stored data - * @ssch_rsch_count: XXX - * @sample_count: - * @device_connect_time: - * @function_pending_time: - * @device_disconnect_time: - * @control_unit_queuing_time: - * @device_active_only_time: - * @device_busy_time: - * @initial_command_response_time: - * - * all values are stored as 64 bit for simplicity, especially + * All values are stored as 64 bit for simplicity, especially * in 32 bit emulation mode. All time values are normalized to * nanoseconds. * Currently, two formats are known, which differ by the size of * this structure, i.e. the last two members are only set when * the extended channel measurement facility (first shipped in * z990 machines) is activated. - * Potentially, more fields could be added, which results in a + * Potentially, more fields could be added, which would result in a * new ioctl number. - **/ + */ struct cmbdata { __u64 size; __u64 elapsed_time; @@ -41,53 +41,18 @@ struct cmbdata { }; /* enable channel measurement */ -#define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) +#define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER, 32) /* enable channel measurement */ -#define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) +#define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER, 33) /* read channel measurement data */ -#define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) +#define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata) #ifdef __KERNEL__ struct ccw_device; -/** - * enable_cmf() - switch on the channel measurement for a specific device - * @cdev: The ccw device to be enabled - * returns 0 for success or a negative error value. - * - * Context: - * non-atomic - **/ extern int enable_cmf(struct ccw_device *cdev); - -/** - * disable_cmf() - switch off the channel measurement for a specific device - * @cdev: The ccw device to be disabled - * returns 0 for success or a negative error value. - * - * Context: - * non-atomic - **/ extern int disable_cmf(struct ccw_device *cdev); - -/** - * cmf_read() - read one value from the current channel measurement block - * @cmf: the channel to be read - * @index: the name of the value that is read - * - * Context: - * any - **/ - extern u64 cmf_read(struct ccw_device *cdev, int index); -/** - * cmf_readall() - read one value from the current channel measurement block - * @cmf: the channel to be read - * @data: a pointer to a data block that will be filled - * - * Context: - * any - **/ -extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data); +extern int cmf_readall(struct ccw_device *cdev, struct cmbdata *data); #endif /* __KERNEL__ */ #endif /* S390_CMB_H */ diff -puN include/asm-s390/s390_ext.h~git-s390 include/asm-s390/s390_ext.h --- a/include/asm-s390/s390_ext.h~git-s390 +++ a/include/asm-s390/s390_ext.h @@ -5,7 +5,7 @@ * include/asm-s390/s390_ext.h * * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright IBM Corp. 1999,2007 * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), * Martin Schwidefsky (schwidefsky@de.ibm.com) */ @@ -14,15 +14,11 @@ typedef void (*ext_int_handler_t)(__u16 code); -/* - * Warning: if you change ext_int_info_t you have to change the - * external interrupt handler in entry.S too. - */ typedef struct ext_int_info_t { struct ext_int_info_t *next; ext_int_handler_t handler; __u16 code; -} __attribute__ ((packed)) ext_int_info_t; +} ext_int_info_t; extern ext_int_info_t *ext_int_hash[]; diff -puN include/asm-s390/system.h~git-s390 include/asm-s390/system.h --- a/include/asm-s390/system.h~git-s390 +++ a/include/asm-s390/system.h @@ -130,6 +130,8 @@ extern void pfault_fini(void); __ret; \ }) +extern void __xchg_called_with_bad_pointer(void); + static inline unsigned long __xchg(unsigned long x, void * ptr, int size) { unsigned long addr, old; @@ -150,8 +152,7 @@ static inline unsigned long __xchg(unsig : "=&d" (old), "=m" (*(int *) addr) : "d" (x << shift), "d" (~(255 << shift)), "a" (addr), "m" (*(int *) addr) : "memory", "cc", "0"); - x = old >> shift; - break; + return old >> shift; case 2: addr = (unsigned long) ptr; shift = (2 ^ (addr & 2)) << 3; @@ -166,8 +167,7 @@ static inline unsigned long __xchg(unsig : "=&d" (old), "=m" (*(int *) addr) : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr), "m" (*(int *) addr) : "memory", "cc", "0"); - x = old >> shift; - break; + return old >> shift; case 4: asm volatile( " l %0,0(%3)\n" @@ -176,8 +176,7 @@ static inline unsigned long __xchg(unsig : "=&d" (old), "=m" (*(int *) ptr) : "d" (x), "a" (ptr), "m" (*(int *) ptr) : "memory", "cc"); - x = old; - break; + return old; #ifdef __s390x__ case 8: asm volatile( @@ -187,11 +186,11 @@ static inline unsigned long __xchg(unsig : "=&d" (old), "=m" (*(long *) ptr) : "d" (x), "a" (ptr), "m" (*(long *) ptr) : "memory", "cc"); - x = old; - break; + return old; #endif /* __s390x__ */ - } - return x; + } + __xchg_called_with_bad_pointer(); + return x; } /* @@ -206,6 +205,8 @@ static inline unsigned long __xchg(unsig ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ (unsigned long)(n),sizeof(*(ptr)))) +extern void __cmpxchg_called_with_bad_pointer(void); + static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) { @@ -270,7 +271,8 @@ __cmpxchg(volatile void *ptr, unsigned l return prev; #endif /* __s390x__ */ } - return old; + __cmpxchg_called_with_bad_pointer(); + return old; } /* _