Commit c73fcc846c91f53fd2c67fd9c6c04888a9e5892e

Authored by David S. Miller
1 parent ede13d81b4

[SPARC]: Fix serial console device detection.

The current scheme works on static interpretation of text names, which
is wrong.

The output-device setting, for example, must be resolved via an alias
or similar to a full path name to the console device.

Paths also contain an optional set of 'options', which starts with a
colon at the end of the path.  The option area is used to specify
which of two serial ports ('a' or 'b') the path refers to when a
device node drives multiple ports.  'a' is assumed if the option
specification is missing.

This was caught by the UltraSPARC-T1 simulator.  The 'output-device'
property was set to 'ttya' and we didn't pick upon the fact that this
is an OBP alias set to '/virtual-devices/console'.  Instead we saw it
as the first serial console device, instead of the hypervisor console.

The infrastructure is now there to take advantage of this to resolve
the console correctly even in multi-head situations in fbcon too.

Thanks to Greg Onufer for the bug report.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 26 changed files with 285 additions and 554 deletions Side-by-side Diff

arch/sparc/kernel/process.c
... ... @@ -39,6 +39,7 @@
39 39 #include <asm/processor.h>
40 40 #include <asm/psr.h>
41 41 #include <asm/elf.h>
  42 +#include <asm/prom.h>
42 43 #include <asm/unistd.h>
43 44  
44 45 /*
... ... @@ -150,7 +151,7 @@
150 151 local_irq_enable();
151 152 mdelay(8);
152 153 local_irq_disable();
153   - if (!serial_console && prom_palette)
  154 + if (prom_palette)
154 155 prom_palette (1);
155 156 prom_halt();
156 157 panic("Halt failed!");
... ... @@ -166,7 +167,7 @@
166 167  
167 168 p = strchr (reboot_command, '\n');
168 169 if (p) *p = 0;
169   - if (!serial_console && prom_palette)
  170 + if (prom_palette)
170 171 prom_palette (1);
171 172 if (cmd)
172 173 prom_reboot(cmd);
... ... @@ -179,7 +180,8 @@
179 180 void machine_power_off(void)
180 181 {
181 182 #ifdef CONFIG_SUN_AUXIO
182   - if (auxio_power_register && (!serial_console || scons_pwroff))
  183 + if (auxio_power_register &&
  184 + (strcmp(of_console_device->type, "serial") || scons_pwroff))
183 185 *auxio_power_register |= AUXIO_POWER_OFF;
184 186 #endif
185 187 machine_halt();
arch/sparc/kernel/prom.c
... ... @@ -397,6 +397,135 @@
397 397 return dp;
398 398 }
399 399  
  400 +struct device_node *of_console_device;
  401 +EXPORT_SYMBOL(of_console_device);
  402 +
  403 +char *of_console_path;
  404 +EXPORT_SYMBOL(of_console_path);
  405 +
  406 +char *of_console_options;
  407 +EXPORT_SYMBOL(of_console_options);
  408 +
  409 +extern void restore_current(void);
  410 +
  411 +static void __init of_console_init(void)
  412 +{
  413 + char *msg = "OF stdout device is: %s\n";
  414 + struct device_node *dp;
  415 + unsigned long flags;
  416 + const char *type;
  417 + phandle node;
  418 + int skip, fd;
  419 +
  420 + of_console_path = prom_early_alloc(256);
  421 +
  422 + switch (prom_vers) {
  423 + case PROM_V0:
  424 + case PROM_SUN4:
  425 + skip = 0;
  426 + switch (*romvec->pv_stdout) {
  427 + case PROMDEV_SCREEN:
  428 + type = "display";
  429 + break;
  430 +
  431 + case PROMDEV_TTYB:
  432 + skip = 1;
  433 + /* FALLTHRU */
  434 +
  435 + case PROMDEV_TTYA:
  436 + type = "serial";
  437 + break;
  438 +
  439 + default:
  440 + prom_printf("Invalid PROM_V0 stdout value %u\n",
  441 + *romvec->pv_stdout);
  442 + prom_halt();
  443 + }
  444 +
  445 + for_each_node_by_type(dp, type) {
  446 + if (!skip--)
  447 + break;
  448 + }
  449 + if (!dp) {
  450 + prom_printf("Cannot find PROM_V0 console node.\n");
  451 + prom_halt();
  452 + }
  453 + of_console_device = dp;
  454 +
  455 + strcpy(of_console_path, dp->full_name);
  456 + if (!strcmp(type, "serial")) {
  457 + strcat(of_console_path,
  458 + (skip ? ":b" : ":a"));
  459 + }
  460 + break;
  461 +
  462 + default:
  463 + case PROM_V2:
  464 + case PROM_V3:
  465 + fd = *romvec->pv_v2bootargs.fd_stdout;
  466 +
  467 + spin_lock_irqsave(&prom_lock, flags);
  468 + node = (*romvec->pv_v2devops.v2_inst2pkg)(fd);
  469 + restore_current();
  470 + spin_unlock_irqrestore(&prom_lock, flags);
  471 +
  472 + if (!node) {
  473 + prom_printf("Cannot resolve stdout node from "
  474 + "instance %08x.\n", fd);
  475 + prom_halt();
  476 + }
  477 + dp = of_find_node_by_phandle(node);
  478 + type = of_get_property(dp, "device_type", NULL);
  479 +
  480 + if (!type) {
  481 + prom_printf("Console stdout lacks "
  482 + "device_type property.\n");
  483 + prom_halt();
  484 + }
  485 +
  486 + if (strcmp(type, "display") && strcmp(type, "serial")) {
  487 + prom_printf("Console device_type is neither display "
  488 + "nor serial.\n");
  489 + prom_halt();
  490 + }
  491 +
  492 + of_console_device = dp;
  493 +
  494 + if (prom_vers == PROM_V2) {
  495 + strcpy(of_console_path, dp->full_name);
  496 + switch (*romvec->pv_stdout) {
  497 + case PROMDEV_TTYA:
  498 + strcat(of_console_path, ":a");
  499 + break;
  500 + case PROMDEV_TTYB:
  501 + strcat(of_console_path, ":b");
  502 + break;
  503 + }
  504 + } else {
  505 + const char *path;
  506 +
  507 + dp = of_find_node_by_path("/");
  508 + path = of_get_property(dp, "stdout-path", NULL);
  509 + if (!path) {
  510 + prom_printf("No stdout-path in root node.\n");
  511 + prom_halt();
  512 + }
  513 + strcpy(of_console_path, path);
  514 + }
  515 + break;
  516 + }
  517 +
  518 + of_console_options = strrchr(of_console_path, ':');
  519 + if (of_console_options) {
  520 + of_console_options++;
  521 + if (*of_console_options == '\0')
  522 + of_console_options = NULL;
  523 + }
  524 +
  525 + prom_printf(msg, of_console_path);
  526 + printk(msg, of_console_path);
  527 +}
  528 +
