Commit 8ea7f559 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

[S390] cio: introduce css_settle

Introduce the css_driver callback settle which can be implemented
by a subchannel driver to wait for the subchannel type specific
asynchronous work to finish.
In channel_subsystem_init_sync we call that for each subchannel
driver.
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 25530553
...@@ -1013,6 +1013,15 @@ static int __init channel_subsystem_init(void) ...@@ -1013,6 +1013,15 @@ static int __init channel_subsystem_init(void)
} }
subsys_initcall(channel_subsystem_init); subsys_initcall(channel_subsystem_init);
static int css_settle(struct device_driver *drv, void *unused)
{
struct css_driver *cssdrv = to_cssdriver(drv);
if (cssdrv->settle)
cssdrv->settle();
return 0;
}
/* /*
* Wait for the initialization of devices to finish, to make sure we are * Wait for the initialization of devices to finish, to make sure we are
* done with our setup if the search for the root device starts. * 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,12 +1033,8 @@ static int __init channel_subsystem_init_sync(void)
/* Wait for the evaluation of subchannels to finish. */ /* Wait for the evaluation of subchannels to finish. */
wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0);
/* Wait for the initialization of ccw devices to finish. */ /* Wait for the subchannel type specific initialization to finish */
wait_event(ccw_device_init_wq, return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle);
atomic_read(&ccw_device_init_count) == 0);
flush_workqueue(ccw_device_work);
return 0;
} }
subsys_initcall_sync(channel_subsystem_init_sync); subsys_initcall_sync(channel_subsystem_init_sync);
......
...@@ -75,6 +75,7 @@ struct chp_link; ...@@ -75,6 +75,7 @@ struct chp_link;
* @freeze: callback for freezing during hibernation snapshotting * @freeze: callback for freezing during hibernation snapshotting
* @thaw: undo work done in @freeze * @thaw: undo work done in @freeze
* @restore: callback for restoring after hibernation * @restore: callback for restoring after hibernation
* @settle: wait for asynchronous work to finish
* @name: name of the device driver * @name: name of the device driver
*/ */
struct css_driver { struct css_driver {
...@@ -92,6 +93,7 @@ struct css_driver { ...@@ -92,6 +93,7 @@ struct css_driver {
int (*freeze)(struct subchannel *); int (*freeze)(struct subchannel *);
int (*thaw) (struct subchannel *); int (*thaw) (struct subchannel *);
int (*restore)(struct subchannel *); int (*restore)(struct subchannel *);
void (*settle)(void);
const char *name; const char *name;
}; };
......
...@@ -131,6 +131,10 @@ static void io_subchannel_shutdown(struct subchannel *); ...@@ -131,6 +131,10 @@ static void io_subchannel_shutdown(struct subchannel *);
static int io_subchannel_sch_event(struct subchannel *, int); static int io_subchannel_sch_event(struct subchannel *, int);
static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
int); int);
static void recovery_func(unsigned long data);
struct workqueue_struct *ccw_device_work;
wait_queue_head_t ccw_device_init_wq;
atomic_t ccw_device_init_count;
static struct css_device_id io_subchannel_ids[] = { static struct css_device_id io_subchannel_ids[] = {
{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
...@@ -151,6 +155,13 @@ static int io_subchannel_prepare(struct subchannel *sch) ...@@ -151,6 +155,13 @@ static int io_subchannel_prepare(struct subchannel *sch)
return 0; return 0;
} }
static void io_subchannel_settle(void)
{
wait_event(ccw_device_init_wq,
atomic_read(&ccw_device_init_count) == 0);
flush_workqueue(ccw_device_work);
}
static struct css_driver io_subchannel_driver = { static struct css_driver io_subchannel_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.subchannel_type = io_subchannel_ids, .subchannel_type = io_subchannel_ids,
...@@ -162,14 +173,9 @@ static struct css_driver io_subchannel_driver = { ...@@ -162,14 +173,9 @@ static struct css_driver io_subchannel_driver = {
.remove = io_subchannel_remove, .remove = io_subchannel_remove,
.shutdown = io_subchannel_shutdown, .shutdown = io_subchannel_shutdown,
.prepare = io_subchannel_prepare, .prepare = io_subchannel_prepare,
.settle = io_subchannel_settle,
}; };
struct workqueue_struct *ccw_device_work;
wait_queue_head_t ccw_device_init_wq;
atomic_t ccw_device_init_count;
static void recovery_func(unsigned long data);
int __init io_subchannel_init(void) int __init io_subchannel_init(void)
{ {
int ret; int ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment