[PATCH] hvc - register all available consoles (was: Re: [PATCH]powerpc/lpar - defer prefered console setup)

From: Bastian Blank
Date: Wed Jul 30 2008 - 03:34:52 EST


On Wed, Jul 30, 2008 at 08:29:19AM +0200, Bastian Blank wrote:
> Okay, so hvc_console is the culprit. It don't register a preferred
> console if it knows it is not the first in the list.

The patch registers all available hvc consoles. It adds one "struct
console" for all possible hvc consoles.

Signed-off-by: Bastian Blank <waldi@xxxxxxxxxx>

diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 44160d5..143a4b2 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -137,15 +137,36 @@ static struct hvc_struct *hvc_get_by_index(int index)
}


+static void hvc_console_print(struct console *co, const char *b,
+ unsigned count);
+static struct tty_driver *hvc_console_device(struct console *c, int *index);
+static int __init hvc_console_setup(struct console *co, char *options);
+
/*
* Initial console vtermnos for console API usage prior to full console
* initialization. Any vty adapter outside this range will not have usable
* console interfaces but can still be used as a tty device. This has to be
* static because kmalloc will not work during early console init.
*/
-static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
-static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
- {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
+struct hvc_console
+{
+ uint32_t vtermno;
+ struct hv_ops *ops;
+ struct console console;
+};
+static struct hvc_console consoles[MAX_NR_HVC_CONSOLES] = {
+ [0 ... MAX_NR_HVC_CONSOLES - 1] = {
+ .vtermno = -1,
+ .console = {
+ .name = "hvc",
+ .write = hvc_console_print,
+ .device = hvc_console_device,
+ .setup = hvc_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ },
+ }
+};

/*
* Console APIs, NOT TTY. These APIs are available immediately when
@@ -164,7 +185,7 @@ static void hvc_console_print(struct console *co, const char *b,
return;

/* This console adapter was removed so it is not usable. */
- if (vtermnos[index] < 0)
+ if (consoles[index].vtermno < 0)
return;

while (count > 0 || i > 0) {
@@ -178,7 +199,7 @@ static void hvc_console_print(struct console *co, const char *b,
--count;
}
} else {
- r = cons_ops[index]->put_chars(vtermnos[index], c, i);
+ r = consoles[index].ops->put_chars(consoles[index].vtermno, c, i);
if (r < 0) {
/* throw away chars on error */
i = 0;
@@ -193,7 +214,7 @@ static void hvc_console_print(struct console *co, const char *b,

static struct tty_driver *hvc_console_device(struct console *c, int *index)
{
- if (vtermnos[c->index] == -1)
+ if (consoles[c->index].vtermno == -1)
return NULL;

*index = c->index;
@@ -205,43 +226,12 @@ static int __init hvc_console_setup(struct console *co, char *options)
if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
return -ENODEV;

- if (vtermnos[co->index] == -1)
+ if (consoles[co->index].vtermno == -1)
return -ENODEV;

return 0;
}

-static struct console hvc_con_driver = {
- .name = "hvc",
- .write = hvc_console_print,
- .device = hvc_console_device,
- .setup = hvc_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/*
- * Early console initialization. Precedes driver initialization.
- *
- * (1) we are first, and the user specified another driver
- * -- index will remain -1
- * (2) we are first and the user specified no driver
- * -- index will be set to 0, then we will fail setup.
- * (3) we are first and the user specified our driver
- * -- index will be set to user specified driver, and we will fail
- * (4) we are after driver, and this initcall will register us
- * -- if the user didn't specify a driver then the console will match
- *
- * Note that for cases 2 and 3, we will match later when the io driver
- * calls hvc_instantiate() and call register again.
- */
-static int __init hvc_console_init(void)
-{
- register_console(&hvc_con_driver);
- return 0;
-}
-console_initcall(hvc_console_init);
-
/* callback when the kboject ref count reaches zero. */
static void destroy_hvc_struct(struct kref *kref)
{
@@ -267,12 +257,13 @@ static void destroy_hvc_struct(struct kref *kref)
*/
int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
{
+ struct hvc_console *hc;
struct hvc_struct *hp;

if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
return -1;

- if (vtermnos[index] != -1)
+ if (consoles[index].vtermno != -1)
return -1;

/* make sure no no tty has been registered in this index */
@@ -282,19 +273,17 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
return -1;
}

- vtermnos[index] = vtermno;
- cons_ops[index] = ops;
+ hc = &consoles[index];
+
+ hc->vtermno = vtermno;
+ hc->ops = ops;
+ hc->console.index = index;

/* reserve all indices up to and including this index */
if (last_hvc < index)
last_hvc = index;

- /* if this index is what the user requested, then register
- * now (setup won't fail at this point). It's ok to just
- * call register again if previously .setup failed.
- */
- if (index == hvc_con_driver.index)
- register_console(&hvc_con_driver);
+ register_console(&hc->console);

return 0;
}
@@ -637,7 +626,7 @@ static int hvc_poll(struct hvc_struct *hp)
}
for (i = 0; i < n; ++i) {
#ifdef CONFIG_MAGIC_SYSRQ
- if (hp->index == hvc_con_driver.index) {
+ if (consoles[hp->index].console.flags & CON_CONSDEV) {
/* Handle the SysRq Hack */
/* XXX should support a sequence */
if (buf[i] == '\x0f') { /* ^O */
@@ -775,8 +764,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
* see if this vterm id matches one registered for console.
*/
for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
- if (vtermnos[i] == hp->vtermno &&
- cons_ops[i] == hp->ops)
+ if (consoles[i].vtermno == hp->vtermno &&
+ consoles[i].ops == hp->ops)
break;

/* no matching slot, just use a counter */
@@ -800,7 +789,7 @@ int __devexit hvc_remove(struct hvc_struct *hp)
tty = hp->tty;

if (hp->index < MAX_NR_HVC_CONSOLES)
- vtermnos[hp->index] = -1;
+ consoles[hp->index].vtermno = -1;

/* Don't whack hp->irq because tty_hangup() will need to free the irq. */

@@ -881,13 +870,16 @@ out:
*/
static void __exit hvc_exit(void)
{
+ int i;
+
if (hvc_driver) {
kthread_stop(hvc_task);

tty_unregister_driver(hvc_driver);
/* return tty_struct instances allocated in hvc_init(). */
put_tty_driver(hvc_driver);
- unregister_console(&hvc_con_driver);
+ for (i = 0; i < MAX_NR_HVC_CONSOLES; i++)
+ unregister_console(&consoles->console);
}
}
module_exit(hvc_exit);

--
There is an order of things in this universe.
-- Apollo, "Who Mourns for Adonais?" stardate 3468.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/