summary refs log tree commit diff
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2009-09-22 22:58:33 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-09-22 22:58:41 +0200
commit2f17644d1cd0121daa0a997ff4eca5b3b44d1fae (patch)
tree898504831cd8424525304eb9e35851f744a03d24 /drivers/s390/cio
parent43c1266ce4dc06bfd236cec31e11e9ecd69c0bef (diff)
downloadlinux-2f17644d1cd0121daa0a997ff4eca5b3b44d1fae.tar.gz
[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: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/css.c65
-rw-r--r--drivers/s390/cio/device.c20
-rw-r--r--drivers/s390/cio/device.h1
3 files changed, 61 insertions, 25 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 393c73c47f87..95805da2bb26 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -601,8 +601,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 	css_evaluate_subchannel(mchk_schid, 0);
 }
 
-static int __init
-__init_channel_subsystem(struct subchannel_id schid, void *data)
+static int __init setup_subchannel(struct subchannel_id schid, void *data)
 {
 	struct subchannel *sch;
 	int ret;
@@ -854,14 +853,13 @@ static struct notifier_block css_power_notifier = {
  * The struct subchannel's are created during probing (except for the
  * static console subchannel).
  */
-static int __init
-init_channel_subsystem (void)
+static int __init css_bus_init(void)
 {
 	int ret, i;
 
 	ret = chsc_determine_css_characteristics();
 	if (ret == -ENOMEM)
-		goto out; /* No need to continue. */
+		goto out;
 
 	ret = chsc_alloc_sei_area();
 	if (ret)
@@ -934,7 +932,6 @@ init_channel_subsystem (void)
 	/* Enable default isc for I/O subchannels. */
 	isc_register(IO_SCH_ISC);
 
-	for_each_subchannel(__init_channel_subsystem, NULL);
 	return 0;
 out_file:
 	if (css_chsc_characteristics.secm)
@@ -966,6 +963,60 @@ out:
 	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)
 {
 	return sch == to_css(sch->dev.parent)->pseudo_subchannel;
@@ -1135,7 +1186,5 @@ void css_driver_unregister(struct css_driver *cdrv)
 }
 EXPORT_SYMBOL_GPL(css_driver_unregister);
 
-subsys_initcall(init_channel_subsystem);
-
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(css_bus_type);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6527f3f34493..4093adc12f2c 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -170,8 +170,7 @@ atomic_t ccw_device_init_count;
 
 static void recovery_func(unsigned long data);
 
-static int __init
-init_ccw_bus_type (void)
+int __init io_subchannel_init(void)
 {
 	int ret;
 
@@ -181,10 +180,10 @@ init_ccw_bus_type (void)
 
 	ccw_device_work = create_singlethread_workqueue("cio");
 	if (!ccw_device_work)
-		return -ENOMEM; /* FIXME: better errno ? */
+		return -ENOMEM;
 	slow_path_wq = create_singlethread_workqueue("kslowcrw");
 	if (!slow_path_wq) {
-		ret = -ENOMEM; /* FIXME: better errno ? */
+		ret = -ENOMEM;
 		goto out_err;
 	}
 	if ((ret = bus_register (&ccw_bus_type)))
@@ -194,9 +193,6 @@ init_ccw_bus_type (void)
 	if (ret)
 		goto out_err;
 
-	wait_event(ccw_device_init_wq,
-		   atomic_read(&ccw_device_init_count) == 0);
-	flush_workqueue(ccw_device_work);
 	return 0;
 out_err:
 	if (ccw_device_work)
@@ -206,16 +202,6 @@ out_err:
 	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 **************************/
 
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index e3975107a578..ed39a2caaf47 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -74,6 +74,7 @@ dev_fsm_final_state(struct ccw_device *cdev)
 extern struct workqueue_struct *ccw_device_work;
 extern wait_queue_head_t ccw_device_init_wq;
 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_init_config(struct subchannel *sch);