400 529 void __init prom_build_devicetree(void)
401 530 {
402 531 struct device_node **nextp;
... ... @@ -409,6 +538,8 @@
409 538 allnodes->child = build_tree(allnodes,
410 539 prom_getchild(allnodes->node),
411 540 &nextp);
  541 + of_console_init();
  542 +
412 543 printk("PROM: Built device tree with %u bytes of memory.\n",
413 544 prom_early_allocated);
414 545 }
arch/sparc/kernel/setup.c
... ... @@ -146,31 +146,6 @@
146 146 }
147 147 }
148 148  
149   -static void __init process_console(char *commands)
150   -{
151   - serial_console = 0;
152   - commands += 8;
153   - /* Linux-style serial */
154   - if (!strncmp(commands, "ttyS", 4))
155   - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1;
156   - else if (!strncmp(commands, "tty", 3)) {
157   - char c = *(commands + 3);
158   - /* Solaris-style serial */
159   - if (c == 'a' || c == 'b')
160   - serial_console = c - 'a' + 1;
161   - /* else Linux-style fbcon, not serial */
162   - }
163   -#if defined(CONFIG_PROM_CONSOLE)
164   - if (!strncmp(commands, "prom", 4)) {
165   - char *p;
166   -
167   - for (p = commands - 8; *p && *p != ' '; p++)
168   - *p = ' ';
169   - conswitchp = &prom_con;
170   - }
171   -#endif
172   -}
173   -
174 149 static void __init boot_flags_init(char *commands)
175 150 {
176 151 while (*commands) {
... ... @@ -187,9 +162,7 @@
187 162 process_switch(*commands++);
188 163 continue;
189 164 }
190   - if (!strncmp(commands, "console=", 8)) {
191   - process_console(commands);
192   - } else if (!strncmp(commands, "mem=", 4)) {
  165 + if (!strncmp(commands, "mem=", 4)) {
193 166 /*
194 167 * "mem=XXX[kKmM] overrides the PROM-reported
195 168 * memory size.
... ... @@ -341,41 +314,6 @@
341 314 smp_setup_cpu_possible_map();
342 315 }
343 316  
344   -static int __init set_preferred_console(void)
345   -{
346   - int idev, odev;
347   -
348   - /* The user has requested a console so this is already set up. */
349   - if (serial_console >= 0)
350   - return -EBUSY;
351   -
352   - idev = prom_query_input_device();
353   - odev = prom_query_output_device();
354   - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
355   - serial_console = 0;
356   - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
357   - serial_console = 1;
358   - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
359   - serial_console = 2;
360   - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
361   - prom_printf("MrCoffee ttya\n");
362   - serial_console = 1;
363   - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
364   - serial_console = 0;
365   - prom_printf("MrCoffee keyboard\n");
366   - } else {
367   - prom_printf("Confusing console (idev %d, odev %d)\n",
368   - idev, odev);
369   - serial_console = 1;
370   - }
371   -
372   - if (serial_console)
373   - return add_preferred_console("ttyS", serial_console - 1, NULL);
374   -
375   - return -ENODEV;
376   -}
377   -console_initcall(set_preferred_console);
378   -
379 317 extern char *sparc_cpu_type;
380 318 extern char *sparc_fpu_type;
381 319  
... ... @@ -461,7 +399,6 @@
461 399 prom_cmdline();
462 400 }
463 401  
464   -int serial_console = -1;
465 402 int stop_a_enabled = 1;
466 403  
467 404 static int __init topology_init(void)
arch/sparc/prom/console.c
... ... @@ -102,120 +102,4 @@
102 102 while(prom_nbputchar(c) == -1) ;
103 103 return;
104 104 }
105   -
106   -/* Query for input device type */
107   -enum prom_input_device
108   -prom_query_input_device(void)
109   -{
110   - unsigned long flags;
111   - int st_p;
112   - char propb[64];
113   - char *p;
114   - int propl;
115   -
116   - switch(prom_vers) {
117   - case PROM_V0:
118   - case PROM_V2:
119   - case PROM_SUN4:
120   - default:
121   - switch(*romvec->pv_stdin) {
122   - case PROMDEV_KBD: return PROMDEV_IKBD;
123   - case PROMDEV_TTYA: return PROMDEV_ITTYA;
124   - case PROMDEV_TTYB: return PROMDEV_ITTYB;
125   - default:
126   - return PROMDEV_I_UNK;
127   - };
128   - case PROM_V3:
129   - spin_lock_irqsave(&prom_lock, flags);
130   - st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
131   - restore_current();
132   - spin_unlock_irqrestore(&prom_lock, flags);
133   - if(prom_node_has_property(st_p, "keyboard"))
134   - return PROMDEV_IKBD;
135   - if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
136   - if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
137   - return PROMDEV_IKBD;
138   - }
139   - if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
140   - if(strncmp(propb, "serial", sizeof("serial")))
141   - return PROMDEV_I_UNK;
142   - }
143   - propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
144   - if(propl > 2) {
145   - p = propb;
146   - while(*p) p++; p -= 2;
147   - if(p[0] == ':') {
148   - if(p[1] == 'a')
149   - return PROMDEV_ITTYA;
150   - else if(p[1] == 'b')
151   - return PROMDEV_ITTYB;
152   - }
153   - }
154   - return PROMDEV_I_UNK;
155   - }
156   -}
157   -
158   -/* Query for output device type */
159   -
160   -enum prom_output_device
161   -prom_query_output_device(void)
162   -{
163   - unsigned long flags;
164   - int st_p;
165   - char propb[64];
166   - char *p;
167   - int propl;
168   -
169   - switch(prom_vers) {
170   - case PROM_V0:
171   - case PROM_SUN4:
172   - switch(*romvec->pv_stdin) {
173   - case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
174   - case PROMDEV_TTYA: return PROMDEV_OTTYA;
175   - case PROMDEV_TTYB: return PROMDEV_OTTYB;
176   - };
177   - break;
178   - case PROM_V2:
179   - case PROM_V3:
180   - spin_lock_irqsave(&prom_lock, flags);
181   - st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
182   - restore_current();
183   - spin_unlock_irqrestore(&prom_lock, flags);
184   - propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
185   - if (propl == sizeof("display") &&
186   - strncmp("display", propb, sizeof("display")) == 0)
187   - {
188   - return PROMDEV_OSCREEN;
189   - }
190   - if(prom_vers == PROM_V3) {
191   - if(propl >= 0 &&
192   - strncmp("serial", propb, sizeof("serial")) != 0)
193   - return PROMDEV_O_UNK;
194   - propl = prom_getproperty(prom_root_node, "stdout-path",
195   - propb, sizeof(propb));
196   - if(propl == CON_SIZE_JMC &&
197   - strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
198   - return PROMDEV_OTTYA;
199   - if(propl > 2) {
200   - p = propb;
201   - while(*p) p++; p-= 2;
202   - if(p[0]==':') {
203   - if(p[1] == 'a')
204   - return PROMDEV_OTTYA;
205   - else if(p[1] == 'b')
206   - return PROMDEV_OTTYB;
207   - }
208   - }
209   - } else {
210   - switch(*romvec->pv_stdin) {
211   - case PROMDEV_TTYA: return PROMDEV_OTTYA;
212   - case PROMDEV_TTYB: return PROMDEV_OTTYB;
213   - };
214   - }
215   - break;
216   - default:
217   - ;
218   - };
219   - return PROMDEV_O_UNK;
220   -}
arch/sparc/prom/misc.c
... ... @@ -58,7 +58,7 @@
58 58 extern void install_linux_ticker(void);
59 59 unsigned long flags;
60 60  
61   - if(!serial_console && prom_palette)
  61 + if (prom_palette)
62 62 prom_palette (1);
63 63 spin_lock_irqsave(&prom_lock, flags);
64 64 install_obp_ticker();
... ... @@ -69,7 +69,7 @@
69 69 #ifdef CONFIG_SUN_AUXIO
70 70 set_auxio(AUXIO_LED, 0);
71 71 #endif
72   - if(!serial_console && prom_palette)
  72 + if (prom_palette)
73 73 prom_palette (0);
74 74 }
75 75  
arch/sparc64/kernel/power.c
... ... @@ -46,7 +46,7 @@
46 46 void machine_power_off(void)
47 47 {
48 48 sstate_poweroff();
49   - if (!serial_console || scons_pwroff) {
  49 + if (strcmp(of_console_device->type, "serial") || scons_pwroff) {
50 50 if (power_reg) {
51 51 /* Both register bits seem to have the
52 52 * same effect, so until I figure out
arch/sparc64/kernel/process.c
... ... @@ -119,7 +119,7 @@
119 119 void machine_halt(void)
120 120 {
121 121 sstate_halt();
122   - if (!serial_console && prom_palette)
  122 + if (prom_palette)
123 123 prom_palette (1);
124 124 if (prom_keyboard)
125 125 prom_keyboard();
... ... @@ -130,7 +130,7 @@
130 130 void machine_alt_power_off(void)
131 131 {
132 132 sstate_poweroff();
133   - if (!serial_console && prom_palette)
  133 + if (prom_palette)
134 134 prom_palette(1);
135 135 if (prom_keyboard)
136 136 prom_keyboard();
... ... @@ -145,7 +145,7 @@
145 145 sstate_reboot();
146 146 p = strchr (reboot_command, '\n');
147 147 if (p) *p = 0;
148   - if (!serial_console && prom_palette)
  148 + if (prom_palette)
149 149 prom_palette (1);
150 150 if (prom_keyboard)
151 151 prom_keyboard();
arch/sparc64/kernel/prom.c
... ... @@ -1646,6 +1646,60 @@
1646 1646 smp_fill_in_sib_core_maps();
1647 1647 }
1648 1648  
  1649 +struct device_node *of_console_device;
  1650 +EXPORT_SYMBOL(of_console_device);
  1651 +
  1652 +char *of_console_path;
  1653 +EXPORT_SYMBOL(of_console_path);
  1654 +
  1655 +char *of_console_options;
  1656 +EXPORT_SYMBOL(of_console_options);
  1657 +
  1658 +static void __init of_console_init(void)
  1659 +{
  1660 + char *msg = "OF stdout device is: %s\n";
  1661 + struct device_node *dp;
  1662 + const char *type;
  1663 + phandle node;
  1664 +
  1665 + of_console_path = prom_early_alloc(256);
  1666 + if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) {
  1667 + prom_printf("Cannot obtain path of stdout.\n");
  1668 + prom_halt();
  1669 + }
  1670 + of_console_options = strrchr(of_console_path, ':');
  1671 + if (of_console_options) {
  1672 + of_console_options++;
  1673 + if (*of_console_options == '\0')
  1674 + of_console_options = NULL;
  1675 + }
  1676 +
  1677 + node = prom_inst2pkg(prom_stdout);
  1678 + if (!node) {
  1679 + prom_printf("Cannot resolve stdout node from "
  1680 + "instance %08x.\n", prom_stdout);
  1681 + prom_halt();
  1682 + }
  1683 +
  1684 + dp = of_find_node_by_phandle(node);
  1685 + type = of_get_property(dp, "device_type", NULL);
  1686 + if (!type) {
  1687 + prom_printf("Console stdout lacks device_type property.\n");
  1688 + prom_halt();
  1689 + }
  1690 +
  1691 + if (strcmp(type, "display") && strcmp(type, "serial")) {
  1692 + prom_printf("Console device_type is neither display "
  1693 + "nor serial.\n");
  1694 + prom_halt();
  1695 + }
  1696 +
  1697 + of_console_device = dp;
  1698 +
  1699 + prom_printf(msg, of_console_path);
  1700 + printk(msg, of_console_path);
  1701 +}
  1702 +
1649 1703 void __init prom_build_devicetree(void)
1650 1704 {
1651 1705 struct device_node **nextp;
... ... @@ -1658,6 +1712,8 @@
1658 1712 allnodes->child = build_tree(allnodes,
1659 1713 prom_getchild(allnodes->node),
1660 1714 &nextp);
  1715 + of_console_init();
  1716 +
1661 1717 printk("PROM: Built device tree with %u bytes of memory.\n",
1662 1718 prom_early_allocated);
1663 1719  
arch/sparc64/kernel/setup.c
... ... @@ -133,33 +133,6 @@
133 133 }
134 134 }
135 135  
136   -static void __init process_console(char *commands)
137   -{
138   - serial_console = 0;
139   - commands += 8;
140   - /* Linux-style serial */
141   - if (!strncmp(commands, "ttyS", 4))
142   - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1;
143   - else if (!strncmp(commands, "tty", 3)) {
144   - char c = *(commands + 3);
145   - /* Solaris-style serial */
146   - if (c == 'a' || c == 'b') {
147   - serial_console = c - 'a' + 1;
148   - prom_printf ("Using /dev/tty%c as console.\n", c);
149   - }
150   - /* else Linux-style fbcon, not serial */
151   - }
152   -#if defined(CONFIG_PROM_CONSOLE)
153   - if (!strncmp(commands, "prom", 4)) {
154   - char *p;
155   -
156   - for (p = commands - 8; *p && *p != ' '; p++)
157   - *p = ' ';
158   - conswitchp = &prom_con;
159   - }
160   -#endif
161   -}
162   -
163 136 static void __init boot_flags_init(char *commands)
164 137 {
165 138 while (*commands) {
... ... @@ -176,9 +149,7 @@
176 149 process_switch(*commands++);
177 150 continue;
178 151 }
179   - if (!strncmp(commands, "console=", 8)) {
180   - process_console(commands);
181   - } else if (!strncmp(commands, "mem=", 4)) {
  152 + if (!strncmp(commands, "mem=", 4)) {
182 153 /*
183 154 * "mem=XXX[kKmM]" overrides the PROM-reported
184 155 * memory size.
... ... @@ -378,44 +349,6 @@
378 349 paging_init();
379 350 }
380 351  
381   -static int __init set_preferred_console(void)
382   -{
383   - int idev, odev;
384   -
385   - /* The user has requested a console so this is already set up. */
386   - if (serial_console >= 0)
387   - return -EBUSY;
388   -
389   - idev = prom_query_input_device();
390   - odev = prom_query_output_device();
391   - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
392   - serial_console = 0;
393   - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
394   - serial_console = 1;
395   - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
396   - serial_console = 2;
397   - } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
398   - serial_console = 3;
399   - } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) {
400   - /* sunhv_console_init() doesn't check the serial_console
401   - * value anyways...
402   - */
403   - serial_console = 4;
404   - return add_preferred_console("ttyHV", 0, NULL);
405   - } else {
406   - prom_printf("Inconsistent console: "
407   - "input %d, output %d\n",
408   - idev, odev);
409   - prom_halt();
410   - }
411   -
412   - if (serial_console)
413   - return add_preferred_console("ttyS", serial_console - 1, NULL);
414   -
415   - return -ENODEV;
416   -}
417   -console_initcall(set_preferred_console);
418   -
419 352 /* BUFFER is PAGE_SIZE bytes long. */
420 353  
421 354 extern char *sparc_cpu_type;
... ... @@ -508,6 +441,5 @@
508 441 prom_cmdline();
509 442 }
510 443  
511   -int serial_console = -1;
512 444 int stop_a_enabled = 1;
arch/sparc64/kernel/sparc64_ksyms.c
... ... @@ -330,7 +330,6 @@
330 330  
331 331 /* for input/keybdev */
332 332 EXPORT_SYMBOL(sun_do_break);
333   -EXPORT_SYMBOL(serial_console);
334 333 EXPORT_SYMBOL(stop_a_enabled);
335 334  
336 335 #ifdef CONFIG_DEBUG_BUGVERBOSE
arch/sparc64/prom/console.c
... ... @@ -73,89 +73,4 @@
73 73 P1275_INOUT(3,1),
74 74 prom_stdout, s, P1275_SIZE(len));
75 75 }
76   -
77   -/* Query for input device type */
78   -enum prom_input_device
79   -prom_query_input_device(void)
80   -{
81   - int st_p;
82   - char propb[64];
83   -
84   - st_p = prom_inst2pkg(prom_stdin);
85   - if(prom_node_has_property(st_p, "keyboard"))
86   - return PROMDEV_IKBD;
87   - prom_getproperty(st_p, "device_type", propb, sizeof(propb));
88   - if(strncmp(propb, "serial", 6))
89   - return PROMDEV_I_UNK;
90   - /* FIXME: Is there any better way how to find out? */
91   - memset(propb, 0, sizeof(propb));
92   - st_p = prom_finddevice ("/options");
93   - prom_getproperty(st_p, "input-device", propb, sizeof(propb));
94   -
95   - /*
96   - * If we get here with propb == 'keyboard', we are on ttya, as
97   - * the PROM defaulted to this due to 'no input device'.
98   - */
99   - if (!strncmp(propb, "keyboard", 8))
100   - return PROMDEV_ITTYA;
101   -
102   - if (!strncmp (propb, "rsc", 3))
103   - return PROMDEV_IRSC;
104   -
105   - if (!strncmp (propb, "virtual-console", 3))
106   - return PROMDEV_IVCONS;
107   -
108   - if (strncmp (propb, "tty", 3) || !propb[3])
109   - return PROMDEV_I_UNK;
110   -
111   - switch (propb[3]) {
112   - case 'a': return PROMDEV_ITTYA;
113   - case 'b': return PROMDEV_ITTYB;
114   - default: return PROMDEV_I_UNK;
115   - }
116   -}
117   -
118   -/* Query for output device type */
119   -
120   -enum prom_output_device
121   -prom_query_output_device(void)
122   -{
123   - int st_p;
124   - char propb[64];
125   - int propl;
126   -
127   - st_p = prom_inst2pkg(prom_stdout);
128   - propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
129   - if (propl >= 0 && propl == sizeof("display") &&
130   - strncmp("display", propb, sizeof("display")) == 0)
131   - return PROMDEV_OSCREEN;
132   - if(strncmp("serial", propb, 6))
133   - return PROMDEV_O_UNK;
134   - /* FIXME: Is there any better way how to find out? */
135   - memset(propb, 0, sizeof(propb));
136   - st_p = prom_finddevice ("/options");
137   - prom_getproperty(st_p, "output-device", propb, sizeof(propb));
138   -
139   - /*
140   - * If we get here with propb == 'screen', we are on ttya, as
141   - * the PROM defaulted to this due to 'no input device'.
142   - */
143   - if (!strncmp(propb, "screen", 6))
144   - return PROMDEV_OTTYA;
145   -
146   - if (!strncmp (propb, "rsc", 3))
147   - return PROMDEV_ORSC;
148   -
149   - if (!strncmp (propb, "virtual-console", 3))
150   - return PROMDEV_OVCONS;
151   -
152   - if (strncmp (propb, "tty", 3) || !propb[3])
153   - return PROMDEV_O_UNK;
154   -
155   - switch (propb[3]) {
156   - case 'a': return PROMDEV_OTTYA;
157   - case 'b': return PROMDEV_OTTYB;
158   - default: return PROMDEV_O_UNK;
159   - }
160   -}
arch/sparc64/prom/misc.c
... ... @@ -72,7 +72,7 @@
72 72  
73 73 local_irq_save(flags);
74 74  
75   - if (!serial_console && prom_palette)
  75 + if (prom_palette)
