]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390: common i/o layer
authorCornelia Huck <cohuck@de.ibm.com>
Sat, 9 Oct 2004 08:04:14 +0000 (01:04 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 9 Oct 2004 08:04:14 +0000 (01:04 -0700)
Common i/o layer changes:
 - Fix error handling in io_subchannel_register.
 - Fix __MAX_SUBCHANNELS limit checking.
 - Clear slow_subchannel structure after kmalloc.
 - Update ssd_info if a different device appears at an already known
   subchannel to get the correct set of chpids.
 - Avoid struct initializers to reduce stack usage of ccwgroup_create,
   readall_cmb and io_subchannel_recog,
 - Setup fields in pmcw in each retry because msch might fail and a stsch
   overwrites them.
 - Prevent irq_exit() in cio_tpi from calling do_softirq by adding a
   local_bh_disable/__local_bh_enable pair.
 - Retry sense id after receiving an unsolicited interrupt.

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>
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c

index 29000d5e70824b00c34097db8326b60fe458b188..4a06c7d0e5e4950899007faebc31725caf900119 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.31 $
+ *   $Revision: 1.33 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *                           IBM Corporation
@@ -229,7 +229,7 @@ s390_redo_validation (void)
        unsigned int irq;
 
        CIO_TRACE_EVENT (0, "redoval");
-       for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+       for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
                int ret;
                struct subchannel *sch;
 
index 9b86522fbe7b2c73b237aaa4efe72b5b1a88b560..21a75ee28b80e0a4a4c6dea1130e5b9d25b9391a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.28 $
+ *   $Revision: 1.29 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -191,14 +191,12 @@ ccwgroup_create(struct device *root,
                gdev->cdev[i]->dev.driver_data = gdev;
        del_drvdata = 1;
 
-       *gdev = (struct ccwgroup_device) {
-               .creator_id = creator_id,
-               .count = argc,
-               .dev = {
-                       .bus = &ccwgroup_bus_type,
-                       .parent = root,
-                       .release = ccwgroup_release,
-               },
+       gdev->creator_id = creator_id;
+       gdev->count = argc;
+       gdev->dev = (struct device ) {
+               .bus = &ccwgroup_bus_type,
+               .parent = root,
+               .release = ccwgroup_release,
        };
 
        snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
index f27b1649d024249dd3597368dc2d1e9ea601e8e8..fa6f0b105f76f7a62f12949b684ea2b8b6b0a357 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.123 $
+ *   $Revision: 1.128 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *                           IBM Corporation
@@ -141,6 +141,7 @@ cio_tpi(void)
        sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
        if (!sch)
                return 1;
+       local_bh_disable();
        irq_enter ();
        spin_lock(&sch->lock);
        memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
@@ -148,6 +149,7 @@ cio_tpi(void)
                sch->driver->irq(&sch->dev);
        spin_unlock(&sch->lock);
        irq_exit ();
+       __local_bh_enable();
        return 1;
 }
 
@@ -409,10 +411,10 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
        if (ccode)
                return -ENODEV;
 
-       sch->schib.pmcw.ena = 1;
-       sch->schib.pmcw.isc = isc;
-       sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
        for (retry = 5, ret = 0; retry > 0; retry--) {
+               sch->schib.pmcw.ena = 1;
+               sch->schib.pmcw.isc = isc;
+               sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
                ret = cio_modify(sch);
                if (ret == -ENODEV)
                        break;
@@ -463,9 +465,8 @@ cio_disable_subchannel (struct subchannel *sch)
                 */
                return -EBUSY;
 
-
-       sch->schib.pmcw.ena = 0;
        for (retry = 5, ret = 0; retry > 0; retry--) {
+               sch->schib.pmcw.ena = 0;
                ret = cio_modify(sch);
                if (ret == -ENODEV)
                        break;
index 788ae49c57959496471f4e9cdcfa1763fb53ee3d..1708a16e4a6fb8def018e24136f8a43f49223888 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.15 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
  *
  * Linux on zSeries Channel Measurement Facility support
  *
@@ -526,29 +526,26 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
        time = get_clock() - cdev->private->cmb_start_time;
        spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-       *data = (struct cmbdata) {
-               /* we only know values before device_busy_time */
-               .size = offsetof(struct cmbdata, device_busy_time),
-
-               /* conver to nanoseconds */
-               .elapsed_time = (time * 1000) >> 12,
-
-               /* copy data to new structure */
-               .ssch_rsch_count                = cmb.ssch_rsch_count,
-               .sample_count                   = cmb.sample_count,
-
-               /* time fields are converted to nanoseconds while copying */
-               .device_connect_time
-                       = time_to_nsec(cmb.device_connect_time),
-               .function_pending_time
-                       = time_to_nsec(cmb.function_pending_time),
-               .device_disconnect_time
-                       = time_to_nsec(cmb.device_disconnect_time),
-               .control_unit_queuing_time
-                       = time_to_nsec(cmb.control_unit_queuing_time),
-               .device_active_only_time
-                       = time_to_nsec(cmb.device_active_only_time),
-       };
+       memset(data, sizeof(struct cmbdata), 0);
+
+       /* we only know values before device_busy_time */
+       data->size = offsetof(struct cmbdata, device_busy_time);
+
+       /* convert to nanoseconds */
+       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;
+
+       /* 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->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);
 
        return 0;
 }
@@ -739,33 +736,29 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
        time = get_clock() - cdev->private->cmb_start_time;
        spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-       *data = (struct cmbdata) {
-               /* we only know values before device_busy_time */
-               .size = offsetof(struct cmbdata, device_busy_time),
-
-               /* conver to nanoseconds */
-               .elapsed_time = (time * 1000) >> 12,
-
-               /* copy data to new structure */
-               .ssch_rsch_count                = cmb.ssch_rsch_count,
-               .sample_count                   = cmb.sample_count,
-
-               /* time fields are converted to nanoseconds while copying */
-               .device_connect_time
-                       = time_to_nsec(cmb.device_connect_time),
-               .function_pending_time
-                       = time_to_nsec(cmb.function_pending_time),
-               .device_disconnect_time
-                       = time_to_nsec(cmb.device_disconnect_time),
-               .control_unit_queuing_time
-                       = time_to_nsec(cmb.control_unit_queuing_time),
-               .device_active_only_time
-                       = time_to_nsec(cmb.device_active_only_time),
-               .device_busy_time
-                       = time_to_nsec(cmb.device_busy_time),
-               .initial_command_response_time
-                       = time_to_nsec(cmb.initial_command_response_time),
-       };
+       memset (data, sizeof(struct cmbdata), 0);
+
+       /* we only know values before device_busy_time */
+       data->size = offsetof(struct cmbdata, device_busy_time);
+
+       /* conver to nanoseconds */
+       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;
+
+       /* 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->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);
+       data->initial_command_response_time
+               = time_to_nsec(cmb.initial_command_response_time);
 
        return 0;
 }
index dba1bfb9aab2692f5159a77b282f11df6df00eed..dd12416e82df0da81b67d6e9807b1f1087268b1e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.80 $
+ *   $Revision: 1.82 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                      IBM Corporation
@@ -278,7 +278,7 @@ css_rescan_devices(void)
 {
        int irq, ret;
 
-       for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+       for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
                ret = css_evaluate_subchannel(irq, 1);
                /* No more memory. It doesn't make sense to continue. No
                 * panic because this can happen in midflight and just
@@ -521,6 +521,7 @@ css_enqueue_subchannel_slow(unsigned long schid)
        new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC);
        if (!new_slow_sch)
                return -ENOMEM;
+       memset(new_slow_sch, sizeof(struct slow_subchannel), 0);
        new_slow_sch->schid = schid;
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head);
index a921b1fea5fdbd6aac2d7a932e63afc4f8a166c2..bf652fa346f37abd3d1289963329bc229cf2d5f1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.120 $
+ *   $Revision: 1.124 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                      IBM Corporation
@@ -540,6 +540,8 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
        return cdev;
 }
 
+extern int css_get_ssd_info(struct subchannel *sch);
+
 void
 ccw_device_do_unreg_rereg(void *data)
 {
@@ -581,6 +583,8 @@ ccw_device_do_unreg_rereg(void *data)
                                device_unregister(&other_sch->dev);
                        }
                }
+               /* Update ssd info here. */
+               css_get_ssd_info(sch);
                cdev->private->devno = sch->schib.pmcw.dev;
        } else
                need_rename = 0;
@@ -633,7 +637,8 @@ io_subchannel_register(void *data)
                sch->dev.driver_data = 0;
                kfree (cdev->private);
                kfree (cdev);
-               goto out;
+               put_device(&sch->dev);
+               return;
        }
 
        ret = subchannel_add_files(cdev->dev.parent);
@@ -707,18 +712,19 @@ static int
 io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 {
        int rc;
+       struct ccw_device_private *priv;
 
        sch->dev.driver_data = cdev;
        sch->driver = &io_subchannel_driver;
        cdev->ccwlock = &sch->lock;
-       *cdev->private = (struct ccw_device_private) {
-               .devno  = sch->schib.pmcw.dev,
-               .irq    = sch->irq,
-               .state  = DEV_STATE_NOT_OPER,
-               .cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list),
-       };
-       init_waitqueue_head(&cdev->private->wait_q);
-       init_timer(&cdev->private->timer);
+       /* Init private data. */
+       priv = cdev->private;
+       priv->devno = sch->schib.pmcw.dev;
+       priv->irq = sch->irq;
+       priv->state = DEV_STATE_NOT_OPER;
+       INIT_LIST_HEAD(&priv->cmb_list);
+       init_waitqueue_head(&priv->wait_q);
+       init_timer(&priv->timer);
 
        /* Set an initial name for the device. */
        snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
index 6a8db84505b35a52810c0cbce1eb72e05bf2ba85..03b569b4b1a0533277e0da600a19568931775851 100644 (file)
@@ -995,6 +995,7 @@ device_trigger_reprobe(struct subchannel *sch)
        if ((sch->lpm & (sch->lpm - 1)) != 0)
                sch->schib.pmcw.mp = 1;
        sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
+       /* We should also udate ssd info, but this has to wait. */
        ccw_device_start_id(cdev, 0);
        spin_unlock_irqrestore(&sch->lock, flags);
 }
index 32365959c23124a5888371a5cb779eb51888c6d5..f6cb8972884c096450c4fa94a7d3299d7e7031dd 100644 (file)
@@ -303,10 +303,10 @@ 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;
-       /* Retry sense id for cc=1. */
+       /* Retry sense id, if needed. */
        if (irb->scsw.stctl ==
            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-               if (irb->scsw.cc == 1) {
+               if ((irb->scsw.cc == 1) || !irb->scsw.actl) {
                        ret = __ccw_device_sense_id_start(cdev);
                        if (ret && ret != -EBUSY)
                                ccw_device_sense_id_done(cdev, ret);