]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390: common i/o layer
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 2 Dec 2004 23:44:20 +0000 (15:44 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 2 Dec 2004 23:44:20 +0000 (15:44 -0800)
From: Cornelia Huck <cohuck@de.ibm.com>
From: Steffen Thoss <thoss@de.ibm.com>

common i/o layer changes:
 - Delay re-registration of a subchannel with a different subchannel id
   until the ccw device removal triggered from the subchannels remove
   function has completed.
 - Fix check when to call unreg_rereg.
 - Fix get_disc_cdev_by_devno.
 - Activate the time delay disablement facility. This saves a few cycles
   in millicode processing.
 - Don't ifdef reset of busy start time.

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/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/qdio.c

index 4038e776f2a86e98a625323f31272b672a5a67be..7b6f85b3e42cbf7388dd3469ea8ba9028f262497 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.128 $
+ *   $Revision: 1.129 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                      IBM Corporation
@@ -525,8 +525,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
                cdev = to_ccwdev(dev);
                if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
                    (cdev->private->devno == devno) &&
-                   (!strncmp(cdev->dev.bus_id, sibling->dev.bus_id,
-                             BUS_ID_SIZE))) {
+                   (cdev != sibling)) {
                        cdev->private->state = DEV_STATE_NOT_OPER;
                        break;
                }
@@ -539,6 +538,24 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
        return cdev;
 }
 
+static void
+ccw_device_add_changed(void *data)
+{
+
+       struct ccw_device *cdev;
+
+       cdev = (struct ccw_device *)data;
+       if (device_add(&cdev->dev)) {
+               put_device(&cdev->dev);
+               return;
+       }
+       set_bit(1, &cdev->private->registered);
+       if (device_add_files(&cdev->dev)) {
+               if (test_and_clear_bit(1, &cdev->private->registered))
+                       device_unregister(&cdev->dev);
+       }
+}
+
 extern int css_get_ssd_info(struct subchannel *sch);
 
 void
@@ -593,15 +610,9 @@ ccw_device_do_unreg_rereg(void *data)
        if (need_rename)
                snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
                          sch->schib.pmcw.dev);
-       if (device_add(&cdev->dev)) {
-               put_device(&cdev->dev);
-               return;
-       }
-       set_bit(1, &cdev->private->registered);
-       if (device_add_files(&cdev->dev)) {
-               if (test_and_clear_bit(1, &cdev->private->registered))
-                       device_unregister(&cdev->dev);
-       }
+       PREPARE_WORK(&cdev->private->kick_work,
+                    ccw_device_add_changed, (void *)cdev);
+       queue_work(ccw_device_work, &cdev->private->kick_work);
 }
 
 static void
index d41f0dda659140bd6f67d5edd2df0dcc384464f8..cacebad072a8bbd849ce950eba6014af65355382 100644 (file)
@@ -154,7 +154,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
        panic("Can't stop i/o on subchannel.\n");
 }
 
-static void
+static int
 ccw_device_handle_oper(struct ccw_device *cdev)
 {
        struct subchannel *sch;
@@ -174,9 +174,10 @@ ccw_device_handle_oper(struct ccw_device *cdev)
                PREPARE_WORK(&cdev->private->kick_work,
                             ccw_device_do_unreg_rereg, (void *)cdev);
                queue_work(ccw_device_work, &cdev->private->kick_work);
-               return;
+               return 0;
        }
        cdev->private->flags.donotify = 1;
+       return 1;
 }
 
 /*
@@ -206,7 +207,7 @@ static void
 ccw_device_recog_done(struct ccw_device *cdev, int state)
 {
        struct subchannel *sch;
-       int notify, old_lpm;
+       int notify, old_lpm, same_dev;
 
        sch = to_subchannel(cdev->dev.parent);
 
@@ -236,6 +237,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                /* Boxed devices don't need extra treatment. */
        }
        notify = 0;
+       same_dev = 0; /* Keep the compiler quiet... */
        switch (state) {
        case DEV_STATE_NOT_OPER:
                CIO_DEBUG(KERN_WARNING, 2,
@@ -244,7 +246,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                break;
        case DEV_STATE_OFFLINE:
                if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
-                       ccw_device_handle_oper(cdev);
+                       same_dev = ccw_device_handle_oper(cdev);
                        notify = 1;
                }
                /* fill out sense information */
@@ -255,10 +257,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
                        .dev_model = cdev->private->senseid.dev_model,
                };
                if (notify) {
-                       /* Get device online again. */
                        cdev->private->state = DEV_STATE_OFFLINE;
-                       ccw_device_online(cdev);
-                       wake_up(&cdev->private->wait_q);
+                       if (same_dev) {
+                               /* Get device online again. */
+                               ccw_device_online(cdev);
+                               wake_up(&cdev->private->wait_q);
+                       }
                        return;
                }
                /* Issue device info message. */
index 3a7c90e5ea868840cf608ac8920a02915707bf65..dc7d2888abe10d99364618f8cca0c143d594e086 100644 (file)
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.89 $"
+#define VERSION_QDIO_C "$Revision: 1.93 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -605,8 +605,8 @@ qdio_kick_outbound_q(struct qdio_q *q)
                        sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
                                atomic_read(&q->busy_siga_counter));
                        QDIO_DBF_TEXT3(0,trace,dbf_text);
-                       q->timing.busy_start=0;
 #endif /* CONFIG_QDIO_DEBUG */
+                       q->timing.busy_start=0;
                        break;
                case (2|QDIO_SIGA_ERROR_B_BIT_SET):
                        /* cc=2 and busy bit: */
@@ -2088,7 +2088,10 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
                u32 kc:4;
                u32 reserved4:21;
                u32 isc:3;
-               u32 reserved5[2];
+               u32 word_with_d_bit;
+               /* set to 0x10000000 to enable
+                * time delay disablement facility */
+               u32 reserved5;
                u32 subsystem_id;
                u32 reserved6[1004];
                struct chsc_header response;
@@ -2126,6 +2129,12 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
        scssc_area->kc = QDIO_STORAGE_KEY;
        scssc_area->isc = TIQDIO_THININT_ISC;
        scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
+       /* enables the time delay disablement facility. Don't care
+        * whether it is really there (i.e. we haven't checked for
+        * it) */
+       scssc_area->word_with_d_bit = 0x10000000;
+
+
 
        result = chsc(scssc_area);
        if (result) {
@@ -2620,6 +2629,7 @@ qdio_allocate(struct qdio_initialize *init_data)
 
        init_MUTEX(&irq_ptr->setting_up_sema);
 
+       /* QDR must be in DMA area since CCW data address is only 32 bit */
        irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
        if (!(irq_ptr->qdr)) {
                kfree(irq_ptr);