76 76 prom_palette(1);
77 77  
78 78 #ifdef CONFIG_SMP
... ... @@ -85,7 +85,7 @@
85 85 smp_release();
86 86 #endif
87 87  
88   - if (!serial_console && prom_palette)
  88 + if (prom_palette)
89 89 prom_palette(0);
90 90  
91 91 local_irq_restore(flags);
arch/sparc64/prom/tree.c
... ... @@ -304,4 +304,12 @@
304 304 if (node == -1) return 0;
305 305 return node;
306 306 }
  307 +
  308 +int prom_ihandle2path(int handle, char *buffer, int bufsize)
  309 +{
  310 + return p1275_cmd("instance-to-path",
  311 + P1275_ARG(1,P1275_ARG_OUT_BUF)|
  312 + P1275_INOUT(3, 1),
  313 + handle, buffer, P1275_SIZE(bufsize));
  314 +}
drivers/serial/suncore.c
... ... @@ -16,9 +16,10 @@
16 16 #include <linux/tty.h>
17 17 #include <linux/errno.h>
18 18 #include <linux/string.h>
  19 +#include <linux/serial_core.h>
19 20 #include <linux/init.h>
20 21  
21   -#include <asm/oplib.h>
  22 +#include <asm/prom.h>
22 23  
23 24 #include "suncore.h"
24 25  
25 26  
26 27  
27 28  
28 29  
29 30  
30 31  
31 32  
32 33  
33 34  
34 35  
35 36  
36 37  
... ... @@ -26,92 +27,60 @@
26 27  
27 28 EXPORT_SYMBOL(sunserial_current_minor);
28 29  
29   -void
30   -sunserial_console_termios(struct console *con)
  30 +int sunserial_console_match(struct console *con, struct device_node *dp,
  31 + struct uart_driver *drv, int line)
