]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: comon i/o layer
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 2 Jul 2004 03:33:55 +0000 (20:33 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 2 Jul 2004 03:33:55 +0000 (20:33 -0700)
From: Utz Bacher <utz.bacher@de.ibm.com>
From: Cornelia Huck <cohuck@de.ibm.com>

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 <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
19 files changed:
arch/s390/kernel/head.S
arch/s390/kernel/head64.S
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/setup.c
drivers/s390/cio/Makefile
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/device_status.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/cio/requestirq.c [deleted file]
include/asm-s390/setup.h

index 068653a5e77e9f5fd206d6975104bfd4a66dc659..fb295b79fed439a5d50c616cb77a9d852bf3f2fc 100644 (file)
@@ -613,10 +613,6 @@ startup:basr  %r13,0                     # get base
         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
index 26caebd7d676f6488f56d3b348df57b98711eee8..e32a8e90febb3a0e4adc56946538a26b4d678c51 100644 (file)
@@ -623,10 +623,6 @@ startup:basr  %r13,0                     # get base
         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
index 90e7fe6687bace50a94502df97d2f0e41b797a9f..90ccb07c1c6520c4ef2510f92e19e7f83490b651 100644 (file)
@@ -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);
index 8b4c40d8f7bf61291448b98c715dbf3f8aae2740..f75cc79ae099ace96a32da8cfd0137840afb70cb 100644 (file)
@@ -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, void *v)
        
         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... */
+}
index 321ed179ca82d1a37a6ccde2363df579bfaf5577..c490c2a1c2fcd8b27fe3be42b33928d2bacd7982 100644 (file)
@@ -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
index 4c8d6df0605d2d7136485cfcc08d113bfcc98234..e5a9b015874813d9db346c6ad4517b0857fa7247 100644 (file)
@@ -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);
index 90f5a9e739e6363f7226d99910856c2a39511bb0..a3390f99ab4cf04c25ba343bda4608db9d10bc63 100644 (file)
@@ -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
index a16f061fdc693885010e0607f6a815be6bb641c0..38e59dd243326a81e7a3a88790ca144d99b6cc17 100644 (file)
@@ -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;
                        }
index 06fb41f382a6ba34df05c213a38b678d71fd3f6e..788ae49c57959496471f4e9cdcfa1763fb53ee3d 100644 (file)
@@ -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;
index f996528550848ed16db395b7c4369df4347bd84f..dba1bfb9aab2692f5159a77b282f11df6df00eed 100644 (file)
@@ -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
 #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 slow)
                        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);
index 508f1a7fbb20de8ebe0fde54049474fd4feab9fd..fe10f20da40a7b07f637debed6e2614d74bbee9e 100644 (file)
@@ -672,8 +672,20 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        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 *cdev, enum dev_event dev_event)
        /* 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_device *cdev, enum dev_event dev_event)
        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 *cdev, enum dev_event dev_event)
        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 *cdev, enum dev_event dev_event)
                }
                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 *cdev, enum dev_event dev_event)
        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;
index aae28c3bb74838ff7b57504d5953fae1b496487f..32365959c23124a5888371a5cb779eb51888c6d5 100644 (file)
@@ -303,15 +303,14 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        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)
index 84dc9bb54748fae7b38acd52cbf21bcf184a5086..6c617ddc13ca4d7138e1f60028d290d0f5d76ae6 100644 (file)
@@ -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
index 35ceeac214d4c0c6e0149f80cef7987fd7748e87..7a808019956ea2133a1cb93372ee03c0cdd248ed 100644 (file)
@@ -143,15 +143,14 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
        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 *cdev, enum dev_event dev_event)
        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 *cdev, enum dev_event dev_event)
        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);
index c345e694df258eb213091df6d25a87194c1dae13..cf8e573dec7434911feba5f4335f88a8b8635c55 100644 (file)
@@ -35,7 +35,7 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
                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_device *cdev, struct irb *irb)
        /*
         * 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;
index f4c9779d2d4aa1a427ff78fbe40c977e0a98395a..4c788065d815a59f84bfb5742923c12d9dce79a5 100644 (file)
@@ -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 <utz.bacher@de.ibm.com>");
@@ -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 qdio_q *q)
        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;
 }
 
 
index 0922d4dacf725909d8e5be57c8c79e867b36ee12..4c75d44280461d8513cbb848f1bcf6df94e02b02 100644 (file)
@@ -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 --git a/drivers/s390/cio/requestirq.c b/drivers/s390/cio/requestirq.c
deleted file mode 100644 (file)
index 0ce71a2..0000000
+++ /dev/null
@@ -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 <linux/module.h>
-#include <linux/config.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <asm/lowcore.h>
-
-#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);
-}
index ba3b3510e9a7daec328750fadd69627425f6d273..0d51c484c2eaeb37830ae9693ece5e1ebf763704 100644 (file)
@@ -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)