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

[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
Loading
Loading
Loading
Loading
+57 −8
Original line number Diff line number Diff line
@@ -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);
+3 −17
Original line number Diff line number Diff line
@@ -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 **************************/

+1 −0
Original line number Diff line number Diff line
@@ -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);