31 32 {
32   - char mode[16], buf[16], *s;
33   - char mode_prop[] = "ttyX-mode";
34   - char cd_prop[] = "ttyX-ignore-cd";
35   - char dtr_prop[] = "ttyX-rts-dtr-off";
36   - char *ssp_console_modes_prop = "ssp-console-modes";
37   - int baud, bits, stop, cflag;
38   - char parity;
39   - int carrier = 0;
40   - int rtsdtr = 1;
41   - int topnd, nd;
  33 + int off;
42 34  
43   - if (!serial_console)
44   - return;
  35 + if (!con || of_console_device != dp)
  36 + return 0;
45 37  
46   - switch (serial_console) {
47   - case PROMDEV_OTTYA:
48   - mode_prop[3] = 'a';
49   - cd_prop[3] = 'a';
50   - dtr_prop[3] = 'a';
51   - break;
  38 + off = 0;
  39 + if (of_console_options &&
  40 + *of_console_options == 'b')
  41 + off = 1;
52 42  
53   - case PROMDEV_OTTYB:
54   - mode_prop[3] = 'b';
55   - cd_prop[3] = 'b';
56   - dtr_prop[3] = 'b';
57   - break;
  43 + if ((line & 1) != off)
  44 + return 0;
58 45  
59   - case PROMDEV_ORSC:
  46 + con->index = line;
  47 + drv->cons = con;
  48 + add_preferred_console(con->name, line, NULL);
60 49  
61   - nd = prom_pathtoinode("rsc");
62   - if (!nd) {
63   - strcpy(mode, "115200,8,n,1,-");
64   - goto no_options;
65   - }
  50 + return 1;
  51 +}
  52 +EXPORT_SYMBOL(sunserial_console_match);
66 53  
67   - if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
68   - strcpy(mode, "115200,8,n,1,-");
69   - goto no_options;
70   - }
  54 +void
  55 +sunserial_console_termios(struct console *con)
  56 +{
  57 + struct device_node *dp;
  58 + const char *od, *mode, *s;
  59 + char mode_prop[] = "ttyX-mode";
  60 + int baud, bits, stop, cflag;
  61 + char parity;
71 62  
72   - memset(mode, 0, sizeof(mode));
73   - prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
74   - goto no_options;
  63 + dp = of_find_node_by_path("/options");
  64 + od = of_get_property(dp, "output-device", NULL);
  65 + if (!strcmp(od, "rsc")) {
  66 + mode = of_get_property(of_console_device,
  67 + "ssp-console-modes", NULL);
  68 + if (!mode)
  69 + mode = "115200,8,n,1,-";
  70 + } else {
  71 + char c;
75 72  
76   - default:
77   - strcpy(mode, "9600,8,n,1,-");
78   - goto no_options;
79   - }
  73 + c = 'a';
  74 + if (of_console_options)
  75 + c = *of_console_options;
80 76  
81   - topnd = prom_getchild(prom_root_node);
82   - nd = prom_searchsiblings(topnd, "options");
83   - if (!nd) {
84   - strcpy(mode, "9600,8,n,1,-");
85   - goto no_options;
86   - }
  77 + mode_prop[3] = c;
87 78  
88   - if (!prom_node_has_property(nd, mode_prop)) {
89   - strcpy(mode, "9600,8,n,1,-");
90   - goto no_options;
  79 + mode = of_get_property(dp, mode_prop, NULL);
  80 + if (!mode)
  81 + mode = "9600,8,n,1,-";
91 82 }
92 83  
93   - memset(mode, 0, sizeof(mode));
94   - prom_getstring(nd, mode_prop, mode, sizeof(mode));
95   -
96   - if (prom_node_has_property(nd, cd_prop)) {
97   - memset(buf, 0, sizeof(buf));
98   - prom_getstring(nd, cd_prop, buf, sizeof(buf));
99   - if (!strcmp(buf, "false"))
100   - carrier = 1;
101   -
102   - /* XXX: this is unused below. */
103   - }
104   -
105   - if (prom_node_has_property(nd, dtr_prop)) {
106   - memset(buf, 0, sizeof(buf));
107   - prom_getstring(nd, dtr_prop, buf, sizeof(buf));
108   - if (!strcmp(buf, "false"))
109   - rtsdtr = 0;
110   -
111   - /* XXX: this is unused below. */
112   - }
113   -
114   -no_options:
115 84 cflag = CREAD | HUPCL | CLOCAL;
116 85  
117 86 s = mode;
drivers/serial/suncore.h
... ... @@ -24,6 +24,8 @@
24 24  
25 25 extern int sunserial_current_minor;
26 26  
  27 +extern int sunserial_console_match(struct console *, struct device_node *,
  28 + struct uart_driver *, int);
27 29 extern void sunserial_console_termios(struct console *);
28 30  
29 31 #endif /* !(_SERIAL_SUN_H) */
drivers/serial/sunhv.c
... ... @@ -520,16 +520,6 @@
520 520 .data = &sunhv_reg,
521 521 };
522 522  
523   -static inline struct console *SUNHV_CONSOLE(void)
524   -{
525   - if (con_is_present())
526   - return NULL;
527   -
528   - sunhv_console.index = 0;
529   -
530   - return &sunhv_console;
531   -}
532   -
533 523 static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
534 524 {
535 525 struct uart_port *port;
... ... @@ -582,7 +572,8 @@
582 572 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
583 573 sunserial_current_minor += 1;
584 574  
585   - sunhv_reg.cons = SUNHV_CONSOLE();
  575 + sunserial_console_match(&sunhv_console, op->node,
  576 + &sunhv_reg, port->line);
586 577  
587 578 err = uart_add_one_port(&sunhv_reg, port);
588 579 if (err)
drivers/serial/sunsab.c
... ... @@ -968,22 +968,6 @@
968 968  
969 969 static inline struct console *SUNSAB_CONSOLE(void)
970 970 {
971   - int i;
972   -
973   - if (con_is_present())
974   - return NULL;
975   -
976   - for (i = 0; i < num_channels; i++) {
977   - int this_minor = sunsab_reg.minor + i;
978   -
979   - if ((this_minor - 64) == (serial_console - 1))
980   - break;
981   - }
982   - if (i == num_channels)
983   - return NULL;
984   -
985   - sunsab_console.index = i;
986   -
987 971 return &sunsab_console;
988 972 }
989 973 #else
990 974  
... ... @@ -1080,7 +1064,12 @@
1080 1064 return err;
1081 1065 }
1082 1066  
  1067 + sunserial_console_match(SUNSAB_CONSOLE(), op->node,
  1068 + &sunsab_reg, up[0].port.line);
