diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/css.c | 17 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 18 |
3 files changed, 25 insertions, 12 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 59c4b94cdb4b..f018835afdf4 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -1013,6 +1013,15 @@ static int __init channel_subsystem_init(void) | |||
1013 | } | 1013 | } |
1014 | subsys_initcall(channel_subsystem_init); | 1014 | subsys_initcall(channel_subsystem_init); |
1015 | 1015 | ||
1016 | static int css_settle(struct device_driver *drv, void *unused) | ||
1017 | { | ||
1018 | struct css_driver *cssdrv = to_cssdriver(drv); | ||
1019 | |||
1020 | if (cssdrv->settle) | ||
1021 | cssdrv->settle(); | ||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1016 | /* | 1025 | /* |
1017 | * Wait for the initialization of devices to finish, to make sure we are | 1026 | * Wait for the initialization of devices to finish, to make sure we are |
1018 | * done with our setup if the search for the root device starts. | 1027 | * done with our setup if the search for the root device starts. |
@@ -1024,12 +1033,8 @@ static int __init channel_subsystem_init_sync(void) | |||
1024 | /* Wait for the evaluation of subchannels to finish. */ | 1033 | /* Wait for the evaluation of subchannels to finish. */ |
1025 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); | 1034 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); |
1026 | 1035 | ||
1027 | /* Wait for the initialization of ccw devices to finish. */ | 1036 | /* Wait for the subchannel type specific initialization to finish */ |
1028 | wait_event(ccw_device_init_wq, | 1037 | return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); |
1029 | atomic_read(&ccw_device_init_count) == 0); | ||
1030 | flush_workqueue(ccw_device_work); | ||
1031 | |||
1032 | return 0; | ||
1033 | } | 1038 | } |
1034 | subsys_initcall_sync(channel_subsystem_init_sync); | 1039 | subsys_initcall_sync(channel_subsystem_init_sync); |
1035 | 1040 | ||
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 9763eeec7458..54acdaade86e 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -75,6 +75,7 @@ struct chp_link; | |||
75 | * @freeze: callback for freezing during hibernation snapshotting | 75 | * @freeze: callback for freezing during hibernation snapshotting |
76 | * @thaw: undo work done in @freeze | 76 | * @thaw: undo work done in @freeze |
77 | * @restore: callback for restoring after hibernation | 77 | * @restore: callback for restoring after hibernation |
78 | * @settle: wait for asynchronous work to finish | ||
78 | * @name: name of the device driver | 79 | * @name: name of the device driver |
79 | */ | 80 | */ |
80 | struct css_driver { | 81 | struct css_driver { |
@@ -92,6 +93,7 @@ struct css_driver { | |||
92 | int (*freeze)(struct subchannel *); | 93 | int (*freeze)(struct subchannel *); |
93 | int (*thaw) (struct subchannel *); | 94 | int (*thaw) (struct subchannel *); |
94 | int (*restore)(struct subchannel *); | 95 | int (*restore)(struct subchannel *); |
96 | void (*settle)(void); | ||
95 | const char *name; | 97 | const char *name; |
96 | }; | 98 | }; |
97 | 99 | ||
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 4093adc12f2c..f780bdd3a04e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -131,6 +131,10 @@ static void io_subchannel_shutdown(struct subchannel *); | |||
131 | static int io_subchannel_sch_event(struct subchannel *, int); | 131 | static int io_subchannel_sch_event(struct subchannel *, int); |
132 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, | 132 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, |
133 | int); | 133 | int); |
134 | static void recovery_func(unsigned long data); | ||
135 | struct workqueue_struct *ccw_device_work; | ||
136 | wait_queue_head_t ccw_device_init_wq; | ||
137 | atomic_t ccw_device_init_count; | ||
134 | 138 | ||
135 | static struct css_device_id io_subchannel_ids[] = { | 139 | static struct css_device_id io_subchannel_ids[] = { |
136 | { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, | 140 | { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, |
@@ -151,6 +155,13 @@ static int io_subchannel_prepare(struct subchannel *sch) | |||
151 | return 0; | 155 | return 0; |
152 | } | 156 | } |
153 | 157 | ||
158 | static void io_subchannel_settle(void) | ||
159 | { | ||
160 | wait_event(ccw_device_init_wq, | ||
161 | atomic_read(&ccw_device_init_count) == 0); | ||
162 | flush_workqueue(ccw_device_work); | ||
163 | } | ||
164 | |||
154 | static struct css_driver io_subchannel_driver = { | 165 | static struct css_driver io_subchannel_driver = { |
155 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
156 | .subchannel_type = io_subchannel_ids, | 167 | .subchannel_type = io_subchannel_ids, |
@@ -162,14 +173,9 @@ static struct css_driver io_subchannel_driver = { | |||
162 | .remove = io_subchannel_remove, | 173 | .remove = io_subchannel_remove, |
163 | .shutdown = io_subchannel_shutdown, | 174 | .shutdown = io_subchannel_shutdown, |
164 | .prepare = io_subchannel_prepare, | 175 | .prepare = io_subchannel_prepare, |
176 | .settle = io_subchannel_settle, | ||
165 | }; | 177 | }; |
166 | 178 | ||
167 | struct workqueue_struct *ccw_device_work; | ||
168 | wait_queue_head_t ccw_device_init_wq; | ||
169 | atomic_t ccw_device_init_count; | ||
170 | |||
171 | static void recovery_func(unsigned long data); | ||
172 | |||
173 | int __init io_subchannel_init(void) | 179 | int __init io_subchannel_init(void) |
174 | { | 180 | { |
175 | int ret; | 181 | int ret; |