Commit 2f17644d authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

[S390] cio: merge init calls

Define initialization sequence of css and ccw bus init calls by merging
them into a single init call. Also introduce channel_subsystem_init_sync
to wait for the initialization of devices to finish.
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 43c1266c
...@@ -601,8 +601,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) ...@@ -601,8 +601,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
css_evaluate_subchannel(mchk_schid, 0); css_evaluate_subchannel(mchk_schid, 0);
} }
static int __init static int __init setup_subchannel(struct subchannel_id schid, void *data)
__init_channel_subsystem(struct subchannel_id schid, void *data)
{ {
struct subchannel *sch; struct subchannel *sch;
int ret; int ret;
...@@ -854,14 +853,13 @@ static struct notifier_block css_power_notifier = { ...@@ -854,14 +853,13 @@ static struct notifier_block css_power_notifier = {
* The struct subchannel's are created during probing (except for the * The struct subchannel's are created during probing (except for the
* static console subchannel). * static console subchannel).
*/ */
static int __init static int __init css_bus_init(void)
init_channel_subsystem (void)
{ {
int ret, i; int ret, i;
ret = chsc_determine_css_characteristics(); ret = chsc_determine_css_characteristics();
if (ret == -ENOMEM) if (ret == -ENOMEM)
goto out; /* No need to continue. */ goto out;
ret = chsc_alloc_sei_area(); ret = chsc_alloc_sei_area();
if (ret) if (ret)
...@@ -934,7 +932,6 @@ init_channel_subsystem (void) ...@@ -934,7 +932,6 @@ init_channel_subsystem (void)
/* Enable default isc for I/O subchannels. */ /* Enable default isc for I/O subchannels. */
isc_register(IO_SCH_ISC); isc_register(IO_SCH_ISC);
for_each_subchannel(__init_channel_subsystem, NULL);
return 0; return 0;
out_file: out_file:
if (css_chsc_characteristics.secm) if (css_chsc_characteristics.secm)
...@@ -966,6 +963,60 @@ init_channel_subsystem (void) ...@@ -966,6 +963,60 @@ init_channel_subsystem (void)
return ret; return ret;
} }
static void __init css_bus_cleanup(void)
{
struct channel_subsystem *css;
int i;
for (i = 0; i <= __MAX_CSSID; i++) {
css = channel_subsystems[i];
device_unregister(&css->pseudo_subchannel->dev);
css->pseudo_subchannel = NULL;
if (css_chsc_characteristics.secm)
device_remove_file(&css->device, &dev_attr_cm_enable);
device_unregister(&css->device);
}
bus_unregister(&css_bus_type);
crw_unregister_handler(CRW_RSC_CSS);
chsc_free_sei_area();
kfree(slow_subchannel_set);
isc_unregister(IO_SCH_ISC);
}
static int __init channel_subsystem_init(void)
{
int ret;
ret = css_bus_init();
if (ret)
return ret;
ret = io_subchannel_init();
if (ret)
css_bus_cleanup();
return ret;
}
subsys_initcall(channel_subsystem_init);
/*
* 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.
*/
static int __init channel_subsystem_init_sync(void)
{
/* Allocate and register subchannels. */
for_each_subchannel(setup_subchannel, NULL);
/* Wait for the initialization of ccw devices to finish. */
wait_event(ccw_device_init_wq,
atomic_read(&ccw_device_init_count) == 0);
flush_workqueue(ccw_device_work);
return 0;
}
subsys_initcall_sync(channel_subsystem_init_sync);
int sch_is_pseudo_sch(struct subchannel *sch) int sch_is_pseudo_sch(struct subchannel *sch)
{ {
return sch == to_css(sch->dev.parent)->pseudo_subchannel; return sch == to_css(sch->dev.parent)->pseudo_subchannel;
...@@ -1135,7 +1186,5 @@ void css_driver_unregister(struct css_driver *cdrv) ...@@ -1135,7 +1186,5 @@ void css_driver_unregister(struct css_driver *cdrv)
} }
EXPORT_SYMBOL_GPL(css_driver_unregister); EXPORT_SYMBOL_GPL(css_driver_unregister);
subsys_initcall(init_channel_subsystem);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(css_bus_type); EXPORT_SYMBOL(css_bus_type);
...@@ -170,8 +170,7 @@ atomic_t ccw_device_init_count; ...@@ -170,8 +170,7 @@ atomic_t ccw_device_init_count;
static void recovery_func(unsigned long data); static void recovery_func(unsigned long data);
static int __init int __init io_subchannel_init(void)
init_ccw_bus_type (void)
{ {
int ret; int ret;
...@@ -181,10 +180,10 @@ init_ccw_bus_type (void) ...@@ -181,10 +180,10 @@ init_ccw_bus_type (void)
ccw_device_work = create_singlethread_workqueue("cio"); ccw_device_work = create_singlethread_workqueue("cio");
if (!ccw_device_work) if (!ccw_device_work)
return -ENOMEM; /* FIXME: better errno ? */ return -ENOMEM;
slow_path_wq = create_singlethread_workqueue("kslowcrw"); slow_path_wq = create_singlethread_workqueue("kslowcrw");
if (!slow_path_wq) { if (!slow_path_wq) {
ret = -ENOMEM; /* FIXME: better errno ? */ ret = -ENOMEM;
goto out_err; goto out_err;
} }
if ((ret = bus_register (&ccw_bus_type))) if ((ret = bus_register (&ccw_bus_type)))
...@@ -194,9 +193,6 @@ init_ccw_bus_type (void) ...@@ -194,9 +193,6 @@ init_ccw_bus_type (void)
if (ret) if (ret)
goto out_err; goto out_err;
wait_event(ccw_device_init_wq,
atomic_read(&ccw_device_init_count) == 0);
flush_workqueue(ccw_device_work);
return 0; return 0;
out_err: out_err:
if (ccw_device_work) if (ccw_device_work)
...@@ -206,16 +202,6 @@ init_ccw_bus_type (void) ...@@ -206,16 +202,6 @@ init_ccw_bus_type (void)
return ret; return ret;
} }
static void __exit
cleanup_ccw_bus_type (void)
{
css_driver_unregister(&io_subchannel_driver);
bus_unregister(&ccw_bus_type);
destroy_workqueue(ccw_device_work);
}
subsys_initcall(init_ccw_bus_type);
module_exit(cleanup_ccw_bus_type);
/************************ device handling **************************/ /************************ device handling **************************/
......
...@@ -74,6 +74,7 @@ dev_fsm_final_state(struct ccw_device *cdev) ...@@ -74,6 +74,7 @@ dev_fsm_final_state(struct ccw_device *cdev)
extern struct workqueue_struct *ccw_device_work; extern struct workqueue_struct *ccw_device_work;
extern wait_queue_head_t ccw_device_init_wq; extern wait_queue_head_t ccw_device_init_wq;
extern atomic_t ccw_device_init_count; extern atomic_t ccw_device_init_count;
int __init io_subchannel_init(void);
void io_subchannel_recog_done(struct ccw_device *cdev); void io_subchannel_recog_done(struct ccw_device *cdev);
void io_subchannel_init_config(struct subchannel *sch); void io_subchannel_init_config(struct subchannel *sch);
......
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