1083 1069 uart_add_one_port(&sunsab_reg, &up[0].port);
  1070 +
  1071 + sunserial_console_match(SUNSAB_CONSOLE(), op->node,
  1072 + &sunsab_reg, up[1].port.line);
1084 1073 uart_add_one_port(&sunsab_reg, &up[1].port);
1085 1074  
1086 1075 dev_set_drvdata(&op->dev, &up[0]);
... ... @@ -1164,7 +1153,6 @@
1164 1153 }
1165 1154  
1166 1155 sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
1167   - sunsab_reg.cons = SUNSAB_CONSOLE();
1168 1156 sunserial_current_minor += num_channels;
1169 1157 }
1170 1158  
drivers/serial/sunsu.c
... ... @@ -1371,28 +1371,12 @@
1371 1371 * Register console.
1372 1372 */
1373 1373  
1374   -static inline struct console *SUNSU_CONSOLE(int num_uart)
  1374 +static inline struct console *SUNSU_CONSOLE(void)
1375 1375 {
1376   - int i;
1377   -
1378   - if (con_is_present())
1379   - return NULL;
1380   -
1381   - for (i = 0; i < num_uart; i++) {
1382   - int this_minor = sunsu_reg.minor + i;
1383   -
1384   - if ((this_minor - 64) == (serial_console - 1))
1385   - break;
1386   - }
1387   - if (i == num_uart)
1388   - return NULL;
1389   -
1390   - sunsu_console.index = i;
1391   -
1392 1376 return &sunsu_console;
1393 1377 }
1394 1378 #else
1395   -#define SUNSU_CONSOLE(num_uart) (NULL)
  1379 +#define SUNSU_CONSOLE() (NULL)
1396 1380 #define sunsu_serial_console_init() do { } while (0)
1397 1381 #endif
1398 1382  
... ... @@ -1482,6 +1466,8 @@
1482 1466  
1483 1467 up->port.ops = &sunsu_pops;
1484 1468  
  1469 + sunserial_console_match(SUNSU_CONSOLE(), dp,
  1470 + &sunsu_reg, up->port.line);
1485 1471 err = uart_add_one_port(&sunsu_reg, &up->port);
1486 1472 if (err)
1487 1473 goto out_unmap;
... ... @@ -1572,7 +1558,6 @@
1572 1558 return err;
1573 1559 sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
1574 1560 sunserial_current_minor += num_uart;
1575   - sunsu_reg.cons = SUNSU_CONSOLE(num_uart);
1576 1561 }
1577 1562  
1578 1563 err = of_register_driver(&su_driver, &of_bus_type);
drivers/serial/sunzilog.c
... ... @@ -1226,23 +1226,6 @@
1226 1226  
1227 1227 static inline struct console *SUNZILOG_CONSOLE(void)
1228 1228 {
1229   - int i;
1230   -
1231   - if (con_is_present())
1232   - return NULL;
1233   -
1234   - for (i = 0; i < NUM_CHANNELS; i++) {
1235   - int this_minor = sunzilog_reg.minor + i;
1236   -
1237   - if ((this_minor - 64) == (serial_console - 1))
1238   - break;
1239   - }
1240   - if (i == NUM_CHANNELS)
1241   - return NULL;
1242   -
1243   - sunzilog_console_ops.index = i;
1244   - sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
1245   -
1246 1229 return &sunzilog_console_ops;
1247 1230 }
1248 1231  
1249 1232  
... ... @@ -1428,12 +1411,18 @@
1428 1411 sunzilog_init_hw(&up[1]);
1429 1412  
1430 1413 if (!keyboard_mouse) {
  1414 + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
  1415 + &sunzilog_reg, up[0].port.line))
  1416 + up->flags |= SUNZILOG_FLAG_IS_CONS;
