diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-02-26 16:37:27 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-02-26 16:37:29 -0500 |
commit | b4c707214c987da021d4d5c4ed54612cf73d80d6 (patch) | |
tree | d31dffc6de708a7069e59925a6fa4080138c90e6 | |
parent | b4563e891a043fe521e62f6f621b928641474ff3 (diff) |
[S390] cio: make wait_events interruptible
Make the potentially long blocking wait_event's used by the cio
settle mechanism interruptible.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/css.c | 18 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 11 |
3 files changed, 21 insertions, 10 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 366affcd9bbf..169a27723c4f 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -1016,19 +1016,22 @@ static int css_settle(struct device_driver *drv, void *unused) | |||
1016 | struct css_driver *cssdrv = to_cssdriver(drv); | 1016 | struct css_driver *cssdrv = to_cssdriver(drv); |
1017 | 1017 | ||
1018 | if (cssdrv->settle) | 1018 | if (cssdrv->settle) |
1019 | cssdrv->settle(); | 1019 | return cssdrv->settle(); |
1020 | return 0; | 1020 | return 0; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static inline void css_complete_work(void) | 1023 | static inline int css_complete_work(void) |
1024 | { | 1024 | { |
1025 | int ret; | 1025 | int ret; |
1026 | 1026 | ||
1027 | /* Wait for the evaluation of subchannels to finish. */ | 1027 | /* Wait for the evaluation of subchannels to finish. */ |
1028 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); | 1028 | ret = wait_event_interruptible(css_eval_wq, |
1029 | atomic_read(&css_eval_scheduled) == 0); | ||
1030 | if (ret) | ||
1031 | return -EINTR; | ||
1029 | flush_workqueue(cio_work_q); | 1032 | flush_workqueue(cio_work_q); |
1030 | /* Wait for the subchannel type specific initialization to finish */ | 1033 | /* Wait for the subchannel type specific initialization to finish */ |
1031 | ret = bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); | 1034 | return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); |
1032 | } | 1035 | } |
1033 | 1036 | ||
1034 | 1037 | ||
@@ -1049,10 +1052,13 @@ subsys_initcall_sync(channel_subsystem_init_sync); | |||
1049 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, | 1052 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, |
1050 | size_t count, loff_t *ppos) | 1053 | size_t count, loff_t *ppos) |
1051 | { | 1054 | { |
1055 | int ret; | ||
1056 | |||
1052 | /* Handle pending CRW's. */ | 1057 | /* Handle pending CRW's. */ |
1053 | crw_wait_for_channel_report(); | 1058 | crw_wait_for_channel_report(); |
1054 | css_complete_work(); | 1059 | ret = css_complete_work(); |
1055 | return count; | 1060 | |
1061 | return ret ? ret : count; | ||
1056 | } | 1062 | } |
1057 | 1063 | ||
1058 | static const struct file_operations cio_settle_proc_fops = { | 1064 | static const struct file_operations cio_settle_proc_fops = { |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index e05525d53ea5..325d813bb8e0 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -95,7 +95,7 @@ struct css_driver { | |||
95 | int (*freeze)(struct subchannel *); | 95 | int (*freeze)(struct subchannel *); |
96 | int (*thaw) (struct subchannel *); | 96 | int (*thaw) (struct subchannel *); |
97 | int (*restore)(struct subchannel *); | 97 | int (*restore)(struct subchannel *); |
98 | void (*settle)(void); | 98 | int (*settle)(void); |
99 | const char *name; | 99 | const char *name; |
100 | }; | 100 | }; |
101 | 101 | ||
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 9c9ea45141af..6aa2f069c6be 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -158,11 +158,16 @@ static int io_subchannel_prepare(struct subchannel *sch) | |||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | static void io_subchannel_settle(void) | 161 | static int io_subchannel_settle(void) |
162 | { | 162 | { |
163 | wait_event(ccw_device_init_wq, | 163 | int ret; |
164 | atomic_read(&ccw_device_init_count) == 0); | 164 | |
165 | ret = wait_event_interruptible(ccw_device_init_wq, | ||
166 | atomic_read(&ccw_device_init_count) == 0); | ||
167 | if (ret) | ||
168 | return -EINTR; | ||
165 | flush_workqueue(cio_work_q); | 169 | flush_workqueue(cio_work_q); |
170 | return 0; | ||
166 | } | 171 | } |
167 | 172 | ||
168 | static struct css_driver io_subchannel_driver = { | 173 | static struct css_driver io_subchannel_driver = { |