|
@@ -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)
|
|
|
{
|