From: Martin Schwidefsky From: Utz Bacher From: Cornelia Huck Common i/o layer changes: - Consolidate store channel subsystem characteristics from its three users (css, cmf and qdio) to a single location. - Always use new stipd format and move creation of global path group to channel subsystem init function. Add dummy init_IRQ to setup.c and remove requestirq.c. - Remove bogus CHPID_LONGS define. - Add more magic to catch chpids coming online again without generating machine checks. - Fix check for unsolicited interrupts. Deferred cc=1 indicates a solicited interrupt. - Fix progress indication in qdio summary bytes to avoid loosing interrupts. - Rename console_device to console_devno to avoid naming conflict. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton --- /dev/null | 45 --------------- 25-akpm/arch/s390/kernel/head.S | 4 - 25-akpm/arch/s390/kernel/head64.S | 4 - 25-akpm/arch/s390/kernel/s390_ksyms.c | 3 - 25-akpm/arch/s390/kernel/setup.c | 16 ++++- 25-akpm/drivers/s390/cio/Makefile | 2 25-akpm/drivers/s390/cio/chsc.c | 58 +++++++++++++++++++ 25-akpm/drivers/s390/cio/chsc.h | 28 +++++++++ 25-akpm/drivers/s390/cio/cio.c | 6 +- 25-akpm/drivers/s390/cio/cmf.c | 6 +- 25-akpm/drivers/s390/cio/css.c | 47 +++++++++++++++- 25-akpm/drivers/s390/cio/device_fsm.c | 47 ++++++++-------- 25-akpm/drivers/s390/cio/device_id.c | 13 ++-- 25-akpm/drivers/s390/cio/device_ops.c | 2 25-akpm/drivers/s390/cio/device_pgid.c | 28 ++++----- 25-akpm/drivers/s390/cio/device_status.c | 7 +- 25-akpm/drivers/s390/cio/qdio.c | 90 +++++++++++-------------------- 25-akpm/drivers/s390/cio/qdio.h | 4 + 25-akpm/include/asm-s390/setup.h | 3 - 19 files changed, 239 insertions(+), 174 deletions(-) diff -puN arch/s390/kernel/head64.S~s390-comon-i-o-layer arch/s390/kernel/head64.S --- 25/arch/s390/kernel/head64.S~s390-comon-i-o-layer 2004-06-30 10:16:33.417679576 -0700 +++ 25-akpm/arch/s390/kernel/head64.S 2004-06-30 10:16:33.451674408 -0700 @@ -623,10 +623,6 @@ startup:basr %r13,0 bne 1f-.LPG1(%r13) oi 7(%r12),4 # set P/390 flag 1: - chi %r0,0x2084 # new stidp format? - bne 2f-.LPG1(%r13) - oi 7(%r12),64 # set new stidp flag -2: # # find out if we have the MVPG instruction diff -puN arch/s390/kernel/head.S~s390-comon-i-o-layer arch/s390/kernel/head.S --- 25/arch/s390/kernel/head.S~s390-comon-i-o-layer 2004-06-30 10:16:33.419679272 -0700 +++ 25-akpm/arch/s390/kernel/head.S 2004-06-30 10:16:33.450674560 -0700 @@ -613,10 +613,6 @@ startup:basr %r13,0 bne .Lnop390-.LPG1(%r13) oi 3(%r12),4 # set P/390 flag .Lnop390: - chi %r0,0x2084 # new stidp format? - bne .Loldfmt-.LPG1(%r13) - oi 3(%r12),64 # set new stidp flag -.Loldfmt: # # find out if we have an IEEE fpu diff -puN arch/s390/kernel/s390_ksyms.c~s390-comon-i-o-layer arch/s390/kernel/s390_ksyms.c --- 25/arch/s390/kernel/s390_ksyms.c~s390-comon-i-o-layer 2004-06-30 10:16:33.420679120 -0700 +++ 25-akpm/arch/s390/kernel/s390_ksyms.c 2004-06-30 10:16:33.451674408 -0700 @@ -72,7 +72,8 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(csum_fold); EXPORT_SYMBOL(console_mode); -EXPORT_SYMBOL(console_device); +EXPORT_SYMBOL(console_devno); +EXPORT_SYMBOL(console_irq); EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); diff -puN arch/s390/kernel/setup.c~s390-comon-i-o-layer arch/s390/kernel/setup.c --- 25/arch/s390/kernel/setup.c~s390-comon-i-o-layer 2004-06-30 10:16:33.422678816 -0700 +++ 25-akpm/arch/s390/kernel/setup.c 2004-06-30 10:16:33.452674256 -0700 @@ -49,7 +49,7 @@ * Machine setup.. */ unsigned int console_mode = 0; -unsigned int console_device = -1; +unsigned int console_devno = -1; unsigned int console_irq = -1; unsigned long memory_size = 0; unsigned long machine_flags = 0; @@ -160,7 +160,7 @@ static int __init condev_setup(char *str vdev = simple_strtoul(str, &str, 0); if (vdev >= 0 && vdev < 65536) { - console_device = vdev; + console_devno = vdev; console_irq = -1; } return 1; @@ -194,7 +194,7 @@ static void __init conmode_default(void) if (MACHINE_IS_VM) { cpcmd("QUERY CONSOLE", query_buffer, 1024); - console_device = simple_strtoul(query_buffer + 5, NULL, 16); + console_devno = simple_strtoul(query_buffer + 5, NULL, 16); ptr = strstr(query_buffer, "SUBCHANNEL ="); console_irq = simple_strtoul(ptr + 13, NULL, 16); cpcmd("QUERY TERM", query_buffer, 1024); @@ -649,3 +649,13 @@ int show_interrupts(struct seq_file *p, return 0; } + +/* + * For compatibilty only. S/390 specific setup of interrupts et al. is done + * much later in init_channel_subsystem(). + */ +void __init +init_IRQ(void) +{ + /* nothing... */ +} diff -puN drivers/s390/cio/chsc.c~s390-comon-i-o-layer drivers/s390/cio/chsc.c --- 25/drivers/s390/cio/chsc.c~s390-comon-i-o-layer 2004-06-30 10:16:33.423678664 -0700 +++ 25-akpm/drivers/s390/cio/chsc.c 2004-06-30 10:16:33.453674104 -0700 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.112 $ + * $Revision: 1.114 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -942,3 +942,59 @@ chsc_alloc_sei_area(void) } subsys_initcall(chsc_alloc_sei_area); + +struct css_general_char css_general_characteristics; +struct css_chsc_char css_chsc_characteristics; + +int __init +chsc_determine_css_characteristics(void) +{ + int result; + struct { + struct chsc_header request; + u32 reserved1; + u32 reserved2; + u32 reserved3; + struct chsc_header response; + u32 reserved4; + u32 general_char[510]; + u32 chsc_char[518]; + } *scsc_area; + + scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!scsc_area) { + printk(KERN_WARNING"cio: Was not able to determine available" \ + "CHSCs due to no memory.\n"); + return -ENOMEM; + } + + scsc_area->request = (struct chsc_header) { + .length = 0x0010, + .code = 0x0010, + }; + + result = chsc(scsc_area); + if (result) { + printk(KERN_WARNING"cio: Was not able to determine " \ + "available CHSCs, cc=%i.\n", result); + result = -EIO; + goto exit; + } + + if (scsc_area->response.code != 1) { + printk(KERN_WARNING"cio: Was not able to determine " \ + "available CHSCs.\n"); + result = -EIO; + goto exit; + } + memcpy(&css_general_characteristics, scsc_area->general_char, + sizeof(css_general_characteristics)); + memcpy(&css_chsc_characteristics, scsc_area->chsc_char, + sizeof(css_chsc_characteristics)); +exit: + free_page ((unsigned long) scsc_area); + return result; +} + +EXPORT_SYMBOL_GPL(css_general_characteristics); +EXPORT_SYMBOL_GPL(css_chsc_characteristics); diff -puN drivers/s390/cio/chsc.h~s390-comon-i-o-layer drivers/s390/cio/chsc.h --- 25/drivers/s390/cio/chsc.h~s390-comon-i-o-layer 2004-06-30 10:16:33.424678512 -0700 +++ 25-akpm/drivers/s390/cio/chsc.h 2004-06-30 10:16:33.454673952 -0700 @@ -23,4 +23,32 @@ extern struct channel_path *chps[]; extern void s390_process_css( void ); extern void chsc_validate_chpids(struct subchannel *); extern void chpid_is_actually_online(int); + +struct css_general_char { + u64 : 41; + u32 aif : 1; /* bit 41 */ + u32 : 3; + u32 mcss : 1; /* bit 45 */ + u32 : 2; + u32 ext_mb : 1; /* bit 48 */ + u32 : 7; + u32 aif_tdd : 1; /* bit 56 */ + u32 : 10; + u32 aif_osa : 1; /* bit 67 */ + u32 : 28; +}__attribute__((packed)); + +struct css_chsc_char { + u64 res; + u64 : 43; + u32 scssc : 1; /* bit 107 */ + u32 scsscf : 1; /* bit 108 */ + u32 : 19; +}__attribute__((packed)); + +extern struct css_general_char css_general_characteristics; +extern struct css_chsc_char css_chsc_characteristics; + +extern int chsc_determine_css_characteristics(void); +extern int css_characteristics_avail; #endif diff -puN drivers/s390/cio/cio.c~s390-comon-i-o-layer drivers/s390/cio/cio.c --- 25/drivers/s390/cio/cio.c~s390-comon-i-o-layer 2004-06-30 10:16:33.426678208 -0700 +++ 25-akpm/drivers/s390/cio/cio.c 2004-06-30 10:16:33.455673800 -0700 @@ -688,15 +688,15 @@ cio_console_irq(void) if (stsch(console_irq, &console_subchannel.schib) != 0 || !console_subchannel.schib.pmcw.dnv) return -1; - console_device = console_subchannel.schib.pmcw.dev; - } else if (console_device != -1) { + console_devno = console_subchannel.schib.pmcw.dev; + } else if (console_devno != -1) { /* At least the console device number is known. */ for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { if (stsch(irq, &console_subchannel.schib) != 0) break; if (console_subchannel.schib.pmcw.dnv && console_subchannel.schib.pmcw.dev == - console_device) { + console_devno) { console_irq = irq; break; } diff -puN drivers/s390/cio/cmf.c~s390-comon-i-o-layer drivers/s390/cio/cmf.c --- 25/drivers/s390/cio/cmf.c~s390-comon-i-o-layer 2004-06-30 10:16:33.427678056 -0700 +++ 25-akpm/drivers/s390/cio/cmf.c 2004-06-30 10:16:33.456673648 -0700 @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.13 $) + * linux/drivers/s390/cio/cmf.c ($Revision: 1.15 $) * * Linux on zSeries Channel Measurement Facility support * @@ -39,6 +39,7 @@ #include "css.h" #include "device.h" #include "ioasm.h" +#include "chsc.h" /* parameter to enable cmf during boot, possible uses are: * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be @@ -996,7 +997,8 @@ init_cmf(void) see if we are running on z990 or up, otherwise fall back to basic mode. */ if (format == CMF_AUTODETECT) { - if (!MACHINE_NEW_STIDP) { + if (!css_characteristics_avail || + !css_general_characteristics.ext_mb) { format = CMF_BASIC; } else { format = CMF_EXTENDED; diff -puN drivers/s390/cio/css.c~s390-comon-i-o-layer drivers/s390/cio/css.c --- 25/drivers/s390/cio/css.c~s390-comon-i-o-layer 2004-06-30 10:16:33.433677144 -0700 +++ 25-akpm/drivers/s390/cio/css.c 2004-06-30 10:16:33.457673496 -0700 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.77 $ + * $Revision: 1.80 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -19,11 +19,15 @@ #include "cio.h" #include "cio_debug.h" #include "ioasm.h" +#include "chsc.h" unsigned int highest_subchannel; int need_rescan = 0; int css_init_done = 0; +struct pgid global_pgid; +int css_characteristics_avail = 0; + struct device css_bus_device = { .bus_id = "css0", }; @@ -201,6 +205,20 @@ css_evaluate_subchannel(int irq, int slo ret = 0; break; } + if (disc && (event == CIO_NO_PATH)) { + /* + * Uargh, hack again. Because we don't get a machine + * check on configure on, our path bookkeeping can + * be out of date here (it's fine while we only do + * logical varying or get chsc machine checks). We + * need to force reprobing or we might miss devices + * coming operational again. It won't do harm in real + * no path situations. + */ + device_trigger_reprobe(sch); + ret = 0; + break; + } if (sch->driver && sch->driver->notify && sch->driver->notify(&sch->dev, event)) { cio_disable_subchannel(sch); @@ -352,9 +370,26 @@ css_process_crw(int irq) return ret; } +static void __init +css_generate_pgid(void) +{ + /* Let's build our path group ID here. */ + if (css_characteristics_avail && css_general_characteristics.mcss) + global_pgid.cpu_addr = 0x8000; + else { +#ifdef CONFIG_SMP + global_pgid.cpu_addr = hard_smp_processor_id(); +#else + global_pgid.cpu_addr = 0; +#endif + } + global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; + global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; + global_pgid.tod_high = (__u32) (get_clock() >> 32); +} + /* - * some of the initialization has already been done from init_IRQ(), - * here we do the rest now that the driver core is running. + * Now that the driver core is running, we can setup our channel subsystem. * The struct subchannel's are created during probing (except for the * static console subchannel). */ @@ -363,6 +398,11 @@ init_channel_subsystem (void) { int ret, irq; + if (chsc_determine_css_characteristics() == 0) + css_characteristics_avail = 1; + + css_generate_pgid(); + if ((ret = bus_register(&css_bus_type))) goto out; if ((ret = device_register (&css_bus_device))) @@ -517,3 +557,4 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(css_bus_type); EXPORT_SYMBOL(s390_root_dev_register); EXPORT_SYMBOL(s390_root_dev_unregister); +EXPORT_SYMBOL_GPL(css_characteristics_avail); diff -puN drivers/s390/cio/device_fsm.c~s390-comon-i-o-layer drivers/s390/cio/device_fsm.c --- 25/drivers/s390/cio/device_fsm.c~s390-comon-i-o-layer 2004-06-30 10:16:33.434676992 -0700 +++ 25-akpm/drivers/s390/cio/device_fsm.c 2004-06-30 10:16:33.458673344 -0700 @@ -672,8 +672,20 @@ ccw_device_irq(struct ccw_device *cdev, irb = (struct irb *) __LC_IRB; /* Check for unsolicited interrupt. */ - if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { + if ((irb->scsw.stctl == + (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) + && (!irb->scsw.cc)) { + if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) && + !irb->esw.esw0.erw.cons) { + /* Unit check but no sense data. Need basic sense. */ + if (ccw_device_do_sense(cdev, irb) != 0) + goto call_handler_unsol; + memcpy(irb, &cdev->private->irb, sizeof(struct irb)); + cdev->private->state = DEV_STATE_W4SENSE; + cdev->private->intparm = 0; + return; + } +call_handler_unsol: if (cdev->handler) cdev->handler (cdev, 0, irb); return; @@ -735,11 +747,15 @@ ccw_device_w4sense(struct ccw_device *cd /* Check for unsolicited interrupt. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (cdev->handler) - cdev->handler (cdev, 0, irb); if (irb->scsw.cc == 1) /* Basic sense hasn't started. Try again. */ ccw_device_do_sense(cdev, irb); + else { + printk("Huh? %s(%s): unsolicited interrupt...\n", + __FUNCTION__, cdev->dev.bus_id); + if (cdev->handler) + cdev->handler (cdev, 0, irb); + } return; } /* Add basic sense info to irb. */ @@ -762,13 +778,6 @@ ccw_device_clear_verify(struct ccw_devic struct irb *irb; irb = (struct irb *) __LC_IRB; - /* Check for unsolicited interrupt. */ - if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (cdev->handler) - cdev->handler (cdev, 0, irb); - return; - } /* Accumulate status. We don't do basic sense. */ ccw_device_accumulate_irb(cdev, irb); /* Try to start delayed device verification. */ @@ -834,15 +843,6 @@ ccw_device_wait4io_irq(struct ccw_device struct subchannel *sch; irb = (struct irb *) __LC_IRB; - /* Check for unsolicited interrupt. */ - if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (cdev->handler) - cdev->handler (cdev, 0, irb); - if (irb->scsw.cc == 1) - goto call_handler; - return; - } /* * Accumulate status and find out if a basic sense is needed. * This is fine since we have already adapted the lpm. @@ -854,7 +854,7 @@ ccw_device_wait4io_irq(struct ccw_device } return; } -call_handler: + /* Iff device is idle, reset timeout. */ sch = to_subchannel(cdev->dev.parent); if (!stsch(sch->irq, &sch->schib)) @@ -923,8 +923,9 @@ ccw_device_stlck_done(struct ccw_device case DEV_EVENT_INTERRUPT: irb = (struct irb *) __LC_IRB; /* Check for unsolicited interrupt. */ - if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) + if ((irb->scsw.stctl == + (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) && + (!irb->scsw.cc)) /* FIXME: we should restart stlck here, but this * is extremely unlikely ... */ goto out_wakeup; diff -puN drivers/s390/cio/device_id.c~s390-comon-i-o-layer drivers/s390/cio/device_id.c --- 25/drivers/s390/cio/device_id.c~s390-comon-i-o-layer 2004-06-30 10:16:33.435676840 -0700 +++ 25-akpm/drivers/s390/cio/device_id.c 2004-06-30 10:16:33.458673344 -0700 @@ -303,15 +303,14 @@ ccw_device_sense_id_irq(struct ccw_devic sch = to_subchannel(cdev->dev.parent); irb = (struct irb *) __LC_IRB; - /* - * Unsolicited interrupts may pertain to an earlier status pending or - * busy condition on the subchannel. Retry sense id. - */ + /* Retry sense id for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - ret = __ccw_device_sense_id_start(cdev); - if (ret && ret != -EBUSY) - ccw_device_sense_id_done(cdev, ret); + if (irb->scsw.cc == 1) { + ret = __ccw_device_sense_id_start(cdev); + if (ret && ret != -EBUSY) + ccw_device_sense_id_done(cdev, ret); + } return; } if (ccw_device_accumulate_and_sense(cdev, irb) != 0) diff -puN drivers/s390/cio/device_ops.c~s390-comon-i-o-layer drivers/s390/cio/device_ops.c --- 25/drivers/s390/cio/device_ops.c~s390-comon-i-o-layer 2004-06-30 10:16:33.437676536 -0700 +++ 25-akpm/drivers/s390/cio/device_ops.c 2004-06-30 10:16:33.459673192 -0700 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.34 $ + * $Revision: 1.47 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff -puN drivers/s390/cio/device_pgid.c~s390-comon-i-o-layer drivers/s390/cio/device_pgid.c --- 25/drivers/s390/cio/device_pgid.c~s390-comon-i-o-layer 2004-06-30 10:16:33.438676384 -0700 +++ 25-akpm/drivers/s390/cio/device_pgid.c 2004-06-30 10:16:33.460673040 -0700 @@ -143,15 +143,14 @@ ccw_device_sense_pgid_irq(struct ccw_dev int ret; irb = (struct irb *) __LC_IRB; - /* - * Unsolicited interrupts may pertain to an earlier status pending or - * busy condition on the subchannel. Retry sense pgid. - */ + /* Retry sense pgid for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - ret = __ccw_device_sense_pgid_start(cdev); - if (ret && ret != -EBUSY) - ccw_device_sense_pgid_done(cdev, ret); + if (irb->scsw.cc == 1) { + ret = __ccw_device_sense_pgid_start(cdev); + if (ret && ret != -EBUSY) + ccw_device_sense_pgid_done(cdev, ret); + } return; } if (ccw_device_accumulate_and_sense(cdev, irb) != 0) @@ -310,13 +309,11 @@ ccw_device_verify_irq(struct ccw_device struct irb *irb; irb = (struct irb *) __LC_IRB; - /* - * Unsolicited interrupts may pertain to an earlier status pending or - * busy condition on the subchannel. Restart path verification. - */ + /* Retry set pgid for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - __ccw_device_verify_start(cdev); + if (irb->scsw.cc == 1) + __ccw_device_verify_start(cdev); return; } if (ccw_device_accumulate_and_sense(cdev, irb) != 0) @@ -397,10 +394,13 @@ ccw_device_disband_irq(struct ccw_device int ret; irb = (struct irb *) __LC_IRB; - /* Ignore unsolicited interrupts. */ + /* Retry set pgid for cc=1. */ if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) + (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { + if (irb->scsw.cc == 1) + __ccw_device_disband_start(cdev); return; + } if (ccw_device_accumulate_and_sense(cdev, irb) != 0) return; sch = to_subchannel(cdev->dev.parent); diff -puN drivers/s390/cio/device_status.c~s390-comon-i-o-layer drivers/s390/cio/device_status.c --- 25/drivers/s390/cio/device_status.c~s390-comon-i-o-layer 2004-06-30 10:16:33.439676232 -0700 +++ 25-akpm/drivers/s390/cio/device_status.c 2004-06-30 10:16:33.460673040 -0700 @@ -35,7 +35,7 @@ ccw_device_msg_control_check(struct ccw_ return; CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check " - "received\n" + "received" " ... device %04X on subchannel %04X, dev_stat " ": %02X sch_stat : %02X\n", cdev->private->devno, cdev->private->irq, @@ -216,8 +216,9 @@ ccw_device_accumulate_irb(struct ccw_dev /* * Don't accumulate unsolicited interrupts. */ - if (irb->scsw.stctl == - (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) + if ((irb->scsw.stctl == + (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) && + (!irb->scsw.cc)) return; cdev_irb = &cdev->private->irb; diff -puN drivers/s390/cio/Makefile~s390-comon-i-o-layer drivers/s390/cio/Makefile --- 25/drivers/s390/cio/Makefile~s390-comon-i-o-layer 2004-06-30 10:16:33.441675928 -0700 +++ 25-akpm/drivers/s390/cio/Makefile 2004-06-30 10:16:33.452674256 -0700 @@ -2,7 +2,7 @@ # Makefile for the S/390 common i/o drivers # -obj-y += airq.o blacklist.o chsc.o cio.o css.o requestirq.o +obj-y += airq.o blacklist.o chsc.o cio.o css.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o diff -puN drivers/s390/cio/qdio.c~s390-comon-i-o-layer drivers/s390/cio/qdio.c --- 25/drivers/s390/cio/qdio.c~s390-comon-i-o-layer 2004-06-30 10:16:33.442675776 -0700 +++ 25-akpm/drivers/s390/cio/qdio.c 2004-06-30 10:16:33.463672584 -0700 @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.80 $" +#define VERSION_QDIO_C "$Revision: 1.83 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -354,7 +354,8 @@ qdio_stop_polling(struct qdio_q *q) SLSB_P_INPUT_NOT_INIT); /* * we don't issue this SYNC_MEMORY, as we trust Rick T and - * moreover will not use the PROCESSING state, so q->polling was 0 + * moreover will not use the PROCESSING state under VM, so + * q->polling was 0 anyway */ /*SYNC_MEMORY;*/ if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED) @@ -732,6 +733,9 @@ qdio_get_inbound_buffer_frontier(struct volatile char *slsb; int first_not_to_check; char dbf_text[15]; +#ifdef QDIO_USE_PROCESSING_STATE + int last_position=-1; +#endif /* QDIO_USE_PROCESSING_STATE */ QDIO_DBF_TEXT4(0,trace,"getibfro"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -774,8 +778,14 @@ check_next: if (q->siga_sync) { set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); } else { - set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_PROCESSING); + /* set the previous buffer to NOT_INIT. The current + * buffer will be set to PROCESSING at the end of + * this function to avoid further interrupts. */ + if (last_position>=0) + set_slsb(&slsb[last_position], + SLSB_P_INPUT_NOT_INIT); atomic_set(&q->polling,1); + last_position=f_mod_no; } #else /* QDIO_USE_PROCESSING_STATE */ set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); @@ -814,6 +824,10 @@ check_next: f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1); atomic_dec(&q->number_of_buffers_used); +#ifdef QDIO_USE_PROCESSING_STATE + last_position=-1; +#endif /* QDIO_USE_PROCESSING_STATE */ + break; /* everything else means frontier not changed (HALTED or so) */ @@ -823,6 +837,11 @@ check_next: out: q->first_to_check=f_mod_no; +#ifdef QDIO_USE_PROCESSING_STATE + if (last_position>=0) + set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING); +#endif /* QDIO_USE_PROCESSING_STATE */ + QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); return q->first_to_check; @@ -1160,7 +1179,7 @@ qdio_inbound_processing(struct qdio_q *q #ifdef QDIO_USE_PROCESSING_STATE static inline int -tiqdio_do_inbound_checks(struct qdio_q *q, int q_laps) +tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) { if (!q) { tiqdio_sched_tl(); @@ -1247,7 +1266,7 @@ again: do { int ret; - ret = tiqdio_do_inbound_checks(q, q_laps); + ret = tiqdio_reset_processing_state(q, q_laps); switch (ret) { case 0: return; @@ -1971,77 +1990,36 @@ out: static unsigned int tiqdio_check_chsc_availability(void) { - int result; char dbf_text[15]; - struct { - struct chsc_header request; - u32 reserved1; - u32 reserved2; - u32 reserved3; - struct chsc_header response; - u32 reserved4; - u32 general_char[510]; - u32 chsc_char[518]; - } *scsc_area; - - scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!scsc_area) { - QDIO_PRINT_WARN("Was not able to determine available" \ - "CHSCs due to no memory.\n"); - return -ENOMEM; - } - - scsc_area->request = (struct chsc_header) { - .length = 0x0010, - .code = 0x0010, - }; - - result=chsc(scsc_area); - if (result) { - QDIO_PRINT_WARN("Was not able to determine " \ - "available CHSCs, cc=%i.\n", - result); - result=-EIO; - goto exit; - } + if (!css_characteristics_avail) + return -EIO; - if (scsc_area->response.code != 1) { - QDIO_PRINT_WARN("Was not able to determine " \ - "available CHSCs.\n"); - result=-EIO; - goto exit; - } /* Check for bit 41. */ - if ((scsc_area->general_char[1] & 0x00400000) != 0x00400000) { + if (!css_general_characteristics.aif) { QDIO_PRINT_WARN("Adapter interruption facility not " \ "installed.\n"); - result=-ENOENT; - goto exit; + return -ENOENT; } /* Check for bits 107 and 108. */ - if ((scsc_area->chsc_char[3] & 0x00180000) != 0x00180000) { + if (!css_chsc_characteristics.scssc || + !css_chsc_characteristics.scsscf) { QDIO_PRINT_WARN("Set Chan Subsys. Char. & Fast-CHSCs " \ "not available.\n"); - result=-ENOENT; - goto exit; + return -ENOENT; } /* Check for OSA/FCP thin interrupts (bit 67). */ - hydra_thinints = ((scsc_area->general_char[2] & 0x10000000) - == 0x10000000); + hydra_thinints = css_general_characteristics.aif_osa; sprintf(dbf_text,"hydrati%1x", hydra_thinints); QDIO_DBF_TEXT0(0,setup,dbf_text); /* Check for aif time delay disablement fac (bit 56). If installed, * omit svs even under lpar (good point by rick again) */ - omit_svs = ((scsc_area->general_char[1] & 0x00000080) - == 0x00000080); + omit_svs = css_general_characteristics.aif_tdd; sprintf(dbf_text,"omitsvs%1x", omit_svs); QDIO_DBF_TEXT0(0,setup,dbf_text); -exit: - free_page ((unsigned long) scsc_area); - return result; + return 0; } diff -puN drivers/s390/cio/qdio.h~s390-comon-i-o-layer drivers/s390/cio/qdio.h --- 25/drivers/s390/cio/qdio.h~s390-comon-i-o-layer 2004-06-30 10:16:33.444675472 -0700 +++ 25-akpm/drivers/s390/cio/qdio.h 2004-06-30 10:16:33.464672432 -0700 @@ -1,7 +1,7 @@ #ifndef _CIO_QDIO_H #define _CIO_QDIO_H -#define VERSION_CIO_QDIO_H "$Revision: 1.23 $" +#define VERSION_CIO_QDIO_H "$Revision: 1.24 $" //#define QDIO_DBF_LIKE_HELL @@ -518,6 +518,8 @@ struct qdio_perf_stats { struct qdio_q { volatile struct slsb slsb; + char unused[QDIO_MAX_BUFFERS_PER_Q]; + __u32 * volatile dev_st_chg_ind; int is_input_q; diff -L drivers/s390/cio/requestirq.c -puN drivers/s390/cio/requestirq.c~s390-comon-i-o-layer /dev/null --- 25/drivers/s390/cio/requestirq.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,45 +0,0 @@ -/* - * drivers/s390/cio/requestirq.c - * S/390 common I/O routines -- enabling and disabling of devices - * $Revision: 1.46 $ - * - * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, - * IBM Corporation - * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) - * Arnd Bergmann (arndb@de.ibm.com) - */ - -#include -#include -#include -#include -#include - -#include "css.h" - -struct pgid global_pgid; -EXPORT_SYMBOL_GPL(global_pgid); - -/* - * init_IRQ is now only used to set the pgid as early as possible - */ -void __init -init_IRQ(void) -{ - /* - * Let's build our path group ID here. - */ - if (MACHINE_NEW_STIDP) - global_pgid.cpu_addr = 0x8000; - else { -#ifdef CONFIG_SMP - global_pgid.cpu_addr = hard_smp_processor_id(); -#else - global_pgid.cpu_addr = 0; -#endif - } - global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; - global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; - global_pgid.tod_high = (__u32) (get_clock() >> 32); -} diff -puN include/asm-s390/setup.h~s390-comon-i-o-layer include/asm-s390/setup.h --- 25/include/asm-s390/setup.h~s390-comon-i-o-layer 2004-06-30 10:16:33.446675168 -0700 +++ 25-akpm/include/asm-s390/setup.h 2004-06-30 10:16:33.465672280 -0700 @@ -36,7 +36,6 @@ extern unsigned long machine_flags; #define MACHINE_IS_P390 (machine_flags & 4) #define MACHINE_HAS_MVPG (machine_flags & 16) #define MACHINE_HAS_DIAG44 (machine_flags & 32) -#define MACHINE_NEW_STIDP (machine_flags & 64) #define MACHINE_HAS_IDTE (machine_flags & 128) #ifndef __s390x__ @@ -54,7 +53,7 @@ extern unsigned long machine_flags; * Console mode. Override with conmode= */ extern unsigned int console_mode; -extern unsigned int console_device; +extern unsigned int console_devno; extern unsigned int console_irq; #define CONSOLE_IS_UNDEFINED (console_mode == 0) _