diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-04-13 15:01:50 +0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-04-17 16:07:32 +0400 |
commit | 863fc8492734822b95671780db803cd9a4b7d923 (patch) | |
tree | badeeb42bc2f1d047849882aecd37fffef91ca20 /drivers/s390/cio/cio.c | |
parent | c135ad1caffe2b35d6316758a605a2b63ca22bb3 (diff) | |
download | linux-863fc8492734822b95671780db803cd9a4b7d923.tar.xz |
s390/cio: get rid of static console subchannel
Remove the static console subchannel (and friends) and use dynamic
allocation for these structures. With this change the console
subchanel is treated (mostly) like any other subchannel and we can
remove some special cases.
Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
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/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 111 |
1 files changed, 34 insertions, 77 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 2c1d53fb2fab..ab99500604b7 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -540,13 +540,9 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) memset(sch, 0, sizeof(struct subchannel)); sch->schid = schid; - if (cio_is_console(schid)) { - sch->lock = cio_get_console_lock(); - } else { - err = cio_create_sch_lock(sch); - if (err) - goto out; - } + err = cio_create_sch_lock(sch); + if (err) + goto out; mutex_init(&sch->reg_mutex); /* @@ -580,8 +576,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) sch->schid.ssid, sch->schid.sch_no, sch->st); return 0; out: - if (!cio_is_console(schid)) - kfree(sch->lock); + kfree(sch->lock); sch->lock = NULL; return err; } @@ -650,9 +645,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) } #ifdef CONFIG_CCW_CONSOLE -static struct subchannel console_subchannel; -static struct io_subchannel_private console_priv; -static int console_subchannel_in_use; +static struct subchannel *console_sch; /* * Use cio_tsch to update the subchannel status and call the interrupt handler @@ -685,119 +678,83 @@ void cio_tsch(struct subchannel *sch) } } -void *cio_get_console_priv(void) +static int cio_test_for_console(struct subchannel_id schid, void *data) { - return &console_priv; -} + struct schib schib; -static int -cio_test_for_console(struct subchannel_id schid, void *data) -{ - if (stsch_err(schid, &console_subchannel.schib) != 0) + if (stsch_err(schid, &schib) != 0) return -ENXIO; - if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) && - console_subchannel.schib.pmcw.dnv && - (console_subchannel.schib.pmcw.dev == console_devno)) { + if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && + (schib.pmcw.dev == console_devno)) { console_irq = schid.sch_no; return 1; /* found */ } return 0; } - -static int -cio_get_console_sch_no(void) +static int cio_get_console_sch_no(void) { struct subchannel_id schid; - + struct schib schib; + init_subchannel_id(&schid); if (console_irq != -1) { /* VM provided us with the irq number of the console. */ schid.sch_no = console_irq; - if (stsch_err(schid, &console_subchannel.schib) != 0 || - (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || - !console_subchannel.schib.pmcw.dnv) + if (stsch_err(schid, &schib) != 0 || + (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv) return -1; - console_devno = console_subchannel.schib.pmcw.dev; + console_devno = schib.pmcw.dev; } else if (console_devno != -1) { /* At least the console device number is known. */ for_each_subchannel(cio_test_for_console, NULL); - if (console_irq == -1) - return -1; - } else { - /* unlike in 2.4, we cannot autoprobe here, since - * the channel subsystem is not fully initialized. - * With some luck, the HWC console can take over */ - return -1; } return console_irq; } -struct subchannel * -cio_probe_console(void) +struct subchannel *cio_probe_console(void) { - int sch_no, ret; struct subchannel_id schid; + struct subchannel *sch; + int sch_no, ret; - if (xchg(&console_subchannel_in_use, 1) != 0) - return ERR_PTR(-EBUSY); sch_no = cio_get_console_sch_no(); if (sch_no == -1) { - console_subchannel_in_use = 0; pr_warning("No CCW console was found\n"); return ERR_PTR(-ENODEV); } - memset(&console_subchannel, 0, sizeof(struct subchannel)); init_subchannel_id(&schid); schid.sch_no = sch_no; - ret = cio_validate_subchannel(&console_subchannel, schid); - if (ret) { - console_subchannel_in_use = 0; - return ERR_PTR(-ENODEV); - } + sch = css_alloc_subchannel(schid); + if (IS_ERR(sch)) + return sch; - /* - * enable console I/O-interrupt subclass - */ isc_register(CONSOLE_ISC); - console_subchannel.config.isc = CONSOLE_ISC; - console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel; - ret = cio_commit_config(&console_subchannel); + sch->config.isc = CONSOLE_ISC; + sch->config.intparm = (u32)(addr_t)sch; + ret = cio_commit_config(sch); if (ret) { isc_unregister(CONSOLE_ISC); - console_subchannel_in_use = 0; + put_device(&sch->dev); return ERR_PTR(ret); } - return &console_subchannel; -} - -void -cio_release_console(void) -{ - console_subchannel.config.intparm = 0; - cio_commit_config(&console_subchannel); - isc_unregister(CONSOLE_ISC); - console_subchannel_in_use = 0; + console_sch = sch; + return sch; } -/* Bah... hack to catch console special sausages. */ -int -cio_is_console(struct subchannel_id schid) +int cio_is_console(struct subchannel_id schid) { - if (!console_subchannel_in_use) + if (!console_sch) return 0; - return schid_equal(&schid, &console_subchannel.schid); + return schid_equal(&schid, &console_sch->schid); } -struct subchannel * -cio_get_console_subchannel(void) +struct subchannel *cio_get_console_subchannel(void) { - if (!console_subchannel_in_use) - return NULL; - return &console_subchannel; + return console_sch; } +#endif /* CONFIG_CCW_CONSOLE */ -#endif static int __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) { |