From c406abd3a6d0cf5ce8db4db155a729a28fb98c4f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 14:56:13 +0200 Subject: [S390] cleanup bitops.h. Encapsulate complete bitops.h with #ifdef __KERNEL__ and remove the now superfluous ALIGN_CS define and its users. This patch is needed for compiling klibc. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- include/asm-s390/bitops.h | 42 +++--------------------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 4d2b126ba159..0ddcdba79e4a 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -12,6 +12,9 @@ * Copyright (C) 1992, Linus Torvalds * */ + +#ifdef __KERNEL__ + #include /* @@ -50,19 +53,6 @@ * with operation of the form "set_bit(bitnr, flags)". */ -/* set ALIGN_CS to 1 if the SMP safe bit operations should - * align the address to 4 byte boundary. It seems to work - * without the alignment. - */ -#ifdef __KERNEL__ -#define ALIGN_CS 0 -#else -#define ALIGN_CS 1 -#ifndef CONFIG_SMP -#error "bitops won't work without CONFIG_SMP" -#endif -#endif - /* bitmap tables from arch/S390/kernel/bitmap.S */ extern const char _oi_bitmap[]; extern const char _ni_bitmap[]; @@ -121,10 +111,6 @@ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make OR mask */ @@ -141,10 +127,6 @@ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make AND mask */ @@ -161,10 +143,6 @@ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make XOR mask */ @@ -182,10 +160,6 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make OR/test mask */ @@ -205,10 +179,6 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make AND/test mask */ @@ -228,10 +198,6 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; -#if ALIGN_CS == 1 - nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ - addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ -#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make XOR/test mask */ @@ -834,8 +800,6 @@ static inline int sched_find_first_bit(unsigned long *b) #include -#ifdef __KERNEL__ - /* * ATTENTION: intel byte ordering convention for ext2 and minix !! * bit 0 is the LSB of addr; bit 31 is the MSB of addr; -- cgit v1.2.3 From 7380534314865528ef080593b291bba32fba60e8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 14:56:23 +0200 Subject: [S390] incomplete stack traces. show_stack() passes a pointer to the current stack frame to show_trace(). Because of tail call optimization the pointer doesn't point to the original stack frame anymory and therefore traces are wrong. Don't pass the pointer of the current stack frame to show_trace(). Instead let show_trace() calculate the pointer on its own. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/traps.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index a46793beeddd..b7630436f693 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -150,13 +150,11 @@ void show_stack(struct task_struct *task, unsigned long *sp) unsigned long *stack; int i; - // debugging aid: "show_stack(NULL);" prints the - // back trace for this cpu. - if (!sp) - sp = task ? (unsigned long *) task->thread.ksp : __r15; + stack = task ? (unsigned long *) task->thread.ksp : __r15; + else + stack = sp; - stack = sp; for (i = 0; i < kstack_depth_to_print; i++) { if (((addr_t) stack & (THREAD_SIZE-1)) == 0) break; -- cgit v1.2.3 From d7d23702554dc13297cff5eaf7a551c802daeab3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 14:56:32 +0200 Subject: [S390] memory detection. The wrong base register is used to read a value from the sclp data structure. The value is used to calculate the memory size. Use correct register %r4. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/head31.S | 2 +- arch/s390/kernel/head64.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 2d3b089bfb83..8f38bfd642cf 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -87,7 +87,7 @@ startup:basr %r13,0 # get base ic %r3,.Lscpa1-PARMAREA(%r4) chi %r3,0x00 jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r13) + l %r3,.Lscpa2-PARMAREA(%r4) .Lcompmem: mr %r2,%r1 # mem in MB on 128-bit l %r1,.Lonemb-.LPG1(%r13) diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index f08c06f45d5c..ad5d87f3aef3 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -86,7 +86,7 @@ startup:basr %r13,0 # get base ic %r3,.Lscpa1-PARMAREA(%r4) chi %r3,0x00 jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r13) + l %r3,.Lscpa2-PARMAREA(%r4) .Lcompmem: mlgr %r2,%r1 # mem in MB on 128-bit l %r1,.Lonemb-.LPG1(%r13) -- cgit v1.2.3 From da039bd1e872b89e1c92c6c891c43b96d0a1bc41 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 29 Jun 2006 14:56:38 +0200 Subject: [S390] cio long busy in read configuration data. Trying to set a DASD root device online can fail under some circumstances with the message "Read configuration data returned error -5". The cause is that read configuration data incorrectly aborts with -EIO when it encounters a temporary busy condition at a storage server. Perform retry when encountering temporary busy conditions. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_ops.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 795abb5a65ba..5c9904b418e1 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -270,7 +270,8 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) * We didn't get channel end / device end. Check if path * verification has been started; we can retry after it has * finished. We also retry unit checks except for command reject - * or intervention required. + * or intervention required. Also check for long busy + * conditions. */ if (cdev->private->flags.doverify || cdev->private->state == DEV_STATE_VERIFY) @@ -279,6 +280,10 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) !(irb->ecw[0] & (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) cdev->private->intparm = -EAGAIN; + else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) && + (irb->scsw.dstat & DEV_STAT_DEV_END) && + (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP)) + cdev->private->intparm = -EAGAIN; else cdev->private->intparm = -EIO; -- cgit v1.2.3 From 231caa1cac555bdd5cb64bf91b554b38e8ddf715 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 29 Jun 2006 14:56:45 +0200 Subject: [S390] channel measurement fix. Specify correct sizeof() in chp_measurement_read() and return correct amount of read data. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 72187e54dcac..4a9da5bdd535 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -918,12 +918,13 @@ chp_measurement_read(struct kobject *kobj, char *buf, loff_t off, size_t count) chp = to_channelpath(container_of(kobj, struct device, kobj)); css = to_css(chp->dev.parent); - size = sizeof(struct cmg_chars); + size = sizeof(struct cmg_entry); /* Only allow single reads. */ if (off || count < size) return 0; chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); + count = size; return count; } -- cgit v1.2.3 From 887ab5992925736ab23985c35f8149739e9de354 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 29 Jun 2006 14:56:52 +0200 Subject: [S390] ccwgroup device unregister. Work around the problem that a device cannot be unregistered from driver_for_each_device() because of klist node refcounting: Get device after device owned by the driver to be unregistered with driver_find_device() and then unregister it. This works because driver_get_device() gets us out of the region of the elevated klist node refcount. driver_find_device() will always get the next device in the list after the found one has been unregistered. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index bdfee7fbaa2e..c7319a07ba35 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -404,21 +404,24 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) } static int -__ccwgroup_driver_unregister_device(struct device *dev, void *data) +__ccwgroup_match_all(struct device *dev, void *data) { - __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); - device_unregister(dev); - put_device(dev); - return 0; + return 1; } void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) { + struct device *dev; + /* We don't want ccwgroup devices to live longer than their driver. */ get_driver(&cdriver->driver); - driver_for_each_device(&cdriver->driver, NULL, NULL, - __ccwgroup_driver_unregister_device); + while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, + __ccwgroup_match_all))) { + __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); + device_unregister(dev); + put_device(dev); + } put_driver(&cdriver->driver); driver_unregister(&cdriver->driver); } -- cgit v1.2.3 From 40154b824331cd9c81c06545761338f3d80a36e2 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 29 Jun 2006 14:57:03 +0200 Subject: [S390] cio async subchannel reprobe. Changes in the DASD driver require an asynchronous implementation of the subchannel reprobe loop. This loop was so far only used by the blacklisting mechanism but is now available to all CCW device drivers. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 35 +----------------------- drivers/s390/cio/css.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ drivers/s390/cio/device.c | 4 +-- drivers/s390/cio/device.h | 6 +++++ include/asm-s390/cio.h | 2 ++ 5 files changed, 74 insertions(+), 36 deletions(-) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 0960bef7b199..15b895496a45 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -224,39 +224,6 @@ is_blacklisted (int ssid, int devno) } #ifdef CONFIG_PROC_FS -static int -__s390_redo_validation(struct subchannel_id schid, void *data) -{ - int ret; - struct subchannel *sch; - - sch = get_subchannel_by_schid(schid); - if (sch) { - /* Already known. */ - put_device(&sch->dev); - return 0; - } - ret = css_probe_device(schid); - if (ret == -ENXIO) - return ret; /* We're through. */ - if (ret == -ENOMEM) - /* Stop validation for now. Bad, but no need for a panic. */ - return ret; - return 0; -} - -/* - * Function: s390_redo_validation - * Look for no longer blacklisted devices - * FIXME: there must be a better way to do this */ -static inline void -s390_redo_validation (void) -{ - CIO_TRACE_EVENT (0, "redoval"); - - for_each_subchannel(__s390_redo_validation, NULL); -} - /* * Function: blacklist_parse_proc_parameters * parse the stuff which is piped to /proc/cio_ignore @@ -281,7 +248,7 @@ blacklist_parse_proc_parameters (char *buf) return; } - s390_redo_validation (); + css_schedule_reprobe(); } /* Iterator struct for all devices. */ diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 74ea8aac4b7d..1d3be80797f8 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -19,9 +19,11 @@ #include "cio_debug.h" #include "ioasm.h" #include "chsc.h" +#include "device.h" int need_rescan = 0; int css_init_done = 0; +static int need_reprobe = 0; static int max_ssid = 0; struct channel_subsystem *css[__MAX_CSSID + 1]; @@ -339,6 +341,67 @@ typedef void (*workfunc)(void *); DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); struct workqueue_struct *slow_path_wq; +/* Reprobe subchannel if unregistered. */ +static int reprobe_subchannel(struct subchannel_id schid, void *data) +{ + struct subchannel *sch; + int ret; + + CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n", + schid.ssid, schid.sch_no); + if (need_reprobe) + return -EAGAIN; + + sch = get_subchannel_by_schid(schid); + if (sch) { + /* Already known. */ + put_device(&sch->dev); + return 0; + } + + ret = css_probe_device(schid); + switch (ret) { + case 0: + break; + case -ENXIO: + case -ENOMEM: + /* These should abort looping */ + break; + default: + ret = 0; + } + + return ret; +} + +/* Work function used to reprobe all unregistered subchannels. */ +static void reprobe_all(void *data) +{ + int ret; + + CIO_MSG_EVENT(2, "reprobe start\n"); + + need_reprobe = 0; + /* Make sure initial subchannel scan is done. */ + wait_event(ccw_device_init_wq, + atomic_read(&ccw_device_init_count) == 0); + ret = for_each_subchannel(reprobe_subchannel, NULL); + + CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, + need_reprobe); +} + +DECLARE_WORK(css_reprobe_work, reprobe_all, NULL); + +/* Schedule reprobing of all unregistered subchannels. */ +void css_schedule_reprobe(void) +{ + need_reprobe = 1; + queue_work(ccw_device_work, &css_reprobe_work); +} + +EXPORT_SYMBOL_GPL(css_schedule_reprobe); + /* * Rescan for new devices. FIXME: This is slow. * This function is called when we have lost CRWs due to overflows and we have diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 8e3053c2a451..eafde43e8410 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -133,8 +133,8 @@ struct css_driver io_subchannel_driver = { struct workqueue_struct *ccw_device_work; struct workqueue_struct *ccw_device_notify_work; -static wait_queue_head_t ccw_device_init_wq; -static atomic_t ccw_device_init_count; +wait_queue_head_t ccw_device_init_wq; +atomic_t ccw_device_init_count; static int __init init_ccw_bus_type (void) diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 11587ebb7289..8e0d1db3dd4e 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -1,6 +1,10 @@ #ifndef S390_DEVICE_H #define S390_DEVICE_H +#include +#include +#include + /* * states of the device statemachine */ @@ -67,6 +71,8 @@ dev_fsm_final_state(struct ccw_device *cdev) extern struct workqueue_struct *ccw_device_work; extern struct workqueue_struct *ccw_device_notify_work; +extern wait_queue_head_t ccw_device_init_wq; +extern atomic_t ccw_device_init_count; void io_subchannel_recog_done(struct ccw_device *cdev); diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index 089cf567c317..2b1619306351 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h @@ -276,6 +276,8 @@ extern void wait_cons_dev(void); extern void clear_all_subchannels(void); +extern void css_schedule_reprobe(void); + #endif #endif -- cgit v1.2.3 From 4980082db1a8aa3ec45aa22cd4a10021955e22ed Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 14:57:25 +0200 Subject: [S390] __syscall_return error check. Fix __syscall_return macro: valid error numbers are in the range of -1..-4095. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- include/asm-s390/unistd.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index e21443d3ea1d..aa7a243862e1 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -394,11 +394,9 @@ #ifdef __KERNEL__ -/* user-visible error numbers are in the range -1 - -122: see */ - #define __syscall_return(type, res) \ do { \ - if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + if ((unsigned long)(res) >= (unsigned long)(-4095)) {\ errno = -(res); \ res = -1; \ } \ -- cgit v1.2.3 From 06fa46a2fcb7e13386707a3eac74f11140a9f818 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Jun 2006 14:57:32 +0200 Subject: [S390] console_unblank woes. The software watchdog calls machine_restart from a timer function. The s390 machine_restart calls console_unblank to flush the console output. This is needed for panic to get the panic message printed. If console_unblank is called in interrupt a BUG is triggered in acquire_console_sem. That makes the software watchdog panic instead of restarting the machine. To get around this problem the call to console_unblank is made conditionally on !in_interrupt() || oops_in_progress. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b282034452a4..813444aac7d7 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -289,19 +289,34 @@ void (*_machine_power_off)(void) = do_machine_power_off_nonsmp; void machine_restart(char *command) { - console_unblank(); + if (!in_interrupt() || oops_in_progress) + /* + * Only unblank the console if we are called in enabled + * context or a bust_spinlocks cleared the way for us. + */ + console_unblank(); _machine_restart(command); } void machine_halt(void) { - console_unblank(); + if (!in_interrupt() || oops_in_progress) + /* + * Only unblank the console if we are called in enabled + * context or a bust_spinlocks cleared the way for us. + */ + console_unblank(); _machine_halt(); } void machine_power_off(void) { - console_unblank(); + if (!in_interrupt() || oops_in_progress) + /* + * Only unblank the console if we are called in enabled + * context or a bust_spinlocks cleared the way for us. + */ + console_unblank(); _machine_power_off(); } -- cgit v1.2.3 From 132fab13635a56a8151641671a2f896be00fd215 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Jun 2006 14:57:39 +0200 Subject: [S390] modular 3270 driver. The initial i/o to a 3270 device is done using the static module variables raw3270_init_data and raw3270_init_request. If the 3270 device driver is built as a module and gets loaded above 2GB, the initial i/o will fail because these variables will get addresses > 2GB. To make it work the two variables are moved to struct raw3270 and the data structure is allocated with GFP_DMA. Signed-off-by: Martin Schwidefsky --- drivers/s390/char/raw3270.c | 67 +++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index eecb2afad5c2..3c1314b7391b 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -50,6 +50,9 @@ struct raw3270 { unsigned char *ascebc; /* ascii -> ebcdic table */ struct class_device *clttydev; /* 3270-class tty device ptr */ struct class_device *cltubdev; /* 3270-class tub device ptr */ + + struct raw3270_request init_request; + unsigned char init_data[256]; }; /* raw3270->flags */ @@ -484,8 +487,6 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */ } __attribute__ ((packed)) aua; } __attribute__ ((packed)); -static unsigned char raw3270_init_data[256]; -static struct raw3270_request raw3270_init_request; static struct diag210 raw3270_init_diag210; static DECLARE_MUTEX(raw3270_init_sem); @@ -644,17 +645,17 @@ __raw3270_size_device(struct raw3270 *rp) * required (3270 device switched to 'stand-by') and command * rejects (old devices that can't do 'read partition'). */ - memset(&raw3270_init_request, 0, sizeof(raw3270_init_request)); - memset(raw3270_init_data, 0, sizeof(raw3270_init_data)); - /* Store 'read partition' data stream to raw3270_init_data */ - memcpy(raw3270_init_data, wbuf, sizeof(wbuf)); - INIT_LIST_HEAD(&raw3270_init_request.list); - raw3270_init_request.ccw.cmd_code = TC_WRITESF; - raw3270_init_request.ccw.flags = CCW_FLAG_SLI; - raw3270_init_request.ccw.count = sizeof(wbuf); - raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); - - rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); + memset(&rp->init_request, 0, sizeof(rp->init_request)); + memset(&rp->init_data, 0, 256); + /* Store 'read partition' data stream to init_data */ + memcpy(&rp->init_data, wbuf, sizeof(wbuf)); + INIT_LIST_HEAD(&rp->init_request.list); + rp->init_request.ccw.cmd_code = TC_WRITESF; + rp->init_request.ccw.flags = CCW_FLAG_SLI; + rp->init_request.ccw.count = sizeof(wbuf); + rp->init_request.ccw.cda = (__u32) __pa(&rp->init_data); + + rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); if (rc) /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ return rc; @@ -679,18 +680,18 @@ __raw3270_size_device(struct raw3270 *rp) * The device accepted the 'read partition' command. Now * set up a read ccw and issue it. */ - raw3270_init_request.ccw.cmd_code = TC_READMOD; - raw3270_init_request.ccw.flags = CCW_FLAG_SLI; - raw3270_init_request.ccw.count = sizeof(raw3270_init_data); - raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); - rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); + rp->init_request.ccw.cmd_code = TC_READMOD; + rp->init_request.ccw.flags = CCW_FLAG_SLI; + rp->init_request.ccw.count = sizeof(rp->init_data); + rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); + rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); if (rc) return rc; /* Got a Query Reply */ - count = sizeof(raw3270_init_data) - raw3270_init_request.rescnt; - uap = (struct raw3270_ua *) (raw3270_init_data + 1); + count = sizeof(rp->init_data) - rp->init_request.rescnt; + uap = (struct raw3270_ua *) (rp->init_data + 1); /* Paranoia check. */ - if (raw3270_init_data[0] != 0x88 || uap->uab.qcode != 0x81) + if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81) return -EOPNOTSUPP; /* Copy rows/columns of default Usable Area */ rp->rows = uap->uab.h; @@ -749,18 +750,18 @@ raw3270_reset_device(struct raw3270 *rp) int rc; down(&raw3270_init_sem); - memset(&raw3270_init_request, 0, sizeof(raw3270_init_request)); - memset(raw3270_init_data, 0, sizeof(raw3270_init_data)); - /* Store reset data stream to raw3270_init_data/raw3270_init_request */ - raw3270_init_data[0] = TW_KR; - INIT_LIST_HEAD(&raw3270_init_request.list); - raw3270_init_request.ccw.cmd_code = TC_EWRITEA; - raw3270_init_request.ccw.flags = CCW_FLAG_SLI; - raw3270_init_request.ccw.count = 1; - raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); + memset(&rp->init_request, 0, sizeof(rp->init_request)); + memset(&rp->init_data, 0, sizeof(rp->init_data)); + /* Store reset data stream to init_data/init_request */ + rp->init_data[0] = TW_KR; + INIT_LIST_HEAD(&rp->init_request.list); + rp->init_request.ccw.cmd_code = TC_EWRITEA; + rp->init_request.ccw.flags = CCW_FLAG_SLI; + rp->init_request.ccw.count = 1; + rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); rp->view = &raw3270_init_view; raw3270_init_view.dev = rp; - rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); + rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); raw3270_init_view.dev = 0; rp->view = 0; up(&raw3270_init_sem); @@ -854,7 +855,7 @@ raw3270_setup_console(struct ccw_device *cdev) char *ascebc; int rc; - rp = (struct raw3270 *) alloc_bootmem(sizeof(struct raw3270)); + rp = (struct raw3270 *) alloc_bootmem_low(sizeof(struct raw3270)); ascebc = (char *) alloc_bootmem(256); rc = raw3270_setup_device(cdev, rp, ascebc); if (rc) @@ -895,7 +896,7 @@ raw3270_create_device(struct ccw_device *cdev) char *ascebc; int rc; - rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL); + rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA); if (!rp) return ERR_PTR(-ENOMEM); ascebc = kmalloc(256, GFP_KERNEL); -- cgit v1.2.3 From f45a43d847c96949d22e702879e52385a1547f6b Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 29 Jun 2006 14:57:46 +0200 Subject: [S390] missing check in dasd_eer_open. Check the return value of kzalloc in dasd_eer_open. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 2d8af709947f..9d574ede1b1d 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -521,6 +521,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) unsigned long flags; eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL); + if (!eerb) + return -ENOMEM; eerb->buffer_page_count = eer_pages; if (eerb->buffer_page_count < 1 || eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { -- cgit v1.2.3 From 445b5b499e0ca1584ee3aa8af298c9ef8c84d711 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Thu, 29 Jun 2006 14:57:52 +0200 Subject: [S390] dasd_eckd_dump_sense bug. The ccw dump function dasd_eckd_dump_ccw_range can crash because it does not take care about the IDAL flag in the ccw. Check for IDALs flag set in CCW and follow the indirect list to print the data that is refered by the ccw. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 145 +++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 7d5a6cee4bd8..7565d30f8c2f 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1521,6 +1521,40 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) } } +/* + * Dump the range of CCWs into 'page' buffer + * and return number of printed chars. + */ +static inline int +dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) +{ + int len, count; + char *datap; + + len = 0; + while (from <= to) { + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " CCW %p: %08X %08X DAT:", + from, ((int *) from)[0], ((int *) from)[1]); + + /* get pointer to data (consider IDALs) */ + if (from->flags & CCW_FLAG_IDA) + datap = (char *) *((addr_t *) (addr_t) from->cda); + else + datap = (char *) ((addr_t) from->cda); + + /* dump data (max 32 bytes) */ + for (count = 0; count < from->count && count < 32; count++) { + if (count % 8 == 0) len += sprintf(page + len, " "); + if (count % 4 == 0) len += sprintf(page + len, " "); + len += sprintf(page + len, "%02x", datap[count]); + } + len += sprintf(page + len, "\n"); + from++; + } + return len; +} + /* * Print sense data and related channel program. * Parts are printed because printk buffer is only 1024 bytes. @@ -1530,8 +1564,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, struct irb *irb) { char *page; - struct ccw1 *act, *end, *last; - int len, sl, sct, count; + struct ccw1 *first, *last, *fail, *from, *to; + int len, sl, sct; page = (char *) get_zeroed_page(GFP_ATOMIC); if (page == NULL) { @@ -1539,7 +1573,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, "No memory to dump sense data"); return; } - len = sprintf(page, KERN_ERR PRINTK_HEADER + /* dump the sense data */ + len = sprintf(page, KERN_ERR PRINTK_HEADER " I/O status report for device %s:\n", device->cdev->dev.bus_id); len += sprintf(page + len, KERN_ERR PRINTK_HEADER @@ -1564,87 +1599,55 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, if (irb->ecw[27] & DASD_SENSE_BIT_0) { /* 24 Byte Sense Data */ - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " 24 Byte: %x MSG %x, " - "%s MSGb to SYSOP\n", - irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, - irb->ecw[1] & 0x10 ? "" : "no"); + sprintf(page + len, KERN_ERR PRINTK_HEADER + " 24 Byte: %x MSG %x, " + "%s MSGb to SYSOP\n", + irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, + irb->ecw[1] & 0x10 ? "" : "no"); } else { /* 32 Byte Sense Data */ - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " 32 Byte: Format: %x " - "Exception class %x\n", - irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); + sprintf(page + len, KERN_ERR PRINTK_HEADER + " 32 Byte: Format: %x " + "Exception class %x\n", + irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); } } else { - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " SORRY - NO VALID SENSE AVAILABLE\n"); + sprintf(page + len, KERN_ERR PRINTK_HEADER + " SORRY - NO VALID SENSE AVAILABLE\n"); } - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); - - /* dump the Channel Program */ - /* print first CCWs (maximum 8) */ - act = req->cpaddr; - for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); - end = min(act + 8, last); - len = sprintf(page, KERN_ERR PRINTK_HEADER + printk("%s", page); + + /* dump the Channel Program (max 140 Bytes per line) */ + /* Count CCW and print first CCWs (maximum 1024 % 140 = 7) */ + first = req->cpaddr; + for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); + to = min(first + 6, last); + len = sprintf(page, KERN_ERR PRINTK_HEADER " Related CP in req: %p\n", req); - while (act <= end) { - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " CCW %p: %08X %08X DAT:", - act, ((int *) act)[0], ((int *) act)[1]); - for (count = 0; count < 32 && count < act->count; - count += sizeof(int)) - len += sprintf(page + len, " %08X", - ((int *) (addr_t) act->cda) - [(count>>2)]); - len += sprintf(page + len, "\n"); - act++; - } - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); + dasd_eckd_dump_ccw_range(first, to, page + len); + printk("%s", page); - /* print failing CCW area */ + /* print failing CCW area (maximum 4) */ + /* scsw->cda is either valid or zero */ len = 0; - if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) { - act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2; - len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); - } - end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last); - while (act <= end) { - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " CCW %p: %08X %08X DAT:", - act, ((int *) act)[0], ((int *) act)[1]); - for (count = 0; count < 32 && count < act->count; - count += sizeof(int)) - len += sprintf(page + len, " %08X", - ((int *) (addr_t) act->cda) - [(count>>2)]); - len += sprintf(page + len, "\n"); - act++; + from = ++to; + fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */ + if (from < fail - 2) { + from = fail - 2; /* there is a gap - print header */ + len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n"); } + to = min(fail + 1, last); + len += dasd_eckd_dump_ccw_range(from, to, page + len); - /* print last CCWs */ - if (act < last - 2) { - act = last - 2; + /* print last CCWs (maximum 2) */ + from = max(from, ++to); + if (from < last - 1) { + from = last - 1; /* there is a gap - print header */ len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); } - while (act <= last) { - len += sprintf(page + len, KERN_ERR PRINTK_HEADER - " CCW %p: %08X %08X DAT:", - act, ((int *) act)[0], ((int *) act)[1]); - for (count = 0; count < 32 && count < act->count; - count += sizeof(int)) - len += sprintf(page + len, " %08X", - ((int *) (addr_t) act->cda) - [(count>>2)]); - len += sprintf(page + len, "\n"); - act++; - } + len += dasd_eckd_dump_ccw_range(from, last, page + len); if (len > 0) - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); + printk("%s", page); free_page((unsigned long) page); } -- cgit v1.2.3 From 9faf06547efe11ccb51678c6805037c7377b85ee Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Thu, 29 Jun 2006 14:57:58 +0200 Subject: [S390] add __cpuinit to appldata cpu hotplug notifier. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/appldata/appldata_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 54d35c130907..f549a80cedb3 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -633,7 +633,7 @@ appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -static int +static int __cpuinit appldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { -- cgit v1.2.3 From 63b122466484e44d09af12bba33b34019757a3c2 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Jun 2006 14:58:05 +0200 Subject: [S390] virtual cpu accounting vs. machine checks. If a machine checks interrupts the external or the i/o interrupt handler before they have completed the cpu time calculations, the accounting goes wrong. After the cpu returned from the machine check handler to the interrupted interrupt handler, a negative cpu time delta can occur. If the accumulated cpu time in lowcore is small enough this value can get negative as well. The next jiffy interrupt will pick up that negative value, shift it by 12 and add the now huge positive value to the cpu time of the process. To solve this the machine check handler is modified not to change any of the timestamps in the lowcore if the machine check interrupted kernel context. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry.S | 79 ++++++++++++++++++++++++++++++++++------------ arch/s390/kernel/entry64.S | 78 +++++++++++++++++++++++++++++++++------------ 2 files changed, 116 insertions(+), 41 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index b2448487854c..74d80c3bba80 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -93,13 +93,22 @@ STACK_SIZE = 1 << STACK_SHIFT l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 .endm - .macro SAVE_ALL psworg,savearea,sync + .macro SAVE_ALL_SYNC psworg,savearea la %r12,\psworg - .if \sync tm \psworg+1,0x01 # test problem state bit bz BASED(2f) # skip stack setup save l %r15,__LC_KERNEL_STACK # problem state -> load ksp - .else +#ifdef CONFIG_CHECK_STACK + b BASED(3f) +2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + bz BASED(stack_overflow) +3: +#endif +2: + .endm + + .macro SAVE_ALL_ASYNC psworg,savearea + la %r12,\psworg tm \psworg+1,0x01 # test problem state bit bnz BASED(1f) # from user -> load async stack clc \psworg+4(4),BASED(.Lcritical_end) @@ -115,7 +124,6 @@ STACK_SIZE = 1 << STACK_SHIFT sra %r14,STACK_SHIFT be BASED(2f) 1: l %r15,__LC_ASYNC_STACK - .endif #ifdef CONFIG_CHECK_STACK b BASED(3f) 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD @@ -196,7 +204,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA lh %r7,0x8a # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING @@ -425,7 +433,7 @@ pgm_check_handler: SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception bnz BASED(pgm_per) # got per exception -> special case - SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -464,7 +472,7 @@ pgm_per: # Normal per exception # pgm_per_std: - SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -490,7 +498,7 @@ pgm_no_vtime2: # it was a single stepped SVC that is causing all the trouble # pgm_svcper: - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -519,7 +527,7 @@ io_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 - SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 + SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -631,7 +639,7 @@ ext_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 - SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 + SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -657,21 +665,31 @@ __critical_end: .globl mcck_int_handler mcck_int_handler: spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs SAVE_ALL_BASE __LC_SAVE_AREA+32 la %r12,__LC_MCK_OLD_PSW tm __LC_MCCK_CODE,0x80 # system damage? bo BASED(mcck_int_main) # yes -> rest of mcck code invalid - tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? - bo BASED(0f) - spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer #ifdef CONFIG_VIRT_CPU_ACCOUNTING - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER - mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER - mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER + mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER + mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA + tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? + bo BASED(1f) + la %r14,__LC_SYNC_ENTER_TIMER + clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER + bl BASED(0f) + la %r14,__LC_ASYNC_ENTER_TIMER +0: clc 0(8,%r14),__LC_EXIT_TIMER + bl BASED(0f) + la %r14,__LC_EXIT_TIMER +0: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER + bl BASED(0f) + la %r14,__LC_LAST_UPDATE_TIMER +0: spt 0(%r14) + mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) +1: #endif -0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? + tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? bno BASED(mcck_int_main) # no -> skip cleanup critical tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit bnz BASED(mcck_int_main) # from user -> load async stack @@ -691,7 +709,7 @@ mcck_int_main: #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? bno BASED(mcck_no_vtime) # no -> skip cleanup critical - tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? + tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(mcck_no_vtime) UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER @@ -715,6 +733,20 @@ mcck_no_vtime: l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # call machine check handler mcck_return: + mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW + ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52 + tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? + bno BASED(0f) + lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 + stpt __LC_EXIT_TIMER + lpsw __LC_RETURN_MCCK_PSW # back to caller +0: +#endif + lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 + lpsw __LC_RETURN_MCCK_PSW # back to caller + RESTORE_ALL __LC_RETURN_MCCK_PSW,0 #ifdef CONFIG_SMP @@ -781,6 +813,8 @@ cleanup_table_sysc_leave: .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 cleanup_table_sysc_work_loop: .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 +cleanup_table_io_return: + .long io_return + 0x80000000, io_leave + 0x80000000 cleanup_table_io_leave: .long io_leave + 0x80000000, io_done + 0x80000000 cleanup_table_io_work_loop: @@ -806,6 +840,11 @@ cleanup_critical: bl BASED(0f) clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) bl BASED(cleanup_sysc_return) +0: + clc 4(4,%r12),BASED(cleanup_table_io_return) + bl BASED(0f) + clc 4(4,%r12),BASED(cleanup_table_io_return+4) + bl BASED(cleanup_io_return) 0: clc 4(4,%r12),BASED(cleanup_table_io_leave) bl BASED(0f) @@ -839,7 +878,7 @@ cleanup_system_call: mvc __LC_SAVE_AREA(16),0(%r12) 0: st %r13,4(%r12) st %r12,__LC_SAVE_AREA+48 # argh - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA l %r12,__LC_SAVE_AREA+48 # argh st %r15,12(%r12) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 2ac095bc0e25..21e601d56139 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -87,13 +87,22 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ larl %r13,system_call .endm - .macro SAVE_ALL psworg,savearea,sync + .macro SAVE_ALL_SYNC psworg,savearea la %r12,\psworg - .if \sync tm \psworg+1,0x01 # test problem state bit jz 2f # skip stack setup save lg %r15,__LC_KERNEL_STACK # problem state -> load ksp - .else +#ifdef CONFIG_CHECK_STACK + j 3f +2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + jz stack_overflow +3: +#endif +2: + .endm + + .macro SAVE_ALL_ASYNC psworg,savearea + la %r12,\psworg tm \psworg+1,0x01 # test problem state bit jnz 1f # from user -> load kernel stack clc \psworg+8(8),BASED(.Lcritical_end) @@ -108,7 +117,6 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ srag %r14,%r14,STACK_SHIFT jz 2f 1: lg %r15,__LC_ASYNC_STACK # load async stack - .endif #ifdef CONFIG_CHECK_STACK j 3f 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD @@ -187,7 +195,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING @@ -446,7 +454,7 @@ pgm_check_handler: SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception jnz pgm_per # got per exception -> special case - SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -485,7 +493,7 @@ pgm_per: # Normal per exception # pgm_per_std: - SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -511,7 +519,7 @@ pgm_no_vtime2: # it was a single stepped SVC that is causing all the trouble # pgm_svcper: - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -539,7 +547,7 @@ io_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 - SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 + SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -647,7 +655,7 @@ ext_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 - SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 + SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -672,21 +680,32 @@ __critical_end: mcck_int_handler: la %r1,4095 # revalidate r1 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1) lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs SAVE_ALL_BASE __LC_SAVE_AREA+64 la %r12,__LC_MCK_OLD_PSW tm __LC_MCCK_CODE,0x80 # system damage? jo mcck_int_main # yes -> rest of mcck code invalid - tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? - jo 0f - spt __LC_LAST_UPDATE_TIMER #ifdef CONFIG_VIRT_CPU_ACCOUNTING - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER - mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER - mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER + la %r14,4095 + mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER + mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) + tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? + jo 1f + la %r14,__LC_SYNC_ENTER_TIMER + clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER + jl 0f + la %r14,__LC_ASYNC_ENTER_TIMER +0: clc 0(8,%r14),__LC_EXIT_TIMER + jl 0f + la %r14,__LC_EXIT_TIMER +0: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER + jl 0f + la %r14,__LC_LAST_UPDATE_TIMER +0: spt 0(%r14) + mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) +1: #endif -0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? + tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? jno mcck_int_main # no -> skip cleanup critical tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit jnz mcck_int_main # from user -> load kernel stack @@ -705,7 +724,7 @@ mcck_int_main: #ifdef CONFIG_VIRT_CPU_ACCOUNTING tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? jno mcck_no_vtime # no -> no timer update - tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? + tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz mcck_no_vtime UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER @@ -727,7 +746,17 @@ mcck_no_vtime: jno mcck_return brasl %r14,s390_handle_mcck mcck_return: - RESTORE_ALL __LC_RETURN_MCCK_PSW,0 + mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW + ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit + lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104 + tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? + jno 0f + stpt __LC_EXIT_TIMER +0: +#endif + lpswe __LC_RETURN_MCCK_PSW # back to caller #ifdef CONFIG_SMP /* @@ -789,6 +818,8 @@ cleanup_table_sysc_leave: .quad sysc_leave, sysc_work_loop cleanup_table_sysc_work_loop: .quad sysc_work_loop, sysc_reschedule +cleanup_table_io_return: + .quad io_return, io_leave cleanup_table_io_leave: .quad io_leave, io_done cleanup_table_io_work_loop: @@ -814,6 +845,11 @@ cleanup_critical: jl 0f clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) jl cleanup_sysc_return +0: + clc 8(8,%r12),BASED(cleanup_table_io_return) + jl 0f + clc 8(8,%r12),BASED(cleanup_table_io_return+8) + jl cleanup_io_return 0: clc 8(8,%r12),BASED(cleanup_table_io_leave) jl 0f @@ -847,7 +883,7 @@ cleanup_system_call: mvc __LC_SAVE_AREA(32),0(%r12) 0: stg %r13,8(%r12) stg %r12,__LC_SAVE_AREA+96 # argh - SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 + SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA lg %r12,__LC_SAVE_AREA+96 # argh stg %r15,24(%r12) -- cgit v1.2.3 From 138c014dcba74211dc4e835658f34a787c40cf17 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Thu, 29 Jun 2006 14:58:12 +0200 Subject: [S390] dasd whitespace and other cosmetics. Dasd code cleanup: 1) remove white space, 2) remove the emacs override sections, and 3) use kzalloc instead of kmalloc. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 54 ++++------- drivers/s390/block/dasd_3370_erp.c | 27 +----- drivers/s390/block/dasd_3990_erp.c | 189 +++++++++++++++++-------------------- drivers/s390/block/dasd_9336_erp.c | 27 +----- drivers/s390/block/dasd_9343_erp.c | 2 +- drivers/s390/block/dasd_devmap.c | 22 +++-- drivers/s390/block/dasd_diag.c | 6 +- drivers/s390/block/dasd_diag.h | 2 +- drivers/s390/block/dasd_eckd.c | 52 ++++------ drivers/s390/block/dasd_eckd.h | 8 +- drivers/s390/block/dasd_erp.c | 8 +- drivers/s390/block/dasd_fba.c | 29 +----- drivers/s390/block/dasd_fba.h | 2 +- drivers/s390/block/dasd_int.h | 37 ++------ drivers/s390/block/dasd_ioctl.c | 12 +-- 15 files changed, 173 insertions(+), 304 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index cfb1fff3787c..7e9978ad1445 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -95,7 +95,7 @@ dasd_alloc_device(void) spin_lock_init(&device->mem_lock); spin_lock_init(&device->request_queue_lock); atomic_set (&device->tasklet_scheduled, 0); - tasklet_init(&device->tasklet, + tasklet_init(&device->tasklet, (void (*)(unsigned long)) dasd_tasklet, (unsigned long) device); INIT_LIST_HEAD(&device->ccw_queue); @@ -128,7 +128,7 @@ dasd_state_new_to_known(struct dasd_device *device) int rc; /* - * As long as the device is not in state DASD_STATE_NEW we want to + * As long as the device is not in state DASD_STATE_NEW we want to * keep the reference count > 0. */ dasd_get_device(device); @@ -336,7 +336,7 @@ dasd_decrease_state(struct dasd_device *device) if (device->state == DASD_STATE_ONLINE && device->target <= DASD_STATE_READY) dasd_state_online_to_ready(device); - + if (device->state == DASD_STATE_READY && device->target <= DASD_STATE_BASIC) dasd_state_ready_to_basic(device); @@ -348,7 +348,7 @@ dasd_decrease_state(struct dasd_device *device) if (device->state == DASD_STATE_BASIC && device->target <= DASD_STATE_KNOWN) dasd_state_basic_to_known(device); - + if (device->state == DASD_STATE_KNOWN && device->target <= DASD_STATE_NEW) dasd_state_known_to_new(device); @@ -994,7 +994,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr); /* Find out the appropriate era_action. */ - if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) + if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) era = dasd_era_fatal; else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && irb->scsw.cstat == 0 && @@ -1004,7 +1004,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, era = dasd_era_fatal; /* don't recover this request */ else if (irb->esw.esw0.erw.cons) era = device->discipline->examine_error(cqr, irb); - else + else era = dasd_era_recover; DBF_DEV_EVENT(DBF_DEBUG, device, "era_code %d", era); @@ -1287,7 +1287,7 @@ __dasd_start_head(struct dasd_device * device) } /* - * Remove requests from the ccw queue. + * Remove requests from the ccw queue. */ static void dasd_flush_ccw_queue(struct dasd_device * device, int all) @@ -1450,23 +1450,23 @@ dasd_sleep_on(struct dasd_ccw_req * cqr) wait_queue_head_t wait_q; struct dasd_device *device; int rc; - + device = cqr->device; spin_lock_irq(get_ccwdev_lock(device->cdev)); - + init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; cqr->callback_data = (void *) &wait_q; cqr->status = DASD_CQR_QUEUED; list_add_tail(&cqr->list, &device->ccw_queue); - + /* let the bh start the request to keep them in order */ dasd_schedule_bh(device); - + spin_unlock_irq(get_ccwdev_lock(device->cdev)); wait_event(wait_q, _wait_for_wakeup(cqr)); - + /* Request status is either done or failed. */ rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; return rc; @@ -1568,7 +1568,7 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr) wait_queue_head_t wait_q; struct dasd_device *device; int rc; - + device = cqr->device; spin_lock_irq(get_ccwdev_lock(device->cdev)); rc = _dasd_term_running_cqr(device); @@ -1576,20 +1576,20 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr) spin_unlock_irq(get_ccwdev_lock(device->cdev)); return rc; } - + init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; cqr->callback_data = (void *) &wait_q; cqr->status = DASD_CQR_QUEUED; list_add(&cqr->list, &device->ccw_queue); - + /* let the bh start the request to keep them in order */ dasd_schedule_bh(device); - + spin_unlock_irq(get_ccwdev_lock(device->cdev)); wait_event(wait_q, _wait_for_wakeup(cqr)); - + /* Request status is either done or failed. */ rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; return rc; @@ -1725,7 +1725,7 @@ dasd_flush_request_queue(struct dasd_device * device) if (!device->request_queue) return; - + spin_lock_irq(&device->request_queue_lock); while (!list_empty(&device->request_queue->queue_head)) { req = elv_next_request(device->request_queue); @@ -2172,21 +2172,3 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); EXPORT_SYMBOL_GPL(dasd_generic_auto_online); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c index 1d11c2a9525d..1ddab8991d92 100644 --- a/drivers/s390/block/dasd_3370_erp.c +++ b/drivers/s390/block/dasd_3370_erp.c @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_3370_erp.c * Author(s)......: Holger Smolinski * Bugreports.to..: @@ -12,10 +12,10 @@ /* - * DASD_3370_ERP_EXAMINE + * DASD_3370_ERP_EXAMINE * * DESCRIPTION - * Checks only for fatal/no/recover error. + * Checks only for fatal/no/recover error. * A detailed examination of the sense data is done later outside * the interrupt handler. * @@ -23,7 +23,7 @@ * 'Chapter 7. 3370 Sense Data'. * * RETURN VALUES - * dasd_era_none no error + * dasd_era_none no error * dasd_era_fatal for all fatal (unrecoverable errors) * dasd_era_recover for all others. */ @@ -82,22 +82,3 @@ dasd_3370_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) return dasd_era_recover; } /* END dasd_3370_erp_examine */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 2ed51562319e..669805d4402d 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1,6 +1,6 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_3990_erp.c - * Author(s)......: Horst Hummel + * Author(s)......: Horst Hummel * Holger Smolinski * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 @@ -25,23 +25,23 @@ struct DCTL_data { } __attribute__ ((packed)); /* - ***************************************************************************** + ***************************************************************************** * SECTION ERP EXAMINATION - ***************************************************************************** + ***************************************************************************** */ /* - * DASD_3990_ERP_EXAMINE_24 + * DASD_3990_ERP_EXAMINE_24 * * DESCRIPTION - * Checks only for fatal (unrecoverable) error. + * Checks only for fatal (unrecoverable) error. * A detailed examination of the sense data is done later outside * the interrupt handler. * * Each bit configuration leading to an action code 2 (Exit with * programming error or unusual condition indication) * are handled as fatal errorīs. - * + * * All other configurations are handled as recoverable errors. * * RETURN VALUES @@ -93,15 +93,15 @@ dasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense) } /* END dasd_3990_erp_examine_24 */ /* - * DASD_3990_ERP_EXAMINE_32 + * DASD_3990_ERP_EXAMINE_32 * * DESCRIPTION - * Checks only for fatal/no/recoverable error. + * Checks only for fatal/no/recoverable error. * A detailed examination of the sense data is done later outside * the interrupt handler. * * RETURN VALUES - * dasd_era_none no error + * dasd_era_none no error * dasd_era_fatal for all fatal (unrecoverable errors) * dasd_era_recover for recoverable others. */ @@ -128,10 +128,10 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense) } /* end dasd_3990_erp_examine_32 */ /* - * DASD_3990_ERP_EXAMINE + * DASD_3990_ERP_EXAMINE * * DESCRIPTION - * Checks only for fatal/no/recover error. + * Checks only for fatal/no/recover error. * A detailed examination of the sense data is done later outside * the interrupt handler. * @@ -139,7 +139,7 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense) * 'Chapter 7. Error Recovery Procedures'. * * RETURN VALUES - * dasd_era_none no error + * dasd_era_none no error * dasd_era_fatal for all fatal (unrecoverable errors) * dasd_era_recover for all others. */ @@ -178,18 +178,18 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) } /* END dasd_3990_erp_examine */ /* - ***************************************************************************** + ***************************************************************************** * SECTION ERP HANDLING - ***************************************************************************** + ***************************************************************************** */ /* - ***************************************************************************** + ***************************************************************************** * 24 and 32 byte sense ERP functions - ***************************************************************************** + ***************************************************************************** */ /* - * DASD_3990_ERP_CLEANUP + * DASD_3990_ERP_CLEANUP * * DESCRIPTION * Removes the already build but not necessary ERP request and sets @@ -197,10 +197,10 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) * * PARAMETER * erp request to be blocked - * final_status either DASD_CQR_DONE or DASD_CQR_FAILED + * final_status either DASD_CQR_DONE or DASD_CQR_FAILED * * RETURN VALUES - * cqr original cqr + * cqr original cqr */ static struct dasd_ccw_req * dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) @@ -214,7 +214,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) } /* end dasd_3990_erp_cleanup */ /* - * DASD_3990_ERP_BLOCK_QUEUE + * DASD_3990_ERP_BLOCK_QUEUE * * DESCRIPTION * Block the given device request queue to prevent from further @@ -237,7 +237,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) } /* - * DASD_3990_ERP_INT_REQ + * DASD_3990_ERP_INT_REQ * * DESCRIPTION * Handles 'Intervention Required' error. @@ -277,7 +277,7 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) } /* end dasd_3990_erp_int_req */ /* - * DASD_3990_ERP_ALTERNATE_PATH + * DASD_3990_ERP_ALTERNATE_PATH * * DESCRIPTION * Repeat the operation on a different channel path. @@ -330,15 +330,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) * DASD_3990_ERP_DCTL * * DESCRIPTION - * Setup cqr to do the Diagnostic Control (DCTL) command with an + * Setup cqr to do the Diagnostic Control (DCTL) command with an * Inhibit Write subcommand (0x20) and the given modifier. * * PARAMETER * erp pointer to the current (failed) ERP * modifier subcommand modifier - * + * * RETURN VALUES - * dctl_cqr pointer to NEW dctl_cqr + * dctl_cqr pointer to NEW dctl_cqr * */ static struct dasd_ccw_req * @@ -386,7 +386,7 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) } /* end dasd_3990_erp_DCTL */ /* - * DASD_3990_ERP_ACTION_1 + * DASD_3990_ERP_ACTION_1 * * DESCRIPTION * Setup ERP to do the ERP action 1 (see Reference manual). @@ -415,7 +415,7 @@ dasd_3990_erp_action_1(struct dasd_ccw_req * erp) } /* end dasd_3990_erp_action_1 */ /* - * DASD_3990_ERP_ACTION_4 + * DASD_3990_ERP_ACTION_4 * * DESCRIPTION * Setup ERP to do the ERP action 4 (see Reference manual). @@ -453,11 +453,11 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) if (sense[25] == 0x1D) { /* state change pending */ - DEV_MESSAGE(KERN_INFO, device, + DEV_MESSAGE(KERN_INFO, device, "waiting for state change pending " "interrupt, %d retries left", erp->retries); - + dasd_3990_erp_block_queue(erp, 30*HZ); } else if (sense[25] == 0x1E) { /* busy */ @@ -469,9 +469,9 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) } else { /* no state change pending - retry */ - DEV_MESSAGE (KERN_INFO, device, + DEV_MESSAGE (KERN_INFO, device, "redriving request immediately, " - "%d retries left", + "%d retries left", erp->retries); erp->status = DASD_CQR_QUEUED; } @@ -482,13 +482,13 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_action_4 */ /* - ***************************************************************************** + ***************************************************************************** * 24 byte sense ERP functions (only) - ***************************************************************************** + ***************************************************************************** */ /* - * DASD_3990_ERP_ACTION_5 + * DASD_3990_ERP_ACTION_5 * * DESCRIPTION * Setup ERP to do the ERP action 5 (see Reference manual). @@ -523,7 +523,7 @@ dasd_3990_erp_action_5(struct dasd_ccw_req * erp) * * PARAMETER * sense current sense data - * + * * RETURN VALUES * void */ @@ -1150,9 +1150,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) * PARAMETER * erp current erp_head * sense current sense data - * + * * RETURN VALUES - * erp 'new' erp_head - pointer to new ERP + * erp 'new' erp_head - pointer to new ERP */ static struct dasd_ccw_req * dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) @@ -1185,7 +1185,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_com_rej */ /* - * DASD_3990_ERP_BUS_OUT + * DASD_3990_ERP_BUS_OUT * * DESCRIPTION * Handles 24 byte 'Bus Out Parity Check' error. @@ -1483,7 +1483,7 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) * * PARAMETER * erp already added default ERP - * + * * RETURN VALUES * erp new erp_head - pointer to new ERP */ @@ -1527,11 +1527,11 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) } /* end dasd_3990_erp_file_prot */ /* - * DASD_3990_ERP_INSPECT_24 + * DASD_3990_ERP_INSPECT_24 * * DESCRIPTION * Does a detailed inspection of the 24 byte sense data - * and sets up a related error recovery action. + * and sets up a related error recovery action. * * PARAMETER * sense sense data of the actual error @@ -1602,13 +1602,13 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense) } /* END dasd_3990_erp_inspect_24 */ /* - ***************************************************************************** + ***************************************************************************** * 32 byte sense ERP functions (only) - ***************************************************************************** + ***************************************************************************** */ /* - * DASD_3990_ERPACTION_10_32 + * DASD_3990_ERPACTION_10_32 * * DESCRIPTION * Handles 32 byte 'Action 10' of Single Program Action Codes. @@ -1616,7 +1616,7 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense) * * PARAMETER * erp current erp_head - * sense current sense data + * sense current sense data * RETURN VALUES * erp modified erp_head */ @@ -1640,18 +1640,18 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) * * DESCRIPTION * Handles 32 byte 'Action 1B' of Single Program Action Codes. - * A write operation could not be finished because of an unexpected + * A write operation could not be finished because of an unexpected * condition. - * The already created 'default erp' is used to get the link to - * the erp chain, but it can not be used for this recovery + * The already created 'default erp' is used to get the link to + * the erp chain, but it can not be used for this recovery * action because it contains no DE/LO data space. * * PARAMETER * default_erp already added default erp. - * sense current sense data + * sense current sense data * * RETURN VALUES - * erp new erp or + * erp new erp or * default_erp in case of imprecise ending or error */ static struct dasd_ccw_req * @@ -1789,16 +1789,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) * DASD_3990_UPDATE_1B * * DESCRIPTION - * Handles the update to the 32 byte 'Action 1B' of Single Program + * Handles the update to the 32 byte 'Action 1B' of Single Program * Action Codes in case the first action was not successful. * The already created 'previous_erp' is the currently not successful - * ERP. + * ERP. * * PARAMETER * previous_erp already created previous erp. - * sense current sense data + * sense current sense data * RETURN VALUES - * erp modified erp + * erp modified erp */ static struct dasd_ccw_req * dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) @@ -1897,7 +1897,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) } /* end dasd_3990_update_1B */ /* - * DASD_3990_ERP_COMPOUND_RETRY + * DASD_3990_ERP_COMPOUND_RETRY * * DESCRIPTION * Handles the compound ERP action retry code. @@ -1943,7 +1943,7 @@ dasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_compound_retry */ /* - * DASD_3990_ERP_COMPOUND_PATH + * DASD_3990_ERP_COMPOUND_PATH * * DESCRIPTION * Handles the compound ERP action for retry on alternate @@ -1965,7 +1965,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) dasd_3990_erp_alternate_path(erp); if (erp->status == DASD_CQR_FAILED) { - /* reset the lpm and the status to be able to + /* reset the lpm and the status to be able to * try further actions. */ erp->lpm = 0; @@ -1980,7 +1980,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_compound_path */ /* - * DASD_3990_ERP_COMPOUND_CODE + * DASD_3990_ERP_COMPOUND_CODE * * DESCRIPTION * Handles the compound ERP action for retry code. @@ -2001,18 +2001,18 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense) switch (sense[28]) { case 0x17: - /* issue a Diagnostic Control command with an + /* issue a Diagnostic Control command with an * Inhibit Write subcommand and controler modifier */ erp = dasd_3990_erp_DCTL(erp, 0x20); break; - + case 0x25: /* wait for 5 seconds and retry again */ erp->retries = 1; - + dasd_3990_erp_block_queue (erp, 5*HZ); break; - + default: /* should not happen - continue */ break; @@ -2026,7 +2026,7 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_compound_code */ /* - * DASD_3990_ERP_COMPOUND_CONFIG + * DASD_3990_ERP_COMPOUND_CONFIG * * DESCRIPTION * Handles the compound ERP action for configruation @@ -2063,10 +2063,10 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_compound_config */ /* - * DASD_3990_ERP_COMPOUND + * DASD_3990_ERP_COMPOUND * * DESCRIPTION - * Does the further compound program action if + * Does the further compound program action if * compound retry was not successful. * * PARAMETER @@ -2110,11 +2110,11 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_compound */ /* - * DASD_3990_ERP_INSPECT_32 + * DASD_3990_ERP_INSPECT_32 * * DESCRIPTION * Does a detailed inspection of the 32 byte sense data - * and sets up a related error recovery action. + * and sets up a related error recovery action. * * PARAMETER * sense sense data of the actual error @@ -2228,9 +2228,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) } /* end dasd_3990_erp_inspect_32 */ /* - ***************************************************************************** + ***************************************************************************** * main ERP control fuctions (24 and 32 byte sense) - ***************************************************************************** + ***************************************************************************** */ /* @@ -2243,7 +2243,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) * PARAMETER * erp pointer to the currently created default ERP * RETURN VALUES - * erp_new contens was possibly modified + * erp_new contens was possibly modified */ static struct dasd_ccw_req * dasd_3990_erp_inspect(struct dasd_ccw_req * erp) @@ -2272,14 +2272,14 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) /* * DASD_3990_ERP_ADD_ERP - * + * * DESCRIPTION * This funtion adds an additional request block (ERP) to the head of * the given cqr (or erp). * This erp is initialized as an default erp (retry TIC) * * PARAMETER - * cqr head of the current ERP-chain (or single cqr if + * cqr head of the current ERP-chain (or single cqr if * first error) * RETURN VALUES * erp pointer to new ERP-chain head @@ -2332,15 +2332,15 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) } /* - * DASD_3990_ERP_ADDITIONAL_ERP - * + * DASD_3990_ERP_ADDITIONAL_ERP + * * DESCRIPTION * An additional ERP is needed to handle the current error. * Add ERP to the head of the ERP-chain containing the ERP processing * determined based on the sense data. * * PARAMETER - * cqr head of the current ERP-chain (or single cqr if + * cqr head of the current ERP-chain (or single cqr if * first error) * * RETURN VALUES @@ -2376,7 +2376,7 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) * 24 byte sense byte 25 and 27 is set as well. * * PARAMETER - * cqr1 first cqr, which will be compared with the + * cqr1 first cqr, which will be compared with the * cqr2 second cqr. * * RETURN VALUES @@ -2415,7 +2415,7 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) * cqr failed cqr (either original cqr or already an erp) * * RETURN VALUES - * erp erp-pointer to the already defined error + * erp erp-pointer to the already defined error * recovery procedure OR * NULL if a 'new' error occurred. */ @@ -2451,10 +2451,10 @@ dasd_3990_erp_in_erp(struct dasd_ccw_req *cqr) * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense) * * DESCRIPTION - * No retry is left for the current ERP. Check what has to be done + * No retry is left for the current ERP. Check what has to be done * with the ERP. * - do further defined ERP action or - * - wait for interrupt or + * - wait for interrupt or * - exit with permanent error * * PARAMETER @@ -2485,7 +2485,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) if (!(sense[2] & DASD_SENSE_BIT_0)) { - /* issue a Diagnostic Control command with an + /* issue a Diagnostic Control command with an * Inhibit Write subcommand */ switch (sense[25]) { @@ -2535,14 +2535,14 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) } /* end dasd_3990_erp_further_erp */ /* - * DASD_3990_ERP_HANDLE_MATCH_ERP + * DASD_3990_ERP_HANDLE_MATCH_ERP * * DESCRIPTION * An error occurred again and an ERP has been detected which is already - * used to handle this error (e.g. retries). + * used to handle this error (e.g. retries). * All prior ERP's are asumed to be successful and therefore removed * from queue. - * If retry counter of matching erp is already 0, it is checked if further + * If retry counter of matching erp is already 0, it is checked if further * action is needed (besides retry) or if the ERP has failed. * * PARAMETER @@ -2631,7 +2631,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, * erp erp-pointer to the head of the ERP action chain. * This means: * - either a ptr to an additional ERP cqr or - * - the original given cqr (which's status might + * - the original given cqr (which's status might * be modified) */ struct dasd_ccw_req * @@ -2723,22 +2723,3 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) return erp; } /* end dasd_3990_erp_action */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c index dc861446d056..6e082688475a 100644 --- a/drivers/s390/block/dasd_9336_erp.c +++ b/drivers/s390/block/dasd_9336_erp.c @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_9336_erp.c * Author(s)......: Holger Smolinski * Bugreports.to..: @@ -12,10 +12,10 @@ /* - * DASD_9336_ERP_EXAMINE + * DASD_9336_ERP_EXAMINE * * DESCRIPTION - * Checks only for fatal/no/recover error. + * Checks only for fatal/no/recover error. * A detailed examination of the sense data is done later outside * the interrupt handler. * @@ -23,7 +23,7 @@ * 'Chapter 7. 9336 Sense Data'. * * RETURN VALUES - * dasd_era_none no error + * dasd_era_none no error * dasd_era_fatal for all fatal (unrecoverable errors) * dasd_era_recover for all others. */ @@ -39,22 +39,3 @@ dasd_9336_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) return dasd_era_recover; } /* END dasd_9336_erp_examine */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c index 4a5b79569aaa..ddecb9808ed4 100644 --- a/drivers/s390/block/dasd_9343_erp.c +++ b/drivers/s390/block/dasd_9343_erp.c @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_9345_erp.c * Author(s)......: Holger Smolinski * Bugreports.to..: diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 216bc4fba199..672e50314b12 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -123,7 +123,7 @@ static inline int dasd_busid(char **str, int *id0, int *id1, int *devno) { int val, old_style; - + /* check for leading '0x' */ old_style = 0; if ((*str)[0] == '0' && (*str)[1] == 'x') { @@ -179,7 +179,7 @@ dasd_feature_list(char *str, char **endp) features = 0; while (1) { - for (len = 0; + for (len = 0; str[len] && str[len] != ':' && str[len] != ')'; len++); if (len == 2 && !strncmp(str, "ro", 2)) features |= DASD_FEATURE_READONLY; @@ -359,7 +359,7 @@ dasd_parse(void) * Add a devmap for the device specified by busid. It is possible that * the devmap already exists (dasd= parameter). The order of the devices * added through this function will define the kdevs for the individual - * devices. + * devices. */ static struct dasd_devmap * dasd_add_busid(char *bus_id, int features) @@ -368,7 +368,7 @@ dasd_add_busid(char *bus_id, int features) int hash; new = (struct dasd_devmap *) - kmalloc(sizeof(struct dasd_devmap), GFP_KERNEL); + kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL); if (!new) return ERR_PTR(-ENOMEM); spin_lock(&dasd_devmap_lock); @@ -630,7 +630,8 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +dasd_ro_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct dasd_devmap *devmap; int ro_flag; @@ -658,7 +659,7 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store); * use_diag controls whether the driver should use diag rather than ssch * to talk to the device */ -static ssize_t +static ssize_t dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dasd_devmap *devmap; @@ -673,7 +674,8 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +dasd_use_diag_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct dasd_devmap *devmap; ssize_t rc; @@ -697,11 +699,11 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const cha return rc; } -static -DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); +static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); static ssize_t -dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf) +dasd_discipline_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct dasd_devmap *devmap; char *dname; diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 3f9d704d2657..4002f6c1c1b3 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_diag.c * Author(s)......: Holger Smolinski * Based on.......: linux/drivers/s390/block/mdisk.c @@ -336,7 +336,7 @@ dasd_diag_check_device(struct dasd_device *device) private = (struct dasd_diag_private *) device->private; if (private == NULL) { - private = kmalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); + private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); if (private == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "memory allocation failed for private data"); @@ -527,7 +527,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) datasize, device); if (IS_ERR(cqr)) return cqr; - + dreq = (struct dasd_diag_req *) cqr->data; dreq->block_count = count; dbio = dreq->bio; diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index 38a4e55f8953..b8c78267ff3e 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_diag.h * Author(s)......: Holger Smolinski * Based on.......: linux/drivers/s390/block/mdisk.h diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 7565d30f8c2f..12257776e79b 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1,7 +1,7 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_eckd.c * Author(s)......: Holger Smolinski - * Horst Hummel + * Horst Hummel * Carsten Otte * Martin Schwidefsky * Bugreports.to..: @@ -210,14 +210,14 @@ check_XRC (struct ccw1 *de_ccw, /* switch on System Time Stamp - needed for XRC Support */ if (private->rdc_data.facilities.XRC_supported) { - + data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ - + data->ep_sys_time = get_clock (); - + de_ccw->count = sizeof (struct DE_eckd_data); - de_ccw->flags |= CCW_FLAG_SLI; + de_ccw->flags |= CCW_FLAG_SLI; } return; @@ -296,8 +296,8 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, /* check for sequential prestage - enhance cylinder range */ if (data->attributes.operation == DASD_SEQ_PRESTAGE || data->attributes.operation == DASD_SEQ_ACCESS) { - - if (end.cyl + private->attrib.nr_cyl < geo.cyl) + + if (end.cyl + private->attrib.nr_cyl < geo.cyl) end.cyl += private->attrib.nr_cyl; else end.cyl = (geo.cyl - 1); @@ -317,7 +317,7 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, struct dasd_eckd_private *private; int sector; int dn, d; - + private = (struct dasd_eckd_private *) device->private; DBF_DEV_EVENT(DBF_INFO, device, @@ -554,7 +554,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) private = (struct dasd_eckd_private *) device->private; if (private == NULL) { - private = kmalloc(sizeof(struct dasd_eckd_private), + private = kzalloc(sizeof(struct dasd_eckd_private), GFP_KERNEL | GFP_DMA); if (private == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", @@ -562,7 +562,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) "data"); return -ENOMEM; } - memset(private, 0, sizeof(struct dasd_eckd_private)); device->private = (void *) private; } /* Invalidate status of initial analysis. */ @@ -773,7 +772,7 @@ dasd_eckd_end_analysis(struct dasd_device *device) ((private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl * blk_per_trk * (device->bp_block >> 9)) >> 1), - ((blk_per_trk * device->bp_block) >> 10), + ((blk_per_trk * device->bp_block) >> 10), private->uses_cdl ? "compatible disk layout" : "linux disk layout"); @@ -970,7 +969,7 @@ dasd_eckd_format_device(struct dasd_device * device, if (i < 3) { ect->kl = 4; ect->dl = sizes_trk0[i] - 4; - } + } } if ((fdata->intensity & 0x08) && fdata->start_unit == 1) { @@ -1270,7 +1269,7 @@ dasd_eckd_fill_info(struct dasd_device * device, /* * Release device ioctl. - * Buils a channel programm to releases a prior reserved + * Buils a channel programm to releases a prior reserved * (see dasd_eckd_reserve) device. */ static int @@ -1310,8 +1309,8 @@ dasd_eckd_release(struct dasd_device *device) /* * Reserve device ioctl. * Options are set to 'synchronous wait for interrupt' and - * 'timeout the request'. This leads to a terminate IO if - * the interrupt is outstanding for a certain time. + * 'timeout the request'. This leads to a terminate IO if + * the interrupt is outstanding for a certain time. */ static int dasd_eckd_reserve(struct dasd_device *device) @@ -1349,7 +1348,7 @@ dasd_eckd_reserve(struct dasd_device *device) /* * Steal lock ioctl - unconditional reserve device. - * Buils a channel programm to break a device's reservation. + * Buils a channel programm to break a device's reservation. * (unconditional reserve) */ static int @@ -1706,22 +1705,3 @@ dasd_eckd_cleanup(void) module_init(dasd_eckd_init); module_exit(dasd_eckd_cleanup); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index d5734e976e1c..9d91c8632569 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -1,7 +1,7 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_eckd.h * Author(s)......: Holger Smolinski - * Horst Hummel + * Horst Hummel * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * @@ -155,7 +155,7 @@ struct dasd_eckd_characteristics { unsigned char reserved2:4; unsigned char reserved3:8; unsigned char defect_wr:1; - unsigned char XRC_supported:1; + unsigned char XRC_supported:1; unsigned char reserved4:1; unsigned char striping:1; unsigned char reserved5:4; @@ -343,7 +343,7 @@ struct dasd_eckd_path { }; /* - * Perform Subsystem Function - Prepare for Read Subsystem Data + * Perform Subsystem Function - Prepare for Read Subsystem Data */ struct dasd_psf_prssd_data { unsigned char order; diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index b842377cb0c6..4108d96f6a5a 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -90,7 +90,7 @@ dasd_default_erp_action(struct dasd_ccw_req * cqr) /* just retry - there is nothing to save ... I got no sense data.... */ if (cqr->retries > 0) { - DEV_MESSAGE (KERN_DEBUG, device, + DEV_MESSAGE (KERN_DEBUG, device, "default ERP called (%i retries left)", cqr->retries); cqr->lpm = LPM_ANYPATH; @@ -155,7 +155,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr) /* * Print the hex dump of the memory used by a request. This includes - * all error recovery ccws that have been chained in from of the + * all error recovery ccws that have been chained in from of the * real request. */ static inline void @@ -227,12 +227,12 @@ dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa) /* * Log bytes arround failed CCW but only if we did * not log the whole CP of the CCW is outside the - * logged CP. + * logged CP. */ if (cplength > 40 || ((addr_t) cpa < (addr_t) lcqr->cpaddr && (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) { - + DEV_MESSAGE(KERN_ERR, device, "Failed CCW (%p) (area):", (void *) (long) cpa); diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 91145698f8e9..d331c6e22c59 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_fba.c * Author(s)......: Holger Smolinski * Bugreports.to..: @@ -125,13 +125,13 @@ static int dasd_fba_check_characteristics(struct dasd_device *device) { struct dasd_fba_private *private; - struct ccw_device *cdev = device->cdev; + struct ccw_device *cdev = device->cdev; void *rdc_data; int rc; private = (struct dasd_fba_private *) device->private; if (private == NULL) { - private = kmalloc(sizeof(struct dasd_fba_private), GFP_KERNEL); + private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL); if (private == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "memory allocation failed for private " @@ -204,7 +204,7 @@ dasd_fba_examine_error(struct dasd_ccw_req * cqr, struct irb * irb) if (irb->scsw.cstat == 0x00 && irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) return dasd_era_none; - + cdev = device->cdev; switch (cdev->id.dev_type) { case 0x3370: @@ -539,7 +539,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In - * addition we have one define extent ccw + 16 bytes of data and a + * addition we have one define extent ccw + 16 bytes of data and a * locate record ccw for each block (stupid devices!) + 16 bytes of data. * That makes: * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. @@ -589,22 +589,3 @@ dasd_fba_cleanup(void) module_init(dasd_fba_init); module_exit(dasd_fba_cleanup); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h index da1fa91fc01d..14c910baa5fe 100644 --- a/drivers/s390/block/dasd_fba.h +++ b/drivers/s390/block/dasd_fba.h @@ -1,4 +1,4 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_fba.h * Author(s)......: Holger Smolinski * Bugreports.to..: diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index d4b13e300a76..2c1fa85a3dad 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -1,7 +1,7 @@ -/* +/* * File...........: linux/drivers/s390/block/dasd_int.h * Author(s)......: Holger Smolinski - * Horst Hummel + * Horst Hummel * Martin Schwidefsky * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 @@ -186,7 +186,7 @@ struct dasd_ccw_req { void *callback_data; }; -/* +/* * dasd_ccw_req -> status can be: */ #define DASD_CQR_FILLED 0x00 /* request is ready to be processed */ @@ -248,7 +248,7 @@ struct dasd_discipline { /* * Error recovery functions. examine_error() returns a value that * indicates what to do for an error condition. If examine_error() - * returns 'dasd_era_recover' erp_action() is called to create a + * returns 'dasd_era_recover' erp_action() is called to create a * special error recovery ccw. erp_postaction() is called after * an error recovery ccw has finished its execution. dump_sense * is called for every error condition to print the sense data @@ -302,11 +302,11 @@ struct dasd_device { spinlock_t request_queue_lock; struct block_device *bdev; unsigned int devindex; - unsigned long blocks; /* size of volume in blocks */ - unsigned int bp_block; /* bytes per block */ - unsigned int s2b_shift; /* log2 (bp_block/512) */ - unsigned long flags; /* per device flags */ - unsigned short features; /* copy of devmap-features (read-only!) */ + unsigned long blocks; /* size of volume in blocks */ + unsigned int bp_block; /* bytes per block */ + unsigned int s2b_shift; /* log2 (bp_block/512) */ + unsigned long flags; /* per device flags */ + unsigned short features; /* copy of devmap-features (read-only!) */ /* extended error reporting stuff (eer) */ struct dasd_ccw_req *eer_cqr; @@ -606,22 +606,3 @@ static inline int dasd_eer_enabled(struct dasd_device *device) #endif /* __KERNEL__ */ #endif /* DASD_H */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: 1 - * tab-width: 8 - * End: - */ diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index b8c80d28df41..302bcd0f28be 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -90,10 +90,10 @@ static int dasd_ioctl_quiesce(struct dasd_device *device) { unsigned long flags; - + if (!capable (CAP_SYS_ADMIN)) return -EACCES; - + DEV_MESSAGE (KERN_DEBUG, device, "%s", "Quiesce IO on device"); spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); @@ -110,13 +110,13 @@ static int dasd_ioctl_resume(struct dasd_device *device) { unsigned long flags; - - if (!capable (CAP_SYS_ADMIN)) + + if (!capable (CAP_SYS_ADMIN)) return -EACCES; DEV_MESSAGE (KERN_DEBUG, device, "%s", "resume IO on device"); - + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); device->stopped &= ~DASD_STOPPED_QUIESCE; spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); @@ -287,7 +287,7 @@ dasd_ioctl_information(struct dasd_device *device, dasd_info->open_count = atomic_read(&device->open_count); if (!device->bdev) dasd_info->open_count++; - + /* * check if device is really formatted * LDL / CDL was returned by 'fill_info' -- cgit v1.2.3 From b1b70306911a35b3851a73c87e6e9bd45a08b893 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 14:58:17 +0200 Subject: [S390] head.S code moving. There is almost no room left for any new code between 0x10000 and 0x10480. Move the code from 0x10000 to 0x11000. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/head.S | 22 ++++++------- arch/s390/kernel/head31.S | 77 +++++++++++++++++++++++---------------------- arch/s390/kernel/head64.S | 79 +++++++++++++++++++++++------------------------ 3 files changed, 88 insertions(+), 90 deletions(-) diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index ea88d066bf04..538c82da49b1 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -1,7 +1,7 @@ /* * arch/s390/kernel/head.S * - * (C) Copyright IBM Corp. 1999, 2005 + * Copyright (C) IBM Corp. 1999,2006 * * Author(s): Hartmut Penner * Martin Schwidefsky @@ -482,24 +482,23 @@ start: .macro GET_IPL_DEVICE .Lget_ipl_device: - basr %r12,0 -.LGID: l %r1,0xb8 # get sid + l %r1,0xb8 # get sid sll %r1,15 # test if subchannel is enabled srl %r1,31 ltr %r1,%r1 - bz 0(%r14) # subchannel disabled + bz 2f-.LPG1(%r13) # subchannel disabled l %r1,0xb8 - la %r5,.Lipl_schib-.LGID(%r12) + la %r5,.Lipl_schib-.LPG1(%r13) stsch 0(%r5) # get schib of subchannel - bnz 0(%r14) # schib not available + bnz 2f-.LPG1(%r13) # schib not available tm 5(%r5),0x01 # devno valid? - bno 0(%r14) - la %r6,ipl_parameter_flags-.LGID(%r12) + bno 2f-.LPG1(%r13) + la %r6,ipl_parameter_flags-.LPG1(%r13) oi 3(%r6),0x01 # set flag - la %r2,ipl_devno-.LGID(%r12) + la %r2,ipl_devno-.LPG1(%r13) mvc 0(2,%r2),6(%r5) # store devno tm 4(%r5),0x80 # qdio capable device? - bno 0(%r14) + bno 2f-.LPG1(%r13) oi 3(%r6),0x02 # set flag # copy ipl parameters @@ -523,7 +522,7 @@ start: ar %r2,%r1 sr %r0,%r4 jne 1b - b 0(%r14) + b 2f-.LPG1(%r13) .align 4 .Lipl_schib: @@ -537,6 +536,7 @@ ipl_parameter_flags: .globl ipl_devno ipl_devno: .word 0 +2: .endm #ifdef CONFIG_64BIT diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 8f38bfd642cf..d00de17b3778 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -1,7 +1,7 @@ /* * arch/s390/kernel/head31.S * - * (C) Copyright IBM Corp. 2005 + * Copyright (C) IBM Corp. 2005,2006 * * Author(s): Hartmut Penner * Martin Schwidefsky @@ -16,12 +16,31 @@ # or linload or SALIPL # .org 0x10000 -startup:basr %r13,0 # get base -.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) - basr %r14, %r1 +startup:basr %r13,0 # get base +.LPG0: l %r13,0f-.LPG0(%r13) + b 0(%r13) +0: .long startup_continue + +# +# params at 10400 (setup.h) +# + .org PARMAREA + .long 0,0 # IPL_DEVICE + .long 0,RAMDISK_ORIGIN # INITRD_START + .long 0,RAMDISK_SIZE # INITRD_SIZE + + .org COMMAND_LINE + .byte "root=/dev/ram0 ro" + .byte 0 + + .org 0x11000 + +startup_continue: + basr %r13,0 # get base +.LPG1: GET_IPL_DEVICE lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers - la %r12,_pstart-.LPG1(%r13) # pointer to parameter area - # move IPL device to lowcore + l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area + # move IPL device to lowcore mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) # @@ -51,8 +70,8 @@ startup:basr %r13,0 # get base a %r1,__LC_EXT_NEW_PSW+4 # set handler st %r1,__LC_EXT_NEW_PSW+4 - la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff - la %r1, .Lsccb-PARMAREA(%r4) # our sccb + l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff + lr %r1,%r4 # our sccb .insn rre,0xb2200000,%r2,%r1 # service call ipm %r1 srl %r1,28 # get cc code @@ -63,7 +82,7 @@ startup:basr %r13,0 # get base be .Lservicecall-.LPG1(%r13) lpsw .Lwaitsclp-.LPG1(%r13) .Lsclph: - lh %r1,.Lsccbr-PARMAREA(%r4) + lh %r1,.Lsccbr-.Lsccb(%r4) chi %r1,0x10 # 0x0010 is the sucess code je .Lprocsccb # let's process the sccb chi %r1,0x1f0 @@ -74,7 +93,7 @@ startup:basr %r13,0 # get base b .Lservicecall-.LPG1(%r13) .Lprocsccb: lhi %r1,0 - icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 + icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 jnz .Lscnd lhi %r1,0x800 # otherwise report 2GB .Lscnd: @@ -84,10 +103,10 @@ startup:basr %r13,0 # get base lr %r1,%r3 .Lno2gb: xr %r3,%r3 # same logic - ic %r3,.Lscpa1-PARMAREA(%r4) + ic %r3,.Lscpa1-.Lsccb(%r4) chi %r3,0x00 jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r4) + l %r3,.Lscpa2-.Lsccb(%r4) .Lcompmem: mr %r2,%r1 # mem in MB on 128-bit l %r1,.Lonemb-.LPG1(%r13) @@ -95,8 +114,6 @@ startup:basr %r13,0 # get base b .Lfchunk-.LPG1(%r13) .align 4 -.Lget_ipl_device_addr: - .long .Lget_ipl_device .Lpmask: .byte 0 .align 8 @@ -242,6 +259,8 @@ startup:basr %r13,0 # get base .long 0 # cr13: home space segment table .long 0xc0000000 # cr14: machine check handling off .long 0 # cr15: linkage stack operations +.Lduct: .long 0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0 .Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp @@ -252,25 +271,9 @@ startup:basr %r13,0 # get base .Lmflags:.long machine_flags .Lbss_bgn: .long __bss_start .Lbss_end: .long _end - - .org PARMAREA-64 -.Lduct: .long 0,0,0,0,0,0,0,0 - .long 0,0,0,0,0,0,0,0 - -# -# params at 10400 (setup.h) -# - .org PARMAREA - .global _pstart -_pstart: - .long 0,0 # IPL_DEVICE - .long 0,RAMDISK_ORIGIN # INITRD_START - .long 0,RAMDISK_SIZE # INITRD_SIZE - - .org COMMAND_LINE - .byte "root=/dev/ram0 ro" - .byte 0 - .org 0x11000 +.Lparmaddr: .long PARMAREA +.Lsccbaddr: .long .Lsccb + .align 4096 .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -287,18 +290,14 @@ _pstart: .Lscpincr2: .quad 0x00 .fill 3984,1,0 - .org 0x12000 - .global _pend -_pend: - - GET_IPL_DEVICE + .align 4096 #ifdef CONFIG_SHARED_KERNEL .org 0x100000 #endif # -# startup-code, running in virtual mode +# startup-code, running in absolute addressing mode # .globl _stext _stext: basr %r13,0 # get base diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index ad5d87f3aef3..47744fcca930 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -1,7 +1,7 @@ /* * arch/s390/kernel/head64.S * - * (C) Copyright IBM Corp. 1999,2005 + * Copyright (C) IBM Corp. 1999,2006 * * Author(s): Hartmut Penner * Martin Schwidefsky @@ -15,18 +15,37 @@ # this is called either by the ipl loader or directly by PSW restart # or linload or SALIPL # - .org 0x10000 -startup:basr %r13,0 # get base + .org 0x10000 +startup:basr %r13,0 # get base +.LPG0: l %r13,0f-.LPG0(%r13) + b 0(%r13) +0: .long startup_continue + +# +# params at 10400 (setup.h) +# + .org PARMAREA + .quad 0 # IPL_DEVICE + .quad RAMDISK_ORIGIN # INITRD_START + .quad RAMDISK_SIZE # INITRD_SIZE + + .org COMMAND_LINE + .byte "root=/dev/ram0 ro" + .byte 0 + + .org 0x11000 + +startup_continue: + basr %r13,0 # get base .LPG1: sll %r13,1 # remove high order bit srl %r13,1 - l %r1,.Lget_ipl_device_addr-.LPG1(%r13) - basr %r14,%r1 + GET_IPL_DEVICE lhi %r1,1 # mode 1 = esame slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode sam64 # switch to 64 bit mode lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers - larl %r12,_pstart # pointer to parameter area + lg %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area # move IPL device to lowcore mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) @@ -55,8 +74,8 @@ startup:basr %r13,0 # get base larl %r1,.Lsclph stg %r1,__LC_EXT_NEW_PSW+8 # set handler - larl %r4,_pstart # %r4 is our index for sccb stuff - la %r1,.Lsccb-PARMAREA(%r4) # our sccb + larl %r4,.Lsccb # %r4 is our index for sccb stuff + lgr %r1,%r4 # our sccb .insn rre,0xb2200000,%r2,%r1 # service call ipm %r1 srl %r1,28 # get cc code @@ -67,7 +86,7 @@ startup:basr %r13,0 # get base be .Lservicecall-.LPG1(%r13) lpswe .Lwaitsclp-.LPG1(%r13) .Lsclph: - lh %r1,.Lsccbr-PARMAREA(%r4) + lh %r1,.Lsccbr-.Lsccb(%r4) chi %r1,0x10 # 0x0010 is the sucess code je .Lprocsccb # let's process the sccb chi %r1,0x1f0 @@ -78,15 +97,15 @@ startup:basr %r13,0 # get base b .Lservicecall-.LPG1(%r13) .Lprocsccb: lghi %r1,0 - icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 + icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 jnz .Lscnd - lg %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one + lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one .Lscnd: xr %r3,%r3 # same logic - ic %r3,.Lscpa1-PARMAREA(%r4) + ic %r3,.Lscpa1-.Lsccb(%r4) chi %r3,0x00 jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r4) + l %r3,.Lscpa2-.Lsccb(%r4) .Lcompmem: mlgr %r2,%r1 # mem in MB on 128-bit l %r1,.Lonemb-.LPG1(%r13) @@ -94,8 +113,6 @@ startup:basr %r13,0 # get base b .Lfchunk-.LPG1(%r13) .align 4 -.Lget_ipl_device_addr: - .long .Lget_ipl_device .Lpmask: .byte 0 .align 8 @@ -242,29 +259,16 @@ startup:basr %r13,0 # get base .quad 0 # cr13: home space segment table .quad 0xc0000000 # cr14: machine check handling off .quad 0 # cr15: linkage stack operations +.Lduct: .long 0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0 .Lpcmsk:.quad 0x0000000180000000 .L4malign:.quad 0xffffffffffc00000 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lnop: .long 0x07000700 +.Lparmaddr: + .quad PARMAREA - .org PARMAREA-64 -.Lduct: .long 0,0,0,0,0,0,0,0 - .long 0,0,0,0,0,0,0,0 - -# -# params at 10400 (setup.h) -# - .org PARMAREA - .global _pstart -_pstart: - .quad 0 # IPL_DEVICE - .quad RAMDISK_ORIGIN # INITRD_START - .quad RAMDISK_SIZE # INITRD_SIZE - - .org COMMAND_LINE - .byte "root=/dev/ram0 ro" - .byte 0 - .org 0x11000 + .align 4096 .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -281,18 +285,14 @@ _pstart: .Lscpincr2: .quad 0x00 .fill 3984,1,0 - .org 0x12000 - .global _pend -_pend: - - GET_IPL_DEVICE + .align 4096 #ifdef CONFIG_SHARED_KERNEL .org 0x100000 #endif # -# startup-code, running in virtual mode +# startup-code, running in absolute addressing mode # .globl _stext _stext: basr %r13,0 # get base @@ -326,4 +326,3 @@ _stext: basr %r13,0 # get base .align 8 .Ldw: .quad 0x0002000180000000,0x0000000000000000 .Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - -- cgit v1.2.3 From cc43ec1ab0ae67c9cd5b3c2483a731afc98cbc2c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Jun 2006 15:02:47 +0200 Subject: [S390] preempt_count initialization. The preempt_count in the thread_info structure must be initialized to 1. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- include/asm-s390/thread_info.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index 8e0c7ed73d03..0a518915bf90 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h @@ -63,6 +63,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ + .preempt_count = 1, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ -- cgit v1.2.3 From 774fc4ef718f7343306ba3695e8a2622cbd9764d Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 29 Jun 2006 15:02:59 +0200 Subject: [S390] dasd eer data format. The struct dasd_eer_header needs the packed attribute, or there will be 6 additional bytes of random data between the fixed header and the variable length part of the eer data. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 9d574ede1b1d..da65f1b032f5 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -276,7 +276,7 @@ struct dasd_eer_header { __u64 tv_sec; __u64 tv_usec; char busid[DASD_EER_BUSID_SIZE]; -}; +} __attribute__ ((packed)); /* * The following function can be used for those triggers that have -- cgit v1.2.3 From 84d11c5dcc4cdfe962fcd58a0302711befcdceda Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Thu, 29 Jun 2006 15:03:17 +0200 Subject: Convert s390_collect_crw_info() in s390mach.c from being started as a deprecated kernel_thread to a kthread. Signed-off-by: Serge E. Hallyn Signed-off-by: Martin Schwidefsky --- drivers/s390/s390mach.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index f99e55308b32..8dc75002acbe 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -56,8 +57,6 @@ s390_collect_crw_info(void *param) unsigned int chain; sem = (struct semaphore *)param; - /* Set a nice name. */ - daemonize("kmcheck"); repeat: down_interruptible(sem); slow = 0; @@ -516,7 +515,7 @@ arch_initcall(machine_check_init); static int __init machine_check_crw_init (void) { - kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES); + kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); ctl_set_bit(14, 28); /* enable channel report MCH */ return 0; } -- cgit v1.2.3 From 3ee526841ba409f7b23f825f120772a79e7d7bd2 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Thu, 29 Jun 2006 15:03:28 +0200 Subject: [S390] avenrun export in appdata_base.c Remove EXPORT_SYMBOL_GPL(avenrun) from appdata_base.c, since it is already exported in kernel/timer.c Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/appldata/appldata_base.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index f549a80cedb3..d0816d473854 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -779,7 +779,6 @@ unsigned long nr_iowait(void) #endif /* MODULE */ EXPORT_SYMBOL_GPL(si_swapinfo); EXPORT_SYMBOL_GPL(nr_threads); -EXPORT_SYMBOL_GPL(avenrun); EXPORT_SYMBOL_GPL(get_full_page_state); EXPORT_SYMBOL_GPL(nr_running); EXPORT_SYMBOL_GPL(nr_iowait); -- cgit v1.2.3 From b4f7b1ee577857aca467e6825122a3b29d6c3c0e Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 29 Jun 2006 15:03:35 +0200 Subject: [S390] cio chpid offline. After setting a path to a dasd offline at the SE, I/O hangs on that dasd for 5 minutes, then continues. I/O for which an interrupt will not be reported after the channel path has been disabled was not terminated by the common I/O layer, causing the dasd MIH to hit after 5 minutes. Be more aggressive in terminating I/O after setting a channel path offline. Also make sure to generate a fake irb if the device driver issues an I/O request after being notified of the killed I/O and clear residual information from the irb before trying to start the delayed verification. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc.c | 3 +-- drivers/s390/cio/device_fsm.c | 2 ++ drivers/s390/cio/device_ops.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 4a9da5bdd535..b00f3ed051a0 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -244,8 +244,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && - (sch->schib.pmcw.lpum == mask) && - (sch->vpm == 0)) { + (sch->schib.pmcw.lpum == mask)) { int cc; cc = cio_clear(sch); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 49ec562d7f60..5ec8ef1df9fa 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -861,6 +861,8 @@ ccw_device_clear_verify(struct ccw_device *cdev, enum dev_event dev_event) irb = (struct irb *) __LC_IRB; /* Accumulate status. We don't do basic sense. */ ccw_device_accumulate_irb(cdev, irb); + /* Remember to clear irb to avoid residuals. */ + memset(&cdev->private->irb, 0, sizeof(struct irb)); /* Try to start delayed device verification. */ ccw_device_online_verify(cdev, 0); /* Note: Don't call handler for cio initiated clear! */ diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 5c9904b418e1..b266ad8e14ff 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -78,7 +78,8 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, return -ENODEV; if (cdev->private->state == DEV_STATE_NOT_OPER) return -ENODEV; - if (cdev->private->state == DEV_STATE_VERIFY) { + if (cdev->private->state == DEV_STATE_VERIFY || + cdev->private->state == DEV_STATE_CLEAR_VERIFY) { /* Remember to fake irb when finished. */ if (!cdev->private->flags.fake_irb) { cdev->private->flags.fake_irb = 1; -- cgit v1.2.3 From 8e0474f3b43e8bec1be164006a378e9dbd439b2c Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Thu, 29 Jun 2006 15:03:42 +0200 Subject: [S390] fix duplicate export of overflow{ug}id overflowuid and overflowgid were exported twice. Remove the export from s390_ksyms.c Signed-off-by: Serge E. Hallyn Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/s390_ksyms.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 4176c77670c4..0886e739d122 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -46,8 +46,6 @@ EXPORT_SYMBOL(__down_interruptible); */ extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(overflowuid); -EXPORT_SYMBOL(overflowgid); EXPORT_SYMBOL(empty_zero_page); /* -- cgit v1.2.3 From 65b73c69c527a295ff3730b0b14e73359a8b4a16 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Jun 2006 15:03:48 +0200 Subject: [S390] remove unused macros from binfmt_elf32.c The two macros NEW_TO_OLD_UID and NEW_TO_OLD_GID in binfmt_elf32.c are not used by any code. Remove them. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/binfmt_elf32.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 1f451c2cb071..12a6311e9838 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -177,11 +177,6 @@ struct elf_prpsinfo32 #include -#undef NEW_TO_OLD_UID -#undef NEW_TO_OLD_GID -#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) -#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) - #define elf_addr_t u32 /* #define init_elf_binfmt init_elf32_binfmt -- cgit v1.2.3 From 8f27766a883149926e7c1f69d9f1d8f68efcd65f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Jun 2006 15:03:54 +0200 Subject: [S390] remove export of sys_call_table Remove export of the sys_call_table symbol to prevent the misuse of it. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry.S | 1 - arch/s390/kernel/entry64.S | 2 -- 2 files changed, 3 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 74d80c3bba80..aa8b52c2140f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -1019,7 +1019,6 @@ cleanup_io_leave_insn: .long cleanup_critical #define SYSCALL(esa,esame,emu) .long esa - .globl sys_call_table sys_call_table: #include "syscalls.S" #undef SYSCALL diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 21e601d56139..f3222a1b2861 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -993,7 +993,6 @@ cleanup_io_leave_insn: .quad __critical_end #define SYSCALL(esa,esame,emu) .long esame - .globl sys_call_table sys_call_table: #include "syscalls.S" #undef SYSCALL @@ -1001,7 +1000,6 @@ sys_call_table: #ifdef CONFIG_COMPAT #define SYSCALL(esa,esame,emu) .long emu - .globl sys_call_table_emu sys_call_table_emu: #include "syscalls.S" #undef SYSCALL -- cgit v1.2.3 From 405455734e1cdec09c37233216f9240cb1a058e5 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Thu, 29 Jun 2006 15:08:18 +0200 Subject: [S390] add PAV support to the dasd driver. Add support for parallel-access-volumes to the dasd driver. This allows concurrent access to dasd devices with multiple channel programs. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 51 +++++++------- drivers/s390/block/dasd_devmap.c | 80 +++++++++++++++++++--- drivers/s390/block/dasd_eckd.c | 140 ++++++++++++++++++++++++++++++--------- drivers/s390/block/dasd_eckd.h | 16 ++++- drivers/s390/block/dasd_fba.c | 20 +----- drivers/s390/block/dasd_int.h | 2 +- include/asm-s390/dasd.h | 8 ++- 7 files changed, 227 insertions(+), 90 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 7e9978ad1445..bafcd2f20ae2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1855,15 +1855,34 @@ dasd_generic_probe (struct ccw_device *cdev, { int ret; + ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + if (ret) { + printk(KERN_WARNING + "dasd_generic_probe: could not set ccw-device options " + "for %s\n", cdev->dev.bus_id); + return ret; + } ret = dasd_add_sysfs_files(cdev); if (ret) { printk(KERN_WARNING "dasd_generic_probe: could not add sysfs entries " "for %s\n", cdev->dev.bus_id); - } else { - cdev->handler = &dasd_int_handler; + return ret; } + cdev->handler = &dasd_int_handler; + /* + * Automatically online either all dasd devices (dasd_autodetect) + * or all devices specified with dasd= parameters during + * initial probe. + */ + if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || + (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0)) + ret = ccw_device_set_online(cdev); + if (ret) + printk(KERN_WARNING + "dasd_generic_probe: could not initially online " + "ccw-device %s\n", cdev->dev.bus_id); return ret; } @@ -1911,6 +1930,8 @@ dasd_generic_set_online (struct ccw_device *cdev, struct dasd_device *device; int rc; + /* first online clears initial online feature flag */ + dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0); device = dasd_create_device(cdev); if (IS_ERR(device)) return PTR_ERR(device); @@ -2065,31 +2086,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) return ret; } -/* - * Automatically online either all dasd devices (dasd_autodetect) or - * all devices specified with dasd= parameters. - */ -static int -__dasd_auto_online(struct device *dev, void *data) -{ - struct ccw_device *cdev; - - cdev = to_ccwdev(dev); - if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0) - ccw_device_set_online(cdev); - return 0; -} - -void -dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) -{ - struct device_driver *drv; - - drv = get_driver(&dasd_discipline_driver->driver); - driver_for_each_device(drv, NULL, NULL, __dasd_auto_online); - put_driver(drv); -} - static int __init dasd_init(void) @@ -2170,5 +2166,4 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove); EXPORT_SYMBOL_GPL(dasd_generic_notify); EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); -EXPORT_SYMBOL_GPL(dasd_generic_auto_online); diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 672e50314b12..9e9ae7179602 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -27,7 +27,7 @@ #include "dasd_int.h" kmem_cache_t *dasd_page_cache; -EXPORT_SYMBOL(dasd_page_cache); +EXPORT_SYMBOL_GPL(dasd_page_cache); /* * dasd_devmap_t is used to store the features and the relation @@ -48,6 +48,20 @@ struct dasd_devmap { struct dasd_uid uid; }; +/* + * dasd_servermap is used to store the server_id of all storage servers + * accessed by DASD device driver. + */ +struct dasd_servermap { + struct list_head list; + struct server_id { + char vendor[4]; + char serial[15]; + } sid; +}; + +static struct list_head dasd_serverlist; + /* * Parameter parsing functions for dasd= parameter. The syntax is: * : (0x)?[0-9a-fA-F]+ @@ -64,6 +78,8 @@ struct dasd_devmap { int dasd_probeonly = 0; /* is true, when probeonly mode is active */ int dasd_autodetect = 0; /* is true, when autodetection is active */ +int dasd_nopav = 0; /* is true, when PAV is disabled */ +EXPORT_SYMBOL_GPL(dasd_nopav); /* * char *dasd[] is intended to hold the ranges supplied by the dasd= statement @@ -228,19 +244,24 @@ dasd_parse_keyword( char *parsestring ) { length = strlen(parsestring); residual_str = parsestring + length; } - if (strncmp ("autodetect", parsestring, length) == 0) { + if (strncmp("autodetect", parsestring, length) == 0) { dasd_autodetect = 1; MESSAGE (KERN_INFO, "%s", "turning to autodetection mode"); return residual_str; } - if (strncmp ("probeonly", parsestring, length) == 0) { + if (strncmp("probeonly", parsestring, length) == 0) { dasd_probeonly = 1; MESSAGE(KERN_INFO, "%s", "turning to probeonly mode"); return residual_str; } - if (strncmp ("fixedbuffers", parsestring, length) == 0) { + if (strncmp("nopav", parsestring, length) == 0) { + dasd_nopav = 1; + MESSAGE(KERN_INFO, "%s", "disable PAV mode"); + return residual_str; + } + if (strncmp("fixedbuffers", parsestring, length) == 0) { if (dasd_page_cache) return residual_str; dasd_page_cache = @@ -294,6 +315,8 @@ dasd_parse_range( char *parsestring ) { features = dasd_feature_list(str, &str); if (features < 0) return ERR_PTR(-EINVAL); + /* each device in dasd= parameter should be set initially online */ + features |= DASD_FEATURE_INITIAL_ONLINE; while (from <= to) { sprintf(bus_id, "%01x.%01x.%04x", from_id0, from_id1, from++); @@ -836,6 +859,38 @@ static struct attribute_group dasd_attr_group = { .attrs = dasd_attrs, }; +/* + * Check if the related storage server is already contained in the + * dasd_serverlist. If server is not contained, create new entry. + * Return 0 if server was already in serverlist, + * 1 if the server was added successfully + * <0 in case of error. + */ +static int +dasd_add_server(struct dasd_uid *uid) +{ + struct dasd_servermap *new, *tmp; + + /* check if server is already contained */ + list_for_each_entry(tmp, &dasd_serverlist, list) + // normale cmp? + if (strncmp(tmp->sid.vendor, uid->vendor, + sizeof(tmp->sid.vendor)) == 0 + && strncmp(tmp->sid.serial, uid->serial, + sizeof(tmp->sid.serial)) == 0) + return 0; + + new = (struct dasd_servermap *) + kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); + if (!new) + return -ENOMEM; + + strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); + strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); + list_add(&new->list, &dasd_serverlist); + return 1; +} + /* * Return copy of the device unique identifier. @@ -856,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) /* * Register the given device unique identifier into devmap struct. + * Return 0 if server was already in serverlist, + * 1 if the server was added successful + * <0 in case of error. */ int dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) { struct dasd_devmap *devmap; + int rc; devmap = dasd_find_busid(cdev->dev.bus_id); if (IS_ERR(devmap)) return PTR_ERR(devmap); spin_lock(&dasd_devmap_lock); devmap->uid = *uid; + rc = dasd_add_server(uid); spin_unlock(&dasd_devmap_lock); - return 0; + return rc; } -EXPORT_SYMBOL(dasd_set_uid); +EXPORT_SYMBOL_GPL(dasd_set_uid); /* * Return value of the specified feature. @@ -882,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature) devmap = dasd_find_busid(cdev->dev.bus_id); if (IS_ERR(devmap)) - return (int) PTR_ERR(devmap); + return PTR_ERR(devmap); return ((devmap->features & feature) != 0); } @@ -898,7 +958,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) devmap = dasd_find_busid(cdev->dev.bus_id); if (IS_ERR(devmap)) - return (int) PTR_ERR(devmap); + return PTR_ERR(devmap); spin_lock(&dasd_devmap_lock); if (flag) @@ -934,8 +994,10 @@ dasd_devmap_init(void) dasd_max_devindex = 0; for (i = 0; i < 256; i++) INIT_LIST_HEAD(&dasd_hashlists[i]); - return 0; + /* Initialize servermap structure. */ + INIT_LIST_HEAD(&dasd_serverlist); + return 0; } void diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 12257776e79b..0dfab30e8089 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "dasd_int.h" @@ -89,17 +90,22 @@ dasd_eckd_probe (struct ccw_device *cdev) { int ret; - ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); - if (ret) + /* set ECKD specific ccw-device options */ + ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); + if (ret) { + printk(KERN_WARNING + "dasd_eckd_probe: could not set ccw-device options " + "for %s\n", cdev->dev.bus_id); return ret; - ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE); - return 0; + } + ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); + return ret; } static int dasd_eckd_set_online(struct ccw_device *cdev) { - return dasd_generic_set_online (cdev, &dasd_eckd_discipline); + return dasd_generic_set_online(cdev, &dasd_eckd_discipline); } static struct ccw_driver dasd_eckd_driver = { @@ -540,6 +546,86 @@ dasd_eckd_read_conf(struct dasd_device *device) return 0; } +/* + * Build CP for Perform Subsystem Function - SSC. + */ +struct dasd_ccw_req * +dasd_eckd_build_psf_ssc(struct dasd_device *device) +{ + struct dasd_ccw_req *cqr; + struct dasd_psf_ssc_data *psf_ssc_data; + struct ccw1 *ccw; + + cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ , + sizeof(struct dasd_psf_ssc_data), + device); + + if (IS_ERR(cqr)) { + DEV_MESSAGE(KERN_WARNING, device, "%s", + "Could not allocate PSF-SSC request"); + return cqr; + } + psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; + psf_ssc_data->order = PSF_ORDER_SSC; + psf_ssc_data->suborder = 0x08; + + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_PSF; + ccw->cda = (__u32)(addr_t)psf_ssc_data; + ccw->count = 66; + + cqr->device = device; + cqr->expires = 10*HZ; + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + return cqr; +} + +/* + * Perform Subsystem Function. + * It is necessary to trigger CIO for channel revalidation since this + * call might change behaviour of DASD devices. + */ +static int +dasd_eckd_psf_ssc(struct dasd_device *device) +{ + struct dasd_ccw_req *cqr; + int rc; + + cqr = dasd_eckd_build_psf_ssc(device); + if (IS_ERR(cqr)) + return PTR_ERR(cqr); + + rc = dasd_sleep_on(cqr); + if (!rc) + /* trigger CIO to reprobe devices */ + css_schedule_reprobe(); + dasd_sfree_request(cqr, cqr->device); + return rc; +} + +/* + * Valide storage server of current device. + */ +static int +dasd_eckd_validate_server(struct dasd_device *device) +{ + int rc; + + /* Currently PAV is the only reason to 'validate' server on LPAR */ + if (dasd_nopav || MACHINE_IS_VM) + return 0; + + rc = dasd_eckd_psf_ssc(device); + if (rc) + /* may be requested feature is not available on server, + * therefore just report error and go ahead */ + DEV_MESSAGE(KERN_INFO, device, + "Perform Subsystem Function returned rc=%d", rc); + /* RE-Read Configuration Data */ + return dasd_eckd_read_conf(device); +} + /* * Check device characteristics. * If the device is accessible using ECKD discipline, the device is enabled. @@ -570,16 +656,29 @@ dasd_eckd_check_characteristics(struct dasd_device *device) private->attrib.operation = DASD_NORMAL_CACHE; private->attrib.nr_cyl = 0; + /* Read Configuration Data */ + rc = dasd_eckd_read_conf(device); + if (rc) + return rc; + + /* Generate device unique id and register in devmap */ + rc = dasd_eckd_generate_uid(device, &uid); + if (rc) + return rc; + rc = dasd_set_uid(device->cdev, &uid); + if (rc == 1) /* new server found */ + rc = dasd_eckd_validate_server(device); + if (rc) + return rc; + /* Read Device Characteristics */ rdc_data = (void *) &(private->rdc_data); memset(rdc_data, 0, sizeof(rdc_data)); rc = read_dev_chars(device->cdev, &rdc_data, 64); - if (rc) { + if (rc) DEV_MESSAGE(KERN_WARNING, device, - "Read device characteristics returned error %d", - rc); - return rc; - } + "Read device characteristics returned " + "rc=%d", rc); DEV_MESSAGE(KERN_INFO, device, "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", @@ -590,19 +689,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) private->rdc_data.no_cyl, private->rdc_data.trk_per_cyl, private->rdc_data.sec_per_trk); - - /* Read Configuration Data */ - rc = dasd_eckd_read_conf (device); - if (rc) - return rc; - - /* Generate device unique id and register in devmap */ - rc = dasd_eckd_generate_uid(device, &uid); - if (rc) - return rc; - - rc = dasd_set_uid(device->cdev, &uid); - return rc; } @@ -1687,14 +1773,8 @@ static struct dasd_discipline dasd_eckd_discipline = { static int __init dasd_eckd_init(void) { - int ret; - ASCEBC(dasd_eckd_discipline.ebcname, 4); - - ret = ccw_driver_register(&dasd_eckd_driver); - if (!ret) - dasd_generic_auto_online(&dasd_eckd_driver); - return ret; + return ccw_driver_register(&dasd_eckd_driver); } static void __exit diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 9d91c8632569..712ff1650134 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -41,9 +41,10 @@ #define DASD_ECKD_CCW_RESERVE 0xB4 /* - *Perform Subsystem Function / Sub-Orders + * Perform Subsystem Function / Sub-Orders */ -#define PSF_ORDER_PRSSD 0x18 +#define PSF_ORDER_PRSSD 0x18 +#define PSF_ORDER_SSC 0x1D /***************************************************************************** * SECTION: Type Definitions @@ -353,4 +354,15 @@ struct dasd_psf_prssd_data { unsigned char varies[9]; } __attribute__ ((packed)); +/* + * Perform Subsystem Function - Set Subsystem Characteristics + */ +struct dasd_psf_ssc_data { + unsigned char order; + unsigned char flags; + unsigned char cu_type[4]; + unsigned char suborder; + unsigned char reserved[59]; +} __attribute__((packed)); + #endif /* DASD_ECKD_H */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index d331c6e22c59..bb7755b9b19d 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -56,19 +56,13 @@ static struct ccw_driver dasd_fba_driver; /* see below */ static int dasd_fba_probe(struct ccw_device *cdev) { - int ret; - - ret = dasd_generic_probe (cdev, &dasd_fba_discipline); - if (ret) - return ret; - ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); - return 0; + return dasd_generic_probe(cdev, &dasd_fba_discipline); } static int dasd_fba_set_online(struct ccw_device *cdev) { - return dasd_generic_set_online (cdev, &dasd_fba_discipline); + return dasd_generic_set_online(cdev, &dasd_fba_discipline); } static struct ccw_driver dasd_fba_driver = { @@ -569,16 +563,8 @@ static struct dasd_discipline dasd_fba_discipline = { static int __init dasd_fba_init(void) { - int ret; - ASCEBC(dasd_fba_discipline.ebcname, 4); - - ret = ccw_driver_register(&dasd_fba_driver); - if (ret) - return ret; - - dasd_generic_auto_online(&dasd_fba_driver); - return 0; + return ccw_driver_register(&dasd_fba_driver); } static void __exit diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 2c1fa85a3dad..03a83efc34c4 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -513,12 +513,12 @@ void dasd_generic_remove (struct ccw_device *cdev); 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 *); /* externals in dasd_devmap.c */ extern int dasd_max_devindex; extern int dasd_probeonly; extern int dasd_autodetect; +extern int dasd_nopav; int dasd_devmap_init(void); void dasd_devmap_exit(void); diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h index 1630c26e8f45..c042f9578081 100644 --- a/include/asm-s390/dasd.h +++ b/include/asm-s390/dasd.h @@ -68,10 +68,12 @@ typedef struct dasd_information2_t { * 0x00: default features * 0x01: readonly (ro) * 0x02: use diag discipline (diag) + * 0x04: set the device initially online (internal use only) */ -#define DASD_FEATURE_DEFAULT 0 -#define DASD_FEATURE_READONLY 1 -#define DASD_FEATURE_USEDIAG 2 +#define DASD_FEATURE_DEFAULT 0x00 +#define DASD_FEATURE_READONLY 0x01 +#define DASD_FEATURE_USEDIAG 0x02 +#define DASD_FEATURE_INITIAL_ONLINE 0x04 #define DASD_PARTN_BITS 2 -- cgit v1.2.3 From 585c3047a881d0f54b93a0dd8ab499b07ed25d09 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 29 Jun 2006 15:08:25 +0200 Subject: [S390] Add vmpanic parameter. Implementation of new kernel parameter vmpanic that provides a means to perform a z/VM CP command after a kernel panic occurred. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- Documentation/kernel-parameters.txt | 9 +++++++-- arch/s390/kernel/setup.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 0d189c93eeaf..25f8d20dac53 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1689,9 +1689,14 @@ running once the system is up. decrease the size and leave more room for directly mapped kernel RAM. - vmhalt= [KNL,S390] + vmhalt= [KNL,S390] Perform z/VM CP command after system halt. + Format: - vmpoff= [KNL,S390] + vmpanic= [KNL,S390] Perform z/VM CP command after kernel panic. + Format: + + vmpoff= [KNL,S390] Perform z/VM CP command after power off. + Format: waveartist= [HW,OSS] Format: ,,, diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 813444aac7d7..2b2551e3510b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,7 @@ void __devinit cpu_init (void) */ char vmhalt_cmd[128] = ""; char vmpoff_cmd[128] = ""; +char vmpanic_cmd[128] = ""; static inline void strncpy_skip_quote(char *dst, char *src, int n) { @@ -146,6 +148,38 @@ static int __init vmpoff_setup(char *str) __setup("vmpoff=", vmpoff_setup); +static int vmpanic_notify(struct notifier_block *self, unsigned long event, + void *data) +{ + if (MACHINE_IS_VM && strlen(vmpanic_cmd) > 0) + cpcmd(vmpanic_cmd, NULL, 0, NULL); + + return NOTIFY_OK; +} + +#define PANIC_PRI_VMPANIC 0 + +static struct notifier_block vmpanic_nb = { + .notifier_call = vmpanic_notify, + .priority = PANIC_PRI_VMPANIC +}; + +static int __init vmpanic_setup(char *str) +{ + static int register_done __initdata = 0; + + strncpy_skip_quote(vmpanic_cmd, str, 127); + vmpanic_cmd[127] = 0; + if (!register_done) { + register_done = 1; + atomic_notifier_chain_register(&panic_notifier_list, + &vmpanic_nb); + } + return 1; +} + +__setup("vmpanic=", vmpanic_setup); + /* * condev= and conmode= setup parameter. */ -- cgit v1.2.3 From 5b5dd21a8e6652fc8b58a32757575cc7fce2b54d Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Thu, 29 Jun 2006 15:08:35 +0200 Subject: [S390] appldata enhancements. Add CPU ID and steal time, and make OS record size variable. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/appldata/appldata.h | 24 ++++++++- arch/s390/appldata/appldata_base.c | 39 +++++--------- arch/s390/appldata/appldata_mem.c | 5 +- arch/s390/appldata/appldata_net_sum.c | 5 +- arch/s390/appldata/appldata_os.c | 98 ++++++++++++++++++++++++----------- 5 files changed, 108 insertions(+), 63 deletions(-) diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h index e806a8922bbb..71d65eb30650 100644 --- a/arch/s390/appldata/appldata.h +++ b/arch/s390/appldata/appldata.h @@ -3,9 +3,9 @@ * * Definitions and interface for Linux - z/VM Monitor Stream. * - * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. * - * Author: Gerald Schaefer + * Author: Gerald Schaefer */ //#define APPLDATA_DEBUG /* Debug messages on/off */ @@ -29,6 +29,22 @@ #define CTL_APPLDATA_NET_SUM 2125 #define CTL_APPLDATA_PROC 2126 +#ifndef CONFIG_64BIT + +#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ +#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ +#define APPLDATA_GEN_EVENT_RECORD 0x02 +#define APPLDATA_START_CONFIG_REC 0x03 + +#else + +#define APPLDATA_START_INTERVAL_REC 0x80 +#define APPLDATA_STOP_REC 0x81 +#define APPLDATA_GEN_EVENT_RECORD 0x82 +#define APPLDATA_START_CONFIG_REC 0x83 + +#endif /* CONFIG_64BIT */ + #define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x) #define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x) #define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x) @@ -53,7 +69,11 @@ struct appldata_ops { void *data; /* record data */ unsigned int size; /* size of record */ struct module *owner; /* THIS_MODULE */ + char mod_lvl[2]; /* modification level, EBCDIC */ }; extern int appldata_register_ops(struct appldata_ops *ops); extern void appldata_unregister_ops(struct appldata_ops *ops); +extern int appldata_diag(char record_nr, u16 function, unsigned long buffer, + u16 length, char *mod_lvl); + diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index d0816d473854..61bc44626c04 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -5,9 +5,9 @@ * Exports appldata_register_ops() and appldata_unregister_ops() for the * data gathering modules. * - * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. * - * Author: Gerald Schaefer + * Author: Gerald Schaefer */ #include @@ -40,22 +40,6 @@ #define TOD_MICRO 0x01000 /* nr. of TOD clock units for 1 microsecond */ -#ifndef CONFIG_64BIT - -#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ -#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ -#define APPLDATA_GEN_EVENT_RECORD 0x02 -#define APPLDATA_START_CONFIG_REC 0x03 - -#else - -#define APPLDATA_START_INTERVAL_REC 0x80 -#define APPLDATA_STOP_REC 0x81 -#define APPLDATA_GEN_EVENT_RECORD 0x82 -#define APPLDATA_START_CONFIG_REC 0x83 - -#endif /* CONFIG_64BIT */ - /* * Parameter list for DIAGNOSE X'DC' @@ -195,8 +179,8 @@ static void appldata_work_fn(void *data) * * prepare parameter list, issue DIAG 0xDC */ -static int appldata_diag(char record_nr, u16 function, unsigned long buffer, - u16 length) +int appldata_diag(char record_nr, u16 function, unsigned long buffer, + u16 length, char *mod_lvl) { unsigned long ry; struct appldata_product_id { @@ -214,7 +198,7 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer, .record_nr = record_nr, .version_nr = {0xF2, 0xF6}, /* "26" */ .release_nr = {0xF0, 0xF1}, /* "01" */ - .mod_lvl = {0xF0, 0xF0}, /* "00" */ + .mod_lvl = {mod_lvl[0], mod_lvl[1]}, }; struct appldata_parameter_list appldata_parameter_list = { .diag = 0xDC, @@ -467,24 +451,25 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, module_put(ops->owner); return -ENODEV; } - ops->active = 1; ops->callback(ops->data); // init record rc = appldata_diag(ops->record_nr, APPLDATA_START_INTERVAL_REC, - (unsigned long) ops->data, ops->size); + (unsigned long) ops->data, ops->size, + ops->mod_lvl); if (rc != 0) { P_ERROR("START DIAG 0xDC for %s failed, " "return code: %d\n", ops->name, rc); module_put(ops->owner); - ops->active = 0; } else { P_INFO("Monitoring %s data enabled, " "DIAG 0xDC started.\n", ops->name); + ops->active = 1; } } else if ((buf[0] == '0') && (ops->active == 1)) { ops->active = 0; rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, - (unsigned long) ops->data, ops->size); + (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); @@ -710,7 +695,8 @@ static void __exit appldata_exit(void) 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); + (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); @@ -739,6 +725,7 @@ MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure"); EXPORT_SYMBOL_GPL(appldata_register_ops); EXPORT_SYMBOL_GPL(appldata_unregister_ops); +EXPORT_SYMBOL_GPL(appldata_diag); #ifdef MODULE /* diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index f0e2fbed3d4c..7915a197d96d 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c @@ -4,9 +4,9 @@ * Data gathering module for Linux-VM Monitor Stream, Stage 1. * Collects data related to memory management. * - * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. * - * Author: Gerald Schaefer + * Author: Gerald Schaefer */ #include @@ -152,6 +152,7 @@ static struct appldata_ops ops = { .callback = &appldata_get_mem_data, .data = &appldata_mem_data, .owner = THIS_MODULE, + .mod_lvl = {0xF0, 0xF0}, /* EBCDIC "00" */ }; diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 2a4c7432db4a..39b7bdecbf05 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c @@ -5,9 +5,9 @@ * Collects accumulated network statistics (Packets received/transmitted, * dropped, errors, ...). * - * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. * - * Author: Gerald Schaefer + * Author: Gerald Schaefer */ #include @@ -152,6 +152,7 @@ static struct appldata_ops ops = { .callback = &appldata_get_net_sum_data, .data = &appldata_net_sum_data, .owner = THIS_MODULE, + .mod_lvl = {0xF0, 0xF0}, /* EBCDIC "00" */ }; diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 99ddd3bf2fba..f2b44a2f1dec 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -4,9 +4,9 @@ * Data gathering module for Linux-VM Monitor Stream, Stage 1. * Collects misc. OS related data (CPU utilization, running processes). * - * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. * - * Author: Gerald Schaefer + * Author: Gerald Schaefer */ #include @@ -44,11 +44,14 @@ struct appldata_os_per_cpu { u32 per_cpu_system; /* ... spent in kernel mode */ u32 per_cpu_idle; /* ... spent in idle mode */ -// New in 2.6 --> + /* New in 2.6 */ u32 per_cpu_irq; /* ... spent in interrupts */ u32 per_cpu_softirq; /* ... spent in softirqs */ u32 per_cpu_iowait; /* ... spent while waiting for I/O */ -// <-- New in 2.6 + + /* New in modification level 01 */ + u32 per_cpu_steal; /* ... stolen by hypervisor */ + u32 cpu_id; /* number of this CPU */ } __attribute__((packed)); struct appldata_os_data { @@ -68,10 +71,9 @@ struct appldata_os_data { u32 avenrun[3]; /* average nr. of running processes during */ /* the last 1, 5 and 15 minutes */ -// New in 2.6 --> + /* New in 2.6 */ u32 nr_iowait; /* number of blocked threads (waiting for I/O) */ -// <-- New in 2.6 /* per cpu data */ struct appldata_os_per_cpu os_cpu[0]; @@ -79,6 +81,14 @@ struct appldata_os_data { static struct appldata_os_data *appldata_os_data; +static struct appldata_ops ops = { + .ctl_nr = CTL_APPLDATA_OS, + .name = "os", + .record_nr = APPLDATA_RECORD_OS_ID, + .owner = THIS_MODULE, + .mod_lvl = {0xF0, 0xF1}, /* EBCDIC "01" */ +}; + static inline void appldata_print_debug(struct appldata_os_data *os_data) { @@ -100,15 +110,17 @@ static inline void appldata_print_debug(struct appldata_os_data *os_data) P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus); for (i = 0; i < os_data->nr_cpus; i++) { P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, " - "idle = %u, irq = %u, softirq = %u, iowait = %u\n", - i, + "idle = %u, irq = %u, softirq = %u, iowait = %u, " + "steal = %u\n", + os_data->os_cpu[i].cpu_id, os_data->os_cpu[i].per_cpu_user, os_data->os_cpu[i].per_cpu_nice, os_data->os_cpu[i].per_cpu_system, os_data->os_cpu[i].per_cpu_idle, os_data->os_cpu[i].per_cpu_irq, os_data->os_cpu[i].per_cpu_softirq, - os_data->os_cpu[i].per_cpu_iowait); + os_data->os_cpu[i].per_cpu_iowait, + os_data->os_cpu[i].per_cpu_steal); } P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1); @@ -123,14 +135,13 @@ static inline void appldata_print_debug(struct appldata_os_data *os_data) */ static void appldata_get_os_data(void *data) { - int i, j; + int i, j, rc; struct appldata_os_data *os_data; + unsigned int new_size; os_data = data; os_data->sync_count_1++; - os_data->nr_cpus = num_online_cpus(); - os_data->nr_threads = nr_threads; os_data->nr_running = nr_running(); os_data->nr_iowait = nr_iowait(); @@ -154,9 +165,44 @@ static void appldata_get_os_data(void *data) cputime_to_jiffies(kstat_cpu(i).cpustat.softirq); os_data->os_cpu[j].per_cpu_iowait = cputime_to_jiffies(kstat_cpu(i).cpustat.iowait); + os_data->os_cpu[j].per_cpu_steal = + cputime_to_jiffies(kstat_cpu(i).cpustat.steal); + os_data->os_cpu[j].cpu_id = i; j++; } + os_data->nr_cpus = j; + + new_size = sizeof(struct appldata_os_data) + + (os_data->nr_cpus * sizeof(struct appldata_os_per_cpu)); + if (ops.size != new_size) { + if (ops.active) { + rc = appldata_diag(APPLDATA_RECORD_OS_ID, + APPLDATA_START_INTERVAL_REC, + (unsigned long) ops.data, new_size, + ops.mod_lvl); + if (rc != 0) { + P_ERROR("os: START NEW DIAG 0xDC failed, " + "return code: %d, new size = %i\n", rc, + new_size); + P_INFO("os: stopping old record now\n"); + } else + P_INFO("os: new record size = %i\n", new_size); + + rc = appldata_diag(APPLDATA_RECORD_OS_ID, + APPLDATA_STOP_REC, + (unsigned long) ops.data, ops.size, + ops.mod_lvl); + if (rc != 0) + P_ERROR("os: STOP OLD DIAG 0xDC failed, " + "return code: %d, old size = %i\n", rc, + ops.size); + else + P_INFO("os: old record size = %i stopped\n", + ops.size); + } + ops.size = new_size; + } os_data->timestamp = get_clock(); os_data->sync_count_2++; #ifdef APPLDATA_DEBUG @@ -165,15 +211,6 @@ static void appldata_get_os_data(void *data) } -static struct appldata_ops ops = { - .ctl_nr = CTL_APPLDATA_OS, - .name = "os", - .record_nr = APPLDATA_RECORD_OS_ID, - .callback = &appldata_get_os_data, - .owner = THIS_MODULE, -}; - - /* * appldata_os_init() * @@ -181,26 +218,25 @@ static struct appldata_ops ops = { */ static int __init appldata_os_init(void) { - int rc, size; + int rc, max_size; - size = sizeof(struct appldata_os_data) + - (NR_CPUS * sizeof(struct appldata_os_per_cpu)); - if (size > APPLDATA_MAX_REC_SIZE) { - P_ERROR("Size of record = %i, bigger than maximum (%i)!\n", - size, APPLDATA_MAX_REC_SIZE); + max_size = sizeof(struct appldata_os_data) + + (NR_CPUS * sizeof(struct appldata_os_per_cpu)); + if (max_size > APPLDATA_MAX_REC_SIZE) { + P_ERROR("Max. size of OS record = %i, bigger than maximum " + "record size (%i)\n", max_size, APPLDATA_MAX_REC_SIZE); rc = -ENOMEM; goto out; } - P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size, + P_DEBUG("max. sizeof(os) = %i, sizeof(os_cpu) = %lu\n", max_size, sizeof(struct appldata_os_per_cpu)); - appldata_os_data = kmalloc(size, GFP_DMA); + appldata_os_data = kzalloc(max_size, GFP_DMA); if (appldata_os_data == NULL) { P_ERROR("No memory for %s!\n", ops.name); rc = -ENOMEM; goto out; } - memset(appldata_os_data, 0, size); appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu); appldata_os_data->cpu_offset = offsetof(struct appldata_os_data, @@ -208,7 +244,7 @@ static int __init appldata_os_init(void) P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset); ops.data = appldata_os_data; - ops.size = size; + ops.callback = &appldata_get_os_data; rc = appldata_register_ops(&ops); if (rc != 0) { P_ERROR("Error registering ops, rc = %i\n", rc); -- cgit v1.2.3 From 94bb063312d872d9269deb2e5c0c7c6d5b0318e1 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 29 Jun 2006 15:08:41 +0200 Subject: [S390] rework of channel measurement facility. Fixes for several channel measurement facility bugs: * Blocks copied from the hardware might not be consistent. Solve this by moving the copying into idle state and repeating the copying. * avg_sample_interval changed with every read, even though no new block was available. Solve this by storing a timestamp when the last new block was received. * Several locking issues. * Measurements were not reenabled after a disconnected device became available again. * Remove #defines for ioctls that were never implemented. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cmf.c | 623 ++++++++++++++++++++++++++++++------------ drivers/s390/cio/device.h | 4 + drivers/s390/cio/device_fsm.c | 18 +- include/asm-s390/cmb.h | 4 - 4 files changed, 468 insertions(+), 181 deletions(-) diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 07ef3f640f4a..1c3e8e9012b0 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -3,9 +3,10 @@ * * Linux on zSeries Channel Measurement Facility support * - * Copyright 2000,2003 IBM Corporation + * Copyright 2000,2006 IBM Corporation * - * Author: Arnd Bergmann + * Authors: Arnd Bergmann + * Cornelia Huck * * original idea from Natarajan Krishnaswami * @@ -96,9 +97,9 @@ module_param(format, bool, 0444); /** * struct cmb_operations - functions to use depending on cmb_format * - * all these functions operate on a struct cmf_device. There is only - * one instance of struct cmb_operations because all cmf_device - * objects are guaranteed to be of the same type. + * Most of these functions operate on a struct ccw_device. There is only + * one instance of struct cmb_operations because the format of the measurement + * data is guaranteed to be the same for every ccw_device. * * @alloc: allocate memory for a channel measurement block, * either with the help of a special pool or with kmalloc @@ -107,6 +108,7 @@ module_param(format, bool, 0444); * @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*); @@ -115,11 +117,19 @@ struct cmb_operations { u64 (*read) (struct ccw_device*, int); int (*readall)(struct ccw_device*, struct cmbdata *); void (*reset) (struct ccw_device*); + void * (*align) (void *); struct attribute_group *attr_group; }; static struct cmb_operations *cmbops; +struct cmb_data { + void *hw_block; /* Pointer to block updated by hardware */ + void *last_block; /* Last changed block copied from hardware block */ + int size; /* Size of hw_block and last_block */ + unsigned long long last_update; /* when last_block was updated */ +}; + /* our user interface is designed in terms of nanoseconds, * while the hardware measures total times in its own * unit.*/ @@ -226,63 +236,229 @@ struct set_schib_struct { unsigned long address; wait_queue_head_t wait; int ret; + struct kref kref; }; +static void cmf_set_schib_release(struct kref *kref) +{ + struct set_schib_struct *set_data; + + set_data = container_of(kref, struct set_schib_struct, kref); + kfree(set_data); +} + +#define CMF_PENDING 1 + static int set_schib_wait(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) { - struct set_schib_struct s = { - .mme = mme, - .mbfc = mbfc, - .address = address, - .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s.wait), - }; + struct set_schib_struct *set_data; + int ret; spin_lock_irq(cdev->ccwlock); - s.ret = set_schib(cdev, mme, mbfc, address); - if (s.ret != -EBUSY) { - goto out_nowait; + if (!cdev->private->cmb) { + ret = -ENODEV; + goto out; } + set_data = kzalloc(sizeof(struct set_schib_struct), GFP_ATOMIC); + if (!set_data) { + ret = -ENOMEM; + goto out; + } + init_waitqueue_head(&set_data->wait); + kref_init(&set_data->kref); + set_data->mme = mme; + set_data->mbfc = mbfc; + set_data->address = address; + + ret = set_schib(cdev, mme, mbfc, address); + if (ret != -EBUSY) + goto out_put; if (cdev->private->state != DEV_STATE_ONLINE) { - s.ret = -EBUSY; /* if the device is not online, don't even try again */ - goto out_nowait; + ret = -EBUSY; + goto out_put; } + cdev->private->state = DEV_STATE_CMFCHANGE; - cdev->private->cmb_wait = &s; - s.ret = 1; + set_data->ret = CMF_PENDING; + cdev->private->cmb_wait = set_data; spin_unlock_irq(cdev->ccwlock); - if (wait_event_interruptible(s.wait, s.ret != 1)) { + if (wait_event_interruptible(set_data->wait, + set_data->ret != CMF_PENDING)) { spin_lock_irq(cdev->ccwlock); - if (s.ret == 1) { - s.ret = -ERESTARTSYS; - cdev->private->cmb_wait = 0; + if (set_data->ret == CMF_PENDING) { + set_data->ret = -ERESTARTSYS; if (cdev->private->state == DEV_STATE_CMFCHANGE) cdev->private->state = DEV_STATE_ONLINE; } spin_unlock_irq(cdev->ccwlock); } - return s.ret; - -out_nowait: + spin_lock_irq(cdev->ccwlock); + cdev->private->cmb_wait = NULL; + ret = set_data->ret; +out_put: + kref_put(&set_data->kref, cmf_set_schib_release); +out: spin_unlock_irq(cdev->ccwlock); - return s.ret; + return ret; } void retry_set_schib(struct ccw_device *cdev) { - struct set_schib_struct *s; + struct set_schib_struct *set_data; + + set_data = cdev->private->cmb_wait; + if (!set_data) { + WARN_ON(1); + return; + } + kref_get(&set_data->kref); + set_data->ret = set_schib(cdev, set_data->mme, set_data->mbfc, + set_data->address); + wake_up(&set_data->wait); + kref_put(&set_data->kref, cmf_set_schib_release); +} + +static int cmf_copy_block(struct ccw_device *cdev) +{ + struct subchannel *sch; + void *reference_buf; + void *hw_block; + struct cmb_data *cmb_data; + + sch = to_subchannel(cdev->dev.parent); + + if (stsch(sch->schid, &sch->schib)) + return -ENODEV; + + if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) { + /* Don't copy if a start function is in progress. */ + if ((!sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED) && + (sch->schib.scsw.actl & + (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) && + (!sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) + return -EBUSY; + } + cmb_data = cdev->private->cmb; + hw_block = cmbops->align(cmb_data->hw_block); + if (!memcmp(cmb_data->last_block, hw_block, cmb_data->size)) + /* No need to copy. */ + return 0; + reference_buf = kzalloc(cmb_data->size, GFP_ATOMIC); + if (!reference_buf) + return -ENOMEM; + /* Ensure consistency of block copied from hardware. */ + do { + memcpy(cmb_data->last_block, hw_block, cmb_data->size); + memcpy(reference_buf, hw_block, cmb_data->size); + } while (memcmp(cmb_data->last_block, reference_buf, cmb_data->size)); + cmb_data->last_update = get_clock(); + kfree(reference_buf); + return 0; +} + +struct copy_block_struct { + wait_queue_head_t wait; + int ret; + struct kref kref; +}; + +static void cmf_copy_block_release(struct kref *kref) +{ + struct copy_block_struct *copy_block; + + copy_block = container_of(kref, struct copy_block_struct, kref); + kfree(copy_block); +} + +static int cmf_cmb_copy_wait(struct ccw_device *cdev) +{ + struct copy_block_struct *copy_block; + int ret; + unsigned long flags; + + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + ret = -ENODEV; + goto out; + } + copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC); + if (!copy_block) { + ret = -ENOMEM; + goto out; + } + init_waitqueue_head(©_block->wait); + kref_init(©_block->kref); + + ret = cmf_copy_block(cdev); + if (ret != -EBUSY) + goto out_put; + + if (cdev->private->state != DEV_STATE_ONLINE) { + ret = -EBUSY; + goto out_put; + } + + cdev->private->state = DEV_STATE_CMFUPDATE; + copy_block->ret = CMF_PENDING; + cdev->private->cmb_wait = copy_block; + + spin_unlock_irqrestore(cdev->ccwlock, flags); + if (wait_event_interruptible(copy_block->wait, + copy_block->ret != CMF_PENDING)) { + spin_lock_irqsave(cdev->ccwlock, flags); + if (copy_block->ret == CMF_PENDING) { + copy_block->ret = -ERESTARTSYS; + if (cdev->private->state == DEV_STATE_CMFUPDATE) + cdev->private->state = DEV_STATE_ONLINE; + } + spin_unlock_irqrestore(cdev->ccwlock, flags); + } + spin_lock_irqsave(cdev->ccwlock, flags); + cdev->private->cmb_wait = NULL; + ret = copy_block->ret; +out_put: + kref_put(©_block->kref, cmf_copy_block_release); +out: + spin_unlock_irqrestore(cdev->ccwlock, flags); + return ret; +} + +void cmf_retry_copy_block(struct ccw_device *cdev) +{ + struct copy_block_struct *copy_block; - s = cdev->private->cmb_wait; - cdev->private->cmb_wait = 0; - if (!s) { + copy_block = cdev->private->cmb_wait; + if (!copy_block) { WARN_ON(1); return; } - s->ret = set_schib(cdev, s->mme, s->mbfc, s->address); - wake_up(&s->wait); + kref_get(©_block->kref); + copy_block->ret = cmf_copy_block(cdev); + wake_up(©_block->wait); + kref_put(©_block->kref, cmf_copy_block_release); +} + +static void cmf_generic_reset(struct ccw_device *cdev) +{ + struct cmb_data *cmb_data; + + spin_lock_irq(cdev->ccwlock); + cmb_data = cdev->private->cmb; + if (cmb_data) { + memset(cmb_data->last_block, 0, cmb_data->size); + /* + * Need to reset hw block as well to make the hardware start + * from 0 again. + */ + memset(cmbops->align(cmb_data->hw_block), 0, cmb_data->size); + cmb_data->last_update = 0; + } + cdev->private->cmb_start_time = get_clock(); + spin_unlock_irq(cdev->ccwlock); } /** @@ -343,8 +519,8 @@ struct cmb { /* insert a single device into the cmb_area list * called with cmb_area.lock held from alloc_cmb */ -static inline int -alloc_cmb_single (struct ccw_device *cdev) +static inline int alloc_cmb_single (struct ccw_device *cdev, + struct cmb_data *cmb_data) { struct cmb *cmb; struct ccw_device_private *node; @@ -358,10 +534,12 @@ alloc_cmb_single (struct ccw_device *cdev) /* find first unused cmb in cmb_area.mem. * this is a little tricky: cmb_area.list - * remains sorted by ->cmb pointers */ + * remains sorted by ->cmb->hw_data pointers */ cmb = cmb_area.mem; list_for_each_entry(node, &cmb_area.list, cmb_list) { - if ((struct cmb*)node->cmb > cmb) + struct cmb_data *data; + data = node->cmb; + if ((struct cmb*)data->hw_block > cmb) break; cmb++; } @@ -372,7 +550,8 @@ alloc_cmb_single (struct ccw_device *cdev) /* insert new cmb */ list_add_tail(&cdev->private->cmb_list, &node->cmb_list); - cdev->private->cmb = cmb; + cmb_data->hw_block = cmb; + cdev->private->cmb = cmb_data; ret = 0; out: spin_unlock_irq(cdev->ccwlock); @@ -385,7 +564,19 @@ alloc_cmb (struct ccw_device *cdev) int ret; struct cmb *mem; ssize_t size; + struct cmb_data *cmb_data; + + /* Allocate private cmb_data. */ + cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL); + if (!cmb_data) + return -ENOMEM; + cmb_data->last_block = kzalloc(sizeof(struct cmb), GFP_KERNEL); + if (!cmb_data->last_block) { + kfree(cmb_data); + return -ENOMEM; + } + cmb_data->size = sizeof(struct cmb); spin_lock(&cmb_area.lock); if (!cmb_area.mem) { @@ -414,29 +605,36 @@ alloc_cmb (struct ccw_device *cdev) } /* do the actual allocation */ - ret = alloc_cmb_single(cdev); + ret = alloc_cmb_single(cdev, cmb_data); out: spin_unlock(&cmb_area.lock); - + if (ret) { + kfree(cmb_data->last_block); + kfree(cmb_data); + } return ret; } -static void -free_cmb(struct ccw_device *cdev) +static void free_cmb(struct ccw_device *cdev) { struct ccw_device_private *priv; - - priv = cdev->private; + struct cmb_data *cmb_data; spin_lock(&cmb_area.lock); spin_lock_irq(cdev->ccwlock); + priv = cdev->private; + if (list_empty(&priv->cmb_list)) { /* already freed */ goto out; } + cmb_data = priv->cmb; priv->cmb = NULL; + if (cmb_data) + kfree(cmb_data->last_block); + kfree(cmb_data); list_del_init(&priv->cmb_list); if (list_empty(&cmb_area.list)) { @@ -451,83 +649,97 @@ out: spin_unlock(&cmb_area.lock); } -static int -set_cmb(struct ccw_device *cdev, u32 mme) +static int set_cmb(struct ccw_device *cdev, u32 mme) { u16 offset; + struct cmb_data *cmb_data; + unsigned long flags; - if (!cdev->private->cmb) + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); return -EINVAL; - - offset = mme ? (struct cmb *)cdev->private->cmb - cmb_area.mem : 0; + } + cmb_data = cdev->private->cmb; + offset = mme ? (struct cmb *)cmb_data->hw_block - cmb_area.mem : 0; + spin_unlock_irqrestore(cdev->ccwlock, flags); 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) { - /* yes, we have to put it on the stack - * because the cmb must only be accessed - * atomically, e.g. with mvc */ - struct cmb cmb; - unsigned long flags; + struct cmb *cmb; u32 val; + int ret; + unsigned long flags; + + ret = cmf_cmb_copy_wait(cdev); + if (ret < 0) + return 0; spin_lock_irqsave(cdev->ccwlock, flags); if (!cdev->private->cmb) { - spin_unlock_irqrestore(cdev->ccwlock, flags); - return 0; + ret = 0; + goto out; } - - cmb = *(struct cmb*)cdev->private->cmb; - spin_unlock_irqrestore(cdev->ccwlock, flags); + cmb = ((struct cmb_data *)cdev->private->cmb)->last_block; switch (index) { case cmb_ssch_rsch_count: - return cmb.ssch_rsch_count; + ret = cmb->ssch_rsch_count; + goto out; case cmb_sample_count: - return cmb.sample_count; + ret = cmb->sample_count; + goto out; case cmb_device_connect_time: - val = cmb.device_connect_time; + val = cmb->device_connect_time; break; case cmb_function_pending_time: - val = cmb.function_pending_time; + val = cmb->function_pending_time; break; case cmb_device_disconnect_time: - val = cmb.device_disconnect_time; + val = cmb->device_disconnect_time; break; case cmb_control_unit_queuing_time: - val = cmb.control_unit_queuing_time; + val = cmb->control_unit_queuing_time; break; case cmb_device_active_only_time: - val = cmb.device_active_only_time; + val = cmb->device_active_only_time; break; default: - return 0; + ret = 0; + goto out; } - return time_to_avg_nsec(val, cmb.sample_count); + ret = time_to_avg_nsec(val, cmb->sample_count); +out: + spin_unlock_irqrestore(cdev->ccwlock, flags); + return ret; } -static int -readall_cmb (struct ccw_device *cdev, struct cmbdata *data) +static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data) { - /* yes, we have to put it on the stack - * because the cmb must only be accessed - * atomically, e.g. with mvc */ - struct cmb cmb; - unsigned long flags; + struct cmb *cmb; + struct cmb_data *cmb_data; u64 time; + unsigned long flags; + int ret; + ret = cmf_cmb_copy_wait(cdev); + if (ret < 0) + return ret; spin_lock_irqsave(cdev->ccwlock, flags); - if (!cdev->private->cmb) { - spin_unlock_irqrestore(cdev->ccwlock, flags); - return -ENODEV; + cmb_data = cdev->private->cmb; + if (!cmb_data) { + ret = -ENODEV; + goto out; } - - cmb = *(struct cmb*)cdev->private->cmb; - time = get_clock() - cdev->private->cmb_start_time; - spin_unlock_irqrestore(cdev->ccwlock, flags); + if (cmb_data->last_update == 0) { + ret = -EAGAIN; + goto out; + } + cmb = cmb_data->last_block; + time = cmb_data->last_update - cdev->private->cmb_start_time; memset(data, 0, sizeof(struct cmbdata)); @@ -538,31 +750,32 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data) data->elapsed_time = (time * 1000) >> 12; /* copy data to new structure */ - data->ssch_rsch_count = cmb.ssch_rsch_count; - data->sample_count = cmb.sample_count; + data->ssch_rsch_count = cmb->ssch_rsch_count; + data->sample_count = cmb->sample_count; /* time fields are converted to nanoseconds while copying */ - data->device_connect_time = time_to_nsec(cmb.device_connect_time); - data->function_pending_time = time_to_nsec(cmb.function_pending_time); - data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); + data->device_connect_time = time_to_nsec(cmb->device_connect_time); + data->function_pending_time = time_to_nsec(cmb->function_pending_time); + data->device_disconnect_time = + time_to_nsec(cmb->device_disconnect_time); data->control_unit_queuing_time - = time_to_nsec(cmb.control_unit_queuing_time); + = time_to_nsec(cmb->control_unit_queuing_time); data->device_active_only_time - = time_to_nsec(cmb.device_active_only_time); + = time_to_nsec(cmb->device_active_only_time); + ret = 0; +out: + spin_unlock_irqrestore(cdev->ccwlock, flags); + return ret; +} - return 0; +static void reset_cmb(struct ccw_device *cdev) +{ + cmf_generic_reset(cdev); } -static void -reset_cmb(struct ccw_device *cdev) +static void * align_cmb(void *area) { - struct cmb *cmb; - spin_lock_irq(cdev->ccwlock); - cmb = cdev->private->cmb; - if (cmb) - memset (cmb, 0, sizeof (*cmb)); - cdev->private->cmb_start_time = get_clock(); - spin_unlock_irq(cdev->ccwlock); + return area; } static struct attribute_group cmf_attr_group; @@ -574,6 +787,7 @@ static struct cmb_operations cmbops_basic = { .read = read_cmb, .readall = readall_cmb, .reset = reset_cmb, + .align = align_cmb, .attr_group = &cmf_attr_group, }; @@ -610,22 +824,34 @@ static inline struct cmbe* cmbe_align(struct cmbe *c) return (struct cmbe*)addr; } -static int -alloc_cmbe (struct ccw_device *cdev) +static int alloc_cmbe (struct ccw_device *cdev) { struct cmbe *cmbe; - cmbe = kmalloc (sizeof (*cmbe) * 2, GFP_KERNEL); + struct cmb_data *cmb_data; + int ret; + + cmbe = kzalloc (sizeof (*cmbe) * 2, GFP_KERNEL); if (!cmbe) return -ENOMEM; - + cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL); + if (!cmb_data) { + ret = -ENOMEM; + goto out_free; + } + cmb_data->last_block = kzalloc(sizeof(struct cmbe), GFP_KERNEL); + if (!cmb_data->last_block) { + ret = -ENOMEM; + goto out_free; + } + cmb_data->size = sizeof(struct cmbe); spin_lock_irq(cdev->ccwlock); if (cdev->private->cmb) { - kfree(cmbe); spin_unlock_irq(cdev->ccwlock); - return -EBUSY; + ret = -EBUSY; + goto out_free; } - - cdev->private->cmb = cmbe; + cmb_data->hw_block = cmbe; + cdev->private->cmb = cmb_data; spin_unlock_irq(cdev->ccwlock); /* activate global measurement if this is the first channel */ @@ -636,14 +862,24 @@ alloc_cmbe (struct ccw_device *cdev) spin_unlock(&cmb_area.lock); return 0; +out_free: + if (cmb_data) + kfree(cmb_data->last_block); + kfree(cmb_data); + kfree(cmbe); + return ret; } -static void -free_cmbe (struct ccw_device *cdev) +static void free_cmbe (struct ccw_device *cdev) { + struct cmb_data *cmb_data; + spin_lock_irq(cdev->ccwlock); - kfree(cdev->private->cmb); + cmb_data = cdev->private->cmb; cdev->private->cmb = NULL; + if (cmb_data) + kfree(cmb_data->last_block); + kfree(cmb_data); spin_unlock_irq(cdev->ccwlock); /* deactivate global measurement if this is the last channel */ @@ -654,89 +890,105 @@ free_cmbe (struct ccw_device *cdev) spin_unlock(&cmb_area.lock); } -static int -set_cmbe(struct ccw_device *cdev, u32 mme) +static int set_cmbe(struct ccw_device *cdev, u32 mme) { unsigned long mba; + struct cmb_data *cmb_data; + unsigned long flags; - if (!cdev->private->cmb) + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); return -EINVAL; - mba = mme ? (unsigned long) cmbe_align(cdev->private->cmb) : 0; + } + cmb_data = cdev->private->cmb; + mba = mme ? (unsigned long) cmbe_align(cmb_data->hw_block) : 0; + spin_unlock_irqrestore(cdev->ccwlock, flags); return set_schib_wait(cdev, mme, 1, mba); } -u64 -read_cmbe (struct ccw_device *cdev, int index) +static u64 read_cmbe (struct ccw_device *cdev, int index) { - /* yes, we have to put it on the stack - * because the cmb must only be accessed - * atomically, e.g. with mvc */ - struct cmbe cmb; - unsigned long flags; + struct cmbe *cmb; + struct cmb_data *cmb_data; u32 val; + int ret; + unsigned long flags; - spin_lock_irqsave(cdev->ccwlock, flags); - if (!cdev->private->cmb) { - spin_unlock_irqrestore(cdev->ccwlock, flags); + ret = cmf_cmb_copy_wait(cdev); + if (ret < 0) return 0; - } - cmb = *cmbe_align(cdev->private->cmb); - spin_unlock_irqrestore(cdev->ccwlock, flags); + spin_lock_irqsave(cdev->ccwlock, flags); + cmb_data = cdev->private->cmb; + if (!cmb_data) { + ret = 0; + goto out; + } + cmb = cmb_data->last_block; switch (index) { case cmb_ssch_rsch_count: - return cmb.ssch_rsch_count; + ret = cmb->ssch_rsch_count; + goto out; case cmb_sample_count: - return cmb.sample_count; + ret = cmb->sample_count; + goto out; case cmb_device_connect_time: - val = cmb.device_connect_time; + val = cmb->device_connect_time; break; case cmb_function_pending_time: - val = cmb.function_pending_time; + val = cmb->function_pending_time; break; case cmb_device_disconnect_time: - val = cmb.device_disconnect_time; + val = cmb->device_disconnect_time; break; case cmb_control_unit_queuing_time: - val = cmb.control_unit_queuing_time; + val = cmb->control_unit_queuing_time; break; case cmb_device_active_only_time: - val = cmb.device_active_only_time; + val = cmb->device_active_only_time; break; case cmb_device_busy_time: - val = cmb.device_busy_time; + val = cmb->device_busy_time; break; case cmb_initial_command_response_time: - val = cmb.initial_command_response_time; + val = cmb->initial_command_response_time; break; default: - return 0; + ret = 0; + goto out; } - return time_to_avg_nsec(val, cmb.sample_count); + ret = time_to_avg_nsec(val, cmb->sample_count); +out: + spin_unlock_irqrestore(cdev->ccwlock, flags); + return ret; } -static int -readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) +static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) { - /* yes, we have to put it on the stack - * because the cmb must only be accessed - * atomically, e.g. with mvc */ - struct cmbe cmb; - unsigned long flags; + struct cmbe *cmb; + struct cmb_data *cmb_data; u64 time; + unsigned long flags; + int ret; + ret = cmf_cmb_copy_wait(cdev); + if (ret < 0) + return ret; spin_lock_irqsave(cdev->ccwlock, flags); - if (!cdev->private->cmb) { - spin_unlock_irqrestore(cdev->ccwlock, flags); - return -ENODEV; + cmb_data = cdev->private->cmb; + if (!cmb_data) { + ret = -ENODEV; + goto out; } - - cmb = *cmbe_align(cdev->private->cmb); - time = get_clock() - cdev->private->cmb_start_time; - spin_unlock_irqrestore(cdev->ccwlock, flags); + if (cmb_data->last_update == 0) { + ret = -EAGAIN; + goto out; + } + time = cmb_data->last_update - cdev->private->cmb_start_time; memset (data, 0, sizeof(struct cmbdata)); @@ -746,35 +998,38 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) /* conver to nanoseconds */ data->elapsed_time = (time * 1000) >> 12; + cmb = cmb_data->last_block; /* copy data to new structure */ - data->ssch_rsch_count = cmb.ssch_rsch_count; - data->sample_count = cmb.sample_count; + data->ssch_rsch_count = cmb->ssch_rsch_count; + data->sample_count = cmb->sample_count; /* time fields are converted to nanoseconds while copying */ - data->device_connect_time = time_to_nsec(cmb.device_connect_time); - data->function_pending_time = time_to_nsec(cmb.function_pending_time); - data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); + data->device_connect_time = time_to_nsec(cmb->device_connect_time); + data->function_pending_time = time_to_nsec(cmb->function_pending_time); + data->device_disconnect_time = + time_to_nsec(cmb->device_disconnect_time); data->control_unit_queuing_time - = time_to_nsec(cmb.control_unit_queuing_time); + = time_to_nsec(cmb->control_unit_queuing_time); data->device_active_only_time - = time_to_nsec(cmb.device_active_only_time); - data->device_busy_time = time_to_nsec(cmb.device_busy_time); + = time_to_nsec(cmb->device_active_only_time); + data->device_busy_time = time_to_nsec(cmb->device_busy_time); data->initial_command_response_time - = time_to_nsec(cmb.initial_command_response_time); + = time_to_nsec(cmb->initial_command_response_time); - return 0; + ret = 0; +out: + spin_unlock_irqrestore(cdev->ccwlock, flags); + return ret; } -static void -reset_cmbe(struct ccw_device *cdev) +static void reset_cmbe(struct ccw_device *cdev) { - struct cmbe *cmb; - spin_lock_irq(cdev->ccwlock); - cmb = cmbe_align(cdev->private->cmb); - if (cmb) - memset (cmb, 0, sizeof (*cmb)); - cdev->private->cmb_start_time = get_clock(); - spin_unlock_irq(cdev->ccwlock); + cmf_generic_reset(cdev); +} + +static void * align_cmbe(void *area) +{ + return cmbe_align(area); } static struct attribute_group cmf_attr_group_ext; @@ -786,6 +1041,7 @@ static struct cmb_operations cmbops_extended = { .read = read_cmbe, .readall = readall_cmbe, .reset = reset_cmbe, + .align = align_cmbe, .attr_group = &cmf_attr_group_ext, }; @@ -803,14 +1059,19 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, struct ccw_device *cdev; long interval; unsigned long count; + struct cmb_data *cmb_data; cdev = to_ccwdev(dev); - interval = get_clock() - cdev->private->cmb_start_time; count = cmf_read(cdev, cmb_sample_count); - if (count) + spin_lock_irq(cdev->ccwlock); + cmb_data = cdev->private->cmb; + if (count) { + interval = cmb_data->last_update - + cdev->private->cmb_start_time; interval /= count; - else + } else interval = -1; + spin_unlock_irq(cdev->ccwlock); return sprintf(buf, "%ld\n", interval); } @@ -823,7 +1084,10 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char int ret; ret = cmf_readall(to_ccwdev(dev), &data); - if (ret) + if (ret == -EAGAIN || ret == -ENODEV) + /* No data (yet/currently) available to use for calculation. */ + return sprintf(buf, "n/a\n"); + else if (ret) return ret; utilization = data.device_connect_time + @@ -982,6 +1246,13 @@ cmf_readall(struct ccw_device *cdev, struct cmbdata *data) return cmbops->readall(cdev, data); } +/* Reenable cmf when a disconnected device becomes available again. */ +int cmf_reenable(struct ccw_device *cdev) +{ + cmbops->reset(cdev); + return cmbops->set(cdev, 2); +} + static int __init init_cmf(void) { diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 8e0d1db3dd4e..00be9a5b4acd 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -27,6 +27,7 @@ enum dev_state { DEV_STATE_DISCONNECTED, DEV_STATE_DISCONNECTED_SENSE_ID, DEV_STATE_CMFCHANGE, + DEV_STATE_CMFUPDATE, /* last element! */ NR_DEV_STATES }; @@ -118,5 +119,8 @@ int ccw_device_stlck(struct ccw_device *); void ccw_device_set_timeout(struct ccw_device *, int); extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); +/* Channel measurement facility related */ void retry_set_schib(struct ccw_device *cdev); +void cmf_retry_copy_block(struct ccw_device *); +int cmf_reenable(struct ccw_device *); #endif diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 5ec8ef1df9fa..7d0dd72635eb 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -336,8 +336,11 @@ ccw_device_oper_notify(void *data) if (!ret) /* Driver doesn't want device back. */ ccw_device_do_unreg_rereg((void *)cdev); - else + else { + /* Reenable channel measurements, if needed. */ + cmf_reenable(cdev); wake_up(&cdev->private->wait_q); + } } /* @@ -1095,6 +1098,13 @@ ccw_device_change_cmfstate(struct ccw_device *cdev, enum dev_event dev_event) dev_fsm_event(cdev, dev_event); } +static void ccw_device_update_cmfblock(struct ccw_device *cdev, + enum dev_event dev_event) +{ + cmf_retry_copy_block(cdev); + cdev->private->state = DEV_STATE_ONLINE; + dev_fsm_event(cdev, dev_event); +} static void ccw_device_quiesce_done(struct ccw_device *cdev, enum dev_event dev_event) @@ -1249,6 +1259,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_EVENT_TIMEOUT] = ccw_device_change_cmfstate, [DEV_EVENT_VERIFY] = ccw_device_change_cmfstate, }, + [DEV_STATE_CMFUPDATE] = { + [DEV_EVENT_NOTOPER] = ccw_device_update_cmfblock, + [DEV_EVENT_INTERRUPT] = ccw_device_update_cmfblock, + [DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock, + [DEV_EVENT_VERIFY] = ccw_device_update_cmfblock, + }, }; /* diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h index 2d09950a9c11..241756f80df3 100644 --- a/include/asm-s390/cmb.h +++ b/include/asm-s390/cmb.h @@ -44,10 +44,6 @@ struct cmbdata { #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) /* enable channel measurement */ #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) -/* reset channel measurement block */ -#define BIODASDRESETCMB _IO(DASD_IOCTL_LETTER,34) -/* read channel measurement data */ -#define BIODASDREADCMB _IOWR(DASD_IOCTL_LETTER,32,__u64) /* read channel measurement data */ #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) -- cgit v1.2.3