[S390] cio: Fix race for "fast" path gone/path back situations.
authorCornelia Huck <cornelia.huck@de.ibm.com>
Thu, 17 Apr 2008 05:45:59 +0000 (07:45 +0200)
committerHeiko Carstens <heiko.carstens@de.ibm.com>
Thu, 17 Apr 2008 05:46:57 +0000 (07:46 +0200)
Make sure we wait for previous evaluations triggered by path state
changes to have settled before we manipulate path states again.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
drivers/s390/cio/chsc.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h

index 007aaeb..b6a40c2 100644 (file)
@@ -217,6 +217,8 @@ void chsc_chp_offline(struct chp_id chpid)
 
        if (chp_get_status(chpid) <= 0)
                return;
+       /* Wait until previous actions have settled. */
+       css_wait_for_slow_path();
        for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
 }
 
@@ -303,7 +305,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
                sprintf(dbf_txt, "fla%x", res_data->fla);
                CIO_TRACE_EVENT( 2, dbf_txt);
        }
-
+       /* Wait until previous actions have settled. */
+       css_wait_for_slow_path();
        /*
         * I/O resources may have become accessible.
         * Scan through all subchannels that may be concerned and
@@ -561,9 +564,12 @@ void chsc_chp_online(struct chp_id chpid)
        sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
        CIO_TRACE_EVENT(2, dbf_txt);
 
-       if (chp_get_status(chpid) != 0)
+       if (chp_get_status(chpid) != 0) {
+               /* Wait until previous actions have settled. */
+               css_wait_for_slow_path();
                for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
                                           &chpid);
+       }
 }
 
 static void __s390_subchannel_vary_chpid(struct subchannel *sch,
@@ -650,6 +656,8 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
  */
 int chsc_chp_vary(struct chp_id chpid, int on)
 {
+       /* Wait until previous actions have settled. */
+       css_wait_for_slow_path();
        /*
         * Redo PathVerification on the devices the chpid connects to
         */
index 3b45bbe..3e829c8 100644 (file)
@@ -533,6 +533,12 @@ void css_schedule_eval_all(void)
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
+void css_wait_for_slow_path(void)
+{
+       flush_workqueue(ccw_device_notify_work);
+       flush_workqueue(slow_path_wq);
+}
+
 /* Reprobe subchannel if unregistered. */
 static int reprobe_subchannel(struct subchannel_id schid, void *data)
 {
index b705545..e191351 100644 (file)
@@ -144,6 +144,7 @@ struct schib;
 int css_sch_is_valid(struct schib *);
 
 extern struct workqueue_struct *slow_path_wq;
+void css_wait_for_slow_path(void);
 
 extern struct attribute_group *subch_attr_groups[];
 #endif