diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-09-22 16:58:33 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-09-22 16:58:41 -0400 |
commit | 2f17644d1cd0121daa0a997ff4eca5b3b44d1fae (patch) | |
tree | 898504831cd8424525304eb9e35851f744a03d24 /drivers/s390 | |
parent | 43c1266ce4dc06bfd236cec31e11e9ecd69c0bef (diff) |
[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')
-rw-r--r-- | drivers/s390/cio/css.c | 65 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 20 | ||||
-rw-r--r-- | drivers/s390/cio/device.h | 1 |
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) | |||
601 | css_evaluate_subchannel(mchk_schid, 0); | 601 | css_evaluate_subchannel(mchk_schid, 0); |
602 | } | 602 | } |
603 | 603 | ||
604 | static int __init | 604 | static int __init setup_subchannel(struct subchannel_id schid, void *data) |
605 | __init_channel_subsystem(struct subchannel_id schid, void *data) | ||
606 | { | 605 | { |
607 | struct subchannel *sch; | 606 | struct subchannel *sch; |
608 | int ret; | 607 | int ret; |
@@ -854,14 +853,13 @@ static struct notifier_block css_power_notifier = { | |||
854 | * The struct subchannel's are created during probing (except for the | 853 | * The struct subchannel's are created during probing (except for the |
855 | * static console subchannel). | 854 | * static console subchannel). |
856 | */ | 855 | */ |
857 | static int __init | 856 | static int __init css_bus_init(void) |
858 | init_channel_subsystem (void) | ||
859 | { | 857 | { |
860 | int ret, i; | 858 | int ret, i; |
861 | 859 | ||
862 | ret = chsc_determine_css_characteristics(); | 860 | ret = chsc_determine_css_characteristics(); |
863 | if (ret == -ENOMEM) | 861 | if (ret == -ENOMEM) |
864 | goto out; /* No need to continue. */ | 862 | goto out; |
865 | 863 | ||
866 | ret = chsc_alloc_sei_area(); | 864 | ret = chsc_alloc_sei_area(); |
867 | if (ret) | 865 | if (ret) |
@@ -934,7 +932,6 @@ init_channel_subsystem (void) | |||
934 | /* Enable default isc for I/O subchannels. */ | 932 | /* Enable default isc for I/O subchannels. */ |
935 | isc_register(IO_SCH_ISC); | 933 | isc_register(IO_SCH_ISC); |
936 | 934 | ||
937 | for_each_subchannel(__init_channel_subsystem, NULL); | ||
938 | return 0; | 935 | return 0; |
939 | out_file: | 936 | out_file: |
940 | if (css_chsc_characteristics.secm) | 937 | if (css_chsc_characteristics.secm) |
@@ -966,6 +963,60 @@ out: | |||
966 | return ret; | 963 | return ret; |
967 | } | 964 | } |
968 | 965 | ||
966 | static void __init css_bus_cleanup(void) | ||
967 | { | ||
968 | struct channel_subsystem *css; | ||
969 | int i; | ||
970 | |||
971 | for (i = 0; i <= __MAX_CSSID; i++) { | ||
972 | css = channel_subsystems[i]; | ||
973 | device_unregister(&css->pseudo_subchannel->dev); | ||
974 | css->pseudo_subchannel = NULL; | ||
975 | if (css_chsc_characteristics.secm) | ||
976 | device_remove_file(&css->device, &dev_attr_cm_enable); | ||
977 | device_unregister(&css->device); | ||
978 | } | ||
979 | bus_unregister(&css_bus_type); | ||
980 | crw_unregister_handler(CRW_RSC_CSS); | ||
981 | chsc_free_sei_area(); | ||
982 | kfree(slow_subchannel_set); | ||
983 | isc_unregister(IO_SCH_ISC); | ||
984 | } | ||
985 | |||
986 | static int __init channel_subsystem_init(void) | ||
987 | { | ||
988 | int ret; | ||
989 | |||
990 | ret = css_bus_init(); | ||
991 | if (ret) | ||
992 | return ret; | ||
993 | |||
994 | ret = io_subchannel_init(); | ||
995 | if (ret) | ||
996 | css_bus_cleanup(); | ||
997 | |||
998 | return ret; | ||
999 | } | ||
1000 | subsys_initcall(channel_subsystem_init); | ||
1001 | |||
1002 | /* | ||
1003 | * Wait for the initialization of devices to finish, to make sure we are | ||
1004 | * done with our setup if the search for the root device starts. | ||
1005 | */ | ||
1006 | static int __init channel_subsystem_init_sync(void) | ||
1007 | { | ||
1008 | /* Allocate and register subchannels. */ | ||
1009 | for_each_subchannel(setup_subchannel, NULL); | ||
1010 | |||
1011 | /* Wait for the initialization of ccw devices to finish. */ | ||
1012 | wait_event(ccw_device_init_wq, | ||
1013 | atomic_read(&ccw_device_init_count) == 0); | ||
1014 | flush_workqueue(ccw_device_work); | ||
1015 | |||
1016 | return 0; | ||
1017 | } | ||
1018 | subsys_initcall_sync(channel_subsystem_init_sync); | ||
1019 | |||
969 | int sch_is_pseudo_sch(struct subchannel *sch) | 1020 | int sch_is_pseudo_sch(struct subchannel *sch) |
970 | { | 1021 | { |
971 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; | 1022 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; |
@@ -1135,7 +1186,5 @@ void css_driver_unregister(struct css_driver *cdrv) | |||
1135 | } | 1186 | } |
1136 | EXPORT_SYMBOL_GPL(css_driver_unregister); | 1187 | EXPORT_SYMBOL_GPL(css_driver_unregister); |
1137 | 1188 | ||
1138 | subsys_initcall(init_channel_subsystem); | ||
1139 | |||
1140 | MODULE_LICENSE("GPL"); | 1189 | MODULE_LICENSE("GPL"); |
1141 | EXPORT_SYMBOL(css_bus_type); | 1190 | 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; | |||
170 | 170 | ||
171 | static void recovery_func(unsigned long data); | 171 | static void recovery_func(unsigned long data); |
172 | 172 | ||
173 | static int __init | 173 | int __init io_subchannel_init(void) |
174 | init_ccw_bus_type (void) | ||
175 | { | 174 | { |
176 | int ret; | 175 | int ret; |
177 | 176 | ||
@@ -181,10 +180,10 @@ init_ccw_bus_type (void) | |||
181 | 180 | ||
182 | ccw_device_work = create_singlethread_workqueue("cio"); | 181 | ccw_device_work = create_singlethread_workqueue("cio"); |
183 | if (!ccw_device_work) | 182 | if (!ccw_device_work) |
184 | return -ENOMEM; /* FIXME: better errno ? */ | 183 | return -ENOMEM; |
185 | slow_path_wq = create_singlethread_workqueue("kslowcrw"); | 184 | slow_path_wq = create_singlethread_workqueue("kslowcrw"); |
186 | if (!slow_path_wq) { | 185 | if (!slow_path_wq) { |
187 | ret = -ENOMEM; /* FIXME: better errno ? */ | 186 | ret = -ENOMEM; |
188 | goto out_err; | 187 | goto out_err; |
189 | } | 188 | } |
190 | if ((ret = bus_register (&ccw_bus_type))) | 189 | if ((ret = bus_register (&ccw_bus_type))) |
@@ -194,9 +193,6 @@ init_ccw_bus_type (void) | |||
194 | if (ret) | 193 | if (ret) |
195 | goto out_err; | 194 | goto out_err; |
196 | 195 | ||
197 | wait_event(ccw_device_init_wq, | ||
198 | atomic_read(&ccw_device_init_count) == 0); | ||
199 | flush_workqueue(ccw_device_work); | ||
200 | return 0; | 196 | return 0; |
201 | out_err: | 197 | out_err: |
202 | if (ccw_device_work) | 198 | if (ccw_device_work) |
@@ -206,16 +202,6 @@ out_err: | |||
206 | return ret; | 202 | return ret; |
207 | } | 203 | } |
208 | 204 | ||
209 | static void __exit | ||
210 | cleanup_ccw_bus_type (void) | ||
211 | { | ||
212 | css_driver_unregister(&io_subchannel_driver); | ||
213 | bus_unregister(&ccw_bus_type); | ||
214 | destroy_workqueue(ccw_device_work); | ||
215 | } | ||
216 | |||
217 | subsys_initcall(init_ccw_bus_type); | ||
218 | module_exit(cleanup_ccw_bus_type); | ||
219 | 205 | ||
220 | /************************ device handling **************************/ | 206 | /************************ device handling **************************/ |
221 | 207 | ||
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) | |||
74 | extern struct workqueue_struct *ccw_device_work; | 74 | extern struct workqueue_struct *ccw_device_work; |
75 | extern wait_queue_head_t ccw_device_init_wq; | 75 | extern wait_queue_head_t ccw_device_init_wq; |
76 | extern atomic_t ccw_device_init_count; | 76 | extern atomic_t ccw_device_init_count; |
77 | int __init io_subchannel_init(void); | ||
77 | 78 | ||
78 | void io_subchannel_recog_done(struct ccw_device *cdev); | 79 | void io_subchannel_recog_done(struct ccw_device *cdev); |
79 | void io_subchannel_init_config(struct subchannel *sch); | 80 | void io_subchannel_init_config(struct subchannel *sch); |