1431 1417 err = uart_add_one_port(&sunzilog_reg, &up[0].port);
1432 1418 if (err) {
1433 1419 of_iounmap(&op->resource[0],
1434 1420 rp, sizeof(struct zilog_layout));
1435 1421 return err;
1436 1422 }
  1423 + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
  1424 + &sunzilog_reg, up[1].port.line))
  1425 + up->flags |= SUNZILOG_FLAG_IS_CONS;
1437 1426 err = uart_add_one_port(&sunzilog_reg, &up[1].port);
1438 1427 if (err) {
1439 1428 uart_remove_one_port(&sunzilog_reg, &up[0].port);
... ... @@ -1531,7 +1520,6 @@
1531 1520 goto out_free_tables;
1532 1521  
1533 1522 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
1534   - sunzilog_reg.cons = SUNZILOG_CONSOLE();
1535 1523  
1536 1524 sunserial_current_minor += uart_count;
1537 1525 }
drivers/video/aty/atyfb_base.c
... ... @@ -2913,10 +2913,6 @@
2913 2913 int node, len, i, j, ret;
2914 2914 u32 mem, chip_id;
2915 2915  
2916   - /* Do not attach when we have a serial console. */
2917   - if (!con_is_present())
2918   - return -ENXIO;
2919   -
2920 2916 /*
2921 2917 * Map memory-mapped registers.
2922 2918 */
drivers/video/igafb.c
... ... @@ -379,10 +379,6 @@
379 379 if (fb_get_options("igafb", NULL))
380 380 return -ENODEV;
381 381  
382   - /* Do not attach when we have a serial console. */
383   - if (!con_is_present())
384   - return -ENXIO;
385   -
386 382 pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
387 383 PCI_DEVICE_ID_INTERG_1682, 0);
388 384 if (pdev == NULL) {
include/asm-sparc/oplib.h
... ... @@ -158,32 +158,6 @@
158 158 extern void prom_printf(char *fmt, ...);
159 159 extern void prom_write(const char *buf, unsigned int len);
160 160  
161   -/* Query for input device type */
162   -
163   -enum prom_input_device {
164   - PROMDEV_IKBD, /* input from keyboard */
165   - PROMDEV_ITTYA, /* input from ttya */
166   - PROMDEV_ITTYB, /* input from ttyb */
167   - PROMDEV_IRSC, /* input from rsc */
168   - PROMDEV_IVCONS, /* input from virtual-console */
169   - PROMDEV_I_UNK,
170   -};
171   -
172   -extern enum prom_input_device prom_query_input_device(void);
173   -
174   -/* Query for output device type */
175   -
176   -enum prom_output_device {
177   - PROMDEV_OSCREEN, /* to screen */
178   - PROMDEV_OTTYA, /* to ttya */
179   - PROMDEV_OTTYB, /* to ttyb */
180   - PROMDEV_ORSC, /* to rsc */
181   - PROMDEV_OVCONS, /* to virtual-console */
182   - PROMDEV_O_UNK,
183   -};
184   -
185   -extern enum prom_output_device prom_query_output_device(void);
186   -
187 161 /* Multiprocessor operations... */
188 162  
189 163 /* Start the CPU with the given device tree node, context table, and context
include/asm-sparc/prom.h
... ... @@ -85,6 +85,10 @@
85 85 */
86 86 #include <linux/of.h>
87 87  
  88 +extern struct device_node *of_console_device;
  89 +extern char *of_console_path;
  90 +extern char *of_console_options;
  91 +
88 92 #endif /* __KERNEL__ */
89 93 #endif /* _SPARC_PROM_H */
include/asm-sparc64/oplib.h
... ... @@ -140,32 +140,6 @@
140 140 extern void prom_printf(const char *fmt, ...);
141 141 extern void prom_write(const char *buf, unsigned int len);
142 142  
143   -/* Query for input device type */
144   -
145   -enum prom_input_device {
146   - PROMDEV_IKBD, /* input from keyboard */
147   - PROMDEV_ITTYA, /* input from ttya */
148   - PROMDEV_ITTYB, /* input from ttyb */
149   - PROMDEV_IRSC, /* input from rsc */
150   - PROMDEV_IVCONS, /* input from virtual-console */
151   - PROMDEV_I_UNK,
152   -};
153   -
154   -extern enum prom_input_device prom_query_input_device(void);
155   -
156   -/* Query for output device type */
157   -
158   -enum prom_output_device {
159   - PROMDEV_OSCREEN, /* to screen */
160   - PROMDEV_OTTYA, /* to ttya */
161   - PROMDEV_OTTYB, /* to ttyb */
162   - PROMDEV_ORSC, /* to rsc */
163   - PROMDEV_OVCONS, /* to virtual-console */
164   - PROMDEV_O_UNK,
165   -};
166   -
167   -extern enum prom_output_device prom_query_output_device(void);
168   -
169 143 /* Multiprocessor operations... */
170 144 #ifdef CONFIG_SMP
171 145 /* Start the CPU with the given device tree node at the passed program
... ... @@ -318,6 +292,8 @@
318 292 extern int prom_inst2pkg(int);
319 293 extern int prom_service_exists(const char *service_name);
320 294 extern void prom_sun4v_guest_soft_state(void);
  295 +
  296 +extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
321 297  
322 298 /* Client interface level routines. */
323 299 extern void prom_set_trap_table(unsigned long tba);
include/asm-sparc64/prom.h
... ... @@ -94,6 +94,10 @@
94 94 */
95 95 #include <linux/of.h>
96 96  
  97 +extern struct device_node *of_console_device;
  98 +extern char *of_console_path;
  99 +extern char *of_console_options;
  100 +
97 101 #endif /* __KERNEL__ */
98 102 #endif /* _SPARC64_PROM_H */
include/asm-sparc64/system.h
... ... @@ -115,13 +115,7 @@
115 115 #ifndef __ASSEMBLY__
116 116  
117 117 extern void sun_do_break(void);
118   -extern int serial_console;
119 118 extern int stop_a_enabled;
120   -
121   -static __inline__ int con_is_present(void)
122   -{
123   - return serial_console ? 0 : 1;
124   -}
125 119  
126 120 extern void synchronize_user_stack(void);
127 121