Commit a752ee56 authored by Grant Likely's avatar Grant Likely

tty: Update hypervisor tty drivers to use core stdout parsing code.

The evh_bytechan, hvc_opal and hvc_vio drivers all open code the parsing
of the stdout node in the device tree. This patch simplifies the driver
by removing the duplicated functionality.
Signed-off-by: default avatarGrant Likely <grant.likely@linaro.org>
parent 00388218
...@@ -36,7 +36,7 @@ struct device_node *of_allnodes; ...@@ -36,7 +36,7 @@ struct device_node *of_allnodes;
EXPORT_SYMBOL(of_allnodes); EXPORT_SYMBOL(of_allnodes);
struct device_node *of_chosen; struct device_node *of_chosen;
struct device_node *of_aliases; struct device_node *of_aliases;
static struct device_node *of_stdout; struct device_node *of_stdout;
static struct kset *of_kset; static struct kset *of_kset;
...@@ -2063,9 +2063,12 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) ...@@ -2063,9 +2063,12 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
of_chosen = of_find_node_by_path("/chosen@0"); of_chosen = of_find_node_by_path("/chosen@0");
if (of_chosen) { if (of_chosen) {
/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
const char *name = of_get_property(of_chosen, "stdout-path", NULL); const char *name = of_get_property(of_chosen, "stdout-path", NULL);
if (!name) if (!name)
name = of_get_property(of_chosen, "linux,stdout-path", NULL); name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (IS_ENABLED(CONFIG_PPC) && !name)
name = of_get_property(of_aliases, "stdout", NULL);
if (name) if (name)
of_stdout = of_find_node_by_path(name); of_stdout = of_find_node_by_path(name);
} }
......
...@@ -108,55 +108,23 @@ static void disable_tx_interrupt(struct ehv_bc_data *bc) ...@@ -108,55 +108,23 @@ static void disable_tx_interrupt(struct ehv_bc_data *bc)
* *
* The byte channel to be used for the console is specified via a "stdout" * The byte channel to be used for the console is specified via a "stdout"
* property in the /chosen node. * property in the /chosen node.
*
* For compatible with legacy device trees, we also look for a "stdout" alias.
*/ */
static int find_console_handle(void) static int find_console_handle(void)
{ {
struct device_node *np, *np2; struct device_node *np = of_stdout;
const char *sprop = NULL; const char *sprop = NULL;
const uint32_t *iprop; const uint32_t *iprop;
np = of_find_node_by_path("/chosen");
if (np)
sprop = of_get_property(np, "stdout-path", NULL);
if (!np || !sprop) {
of_node_put(np);
np = of_find_node_by_name(NULL, "aliases");
if (np)
sprop = of_get_property(np, "stdout", NULL);
}
if (!sprop) {
of_node_put(np);
return 0;
}
/* We don't care what the aliased node is actually called. We only /* We don't care what the aliased node is actually called. We only
* care if it's compatible with "epapr,hv-byte-channel", because that * care if it's compatible with "epapr,hv-byte-channel", because that
* indicates that it's a byte channel node. We use a temporary * indicates that it's a byte channel node.
* variable, 'np2', because we can't release 'np' until we're done with
* 'sprop'.
*/ */
np2 = of_find_node_by_path(sprop); if (!np || !of_device_is_compatible(np, "epapr,hv-byte-channel"))
of_node_put(np);
np = np2;
if (!np) {
pr_warning("ehv-bc: stdout node '%s' does not exist\n", sprop);
return 0;
}
/* Is it a byte channel? */
if (!of_device_is_compatible(np, "epapr,hv-byte-channel")) {
of_node_put(np);
return 0; return 0;
}
stdout_irq = irq_of_parse_and_map(np, 0); stdout_irq = irq_of_parse_and_map(np, 0);
if (stdout_irq == NO_IRQ) { if (stdout_irq == NO_IRQ) {
pr_err("ehv-bc: no 'interrupts' property in %s node\n", sprop); pr_err("ehv-bc: no 'interrupts' property in %s node\n", np->full_name);
of_node_put(np);
return 0; return 0;
} }
...@@ -167,12 +135,9 @@ static int find_console_handle(void) ...@@ -167,12 +135,9 @@ static int find_console_handle(void)
if (!iprop) { if (!iprop) {
pr_err("ehv-bc: no 'hv-handle' property in %s node\n", pr_err("ehv-bc: no 'hv-handle' property in %s node\n",
np->name); np->name);
of_node_put(np);
return 0; return 0;
} }
stdout_bc = be32_to_cpu(*iprop); stdout_bc = be32_to_cpu(*iprop);
of_node_put(np);
return 1; return 1;
} }
......
...@@ -342,22 +342,13 @@ static void udbg_init_opal_common(void) ...@@ -342,22 +342,13 @@ static void udbg_init_opal_common(void)
void __init hvc_opal_init_early(void) void __init hvc_opal_init_early(void)
{ {
struct device_node *stdout_node = NULL; struct device_node *stdout_node = of_node_get(of_stdout);
const __be32 *termno; const __be32 *termno;
const char *name = NULL;
const struct hv_ops *ops; const struct hv_ops *ops;
u32 index; u32 index;
/* find the boot console from /chosen/stdout */ /* If the console wasn't in /chosen, try /ibm,opal */
if (of_chosen) if (!stdout_node) {
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (name) {
stdout_node = of_find_node_by_path(name);
if (!stdout_node) {
pr_err("hvc_opal: Failed to locate default console!\n");
return;
}
} else {
struct device_node *opal, *np; struct device_node *opal, *np;
/* Current OPAL takeover doesn't provide the stdout /* Current OPAL takeover doesn't provide the stdout
......
...@@ -404,42 +404,35 @@ module_exit(hvc_vio_exit); ...@@ -404,42 +404,35 @@ module_exit(hvc_vio_exit);
void __init hvc_vio_init_early(void) void __init hvc_vio_init_early(void)
{ {
struct device_node *stdout_node;
const __be32 *termno; const __be32 *termno;
const char *name; const char *name;
const struct hv_ops *ops; const struct hv_ops *ops;
/* find the boot console from /chosen/stdout */ /* find the boot console from /chosen/stdout */
if (!of_chosen) if (!of_stdout)
return; return;
name = of_get_property(of_chosen, "linux,stdout-path", NULL); name = of_get_property(of_stdout, "name", NULL);
if (name == NULL)
return;
stdout_node = of_find_node_by_path(name);
if (!stdout_node)
return;
name = of_get_property(stdout_node, "name", NULL);
if (!name) { if (!name) {
printk(KERN_WARNING "stdout node missing 'name' property!\n"); printk(KERN_WARNING "stdout node missing 'name' property!\n");
goto out; return;
} }
/* Check if it's a virtual terminal */ /* Check if it's a virtual terminal */
if (strncmp(name, "vty", 3) != 0) if (strncmp(name, "vty", 3) != 0)
goto out; return;
termno = of_get_property(stdout_node, "reg", NULL); termno = of_get_property(of_stdout, "reg", NULL);
if (termno == NULL) if (termno == NULL)
goto out; return;
hvterm_priv0.termno = of_read_number(termno, 1); hvterm_priv0.termno = of_read_number(termno, 1);
spin_lock_init(&hvterm_priv0.buf_lock); spin_lock_init(&hvterm_priv0.buf_lock);
hvterm_privs[0] = &hvterm_priv0; hvterm_privs[0] = &hvterm_priv0;
/* Check the protocol */ /* Check the protocol */
if (of_device_is_compatible(stdout_node, "hvterm1")) { if (of_device_is_compatible(of_stdout, "hvterm1")) {
hvterm_priv0.proto = HV_PROTOCOL_RAW; hvterm_priv0.proto = HV_PROTOCOL_RAW;
ops = &hvterm_raw_ops; ops = &hvterm_raw_ops;
} }
else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) { else if (of_device_is_compatible(of_stdout, "hvterm-protocol")) {
hvterm_priv0.proto = HV_PROTOCOL_HVSI; hvterm_priv0.proto = HV_PROTOCOL_HVSI;
ops = &hvterm_hvsi_ops; ops = &hvterm_hvsi_ops;
hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars, hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
...@@ -447,7 +440,7 @@ void __init hvc_vio_init_early(void) ...@@ -447,7 +440,7 @@ void __init hvc_vio_init_early(void)
/* HVSI, perform the handshake now */ /* HVSI, perform the handshake now */
hvsilib_establish(&hvterm_priv0.hvsi); hvsilib_establish(&hvterm_priv0.hvsi);
} else } else
goto out; return;
udbg_putc = udbg_hvc_putc; udbg_putc = udbg_hvc_putc;
udbg_getc = udbg_hvc_getc; udbg_getc = udbg_hvc_getc;
udbg_getc_poll = udbg_hvc_getc_poll; udbg_getc_poll = udbg_hvc_getc_poll;
...@@ -456,14 +449,12 @@ void __init hvc_vio_init_early(void) ...@@ -456,14 +449,12 @@ void __init hvc_vio_init_early(void)
* backend for HVSI, only do udbg * backend for HVSI, only do udbg
*/ */
if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
goto out; return;
#endif #endif
/* Check whether the user has requested a different console. */ /* Check whether the user has requested a different console. */
if (!strstr(cmd_line, "console=")) if (!strstr(cmd_line, "console="))
add_preferred_console("hvc", 0, NULL); add_preferred_console("hvc", 0, NULL);
hvc_instantiate(0, 0, ops); hvc_instantiate(0, 0, ops);
out:
of_node_put(stdout_node);
} }
/* call this from early_init() for a working debug console on /* call this from early_init() for a working debug console on
......
...@@ -113,6 +113,7 @@ static inline void of_node_put(struct device_node *node) { } ...@@ -113,6 +113,7 @@ static inline void of_node_put(struct device_node *node) { }
extern struct device_node *of_allnodes; extern struct device_node *of_allnodes;
extern struct device_node *of_chosen; extern struct device_node *of_chosen;
extern struct device_node *of_aliases; extern struct device_node *of_aliases;
extern struct device_node *of_stdout;
extern raw_spinlock_t devtree_lock; extern raw_spinlock_t devtree_lock;
static inline bool of_have_populated_dt(void) static inline bool of_have_populated_dt(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment