Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

+283 -552
+5 -3
arch/sparc/kernel/process.c
··· 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 /* ··· 151 150 local_irq_enable(); 152 151 mdelay(8); 153 152 local_irq_disable(); 154 - if (!serial_console && prom_palette) 153 + if (prom_palette) 155 154 prom_palette (1); 156 155 prom_halt(); 157 156 panic("Halt failed!"); ··· 167 166 168 167 p = strchr (reboot_command, '\n'); 169 168 if (p) *p = 0; 170 - if (!serial_console && prom_palette) 169 + if (prom_palette) 171 170 prom_palette (1); 172 171 if (cmd) 173 172 prom_reboot(cmd); ··· 180 179 void machine_power_off(void) 181 180 { 182 181 #ifdef CONFIG_SUN_AUXIO 183 - if (auxio_power_register && (!serial_console || scons_pwroff)) 182 + if (auxio_power_register && 183 + (strcmp(of_console_device->type, "serial") || scons_pwroff)) 184 184 *auxio_power_register |= AUXIO_POWER_OFF; 185 185 #endif 186 186 machine_halt();
+131
arch/sparc/kernel/prom.c
··· 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; ··· 538 409 allnodes->child = build_tree(allnodes, 539 410 prom_getchild(allnodes->node), 540 411 &nextp); 412 + of_console_init(); 413 + 541 414 printk("PROM: Built device tree with %u bytes of memory.\n", 542 415 prom_early_allocated); 543 416 }
+1 -64
arch/sparc/kernel/setup.c
··· 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) { ··· 162 187 process_switch(*commands++); 163 188 continue; 164 189 } 165 - if (!strncmp(commands, "console=", 8)) { 166 - process_console(commands); 167 - } else if (!strncmp(commands, "mem=", 4)) { 190 + if (!strncmp(commands, "mem=", 4)) { 168 191 /* 169 192 * "mem=XXX[kKmM] overrides the PROM-reported 170 193 * memory size. ··· 314 341 smp_setup_cpu_possible_map(); 315 342 } 316 343 317 - static int __init set_preferred_console(void) 318 - { 319 - int idev, odev; 320 - 321 - /* The user has requested a console so this is already set up. */ 322 - if (serial_console >= 0) 323 - return -EBUSY; 324 - 325 - idev = prom_query_input_device(); 326 - odev = prom_query_output_device(); 327 - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { 328 - serial_console = 0; 329 - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { 330 - serial_console = 1; 331 - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { 332 - serial_console = 2; 333 - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) { 334 - prom_printf("MrCoffee ttya\n"); 335 - serial_console = 1; 336 - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) { 337 - serial_console = 0; 338 - prom_printf("MrCoffee keyboard\n"); 339 - } else { 340 - prom_printf("Confusing console (idev %d, odev %d)\n", 341 - idev, odev); 342 - serial_console = 1; 343 - } 344 - 345 - if (serial_console) 346 - return add_preferred_console("ttyS", serial_console - 1, NULL); 347 - 348 - return -ENODEV; 349 - } 350 - console_initcall(set_preferred_console); 351 - 352 344 extern char *sparc_cpu_type; 353 345 extern char *sparc_fpu_type; 354 346 ··· 399 461 prom_cmdline(); 400 462 } 401 463 402 - int serial_console = -1; 403 464 int stop_a_enabled = 1; 404 465 405 466 static int __init topology_init(void)
-116
arch/sparc/prom/console.c
··· 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 - }
+2 -2
arch/sparc/prom/misc.c
··· 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 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
+1 -1
arch/sparc64/kernel/power.c
··· 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
+3 -3
arch/sparc64/kernel/process.c
··· 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 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 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();
+56
arch/sparc64/kernel/prom.c
··· 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; ··· 1712 1658 allnodes->child = build_tree(allnodes, 1713 1659 prom_getchild(allnodes->node), 1714 1660 &nextp); 1661 + of_console_init(); 1662 + 1715 1663 printk("PROM: Built device tree with %u bytes of memory.\n", 1716 1664 prom_early_allocated); 1717 1665
+1 -69
arch/sparc64/kernel/setup.c
··· 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) { ··· 149 176 process_switch(*commands++); 150 177 continue; 151 178 } 152 - if (!strncmp(commands, "console=", 8)) { 153 - process_console(commands); 154 - } else if (!strncmp(commands, "mem=", 4)) { 179 + if (!strncmp(commands, "mem=", 4)) { 155 180 /* 156 181 * "mem=XXX[kKmM]" overrides the PROM-reported 157 182 * memory size. ··· 349 378 paging_init(); 350 379 } 351 380 352 - static int __init set_preferred_console(void) 353 - { 354 - int idev, odev; 355 - 356 - /* The user has requested a console so this is already set up. */ 357 - if (serial_console >= 0) 358 - return -EBUSY; 359 - 360 - idev = prom_query_input_device(); 361 - odev = prom_query_output_device(); 362 - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { 363 - serial_console = 0; 364 - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { 365 - serial_console = 1; 366 - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { 367 - serial_console = 2; 368 - } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { 369 - serial_console = 3; 370 - } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) { 371 - /* sunhv_console_init() doesn't check the serial_console 372 - * value anyways... 373 - */ 374 - serial_console = 4; 375 - return add_preferred_console("ttyHV", 0, NULL); 376 - } else { 377 - prom_printf("Inconsistent console: " 378 - "input %d, output %d\n", 379 - idev, odev); 380 - prom_halt(); 381 - } 382 - 383 - if (serial_console) 384 - return add_preferred_console("ttyS", serial_console - 1, NULL); 385 - 386 - return -ENODEV; 387 - } 388 - console_initcall(set_preferred_console); 389 - 390 381 /* BUFFER is PAGE_SIZE bytes long. */ 391 382 392 383 extern char *sparc_cpu_type; ··· 441 508 prom_cmdline(); 442 509 } 443 510 444 - int serial_console = -1; 445 511 int stop_a_enabled = 1;
-1
arch/sparc64/kernel/sparc64_ksyms.c
··· 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
-85
arch/sparc64/prom/console.c
··· 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 - }
+2 -2
arch/sparc64/prom/misc.c
··· 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 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);
+8
arch/sparc64/prom/tree.c
··· 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 + }
+44 -75
drivers/serial/suncore.c
··· 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 ··· 27 26 28 27 EXPORT_SYMBOL(sunserial_current_minor); 29 28 29 + int sunserial_console_match(struct console *con, struct device_node *dp, 30 + struct uart_driver *drv, int line) 31 + { 32 + int off; 33 + 34 + if (!con || of_console_device != dp) 35 + return 0; 36 + 37 + off = 0; 38 + if (of_console_options && 39 + *of_console_options == 'b') 40 + off = 1; 41 + 42 + if ((line & 1) != off) 43 + return 0; 44 + 45 + con->index = line; 46 + drv->cons = con; 47 + add_preferred_console(con->name, line, NULL); 48 + 49 + return 1; 50 + } 51 + EXPORT_SYMBOL(sunserial_console_match); 52 + 30 53 void 31 54 sunserial_console_termios(struct console *con) 32 55 { 33 - char mode[16], buf[16], *s; 56 + struct device_node *dp; 57 + const char *od, *mode, *s; 34 58 char mode_prop[] = "ttyX-mode"; 35 - char cd_prop[] = "ttyX-ignore-cd"; 36 - char dtr_prop[] = "ttyX-rts-dtr-off"; 37 - char *ssp_console_modes_prop = "ssp-console-modes"; 38 59 int baud, bits, stop, cflag; 39 60 char parity; 40 - int carrier = 0; 41 - int rtsdtr = 1; 42 - int topnd, nd; 43 61 44 - if (!serial_console) 45 - return; 62 + dp = of_find_node_by_path("/options"); 63 + od = of_get_property(dp, "output-device", NULL); 64 + if (!strcmp(od, "rsc")) { 65 + mode = of_get_property(of_console_device, 66 + "ssp-console-modes", NULL); 67 + if (!mode) 68 + mode = "115200,8,n,1,-"; 69 + } else { 70 + char c; 46 71 47 - switch (serial_console) { 48 - case PROMDEV_OTTYA: 49 - mode_prop[3] = 'a'; 50 - cd_prop[3] = 'a'; 51 - dtr_prop[3] = 'a'; 52 - break; 72 + c = 'a'; 73 + if (of_console_options) 74 + c = *of_console_options; 53 75 54 - case PROMDEV_OTTYB: 55 - mode_prop[3] = 'b'; 56 - cd_prop[3] = 'b'; 57 - dtr_prop[3] = 'b'; 58 - break; 76 + mode_prop[3] = c; 59 77 60 - case PROMDEV_ORSC: 61 - 62 - nd = prom_pathtoinode("rsc"); 63 - if (!nd) { 64 - strcpy(mode, "115200,8,n,1,-"); 65 - goto no_options; 66 - } 67 - 68 - if (!prom_node_has_property(nd, ssp_console_modes_prop)) { 69 - strcpy(mode, "115200,8,n,1,-"); 70 - goto no_options; 71 - } 72 - 73 - memset(mode, 0, sizeof(mode)); 74 - prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode)); 75 - goto no_options; 76 - 77 - default: 78 - strcpy(mode, "9600,8,n,1,-"); 79 - goto no_options; 78 + mode = of_get_property(dp, mode_prop, NULL); 79 + if (!mode) 80 + mode = "9600,8,n,1,-"; 80 81 } 81 82 82 - topnd = prom_getchild(prom_root_node); 83 - nd = prom_searchsiblings(topnd, "options"); 84 - if (!nd) { 85 - strcpy(mode, "9600,8,n,1,-"); 86 - goto no_options; 87 - } 88 - 89 - if (!prom_node_has_property(nd, mode_prop)) { 90 - strcpy(mode, "9600,8,n,1,-"); 91 - goto no_options; 92 - } 93 - 94 - memset(mode, 0, sizeof(mode)); 95 - prom_getstring(nd, mode_prop, mode, sizeof(mode)); 96 - 97 - if (prom_node_has_property(nd, cd_prop)) { 98 - memset(buf, 0, sizeof(buf)); 99 - prom_getstring(nd, cd_prop, buf, sizeof(buf)); 100 - if (!strcmp(buf, "false")) 101 - carrier = 1; 102 - 103 - /* XXX: this is unused below. */ 104 - } 105 - 106 - if (prom_node_has_property(nd, dtr_prop)) { 107 - memset(buf, 0, sizeof(buf)); 108 - prom_getstring(nd, dtr_prop, buf, sizeof(buf)); 109 - if (!strcmp(buf, "false")) 110 - rtsdtr = 0; 111 - 112 - /* XXX: this is unused below. */ 113 - } 114 - 115 - no_options: 116 83 cflag = CREAD | HUPCL | CLOCAL; 117 84 118 85 s = mode;
+2
drivers/serial/suncore.h
··· 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) */
+2 -11
drivers/serial/sunhv.c
··· 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; ··· 572 582 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; 573 583 sunserial_current_minor += 1; 574 584 575 - sunhv_reg.cons = SUNHV_CONSOLE(); 585 + sunserial_console_match(&sunhv_console, op->node, 586 + &sunhv_reg, port->line); 576 587 577 588 err = uart_add_one_port(&sunhv_reg, port); 578 589 if (err)
+5 -17
drivers/serial/sunsab.c
··· 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 ··· 1064 1080 return err; 1065 1081 } 1066 1082 1083 + sunserial_console_match(SUNSAB_CONSOLE(), op->node, 1084 + &sunsab_reg, up[0].port.line); 1067 1085 uart_add_one_port(&sunsab_reg, &up[0].port); 1086 + 1087 + sunserial_console_match(SUNSAB_CONSOLE(), op->node, 1088 + &sunsab_reg, up[1].port.line); 1068 1089 uart_add_one_port(&sunsab_reg, &up[1].port); 1069 1090 1070 1091 dev_set_drvdata(&op->dev, &up[0]); ··· 1153 1164 } 1154 1165 1155 1166 sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; 1156 - sunsab_reg.cons = SUNSAB_CONSOLE(); 1157 1167 sunserial_current_minor += num_channels; 1158 1168 } 1159 1169
+4 -19
drivers/serial/sunsu.c
··· 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 ··· 1466 1482 1467 1483 up->port.ops = &sunsu_pops; 1468 1484 1485 + sunserial_console_match(SUNSU_CONSOLE(), dp, 1486 + &sunsu_reg, up->port.line); 1469 1487 err = uart_add_one_port(&sunsu_reg, &up->port); 1470 1488 if (err) 1471 1489 goto out_unmap; ··· 1558 1572 return err; 1559 1573 sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; 1560 1574 sunserial_current_minor += num_uart; 1561 - sunsu_reg.cons = SUNSU_CONSOLE(num_uart); 1562 1575 } 1563 1576 1564 1577 err = of_register_driver(&su_driver, &of_bus_type);
+6 -18
drivers/serial/sunzilog.c
··· 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 ··· 1411 1428 sunzilog_init_hw(&up[1]); 1412 1429 1413 1430 if (!keyboard_mouse) { 1431 + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, 1432 + &sunzilog_reg, up[0].port.line)) 1433 + up->flags |= SUNZILOG_FLAG_IS_CONS; 1414 1434 err = uart_add_one_port(&sunzilog_reg, &up[0].port); 1415 1435 if (err) { 1416 1436 of_iounmap(&op->resource[0], 1417 1437 rp, sizeof(struct zilog_layout)); 1418 1438 return err; 1419 1439 } 1440 + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, 1441 + &sunzilog_reg, up[1].port.line)) 1442 + up->flags |= SUNZILOG_FLAG_IS_CONS; 1420 1443 err = uart_add_one_port(&sunzilog_reg, &up[1].port); 1421 1444 if (err) { 1422 1445 uart_remove_one_port(&sunzilog_reg, &up[0].port); ··· 1520 1531 goto out_free_tables; 1521 1532 1522 1533 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; 1523 - sunzilog_reg.cons = SUNZILOG_CONSOLE(); 1524 1534 1525 1535 sunserial_current_minor += uart_count; 1526 1536 }
-4
drivers/video/aty/atyfb_base.c
··· 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 */
-4
drivers/video/igafb.c
··· 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) {
-26
include/asm-sparc/oplib.h
··· 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
+4
include/asm-sparc/prom.h
··· 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 */
+2 -26
include/asm-sparc64/oplib.h
··· 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 ··· 292 318 extern int prom_inst2pkg(int); 293 319 extern int prom_service_exists(const char *service_name); 294 320 extern void prom_sun4v_guest_soft_state(void); 321 + 322 + extern int prom_ihandle2path(int handle, char *buffer, int bufsize); 295 323 296 324 /* Client interface level routines. */ 297 325 extern void prom_set_trap_table(unsigned long tba);
+4
include/asm-sparc64/prom.h
··· 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 */
-6
include/asm-sparc64/system.h
··· 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