diff options
46 files changed, 926 insertions, 833 deletions
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 7bb86b9cdaa3..ac352eb6dff3 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c | |||
| @@ -148,6 +148,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d | |||
| 148 | { | 148 | { |
| 149 | const struct linux_prom_registers *regs; | 149 | const struct linux_prom_registers *regs; |
| 150 | struct linux_ebus_child *child; | 150 | struct linux_ebus_child *child; |
| 151 | struct dev_archdata *sd; | ||
| 151 | const int *irqs; | 152 | const int *irqs; |
| 152 | int i, n, len; | 153 | int i, n, len; |
| 153 | unsigned long baseaddr; | 154 | unsigned long baseaddr; |
| @@ -234,6 +235,10 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d | |||
| 234 | } | 235 | } |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 238 | sd = &dev->ofdev.dev.archdata; | ||
| 239 | sd->prom_node = dp; | ||
| 240 | sd->op = &dev->ofdev; | ||
| 241 | |||
| 237 | dev->ofdev.node = dp; | 242 | dev->ofdev.node = dp; |
| 238 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | 243 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; |
| 239 | dev->ofdev.dev.bus = &ebus_bus_type; | 244 | dev->ofdev.dev.bus = &ebus_bus_type; |
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 7176040caba0..36383f73d685 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c | |||
| @@ -420,11 +420,16 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
| 420 | { | 420 | { |
| 421 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); | 421 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); |
| 422 | const struct linux_prom_irqs *intr; | 422 | const struct linux_prom_irqs *intr; |
| 423 | struct dev_archdata *sd; | ||
| 423 | int len, i; | 424 | int len, i; |
| 424 | 425 | ||
| 425 | if (!op) | 426 | if (!op) |
| 426 | return NULL; | 427 | return NULL; |
| 427 | 428 | ||
| 429 | sd = &op->dev.archdata; | ||
| 430 | sd->prom_node = dp; | ||
| 431 | sd->op = op; | ||
| 432 | |||
| 428 | op->node = dp; | 433 | op->node = dp; |
| 429 | 434 | ||
| 430 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", | 435 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", |
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 8c37f8f5adb7..33f7a3ddb104 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
| 40 | #include <asm/psr.h> | 40 | #include <asm/psr.h> |
| 41 | #include <asm/elf.h> | 41 | #include <asm/elf.h> |
| 42 | #include <asm/prom.h> | ||
| 42 | #include <asm/unistd.h> | 43 | #include <asm/unistd.h> |
| 43 | 44 | ||
| 44 | /* | 45 | /* |
| @@ -150,7 +151,7 @@ void machine_halt(void) | |||
| 150 | local_irq_enable(); | 151 | local_irq_enable(); |
| 151 | mdelay(8); | 152 | mdelay(8); |
| 152 | local_irq_disable(); | 153 | local_irq_disable(); |
| 153 | if (!serial_console && prom_palette) | 154 | if (prom_palette) |
| 154 | prom_palette (1); | 155 | prom_palette (1); |
| 155 | prom_halt(); | 156 | prom_halt(); |
| 156 | panic("Halt failed!"); | 157 | panic("Halt failed!"); |
| @@ -166,7 +167,7 @@ void machine_restart(char * cmd) | |||
| 166 | 167 | ||
| 167 | p = strchr (reboot_command, '\n'); | 168 | p = strchr (reboot_command, '\n'); |
| 168 | if (p) *p = 0; | 169 | if (p) *p = 0; |
| 169 | if (!serial_console && prom_palette) | 170 | if (prom_palette) |
| 170 | prom_palette (1); | 171 | prom_palette (1); |
| 171 | if (cmd) | 172 | if (cmd) |
| 172 | prom_reboot(cmd); | 173 | prom_reboot(cmd); |
| @@ -179,7 +180,8 @@ void machine_restart(char * cmd) | |||
| 179 | void machine_power_off(void) | 180 | void machine_power_off(void) |
| 180 | { | 181 | { |
| 181 | #ifdef CONFIG_SUN_AUXIO | 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 | *auxio_power_register |= AUXIO_POWER_OFF; | 185 | *auxio_power_register |= AUXIO_POWER_OFF; |
| 184 | #endif | 186 | #endif |
| 185 | machine_halt(); | 187 | machine_halt(); |
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 012f98346bcd..e3a537650db1 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c | |||
| @@ -397,6 +397,135 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl | |||
| 397 | return dp; | 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 | void __init prom_build_devicetree(void) | 529 | void __init prom_build_devicetree(void) |
| 401 | { | 530 | { |
| 402 | struct device_node **nextp; | 531 | struct device_node **nextp; |
| @@ -409,6 +538,8 @@ void __init prom_build_devicetree(void) | |||
| 409 | allnodes->child = build_tree(allnodes, | 538 | allnodes->child = build_tree(allnodes, |
| 410 | prom_getchild(allnodes->node), | 539 | prom_getchild(allnodes->node), |
| 411 | &nextp); | 540 | &nextp); |
| 541 | of_console_init(); | ||
| 542 | |||
| 412 | printk("PROM: Built device tree with %u bytes of memory.\n", | 543 | printk("PROM: Built device tree with %u bytes of memory.\n", |
| 413 | prom_early_allocated); | 544 | prom_early_allocated); |
| 414 | } | 545 | } |
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 64c0ed98820a..f8228383895a 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c | |||
| @@ -146,31 +146,6 @@ static void __init process_switch(char 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 | static void __init boot_flags_init(char *commands) | 149 | static void __init boot_flags_init(char *commands) |
| 175 | { | 150 | { |
| 176 | while (*commands) { | 151 | while (*commands) { |
| @@ -187,9 +162,7 @@ static void __init boot_flags_init(char *commands) | |||
| 187 | process_switch(*commands++); | 162 | process_switch(*commands++); |
| 188 | continue; | 163 | continue; |
| 189 | } | 164 | } |
| 190 | if (!strncmp(commands, "console=", 8)) { | 165 | if (!strncmp(commands, "mem=", 4)) { |
| 191 | process_console(commands); | ||
| 192 | } else if (!strncmp(commands, "mem=", 4)) { | ||
| 193 | /* | 166 | /* |
| 194 | * "mem=XXX[kKmM] overrides the PROM-reported | 167 | * "mem=XXX[kKmM] overrides the PROM-reported |
| 195 | * memory size. | 168 | * memory size. |
| @@ -341,41 +314,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 341 | smp_setup_cpu_possible_map(); | 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 | extern char *sparc_cpu_type; | 317 | extern char *sparc_cpu_type; |
| 380 | extern char *sparc_fpu_type; | 318 | extern char *sparc_fpu_type; |
| 381 | 319 | ||
| @@ -461,7 +399,6 @@ void sun_do_break(void) | |||
| 461 | prom_cmdline(); | 399 | prom_cmdline(); |
| 462 | } | 400 | } |
| 463 | 401 | ||
| 464 | int serial_console = -1; | ||
| 465 | int stop_a_enabled = 1; | 402 | int stop_a_enabled = 1; |
| 466 | 403 | ||
| 467 | static int __init topology_init(void) | 404 | static int __init topology_init(void) |
diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index 4e6e41d3291d..8d1cfb0d5068 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c | |||
| @@ -102,119 +102,3 @@ prom_putchar(char c) | |||
| 102 | while(prom_nbputchar(c) == -1) ; | 102 | while(prom_nbputchar(c) == -1) ; |
| 103 | return; | 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 | } | ||
diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c index 1942c7c05cb1..37cff5f54704 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc.c | |||
| @@ -58,7 +58,7 @@ prom_cmdline(void) | |||
| 58 | extern void install_linux_ticker(void); | 58 | extern void install_linux_ticker(void); |
| 59 | unsigned long flags; | 59 | unsigned long flags; |
| 60 | 60 | ||
| 61 | if(!serial_console && prom_palette) | 61 | if (prom_palette) |
| 62 | prom_palette (1); | 62 | prom_palette (1); |
| 63 | spin_lock_irqsave(&prom_lock, flags); | 63 | spin_lock_irqsave(&prom_lock, flags); |
| 64 | install_obp_ticker(); | 64 | install_obp_ticker(); |
| @@ -69,7 +69,7 @@ prom_cmdline(void) | |||
| 69 | #ifdef CONFIG_SUN_AUXIO | 69 | #ifdef CONFIG_SUN_AUXIO |
| 70 | set_auxio(AUXIO_LED, 0); | 70 | set_auxio(AUXIO_LED, 0); |
| 71 | #endif | 71 | #endif |
| 72 | if(!serial_console && prom_palette) | 72 | if (prom_palette) |
| 73 | prom_palette (0); | 73 | prom_palette (0); |
| 74 | } | 74 | } |
| 75 | 75 | ||
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index 1a2062ecb0bc..9f472a79d37e 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c | |||
| @@ -124,10 +124,11 @@ struct ds_data_nack { | |||
| 124 | __u64 result; | 124 | __u64 result; |
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | struct ds_info; | ||
| 127 | struct ds_cap_state { | 128 | struct ds_cap_state { |
| 128 | __u64 handle; | 129 | __u64 handle; |
| 129 | 130 | ||
| 130 | void (*data)(struct ldc_channel *lp, | 131 | void (*data)(struct ds_info *dp, |
| 131 | struct ds_cap_state *cp, | 132 | struct ds_cap_state *cp, |
| 132 | void *buf, int len); | 133 | void *buf, int len); |
| 133 | 134 | ||
| @@ -139,27 +140,27 @@ struct ds_cap_state { | |||
| 139 | #define CAP_STATE_REGISTERED 0x02 | 140 | #define CAP_STATE_REGISTERED 0x02 |
| 140 | }; | 141 | }; |
| 141 | 142 | ||
| 142 | static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp, | 143 | static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp, |
| 143 | void *buf, int len); | 144 | void *buf, int len); |
| 144 | static void domain_shutdown_data(struct ldc_channel *lp, | 145 | static void domain_shutdown_data(struct ds_info *dp, |
| 145 | struct ds_cap_state *cp, | 146 | struct ds_cap_state *cp, |
| 146 | void *buf, int len); | 147 | void *buf, int len); |
| 147 | static void domain_panic_data(struct ldc_channel *lp, | 148 | static void domain_panic_data(struct ds_info *dp, |
| 148 | struct ds_cap_state *cp, | 149 | struct ds_cap_state *cp, |
| 149 | void *buf, int len); | 150 | void *buf, int len); |
| 150 | #ifdef CONFIG_HOTPLUG_CPU | 151 | #ifdef CONFIG_HOTPLUG_CPU |
| 151 | static void dr_cpu_data(struct ldc_channel *lp, | 152 | static void dr_cpu_data(struct ds_info *dp, |
| 152 | struct ds_cap_state *cp, | 153 | struct ds_cap_state *cp, |
| 153 | void *buf, int len); | 154 | void *buf, int len); |
| 154 | #endif | 155 | #endif |
| 155 | static void ds_pri_data(struct ldc_channel *lp, | 156 | static void ds_pri_data(struct ds_info *dp, |
| 156 | struct ds_cap_state *cp, | 157 | struct ds_cap_state *cp, |
| 157 | void *buf, int len); | 158 | void *buf, int len); |
| 158 | static void ds_var_data(struct ldc_channel *lp, | 159 | static void ds_var_data(struct ds_info *dp, |
| 159 | struct ds_cap_state *cp, | 160 | struct ds_cap_state *cp, |
| 160 | void *buf, int len); | 161 | void *buf, int len); |
| 161 | 162 | ||
| 162 | struct ds_cap_state ds_states[] = { | 163 | struct ds_cap_state ds_states_template[] = { |
| 163 | { | 164 | { |
| 164 | .service_id = "md-update", | 165 | .service_id = "md-update", |
| 165 | .data = md_update_data, | 166 | .data = md_update_data, |
| @@ -200,30 +201,38 @@ struct ds_info { | |||
| 200 | #define DS_HS_START 0x01 | 201 | #define DS_HS_START 0x01 |
| 201 | #define DS_HS_DONE 0x02 | 202 | #define DS_HS_DONE 0x02 |
| 202 | 203 | ||
| 204 | u64 id; | ||
| 205 | |||
| 203 | void *rcv_buf; | 206 | void *rcv_buf; |
| 204 | int rcv_buf_len; | 207 | int rcv_buf_len; |
| 208 | |||
| 209 | struct ds_cap_state *ds_states; | ||
| 210 | int num_ds_states; | ||
| 211 | |||
| 212 | struct ds_info *next; | ||
| 205 | }; | 213 | }; |
| 206 | 214 | ||
| 207 | static struct ds_info *ds_info; | 215 | static struct ds_info *ds_info_list; |
| 208 | 216 | ||
| 209 | static struct ds_cap_state *find_cap(u64 handle) | 217 | static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle) |
| 210 | { | 218 | { |
| 211 | unsigned int index = handle >> 32; | 219 | unsigned int index = handle >> 32; |
| 212 | 220 | ||
| 213 | if (index >= ARRAY_SIZE(ds_states)) | 221 | if (index >= dp->num_ds_states) |
| 214 | return NULL; | 222 | return NULL; |
| 215 | return &ds_states[index]; | 223 | return &dp->ds_states[index]; |
| 216 | } | 224 | } |
| 217 | 225 | ||
| 218 | static struct ds_cap_state *find_cap_by_string(const char *name) | 226 | static struct ds_cap_state *find_cap_by_string(struct ds_info *dp, |
| 227 | const char *name) | ||
| 219 | { | 228 | { |
| 220 | int i; | 229 | int i; |
| 221 | 230 | ||
| 222 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 231 | for (i = 0; i < dp->num_ds_states; i++) { |
| 223 | if (strcmp(ds_states[i].service_id, name)) | 232 | if (strcmp(dp->ds_states[i].service_id, name)) |
| 224 | continue; | 233 | continue; |
| 225 | 234 | ||
| 226 | return &ds_states[i]; | 235 | return &dp->ds_states[i]; |
| 227 | } | 236 | } |
| 228 | return NULL; | 237 | return NULL; |
| 229 | } | 238 | } |
| @@ -264,10 +273,11 @@ struct ds_md_update_res { | |||
| 264 | __u32 result; | 273 | __u32 result; |
| 265 | }; | 274 | }; |
| 266 | 275 | ||
| 267 | static void md_update_data(struct ldc_channel *lp, | 276 | static void md_update_data(struct ds_info *dp, |
| 268 | struct ds_cap_state *dp, | 277 | struct ds_cap_state *cp, |
| 269 | void *buf, int len) | 278 | void *buf, int len) |
| 270 | { | 279 | { |
| 280 | struct ldc_channel *lp = dp->lp; | ||
| 271 | struct ds_data *dpkt = buf; | 281 | struct ds_data *dpkt = buf; |
| 272 | struct ds_md_update_req *rp; | 282 | struct ds_md_update_req *rp; |
| 273 | struct { | 283 | struct { |
| @@ -277,14 +287,14 @@ static void md_update_data(struct ldc_channel *lp, | |||
| 277 | 287 | ||
| 278 | rp = (struct ds_md_update_req *) (dpkt + 1); | 288 | rp = (struct ds_md_update_req *) (dpkt + 1); |
| 279 | 289 | ||
| 280 | printk(KERN_INFO PFX "Machine description update.\n"); | 290 | printk(KERN_INFO "ds-%lu: Machine description update.\n", dp->id); |
| 281 | 291 | ||
| 282 | mdesc_update(); | 292 | mdesc_update(); |
| 283 | 293 | ||
| 284 | memset(&pkt, 0, sizeof(pkt)); | 294 | memset(&pkt, 0, sizeof(pkt)); |
| 285 | pkt.data.tag.type = DS_DATA; | 295 | pkt.data.tag.type = DS_DATA; |
| 286 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 296 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
| 287 | pkt.data.handle = dp->handle; | 297 | pkt.data.handle = cp->handle; |
| 288 | pkt.res.req_num = rp->req_num; | 298 | pkt.res.req_num = rp->req_num; |
| 289 | pkt.res.result = DS_OK; | 299 | pkt.res.result = DS_OK; |
| 290 | 300 | ||
| @@ -302,10 +312,11 @@ struct ds_shutdown_res { | |||
| 302 | char reason[1]; | 312 | char reason[1]; |
| 303 | }; | 313 | }; |
| 304 | 314 | ||
| 305 | static void domain_shutdown_data(struct ldc_channel *lp, | 315 | static void domain_shutdown_data(struct ds_info *dp, |
| 306 | struct ds_cap_state *dp, | 316 | struct ds_cap_state *cp, |
| 307 | void *buf, int len) | 317 | void *buf, int len) |
| 308 | { | 318 | { |
| 319 | struct ldc_channel *lp = dp->lp; | ||
| 309 | struct ds_data *dpkt = buf; | 320 | struct ds_data *dpkt = buf; |
| 310 | struct ds_shutdown_req *rp; | 321 | struct ds_shutdown_req *rp; |
| 311 | struct { | 322 | struct { |
| @@ -315,13 +326,13 @@ static void domain_shutdown_data(struct ldc_channel *lp, | |||
| 315 | 326 | ||
| 316 | rp = (struct ds_shutdown_req *) (dpkt + 1); | 327 | rp = (struct ds_shutdown_req *) (dpkt + 1); |
| 317 | 328 | ||
| 318 | printk(KERN_ALERT PFX "Shutdown request from " | 329 | printk(KERN_ALERT "ds-%lu: Shutdown request from " |
| 319 | "LDOM manager received.\n"); | 330 | "LDOM manager received.\n", dp->id); |
| 320 | 331 | ||
| 321 | memset(&pkt, 0, sizeof(pkt)); | 332 | memset(&pkt, 0, sizeof(pkt)); |
| 322 | pkt.data.tag.type = DS_DATA; | 333 | pkt.data.tag.type = DS_DATA; |
| 323 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 334 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
| 324 | pkt.data.handle = dp->handle; | 335 | pkt.data.handle = cp->handle; |
| 325 | pkt.res.req_num = rp->req_num; | 336 | pkt.res.req_num = rp->req_num; |
| 326 | pkt.res.result = DS_OK; | 337 | pkt.res.result = DS_OK; |
| 327 | pkt.res.reason[0] = 0; | 338 | pkt.res.reason[0] = 0; |
| @@ -341,10 +352,11 @@ struct ds_panic_res { | |||
| 341 | char reason[1]; | 352 | char reason[1]; |
| 342 | }; | 353 | }; |
| 343 | 354 | ||
| 344 | static void domain_panic_data(struct ldc_channel *lp, | 355 | static void domain_panic_data(struct ds_info *dp, |
| 345 | struct ds_cap_state *dp, | 356 | struct ds_cap_state *cp, |
| 346 | void *buf, int len) | 357 | void *buf, int len) |
| 347 | { | 358 | { |
| 359 | struct ldc_channel *lp = dp->lp; | ||
| 348 | struct ds_data *dpkt = buf; | 360 | struct ds_data *dpkt = buf; |
| 349 | struct ds_panic_req *rp; | 361 | struct ds_panic_req *rp; |
| 350 | struct { | 362 | struct { |
| @@ -354,13 +366,13 @@ static void domain_panic_data(struct ldc_channel *lp, | |||
| 354 | 366 | ||
| 355 | rp = (struct ds_panic_req *) (dpkt + 1); | 367 | rp = (struct ds_panic_req *) (dpkt + 1); |
| 356 | 368 | ||
| 357 | printk(KERN_ALERT PFX "Panic request from " | 369 | printk(KERN_ALERT "ds-%lu: Panic request from " |
| 358 | "LDOM manager received.\n"); | 370 | "LDOM manager received.\n", dp->id); |
| 359 | 371 | ||
| 360 | memset(&pkt, 0, sizeof(pkt)); | 372 | memset(&pkt, 0, sizeof(pkt)); |
| 361 | pkt.data.tag.type = DS_DATA; | 373 | pkt.data.tag.type = DS_DATA; |
| 362 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 374 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
| 363 | pkt.data.handle = dp->handle; | 375 | pkt.data.handle = cp->handle; |
| 364 | pkt.res.req_num = rp->req_num; | 376 | pkt.res.req_num = rp->req_num; |
| 365 | pkt.res.result = DS_OK; | 377 | pkt.res.result = DS_OK; |
| 366 | pkt.res.reason[0] = 0; | 378 | pkt.res.reason[0] = 0; |
| @@ -403,10 +415,11 @@ struct dr_cpu_resp_entry { | |||
| 403 | __u32 str_off; | 415 | __u32 str_off; |
| 404 | }; | 416 | }; |
| 405 | 417 | ||
| 406 | static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 418 | static void __dr_cpu_send_error(struct ds_info *dp, |
| 419 | struct ds_cap_state *cp, | ||
| 420 | struct ds_data *data) | ||
| 407 | { | 421 | { |
| 408 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); | 422 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); |
| 409 | struct ds_info *dp = ds_info; | ||
| 410 | struct { | 423 | struct { |
| 411 | struct ds_data data; | 424 | struct ds_data data; |
| 412 | struct dr_cpu_tag tag; | 425 | struct dr_cpu_tag tag; |
| @@ -428,12 +441,14 @@ static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | |||
| 428 | __ds_send(dp->lp, &pkt, msg_len); | 441 | __ds_send(dp->lp, &pkt, msg_len); |
| 429 | } | 442 | } |
| 430 | 443 | ||
| 431 | static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 444 | static void dr_cpu_send_error(struct ds_info *dp, |
| 445 | struct ds_cap_state *cp, | ||
| 446 | struct ds_data *data) | ||
| 432 | { | 447 | { |
| 433 | unsigned long flags; | 448 | unsigned long flags; |
| 434 | 449 | ||
| 435 | spin_lock_irqsave(&ds_lock, flags); | 450 | spin_lock_irqsave(&ds_lock, flags); |
| 436 | __dr_cpu_send_error(cp, data); | 451 | __dr_cpu_send_error(dp, cp, data); |
| 437 | spin_unlock_irqrestore(&ds_lock, flags); | 452 | spin_unlock_irqrestore(&ds_lock, flags); |
| 438 | } | 453 | } |
| 439 | 454 | ||
| @@ -511,7 +526,9 @@ static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus, | |||
| 511 | } | 526 | } |
| 512 | } | 527 | } |
| 513 | 528 | ||
| 514 | static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | 529 | static int dr_cpu_configure(struct ds_info *dp, |
| 530 | struct ds_cap_state *cp, | ||
| 531 | u64 req_num, | ||
| 515 | cpumask_t *mask) | 532 | cpumask_t *mask) |
| 516 | { | 533 | { |
| 517 | struct ds_data *resp; | 534 | struct ds_data *resp; |
| @@ -533,7 +550,8 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
| 533 | for_each_cpu_mask(cpu, *mask) { | 550 | for_each_cpu_mask(cpu, *mask) { |
| 534 | int err; | 551 | int err; |
| 535 | 552 | ||
| 536 | printk(KERN_INFO PFX "Starting cpu %d...\n", cpu); | 553 | printk(KERN_INFO "ds-%lu: Starting cpu %d...\n", |
| 554 | dp->id, cpu); | ||
| 537 | err = cpu_up(cpu); | 555 | err = cpu_up(cpu); |
| 538 | if (err) { | 556 | if (err) { |
| 539 | __u32 res = DR_CPU_RES_FAILURE; | 557 | __u32 res = DR_CPU_RES_FAILURE; |
| @@ -548,14 +566,14 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
| 548 | res = DR_CPU_RES_CPU_NOT_RESPONDING; | 566 | res = DR_CPU_RES_CPU_NOT_RESPONDING; |
| 549 | } | 567 | } |
| 550 | 568 | ||
| 551 | printk(KERN_INFO PFX "CPU startup failed err=%d\n", | 569 | printk(KERN_INFO "ds-%lu: CPU startup failed err=%d\n", |
| 552 | err); | 570 | dp->id, err); |
| 553 | dr_cpu_mark(resp, cpu, ncpus, res, stat); | 571 | dr_cpu_mark(resp, cpu, ncpus, res, stat); |
| 554 | } | 572 | } |
| 555 | } | 573 | } |
| 556 | 574 | ||
| 557 | spin_lock_irqsave(&ds_lock, flags); | 575 | spin_lock_irqsave(&ds_lock, flags); |
| 558 | __ds_send(ds_info->lp, resp, resp_len); | 576 | __ds_send(dp->lp, resp, resp_len); |
| 559 | spin_unlock_irqrestore(&ds_lock, flags); | 577 | spin_unlock_irqrestore(&ds_lock, flags); |
| 560 | 578 | ||
| 561 | kfree(resp); | 579 | kfree(resp); |
| @@ -566,7 +584,9 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
| 566 | return 0; | 584 | return 0; |
| 567 | } | 585 | } |
| 568 | 586 | ||
| 569 | static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | 587 | static int dr_cpu_unconfigure(struct ds_info *dp, |
| 588 | struct ds_cap_state *cp, | ||
| 589 | u64 req_num, | ||
| 570 | cpumask_t *mask) | 590 | cpumask_t *mask) |
| 571 | { | 591 | { |
| 572 | struct ds_data *resp; | 592 | struct ds_data *resp; |
| @@ -586,8 +606,8 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
| 586 | for_each_cpu_mask(cpu, *mask) { | 606 | for_each_cpu_mask(cpu, *mask) { |
| 587 | int err; | 607 | int err; |
| 588 | 608 | ||
| 589 | printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n", | 609 | printk(KERN_INFO "ds-%lu: Shutting down cpu %d...\n", |
| 590 | smp_processor_id(), cpu); | 610 | dp->id, cpu); |
| 591 | err = cpu_down(cpu); | 611 | err = cpu_down(cpu); |
| 592 | if (err) | 612 | if (err) |
| 593 | dr_cpu_mark(resp, cpu, ncpus, | 613 | dr_cpu_mark(resp, cpu, ncpus, |
| @@ -596,7 +616,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
| 596 | } | 616 | } |
| 597 | 617 | ||
| 598 | spin_lock_irqsave(&ds_lock, flags); | 618 | spin_lock_irqsave(&ds_lock, flags); |
| 599 | __ds_send(ds_info->lp, resp, resp_len); | 619 | __ds_send(dp->lp, resp, resp_len); |
| 600 | spin_unlock_irqrestore(&ds_lock, flags); | 620 | spin_unlock_irqrestore(&ds_lock, flags); |
| 601 | 621 | ||
| 602 | kfree(resp); | 622 | kfree(resp); |
| @@ -604,7 +624,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
| 604 | return 0; | 624 | return 0; |
| 605 | } | 625 | } |
| 606 | 626 | ||
| 607 | static void dr_cpu_data(struct ldc_channel *lp, | 627 | static void dr_cpu_data(struct ds_info *dp, |
| 608 | struct ds_cap_state *cp, | 628 | struct ds_cap_state *cp, |
| 609 | void *buf, int len) | 629 | void *buf, int len) |
| 610 | { | 630 | { |
| @@ -623,7 +643,7 @@ static void dr_cpu_data(struct ldc_channel *lp, | |||
| 623 | break; | 643 | break; |
| 624 | 644 | ||
| 625 | default: | 645 | default: |
| 626 | dr_cpu_send_error(cp, data); | 646 | dr_cpu_send_error(dp, cp, data); |
| 627 | return; | 647 | return; |
| 628 | } | 648 | } |
| 629 | 649 | ||
| @@ -639,12 +659,12 @@ static void dr_cpu_data(struct ldc_channel *lp, | |||
| 639 | } | 659 | } |
| 640 | 660 | ||
| 641 | if (tag->type == DR_CPU_CONFIGURE) | 661 | if (tag->type == DR_CPU_CONFIGURE) |
| 642 | err = dr_cpu_configure(cp, req_num, &mask); | 662 | err = dr_cpu_configure(dp, cp, req_num, &mask); |
| 643 | else | 663 | else |
| 644 | err = dr_cpu_unconfigure(cp, req_num, &mask); | 664 | err = dr_cpu_unconfigure(dp, cp, req_num, &mask); |
| 645 | 665 | ||
| 646 | if (err) | 666 | if (err) |
| 647 | dr_cpu_send_error(cp, data); | 667 | dr_cpu_send_error(dp, cp, data); |
| 648 | } | 668 | } |
| 649 | #endif /* CONFIG_HOTPLUG_CPU */ | 669 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 650 | 670 | ||
| @@ -656,8 +676,8 @@ struct ds_pri_msg { | |||
| 656 | #define DS_PRI_UPDATE 0x02 | 676 | #define DS_PRI_UPDATE 0x02 |
| 657 | }; | 677 | }; |
| 658 | 678 | ||
| 659 | static void ds_pri_data(struct ldc_channel *lp, | 679 | static void ds_pri_data(struct ds_info *dp, |
| 660 | struct ds_cap_state *dp, | 680 | struct ds_cap_state *cp, |
| 661 | void *buf, int len) | 681 | void *buf, int len) |
| 662 | { | 682 | { |
| 663 | struct ds_data *dpkt = buf; | 683 | struct ds_data *dpkt = buf; |
| @@ -665,8 +685,8 @@ static void ds_pri_data(struct ldc_channel *lp, | |||
| 665 | 685 | ||
| 666 | rp = (struct ds_pri_msg *) (dpkt + 1); | 686 | rp = (struct ds_pri_msg *) (dpkt + 1); |
| 667 | 687 | ||
| 668 | printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n", | 688 | printk(KERN_INFO "ds-%lu: PRI REQ [%lx:%lx], len=%d\n", |
| 669 | rp->req_num, rp->type, len); | 689 | dp->id, rp->req_num, rp->type, len); |
| 670 | } | 690 | } |
| 671 | 691 | ||
| 672 | struct ds_var_hdr { | 692 | struct ds_var_hdr { |
| @@ -701,8 +721,8 @@ static DEFINE_MUTEX(ds_var_mutex); | |||
| 701 | static int ds_var_doorbell; | 721 | static int ds_var_doorbell; |
| 702 | static int ds_var_response; | 722 | static int ds_var_response; |
| 703 | 723 | ||
| 704 | static void ds_var_data(struct ldc_channel *lp, | 724 | static void ds_var_data(struct ds_info *dp, |
| 705 | struct ds_cap_state *dp, | 725 | struct ds_cap_state *cp, |
| 706 | void *buf, int len) | 726 | void *buf, int len) |
| 707 | { | 727 | { |
| 708 | struct ds_data *dpkt = buf; | 728 | struct ds_data *dpkt = buf; |
| @@ -721,14 +741,35 @@ static void ds_var_data(struct ldc_channel *lp, | |||
| 721 | 741 | ||
| 722 | void ldom_set_var(const char *var, const char *value) | 742 | void ldom_set_var(const char *var, const char *value) |
| 723 | { | 743 | { |
| 724 | struct ds_info *dp = ds_info; | ||
| 725 | struct ds_cap_state *cp; | 744 | struct ds_cap_state *cp; |
| 745 | struct ds_info *dp; | ||
| 746 | unsigned long flags; | ||
| 747 | |||
| 748 | spin_lock_irqsave(&ds_lock, flags); | ||
| 749 | cp = NULL; | ||
| 750 | for (dp = ds_info_list; dp; dp = dp->next) { | ||
| 751 | struct ds_cap_state *tmp; | ||
| 752 | |||
| 753 | tmp = find_cap_by_string(dp, "var-config"); | ||
| 754 | if (tmp && tmp->state == CAP_STATE_REGISTERED) { | ||
| 755 | cp = tmp; | ||
| 756 | break; | ||
| 757 | } | ||
| 758 | } | ||
| 759 | if (!cp) { | ||
| 760 | for (dp = ds_info_list; dp; dp = dp->next) { | ||
| 761 | struct ds_cap_state *tmp; | ||
| 726 | 762 | ||
| 727 | cp = find_cap_by_string("var-config"); | 763 | tmp = find_cap_by_string(dp, "var-config-backup"); |
| 728 | if (cp->state != CAP_STATE_REGISTERED) | 764 | if (tmp && tmp->state == CAP_STATE_REGISTERED) { |
| 729 | cp = find_cap_by_string("var-config-backup"); | 765 | cp = tmp; |
| 766 | break; | ||
| 767 | } | ||
| 768 | } | ||
| 769 | } | ||
| 770 | spin_unlock_irqrestore(&ds_lock, flags); | ||
| 730 | 771 | ||
| 731 | if (cp->state == CAP_STATE_REGISTERED) { | 772 | if (cp) { |
| 732 | union { | 773 | union { |
| 733 | struct { | 774 | struct { |
| 734 | struct ds_data data; | 775 | struct ds_data data; |
| @@ -736,7 +777,6 @@ void ldom_set_var(const char *var, const char *value) | |||
| 736 | } header; | 777 | } header; |
| 737 | char all[512]; | 778 | char all[512]; |
| 738 | } pkt; | 779 | } pkt; |
| 739 | unsigned long flags; | ||
| 740 | char *base, *p; | 780 | char *base, *p; |
| 741 | int msg_len, loops; | 781 | int msg_len, loops; |
| 742 | 782 | ||
| @@ -777,9 +817,9 @@ void ldom_set_var(const char *var, const char *value) | |||
| 777 | 817 | ||
| 778 | if (ds_var_doorbell == 0 || | 818 | if (ds_var_doorbell == 0 || |
| 779 | ds_var_response != DS_VAR_SUCCESS) | 819 | ds_var_response != DS_VAR_SUCCESS) |
| 780 | printk(KERN_ERR PFX "var-config [%s:%s] " | 820 | printk(KERN_ERR "ds-%lu: var-config [%s:%s] " |
| 781 | "failed, response(%d).\n", | 821 | "failed, response(%d).\n", |
| 782 | var, value, | 822 | dp->id, var, value, |
| 783 | ds_var_response); | 823 | ds_var_response); |
| 784 | } else { | 824 | } else { |
| 785 | printk(KERN_ERR PFX "var-config not registered so " | 825 | printk(KERN_ERR PFX "var-config not registered so " |
| @@ -811,8 +851,8 @@ void ldom_power_off(void) | |||
| 811 | 851 | ||
| 812 | static void ds_conn_reset(struct ds_info *dp) | 852 | static void ds_conn_reset(struct ds_info *dp) |
| 813 | { | 853 | { |
| 814 | printk(KERN_ERR PFX "ds_conn_reset() from %p\n", | 854 | printk(KERN_ERR "ds-%lu: ds_conn_reset() from %p\n", |
| 815 | __builtin_return_address(0)); | 855 | dp->id, __builtin_return_address(0)); |
| 816 | } | 856 | } |
| 817 | 857 | ||
| 818 | static int register_services(struct ds_info *dp) | 858 | static int register_services(struct ds_info *dp) |
| @@ -820,12 +860,12 @@ static int register_services(struct ds_info *dp) | |||
| 820 | struct ldc_channel *lp = dp->lp; | 860 | struct ldc_channel *lp = dp->lp; |
| 821 | int i; | 861 | int i; |
| 822 | 862 | ||
| 823 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 863 | for (i = 0; i < dp->num_ds_states; i++) { |
| 824 | struct { | 864 | struct { |
| 825 | struct ds_reg_req req; | 865 | struct ds_reg_req req; |
| 826 | u8 id_buf[256]; | 866 | u8 id_buf[256]; |
| 827 | } pbuf; | 867 | } pbuf; |
| 828 | struct ds_cap_state *cp = &ds_states[i]; | 868 | struct ds_cap_state *cp = &dp->ds_states[i]; |
| 829 | int err, msg_len; | 869 | int err, msg_len; |
| 830 | u64 new_count; | 870 | u64 new_count; |
| 831 | 871 | ||
| @@ -870,28 +910,26 @@ static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt) | |||
| 870 | 910 | ||
| 871 | if (pkt->type == DS_REG_ACK) { | 911 | if (pkt->type == DS_REG_ACK) { |
| 872 | struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt; | 912 | struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt; |
| 873 | struct ds_cap_state *cp = find_cap(ap->handle); | 913 | struct ds_cap_state *cp = find_cap(dp, ap->handle); |
| 874 | 914 | ||
| 875 | if (!cp) { | 915 | if (!cp) { |
| 876 | printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n", | 916 | printk(KERN_ERR "ds-%lu: REG ACK for unknown " |
| 877 | ap->handle); | 917 | "handle %lx\n", dp->id, ap->handle); |
| 878 | return 0; | 918 | return 0; |
| 879 | } | 919 | } |
| 880 | printk(KERN_INFO PFX "Registered %s service.\n", | 920 | printk(KERN_INFO "ds-%lu: Registered %s service.\n", |
| 881 | cp->service_id); | 921 | dp->id, cp->service_id); |
| 882 | cp->state = CAP_STATE_REGISTERED; | 922 | cp->state = CAP_STATE_REGISTERED; |
| 883 | } else if (pkt->type == DS_REG_NACK) { | 923 | } else if (pkt->type == DS_REG_NACK) { |
| 884 | struct ds_reg_nack *np = (struct ds_reg_nack *) pkt; | 924 | struct ds_reg_nack *np = (struct ds_reg_nack *) pkt; |
| 885 | struct ds_cap_state *cp = find_cap(np->handle); | 925 | struct ds_cap_state *cp = find_cap(dp, np->handle); |
| 886 | 926 | ||
| 887 | if (!cp) { | 927 | if (!cp) { |
| 888 | printk(KERN_ERR PFX "REG NACK for " | 928 | printk(KERN_ERR "ds-%lu: REG NACK for " |
| 889 | "unknown handle %lx\n", | 929 | "unknown handle %lx\n", |
| 890 | np->handle); | 930 | dp->id, np->handle); |
| 891 | return 0; | 931 | return 0; |
| 892 | } | 932 | } |
| 893 | printk(KERN_INFO PFX "Could not register %s service\n", | ||
| 894 | cp->service_id); | ||
| 895 | cp->state = CAP_STATE_UNKNOWN; | 933 | cp->state = CAP_STATE_UNKNOWN; |
| 896 | } | 934 | } |
| 897 | 935 | ||
| @@ -922,6 +960,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ds_wait); | |||
| 922 | 960 | ||
| 923 | struct ds_queue_entry { | 961 | struct ds_queue_entry { |
| 924 | struct list_head list; | 962 | struct list_head list; |
| 963 | struct ds_info *dp; | ||
| 925 | int req_len; | 964 | int req_len; |
| 926 | int __pad; | 965 | int __pad; |
| 927 | u64 req[0]; | 966 | u64 req[0]; |
| @@ -930,7 +969,6 @@ struct ds_queue_entry { | |||
| 930 | static void process_ds_work(void) | 969 | static void process_ds_work(void) |
| 931 | { | 970 | { |
| 932 | struct ds_queue_entry *qp, *tmp; | 971 | struct ds_queue_entry *qp, *tmp; |
| 933 | static struct ds_info *dp; | ||
| 934 | unsigned long flags; | 972 | unsigned long flags; |
| 935 | LIST_HEAD(todo); | 973 | LIST_HEAD(todo); |
| 936 | 974 | ||
| @@ -939,22 +977,22 @@ static void process_ds_work(void) | |||
| 939 | INIT_LIST_HEAD(&ds_work_list); | 977 | INIT_LIST_HEAD(&ds_work_list); |
| 940 | spin_unlock_irqrestore(&ds_lock, flags); | 978 | spin_unlock_irqrestore(&ds_lock, flags); |
| 941 | 979 | ||
| 942 | dp = ds_info; | ||
| 943 | |||
| 944 | list_for_each_entry_safe(qp, tmp, &todo, list) { | 980 | list_for_each_entry_safe(qp, tmp, &todo, list) { |
| 945 | struct ds_data *dpkt = (struct ds_data *) qp->req; | 981 | struct ds_data *dpkt = (struct ds_data *) qp->req; |
| 946 | struct ds_cap_state *cp = find_cap(dpkt->handle); | 982 | struct ds_info *dp = qp->dp; |
| 983 | struct ds_cap_state *cp = find_cap(dp, dpkt->handle); | ||
| 947 | int req_len = qp->req_len; | 984 | int req_len = qp->req_len; |
| 948 | 985 | ||
| 949 | if (!cp) { | 986 | if (!cp) { |
| 950 | printk(KERN_ERR PFX "Data for unknown handle %lu\n", | 987 | printk(KERN_ERR "ds-%lu: Data for unknown " |
| 951 | dpkt->handle); | 988 | "handle %lu\n", |
| 989 | dp->id, dpkt->handle); | ||
| 952 | 990 | ||
| 953 | spin_lock_irqsave(&ds_lock, flags); | 991 | spin_lock_irqsave(&ds_lock, flags); |
| 954 | __send_ds_nack(dp, dpkt->handle); | 992 | __send_ds_nack(dp, dpkt->handle); |
| 955 | spin_unlock_irqrestore(&ds_lock, flags); | 993 | spin_unlock_irqrestore(&ds_lock, flags); |
| 956 | } else { | 994 | } else { |
| 957 | cp->data(dp->lp, cp, dpkt, req_len); | 995 | cp->data(dp, cp, dpkt, req_len); |
| 958 | } | 996 | } |
| 959 | 997 | ||
| 960 | list_del(&qp->list); | 998 | list_del(&qp->list); |
| @@ -990,6 +1028,7 @@ static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len) | |||
| 990 | if (!qp) { | 1028 | if (!qp) { |
| 991 | __send_ds_nack(dp, dpkt->handle); | 1029 | __send_ds_nack(dp, dpkt->handle); |
| 992 | } else { | 1030 | } else { |
| 1031 | qp->dp = dp; | ||
| 993 | memcpy(&qp->req, pkt, len); | 1032 | memcpy(&qp->req, pkt, len); |
| 994 | list_add_tail(&qp->list, &ds_work_list); | 1033 | list_add_tail(&qp->list, &ds_work_list); |
| 995 | wake_up(&ds_wait); | 1034 | wake_up(&ds_wait); |
| @@ -1019,8 +1058,8 @@ static void ds_reset(struct ds_info *dp) | |||
| 1019 | 1058 | ||
| 1020 | dp->hs_state = 0; | 1059 | dp->hs_state = 0; |
| 1021 | 1060 | ||
| 1022 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 1061 | for (i = 0; i < dp->num_ds_states; i++) { |
| 1023 | struct ds_cap_state *cp = &ds_states[i]; | 1062 | struct ds_cap_state *cp = &dp->ds_states[i]; |
| 1024 | 1063 | ||
| 1025 | cp->state = CAP_STATE_UNKNOWN; | 1064 | cp->state = CAP_STATE_UNKNOWN; |
| 1026 | } | 1065 | } |
| @@ -1048,7 +1087,8 @@ static void ds_event(void *arg, int event) | |||
| 1048 | } | 1087 | } |
| 1049 | 1088 | ||
| 1050 | if (event != LDC_EVENT_DATA_READY) { | 1089 | if (event != LDC_EVENT_DATA_READY) { |
| 1051 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); | 1090 | printk(KERN_WARNING "ds-%lu: Unexpected LDC event %d\n", |
| 1091 | dp->id, event); | ||
| 1052 | spin_unlock_irqrestore(&ds_lock, flags); | 1092 | spin_unlock_irqrestore(&ds_lock, flags); |
| 1053 | return; | 1093 | return; |
| 1054 | } | 1094 | } |
| @@ -1099,9 +1139,11 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
| 1099 | .mtu = 4096, | 1139 | .mtu = 4096, |
| 1100 | .mode = LDC_MODE_STREAM, | 1140 | .mode = LDC_MODE_STREAM, |
| 1101 | }; | 1141 | }; |
| 1142 | struct mdesc_handle *hp; | ||
| 1102 | struct ldc_channel *lp; | 1143 | struct ldc_channel *lp; |
| 1103 | struct ds_info *dp; | 1144 | struct ds_info *dp; |
| 1104 | int err; | 1145 | const u64 *val; |
| 1146 | int err, i; | ||
| 1105 | 1147 | ||
| 1106 | if (ds_version_printed++ == 0) | 1148 | if (ds_version_printed++ == 0) |
| 1107 | printk(KERN_INFO "%s", version); | 1149 | printk(KERN_INFO "%s", version); |
| @@ -1111,19 +1153,37 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
| 1111 | if (!dp) | 1153 | if (!dp) |
| 1112 | goto out_err; | 1154 | goto out_err; |
| 1113 | 1155 | ||
| 1156 | hp = mdesc_grab(); | ||
| 1157 | val = mdesc_get_property(hp, vdev->mp, "id", NULL); | ||
| 1158 | if (val) | ||
| 1159 | dp->id = *val; | ||
| 1160 | mdesc_release(hp); | ||
| 1161 | |||
| 1114 | dp->rcv_buf = kzalloc(4096, GFP_KERNEL); | 1162 | dp->rcv_buf = kzalloc(4096, GFP_KERNEL); |
| 1115 | if (!dp->rcv_buf) | 1163 | if (!dp->rcv_buf) |
| 1116 | goto out_free_dp; | 1164 | goto out_free_dp; |
| 1117 | 1165 | ||
| 1118 | dp->rcv_buf_len = 4096; | 1166 | dp->rcv_buf_len = 4096; |
| 1119 | 1167 | ||
| 1168 | dp->ds_states = kzalloc(sizeof(ds_states_template), | ||
| 1169 | GFP_KERNEL); | ||
| 1170 | if (!dp->ds_states) | ||
| 1171 | goto out_free_rcv_buf; | ||
| 1172 | |||
| 1173 | memcpy(dp->ds_states, ds_states_template, | ||
| 1174 | sizeof(ds_states_template)); | ||
| 1175 | dp->num_ds_states = ARRAY_SIZE(ds_states_template); | ||
| 1176 | |||
| 1177 | for (i = 0; i < dp->num_ds_states; i++) | ||
| 1178 | dp->ds_states[i].handle = ((u64)i << 32); | ||
| 1179 | |||
| 1120 | ds_cfg.tx_irq = vdev->tx_irq; | 1180 | ds_cfg.tx_irq = vdev->tx_irq; |
| 1121 | ds_cfg.rx_irq = vdev->rx_irq; | 1181 | ds_cfg.rx_irq = vdev->rx_irq; |
| 1122 | 1182 | ||
| 1123 | lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); | 1183 | lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); |
| 1124 | if (IS_ERR(lp)) { | 1184 | if (IS_ERR(lp)) { |
| 1125 | err = PTR_ERR(lp); | 1185 | err = PTR_ERR(lp); |
| 1126 | goto out_free_rcv_buf; | 1186 | goto out_free_ds_states; |
| 1127 | } | 1187 | } |
| 1128 | dp->lp = lp; | 1188 | dp->lp = lp; |
| 1129 | 1189 | ||
| @@ -1131,13 +1191,19 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
| 1131 | if (err) | 1191 | if (err) |
| 1132 | goto out_free_ldc; | 1192 | goto out_free_ldc; |
| 1133 | 1193 | ||
| 1134 | ds_info = dp; | 1194 | spin_lock_irq(&ds_lock); |
| 1195 | dp->next = ds_info_list; | ||
| 1196 | ds_info_list = dp; | ||
| 1197 | spin_unlock_irq(&ds_lock); | ||
| 1135 | 1198 | ||
| 1136 | return err; | 1199 | return err; |
| 1137 | 1200 | ||
| 1138 | out_free_ldc: | 1201 | out_free_ldc: |
| 1139 | ldc_free(dp->lp); | 1202 | ldc_free(dp->lp); |
| 1140 | 1203 | ||
| 1204 | out_free_ds_states: | ||
| 1205 | kfree(dp->ds_states); | ||
| 1206 | |||
| 1141 | out_free_rcv_buf: | 1207 | out_free_rcv_buf: |
| 1142 | kfree(dp->rcv_buf); | 1208 | kfree(dp->rcv_buf); |
| 1143 | 1209 | ||
| @@ -1172,11 +1238,6 @@ static struct vio_driver ds_driver = { | |||
| 1172 | 1238 | ||
| 1173 | static int __init ds_init(void) | 1239 | static int __init ds_init(void) |
| 1174 | { | 1240 | { |
| 1175 | int i; | ||
| 1176 | |||
| 1177 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) | ||
| 1178 | ds_states[i].handle = ((u64)i << 32); | ||
| 1179 | |||
| 1180 | kthread_run(ds_thread, NULL, "kldomd"); | 1241 | kthread_run(ds_thread, NULL, "kldomd"); |
| 1181 | 1242 | ||
| 1182 | return vio_register_driver(&ds_driver); | 1243 | return vio_register_driver(&ds_driver); |
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index ad55a9bb50dd..6d2956179cde 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
| @@ -362,6 +362,7 @@ static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | |||
| 362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) | 362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) |
| 363 | { | 363 | { |
| 364 | struct linux_ebus_child *child; | 364 | struct linux_ebus_child *child; |
| 365 | struct dev_archdata *sd; | ||
| 365 | struct of_device *op; | 366 | struct of_device *op; |
| 366 | int i, len; | 367 | int i, len; |
| 367 | 368 | ||
| @@ -387,6 +388,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de | |||
| 387 | dev->irqs[i] = op->irqs[i]; | 388 | dev->irqs[i] = op->irqs[i]; |
| 388 | } | 389 | } |
| 389 | 390 | ||
| 391 | sd = &dev->ofdev.dev.archdata; | ||
| 392 | sd->prom_node = dp; | ||
| 393 | sd->op = &dev->ofdev; | ||
| 394 | |||
| 390 | dev->ofdev.node = dp; | 395 | dev->ofdev.node = dp; |
| 391 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | 396 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; |
| 392 | dev->ofdev.dev.bus = &ebus_bus_type; | 397 | dev->ofdev.dev.bus = &ebus_bus_type; |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index c72795666a62..db31bf6b42db 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
| @@ -87,7 +87,11 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY | |||
| 87 | */ | 87 | */ |
| 88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) | 88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) |
| 89 | 89 | ||
| 90 | static unsigned int virt_to_real_irq_table[NR_IRQS]; | 90 | static struct { |
| 91 | unsigned int irq; | ||
| 92 | unsigned int dev_handle; | ||
| 93 | unsigned int dev_ino; | ||
| 94 | } virt_to_real_irq_table[NR_IRQS]; | ||
| 91 | 95 | ||
| 92 | static unsigned char virt_irq_alloc(unsigned int real_irq) | 96 | static unsigned char virt_irq_alloc(unsigned int real_irq) |
| 93 | { | 97 | { |
| @@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
| 96 | BUILD_BUG_ON(NR_IRQS >= 256); | 100 | BUILD_BUG_ON(NR_IRQS >= 256); |
| 97 | 101 | ||
| 98 | for (ent = 1; ent < NR_IRQS; ent++) { | 102 | for (ent = 1; ent < NR_IRQS; ent++) { |
| 99 | if (!virt_to_real_irq_table[ent]) | 103 | if (!virt_to_real_irq_table[ent].irq) |
| 100 | break; | 104 | break; |
| 101 | } | 105 | } |
| 102 | if (ent >= NR_IRQS) { | 106 | if (ent >= NR_IRQS) { |
| @@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
| 104 | return 0; | 108 | return 0; |
| 105 | } | 109 | } |
| 106 | 110 | ||
| 107 | virt_to_real_irq_table[ent] = real_irq; | 111 | virt_to_real_irq_table[ent].irq = real_irq; |
| 108 | 112 | ||
| 109 | return ent; | 113 | return ent; |
| 110 | } | 114 | } |
| @@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq) | |||
| 117 | if (virt_irq >= NR_IRQS) | 121 | if (virt_irq >= NR_IRQS) |
| 118 | return; | 122 | return; |
| 119 | 123 | ||
| 120 | real_irq = virt_to_real_irq_table[virt_irq]; | 124 | real_irq = virt_to_real_irq_table[virt_irq].irq; |
| 121 | virt_to_real_irq_table[virt_irq] = 0; | 125 | virt_to_real_irq_table[virt_irq].irq = 0; |
| 122 | 126 | ||
| 123 | __bucket(real_irq)->virt_irq = 0; | 127 | __bucket(real_irq)->virt_irq = 0; |
| 124 | } | 128 | } |
| @@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq) | |||
| 126 | 130 | ||
| 127 | static unsigned int virt_to_real_irq(unsigned char virt_irq) | 131 | static unsigned int virt_to_real_irq(unsigned char virt_irq) |
| 128 | { | 132 | { |
| 129 | return virt_to_real_irq_table[virt_irq]; | 133 | return virt_to_real_irq_table[virt_irq].irq; |
| 130 | } | 134 | } |
| 131 | 135 | ||
| 132 | /* | 136 | /* |
| @@ -336,15 +340,15 @@ static void sun4v_irq_enable(unsigned int virt_irq) | |||
| 336 | 340 | ||
| 337 | err = sun4v_intr_settarget(ino, cpuid); | 341 | err = sun4v_intr_settarget(ino, cpuid); |
| 338 | if (err != HV_EOK) | 342 | if (err != HV_EOK) |
| 339 | printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", | 343 | printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " |
| 340 | ino, cpuid, err); | 344 | "err(%d)\n", ino, cpuid, err); |
| 341 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); | 345 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); |
| 342 | if (err != HV_EOK) | 346 | if (err != HV_EOK) |
| 343 | printk("sun4v_intr_setstate(%x): " | 347 | printk(KERN_ERR "sun4v_intr_setstate(%x): " |
| 344 | "err(%d)\n", ino, err); | 348 | "err(%d)\n", ino, err); |
| 345 | err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); | 349 | err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); |
| 346 | if (err != HV_EOK) | 350 | if (err != HV_EOK) |
| 347 | printk("sun4v_intr_setenabled(%x): err(%d)\n", | 351 | printk(KERN_ERR "sun4v_intr_setenabled(%x): err(%d)\n", |
| 348 | ino, err); | 352 | ino, err); |
| 349 | } | 353 | } |
| 350 | } | 354 | } |
| @@ -362,8 +366,8 @@ static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
| 362 | 366 | ||
| 363 | err = sun4v_intr_settarget(ino, cpuid); | 367 | err = sun4v_intr_settarget(ino, cpuid); |
| 364 | if (err != HV_EOK) | 368 | if (err != HV_EOK) |
| 365 | printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", | 369 | printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " |
| 366 | ino, cpuid, err); | 370 | "err(%d)\n", ino, cpuid, err); |
| 367 | } | 371 | } |
| 368 | } | 372 | } |
| 369 | 373 | ||
| @@ -377,7 +381,7 @@ static void sun4v_irq_disable(unsigned int virt_irq) | |||
| 377 | 381 | ||
| 378 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); | 382 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); |
| 379 | if (err != HV_EOK) | 383 | if (err != HV_EOK) |
| 380 | printk("sun4v_intr_setenabled(%x): " | 384 | printk(KERN_ERR "sun4v_intr_setenabled(%x): " |
| 381 | "err(%d)\n", ino, err); | 385 | "err(%d)\n", ino, err); |
| 382 | } | 386 | } |
| 383 | } | 387 | } |
| @@ -410,7 +414,7 @@ static void sun4v_irq_end(unsigned int virt_irq) | |||
| 410 | 414 | ||
| 411 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); | 415 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); |
| 412 | if (err != HV_EOK) | 416 | if (err != HV_EOK) |
| 413 | printk("sun4v_intr_setstate(%x): " | 417 | printk(KERN_ERR "sun4v_intr_setstate(%x): " |
| 414 | "err(%d)\n", ino, err); | 418 | "err(%d)\n", ino, err); |
| 415 | } | 419 | } |
| 416 | } | 420 | } |
| @@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq) | |||
| 418 | static void sun4v_virq_enable(unsigned int virt_irq) | 422 | static void sun4v_virq_enable(unsigned int virt_irq) |
| 419 | { | 423 | { |
| 420 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 424 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
| 421 | unsigned int ino = bucket - &ivector_table[0]; | ||
| 422 | 425 | ||
| 423 | if (likely(bucket)) { | 426 | if (likely(bucket)) { |
| 424 | unsigned long cpuid, dev_handle, dev_ino; | 427 | unsigned long cpuid, dev_handle, dev_ino; |
| @@ -426,24 +429,24 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
| 426 | 429 | ||
| 427 | cpuid = irq_choose_cpu(virt_irq); | 430 | cpuid = irq_choose_cpu(virt_irq); |
| 428 | 431 | ||
| 429 | dev_handle = ino & IMAP_IGN; | 432 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
| 430 | dev_ino = ino & IMAP_INO; | 433 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
| 431 | 434 | ||
| 432 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 435 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
| 433 | if (err != HV_EOK) | 436 | if (err != HV_EOK) |
| 434 | printk("sun4v_vintr_set_target(%lx,%lx,%lu): " | 437 | printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " |
| 435 | "err(%d)\n", | 438 | "err(%d)\n", |
| 436 | dev_handle, dev_ino, cpuid, err); | 439 | dev_handle, dev_ino, cpuid, err); |
| 437 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 440 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
| 438 | HV_INTR_STATE_IDLE); | 441 | HV_INTR_STATE_IDLE); |
| 439 | if (err != HV_EOK) | 442 | if (err != HV_EOK) |
| 440 | printk("sun4v_vintr_set_state(%lx,%lx," | 443 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
| 441 | "HV_INTR_STATE_IDLE): err(%d)\n", | 444 | "HV_INTR_STATE_IDLE): err(%d)\n", |
| 442 | dev_handle, dev_ino, err); | 445 | dev_handle, dev_ino, err); |
| 443 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 446 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
| 444 | HV_INTR_ENABLED); | 447 | HV_INTR_ENABLED); |
| 445 | if (err != HV_EOK) | 448 | if (err != HV_EOK) |
| 446 | printk("sun4v_vintr_set_state(%lx,%lx," | 449 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
| 447 | "HV_INTR_ENABLED): err(%d)\n", | 450 | "HV_INTR_ENABLED): err(%d)\n", |
| 448 | dev_handle, dev_ino, err); | 451 | dev_handle, dev_ino, err); |
| 449 | } | 452 | } |
| @@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
| 452 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | 455 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) |
| 453 | { | 456 | { |
| 454 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 457 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
| 455 | unsigned int ino = bucket - &ivector_table[0]; | ||
| 456 | 458 | ||
| 457 | if (likely(bucket)) { | 459 | if (likely(bucket)) { |
| 458 | unsigned long cpuid, dev_handle, dev_ino; | 460 | unsigned long cpuid, dev_handle, dev_ino; |
| @@ -460,12 +462,12 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
| 460 | 462 | ||
| 461 | cpuid = irq_choose_cpu(virt_irq); | 463 | cpuid = irq_choose_cpu(virt_irq); |
| 462 | 464 | ||
| 463 | dev_handle = ino & IMAP_IGN; | 465 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
| 464 | dev_ino = ino & IMAP_INO; | 466 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
| 465 | 467 | ||
| 466 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 468 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
| 467 | if (err != HV_EOK) | 469 | if (err != HV_EOK) |
| 468 | printk("sun4v_vintr_set_target(%lx,%lx,%lu): " | 470 | printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " |
| 469 | "err(%d)\n", | 471 | "err(%d)\n", |
| 470 | dev_handle, dev_ino, cpuid, err); | 472 | dev_handle, dev_ino, cpuid, err); |
| 471 | } | 473 | } |
| @@ -474,19 +476,18 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
| 474 | static void sun4v_virq_disable(unsigned int virt_irq) | 476 | static void sun4v_virq_disable(unsigned int virt_irq) |
| 475 | { | 477 | { |
| 476 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 478 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
| 477 | unsigned int ino = bucket - &ivector_table[0]; | ||
| 478 | 479 | ||
| 479 | if (likely(bucket)) { | 480 | if (likely(bucket)) { |
| 480 | unsigned long dev_handle, dev_ino; | 481 | unsigned long dev_handle, dev_ino; |
| 481 | int err; | 482 | int err; |
| 482 | 483 | ||
| 483 | dev_handle = ino & IMAP_IGN; | 484 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
| 484 | dev_ino = ino & IMAP_INO; | 485 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
| 485 | 486 | ||
| 486 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 487 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
| 487 | HV_INTR_DISABLED); | 488 | HV_INTR_DISABLED); |
| 488 | if (err != HV_EOK) | 489 | if (err != HV_EOK) |
| 489 | printk("sun4v_vintr_set_state(%lx,%lx," | 490 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
| 490 | "HV_INTR_DISABLED): err(%d)\n", | 491 | "HV_INTR_DISABLED): err(%d)\n", |
| 491 | dev_handle, dev_ino, err); | 492 | dev_handle, dev_ino, err); |
| 492 | } | 493 | } |
| @@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
| 495 | static void sun4v_virq_end(unsigned int virt_irq) | 496 | static void sun4v_virq_end(unsigned int virt_irq) |
| 496 | { | 497 | { |
| 497 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 498 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
| 498 | unsigned int ino = bucket - &ivector_table[0]; | ||
| 499 | struct irq_desc *desc = irq_desc + virt_irq; | 499 | struct irq_desc *desc = irq_desc + virt_irq; |
| 500 | 500 | ||
| 501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
| @@ -505,13 +505,13 @@ static void sun4v_virq_end(unsigned int virt_irq) | |||
| 505 | unsigned long dev_handle, dev_ino; | 505 | unsigned long dev_handle, dev_ino; |
| 506 | int err; | 506 | int err; |
| 507 | 507 | ||
| 508 | dev_handle = ino & IMAP_IGN; | 508 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
| 509 | dev_ino = ino & IMAP_INO; | 509 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
| 510 | 510 | ||
| 511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
| 512 | HV_INTR_STATE_IDLE); | 512 | HV_INTR_STATE_IDLE); |
| 513 | if (err != HV_EOK) | 513 | if (err != HV_EOK) |
| 514 | printk("sun4v_vintr_set_state(%lx,%lx," | 514 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
| 515 | "HV_INTR_STATE_IDLE): err(%d)\n", | 515 | "HV_INTR_STATE_IDLE): err(%d)\n", |
| 516 | dev_handle, dev_ino, err); | 516 | dev_handle, dev_ino, err); |
| 517 | } | 517 | } |
| @@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | |||
| 700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) |
| 701 | { | 701 | { |
| 702 | unsigned long sysino, hv_err; | 702 | unsigned long sysino, hv_err; |
| 703 | unsigned int virq; | ||
| 703 | 704 | ||
| 704 | BUG_ON(devhandle & devino); | 705 | BUG_ON(devhandle & devino); |
| 705 | 706 | ||
| @@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
| 713 | prom_halt(); | 714 | prom_halt(); |
| 714 | } | 715 | } |
| 715 | 716 | ||
| 716 | return sun4v_build_common(sysino, &sun4v_virq); | 717 | virq = sun4v_build_common(sysino, &sun4v_virq); |
| 718 | |||
| 719 | virt_to_real_irq_table[virq].dev_handle = devhandle; | ||
| 720 | virt_to_real_irq_table[virq].dev_ino = devino; | ||
| 721 | |||
| 722 | return virq; | ||
| 717 | } | 723 | } |
| 718 | 724 | ||
| 719 | #ifdef CONFIG_PCI_MSI | 725 | #ifdef CONFIG_PCI_MSI |
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 6a6882e57ff2..1a1043fcf97d 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c | |||
| @@ -79,6 +79,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
| 79 | 79 | ||
| 80 | while (dp) { | 80 | while (dp) { |
| 81 | struct sparc_isa_device *isa_dev; | 81 | struct sparc_isa_device *isa_dev; |
| 82 | struct dev_archdata *sd; | ||
| 82 | 83 | ||
| 83 | isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); | 84 | isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); |
| 84 | if (!isa_dev) { | 85 | if (!isa_dev) { |
| @@ -86,6 +87,10 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
| 86 | return; | 87 | return; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 90 | sd = &isa_dev->ofdev.dev.archdata; | ||
| 91 | sd->prom_node = dp; | ||
| 92 | sd->op = &isa_dev->ofdev; | ||
| 93 | |||
| 89 | isa_dev->ofdev.node = dp; | 94 | isa_dev->ofdev.node = dp; |
| 90 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; | 95 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; |
| 91 | isa_dev->ofdev.dev.bus = &isa_bus_type; | 96 | isa_dev->ofdev.dev.bus = &isa_bus_type; |
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 13a79fe5115b..cce4d0ddf5d5 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c | |||
| @@ -83,7 +83,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp, | |||
| 83 | hp->handle_size = handle_size; | 83 | hp->handle_size = handle_size; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size) | 86 | static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size) |
| 87 | { | 87 | { |
| 88 | struct mdesc_handle *hp; | 88 | struct mdesc_handle *hp; |
| 89 | unsigned int handle_size, alloc_size; | 89 | unsigned int handle_size, alloc_size; |
| @@ -123,7 +123,7 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp) | |||
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | static struct mdesc_mem_ops bootmem_mdesc_memops = { | 126 | static struct mdesc_mem_ops bootmem_mdesc_ops = { |
| 127 | .alloc = mdesc_bootmem_alloc, | 127 | .alloc = mdesc_bootmem_alloc, |
| 128 | .free = mdesc_bootmem_free, | 128 | .free = mdesc_bootmem_free, |
| 129 | }; | 129 | }; |
| @@ -860,7 +860,7 @@ void __init sun4v_mdesc_init(void) | |||
| 860 | 860 | ||
| 861 | printk("MDESC: Size is %lu bytes.\n", len); | 861 | printk("MDESC: Size is %lu bytes.\n", len); |
| 862 | 862 | ||
| 863 | hp = mdesc_alloc(len, &bootmem_mdesc_memops); | 863 | hp = mdesc_alloc(len, &bootmem_mdesc_ops); |
| 864 | if (hp == NULL) { | 864 | if (hp == NULL) { |
| 865 | prom_printf("MDESC: alloc of %lu bytes failed.\n", len); | 865 | prom_printf("MDESC: alloc of %lu bytes failed.\n", len); |
| 866 | prom_halt(); | 866 | prom_halt(); |
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 7b0dce9604ee..4cc77485f536 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
| @@ -752,11 +752,16 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
| 752 | { | 752 | { |
| 753 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); | 753 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); |
| 754 | const unsigned int *irq; | 754 | const unsigned int *irq; |
| 755 | struct dev_archdata *sd; | ||
| 755 | int len, i; | 756 | int len, i; |
| 756 | 757 | ||
| 757 | if (!op) | 758 | if (!op) |
| 758 | return NULL; | 759 | return NULL; |
| 759 | 760 | ||
| 761 | sd = &op->dev.archdata; | ||
| 762 | sd->prom_node = dp; | ||
| 763 | sd->op = op; | ||
| 764 | |||
| 760 | op->node = dp; | 765 | op->node = dp; |
| 761 | 766 | ||
| 762 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", | 767 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 6b3fe2c1d65e..639cf06ca372 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
| @@ -1129,7 +1129,7 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |||
| 1129 | } | 1129 | } |
| 1130 | #endif /* !(CONFIG_PCI_MSI) */ | 1130 | #endif /* !(CONFIG_PCI_MSI) */ |
| 1131 | 1131 | ||
| 1132 | static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) | 1132 | static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) |
| 1133 | { | 1133 | { |
| 1134 | struct pci_pbm_info *pbm; | 1134 | struct pci_pbm_info *pbm; |
| 1135 | 1135 | ||
| @@ -1163,7 +1163,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
| 1163 | pci_sun4v_msi_init(pbm); | 1163 | pci_sun4v_msi_init(pbm); |
| 1164 | } | 1164 | } |
| 1165 | 1165 | ||
| 1166 | void sun4v_pci_init(struct device_node *dp, char *model_name) | 1166 | void __init sun4v_pci_init(struct device_node *dp, char *model_name) |
| 1167 | { | 1167 | { |
| 1168 | static int hvapi_negotiated = 0; | 1168 | static int hvapi_negotiated = 0; |
| 1169 | struct pci_controller_info *p; | 1169 | struct pci_controller_info *p; |
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index b00feb01c16f..881a09ee4c4c 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c | |||
| @@ -46,7 +46,7 @@ static void (*poweroff_method)(void) = machine_alt_power_off; | |||
| 46 | void machine_power_off(void) | 46 | void machine_power_off(void) |
| 47 | { | 47 | { |
| 48 | sstate_poweroff(); | 48 | sstate_poweroff(); |
| 49 | if (!serial_console || scons_pwroff) { | 49 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) { |
| 50 | if (power_reg) { | 50 | if (power_reg) { |
| 51 | /* Both register bits seem to have the | 51 | /* Both register bits seem to have the |
| 52 | * same effect, so until I figure out | 52 | * same effect, so until I figure out |
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 93557507ec9f..fd7899ba1d70 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
| @@ -119,7 +119,7 @@ extern void (*prom_keyboard)(void); | |||
| 119 | void machine_halt(void) | 119 | void machine_halt(void) |
| 120 | { | 120 | { |
| 121 | sstate_halt(); | 121 | sstate_halt(); |
| 122 | if (!serial_console && prom_palette) | 122 | if (prom_palette) |
| 123 | prom_palette (1); | 123 | prom_palette (1); |
| 124 | if (prom_keyboard) | 124 | if (prom_keyboard) |
| 125 | prom_keyboard(); | 125 | prom_keyboard(); |
| @@ -130,7 +130,7 @@ void machine_halt(void) | |||
| 130 | void machine_alt_power_off(void) | 130 | void machine_alt_power_off(void) |
| 131 | { | 131 | { |
| 132 | sstate_poweroff(); | 132 | sstate_poweroff(); |
| 133 | if (!serial_console && prom_palette) | 133 | if (prom_palette) |
| 134 | prom_palette(1); | 134 | prom_palette(1); |
| 135 | if (prom_keyboard) | 135 | if (prom_keyboard) |
| 136 | prom_keyboard(); | 136 | prom_keyboard(); |
| @@ -145,7 +145,7 @@ void machine_restart(char * cmd) | |||
| 145 | sstate_reboot(); | 145 | sstate_reboot(); |
| 146 | p = strchr (reboot_command, '\n'); | 146 | p = strchr (reboot_command, '\n'); |
| 147 | if (p) *p = 0; | 147 | if (p) *p = 0; |
| 148 | if (!serial_console && prom_palette) | 148 | if (prom_palette) |
| 149 | prom_palette (1); | 149 | prom_palette (1); |
| 150 | if (prom_keyboard) | 150 | if (prom_keyboard) |
| 151 | prom_keyboard(); | 151 | prom_keyboard(); |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 2b2017ce2267..f4e0a9ad9be3 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
| @@ -1646,6 +1646,60 @@ static void __init of_fill_in_cpu_data(void) | |||
| 1646 | smp_fill_in_sib_core_maps(); | 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 | void __init prom_build_devicetree(void) | 1703 | void __init prom_build_devicetree(void) |
| 1650 | { | 1704 | { |
| 1651 | struct device_node **nextp; | 1705 | struct device_node **nextp; |
| @@ -1658,6 +1712,8 @@ void __init prom_build_devicetree(void) | |||
| 1658 | allnodes->child = build_tree(allnodes, | 1712 | allnodes->child = build_tree(allnodes, |
| 1659 | prom_getchild(allnodes->node), | 1713 | prom_getchild(allnodes->node), |
| 1660 | &nextp); | 1714 | &nextp); |
| 1715 | of_console_init(); | ||
| 1716 | |||
| 1661 | printk("PROM: Built device tree with %u bytes of memory.\n", | 1717 | printk("PROM: Built device tree with %u bytes of memory.\n", |
| 1662 | prom_early_allocated); | 1718 | prom_early_allocated); |
| 1663 | 1719 | ||
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index aafde3dd9fd4..0f5be828ee92 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c | |||
| @@ -133,33 +133,6 @@ static void __init process_switch(char 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 | static void __init boot_flags_init(char *commands) | 136 | static void __init boot_flags_init(char *commands) |
| 164 | { | 137 | { |
| 165 | while (*commands) { | 138 | while (*commands) { |
| @@ -176,9 +149,7 @@ static void __init boot_flags_init(char *commands) | |||
| 176 | process_switch(*commands++); | 149 | process_switch(*commands++); |
| 177 | continue; | 150 | continue; |
| 178 | } | 151 | } |
| 179 | if (!strncmp(commands, "console=", 8)) { | 152 | if (!strncmp(commands, "mem=", 4)) { |
| 180 | process_console(commands); | ||
| 181 | } else if (!strncmp(commands, "mem=", 4)) { | ||
| 182 | /* | 153 | /* |
| 183 | * "mem=XXX[kKmM]" overrides the PROM-reported | 154 | * "mem=XXX[kKmM]" overrides the PROM-reported |
| 184 | * memory size. | 155 | * memory size. |
| @@ -378,44 +349,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 378 | paging_init(); | 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 | /* BUFFER is PAGE_SIZE bytes long. */ | 352 | /* BUFFER is PAGE_SIZE bytes long. */ |
| 420 | 353 | ||
| 421 | extern char *sparc_cpu_type; | 354 | extern char *sparc_cpu_type; |
| @@ -508,5 +441,4 @@ void sun_do_break(void) | |||
| 508 | prom_cmdline(); | 441 | prom_cmdline(); |
| 509 | } | 442 | } |
| 510 | 443 | ||
| 511 | int serial_console = -1; | ||
| 512 | int stop_a_enabled = 1; | 444 | int stop_a_enabled = 1; |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 719d676c2ddc..7d36531aa5b9 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
| @@ -330,7 +330,6 @@ EXPORT_SYMBOL(VISenter); | |||
| 330 | 330 | ||
| 331 | /* for input/keybdev */ | 331 | /* for input/keybdev */ |
| 332 | EXPORT_SYMBOL(sun_do_break); | 332 | EXPORT_SYMBOL(sun_do_break); |
| 333 | EXPORT_SYMBOL(serial_console); | ||
| 334 | EXPORT_SYMBOL(stop_a_enabled); | 333 | EXPORT_SYMBOL(stop_a_enabled); |
| 335 | 334 | ||
| 336 | #ifdef CONFIG_DEBUG_BUGVERBOSE | 335 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 592ffcd57605..e340eb401fb9 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
| @@ -1434,6 +1434,78 @@ static int bq4802_set_rtc_time(struct rtc_time *time) | |||
| 1434 | 1434 | ||
| 1435 | return 0; | 1435 | return 0; |
| 1436 | } | 1436 | } |
| 1437 | |||
| 1438 | static void cmos_get_rtc_time(struct rtc_time *rtc_tm) | ||
| 1439 | { | ||
| 1440 | unsigned char ctrl; | ||
| 1441 | |||
| 1442 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | ||
| 1443 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | ||
| 1444 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | ||
| 1445 | rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); | ||
| 1446 | rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); | ||
| 1447 | rtc_tm->tm_year = CMOS_READ(RTC_YEAR); | ||
| 1448 | rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); | ||
| 1449 | |||
| 1450 | ctrl = CMOS_READ(RTC_CONTROL); | ||
| 1451 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 1452 | BCD_TO_BIN(rtc_tm->tm_sec); | ||
| 1453 | BCD_TO_BIN(rtc_tm->tm_min); | ||
| 1454 | BCD_TO_BIN(rtc_tm->tm_hour); | ||
| 1455 | BCD_TO_BIN(rtc_tm->tm_mday); | ||
| 1456 | BCD_TO_BIN(rtc_tm->tm_mon); | ||
| 1457 | BCD_TO_BIN(rtc_tm->tm_year); | ||
| 1458 | BCD_TO_BIN(rtc_tm->tm_wday); | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | if (rtc_tm->tm_year <= 69) | ||
| 1462 | rtc_tm->tm_year += 100; | ||
| 1463 | |||
| 1464 | rtc_tm->tm_mon--; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | static int cmos_set_rtc_time(struct rtc_time *rtc_tm) | ||
| 1468 | { | ||
| 1469 | unsigned char mon, day, hrs, min, sec; | ||
| 1470 | unsigned char save_control, save_freq_select; | ||
| 1471 | unsigned int yrs; | ||
| 1472 | |||
| 1473 | yrs = rtc_tm->tm_year; | ||
| 1474 | mon = rtc_tm->tm_mon + 1; | ||
| 1475 | day = rtc_tm->tm_mday; | ||
| 1476 | hrs = rtc_tm->tm_hour; | ||
| 1477 | min = rtc_tm->tm_min; | ||
| 1478 | sec = rtc_tm->tm_sec; | ||
| 1479 | |||
| 1480 | if (yrs >= 100) | ||
| 1481 | yrs -= 100; | ||
| 1482 | |||
| 1483 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 1484 | BIN_TO_BCD(sec); | ||
| 1485 | BIN_TO_BCD(min); | ||
| 1486 | BIN_TO_BCD(hrs); | ||
| 1487 | BIN_TO_BCD(day); | ||
| 1488 | BIN_TO_BCD(mon); | ||
| 1489 | BIN_TO_BCD(yrs); | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | save_control = CMOS_READ(RTC_CONTROL); | ||
| 1493 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
| 1494 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
| 1495 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
| 1496 | |||
| 1497 | CMOS_WRITE(yrs, RTC_YEAR); | ||
| 1498 | CMOS_WRITE(mon, RTC_MONTH); | ||
| 1499 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | ||
| 1500 | CMOS_WRITE(hrs, RTC_HOURS); | ||
| 1501 | CMOS_WRITE(min, RTC_MINUTES); | ||
| 1502 | CMOS_WRITE(sec, RTC_SECONDS); | ||
| 1503 | |||
| 1504 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
| 1505 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
| 1506 | |||
| 1507 | return 0; | ||
| 1508 | } | ||
| 1437 | #endif /* CONFIG_PCI */ | 1509 | #endif /* CONFIG_PCI */ |
| 1438 | 1510 | ||
| 1439 | struct mini_rtc_ops { | 1511 | struct mini_rtc_ops { |
| @@ -1456,6 +1528,11 @@ static struct mini_rtc_ops bq4802_rtc_ops = { | |||
| 1456 | .get_rtc_time = bq4802_get_rtc_time, | 1528 | .get_rtc_time = bq4802_get_rtc_time, |
| 1457 | .set_rtc_time = bq4802_set_rtc_time, | 1529 | .set_rtc_time = bq4802_set_rtc_time, |
| 1458 | }; | 1530 | }; |
| 1531 | |||
| 1532 | static struct mini_rtc_ops cmos_rtc_ops = { | ||
| 1533 | .get_rtc_time = cmos_get_rtc_time, | ||
| 1534 | .set_rtc_time = cmos_set_rtc_time, | ||
| 1535 | }; | ||
| 1459 | #endif /* CONFIG_PCI */ | 1536 | #endif /* CONFIG_PCI */ |
| 1460 | 1537 | ||
| 1461 | static struct mini_rtc_ops *mini_rtc_ops; | 1538 | static struct mini_rtc_ops *mini_rtc_ops; |
| @@ -1583,6 +1660,8 @@ static int __init rtc_mini_init(void) | |||
| 1583 | #ifdef CONFIG_PCI | 1660 | #ifdef CONFIG_PCI |
| 1584 | else if (bq4802_regs) | 1661 | else if (bq4802_regs) |
| 1585 | mini_rtc_ops = &bq4802_rtc_ops; | 1662 | mini_rtc_ops = &bq4802_rtc_ops; |
| 1663 | else if (ds1287_regs) | ||
| 1664 | mini_rtc_ops = &cmos_rtc_ops; | ||
| 1586 | #endif /* CONFIG_PCI */ | 1665 | #endif /* CONFIG_PCI */ |
| 1587 | else | 1666 | else |
| 1588 | return -ENODEV; | 1667 | return -ENODEV; |
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 491223a6628f..3685daf5157f 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
| @@ -205,7 +205,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
| 205 | struct device_node *dp; | 205 | struct device_node *dp; |
| 206 | struct vio_dev *vdev; | 206 | struct vio_dev *vdev; |
| 207 | int err, tlen, clen; | 207 | int err, tlen, clen; |
| 208 | const u64 *id; | 208 | const u64 *id, *cfg_handle; |
| 209 | u64 a; | ||
| 209 | 210 | ||
| 210 | type = mdesc_get_property(hp, mp, "device-type", &tlen); | 211 | type = mdesc_get_property(hp, mp, "device-type", &tlen); |
| 211 | if (!type) { | 212 | if (!type) { |
| @@ -221,26 +222,18 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
| 221 | return NULL; | 222 | return NULL; |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | if (!strcmp(type, "vdc-port")) { | 225 | id = mdesc_get_property(hp, mp, "id", NULL); |
| 225 | u64 a; | ||
| 226 | 226 | ||
| 227 | id = NULL; | 227 | cfg_handle = NULL; |
| 228 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { | 228 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { |
| 229 | u64 target; | 229 | u64 target; |
| 230 | 230 | ||
| 231 | target = mdesc_arc_target(hp, a); | 231 | target = mdesc_arc_target(hp, a); |
| 232 | id = mdesc_get_property(hp, target, | 232 | cfg_handle = mdesc_get_property(hp, target, |
| 233 | "cfg-handle", NULL); | 233 | "cfg-handle", NULL); |
| 234 | if (id) | 234 | if (cfg_handle) |
| 235 | break; | 235 | break; |
| 236 | } | 236 | } |
| 237 | if (!id) { | ||
| 238 | printk(KERN_ERR "VIO: vdc-port lacks parent " | ||
| 239 | "cfg-handle.\n"); | ||
| 240 | return NULL; | ||
| 241 | } | ||
| 242 | } else | ||
| 243 | id = mdesc_get_property(hp, mp, "id", NULL); | ||
| 244 | 237 | ||
| 245 | bus_id_name = type; | 238 | bus_id_name = type; |
| 246 | if (!strcmp(type, "domain-services-port")) | 239 | if (!strcmp(type, "domain-services-port")) |
| @@ -285,10 +278,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
| 285 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", | 278 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", |
| 286 | bus_id_name); | 279 | bus_id_name); |
| 287 | vdev->dev_no = ~(u64)0; | 280 | vdev->dev_no = ~(u64)0; |
| 288 | } else { | 281 | } else if (!cfg_handle) { |
| 289 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", | 282 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", |
| 290 | bus_id_name, *id); | 283 | bus_id_name, *id); |
| 291 | vdev->dev_no = *id; | 284 | vdev->dev_no = *id; |
| 285 | } else { | ||
| 286 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu", | ||
| 287 | bus_id_name, *cfg_handle, *id); | ||
| 288 | vdev->dev_no = *cfg_handle; | ||
| 292 | } | 289 | } |
| 293 | 290 | ||
| 294 | vdev->dev.parent = parent; | 291 | vdev->dev.parent = parent; |
diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c index 7c25c54cefdc..3fafa9a8b50b 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc64/prom/console.c | |||
| @@ -73,88 +73,3 @@ prom_puts(const char *s, int len) | |||
| 73 | P1275_INOUT(3,1), | 73 | P1275_INOUT(3,1), |
| 74 | prom_stdout, s, P1275_SIZE(len)); | 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 | } | ||
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index 33c5b7da31e5..68c83ad04ad9 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c | |||
| @@ -72,7 +72,7 @@ void prom_cmdline(void) | |||
| 72 | 72 | ||
| 73 | local_irq_save(flags); | 73 | local_irq_save(flags); |
| 74 | 74 | ||
| 75 | if (!serial_console && prom_palette) | 75 | if (prom_palette) |
| 76 | prom_palette(1); | 76 | prom_palette(1); |
| 77 | 77 | ||
| 78 | #ifdef CONFIG_SMP | 78 | #ifdef CONFIG_SMP |
| @@ -85,7 +85,7 @@ void prom_cmdline(void) | |||
| 85 | smp_release(); | 85 | smp_release(); |
| 86 | #endif | 86 | #endif |
| 87 | 87 | ||
| 88 | if (!serial_console && prom_palette) | 88 | if (prom_palette) |
| 89 | prom_palette(0); | 89 | prom_palette(0); |
| 90 | 90 | ||
| 91 | local_irq_restore(flags); | 91 | local_irq_restore(flags); |
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c index 17b7ecfe7ca9..b2c5b12c9818 100644 --- a/arch/sparc64/prom/tree.c +++ b/arch/sparc64/prom/tree.c | |||
| @@ -304,3 +304,11 @@ prom_pathtoinode(const char *path) | |||
| 304 | if (node == -1) return 0; | 304 | if (node == -1) return 0; |
| 305 | return node; | 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 | } | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4373d7cdc5d2..c8dfd18bea44 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -726,7 +726,7 @@ config NVRAM | |||
| 726 | 726 | ||
| 727 | config RTC | 727 | config RTC |
| 728 | tristate "Enhanced Real Time Clock Support" | 728 | tristate "Enhanced Real Time Clock Support" |
| 729 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 | 729 | depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC64 && (!SPARC32 || PCI) && !FRV && !ARM && !SUPERH && !S390 |
| 730 | ---help--- | 730 | ---help--- |
| 731 | If you say Y here and create a character special file /dev/rtc with | 731 | If you say Y here and create a character special file /dev/rtc with |
| 732 | major number 10 and minor number 135 using mknod ("man mknod"), you | 732 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 22cf7aa56cc4..30c3f54c7666 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -86,12 +86,9 @@ | |||
| 86 | #include <asm/hpet.h> | 86 | #include <asm/hpet.h> |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
| 89 | #ifdef __sparc__ | 89 | #ifdef CONFIG_SPARC32 |
| 90 | #include <linux/pci.h> | 90 | #include <linux/pci.h> |
| 91 | #include <asm/ebus.h> | 91 | #include <asm/ebus.h> |
| 92 | #ifdef __sparc_v9__ | ||
| 93 | #include <asm/isa.h> | ||
| 94 | #endif | ||
| 95 | 92 | ||
| 96 | static unsigned long rtc_port; | 93 | static unsigned long rtc_port; |
| 97 | static int rtc_irq = PCI_IRQ_NONE; | 94 | static int rtc_irq = PCI_IRQ_NONE; |
| @@ -930,13 +927,9 @@ static int __init rtc_init(void) | |||
| 930 | unsigned int year, ctrl; | 927 | unsigned int year, ctrl; |
| 931 | char *guess = NULL; | 928 | char *guess = NULL; |
| 932 | #endif | 929 | #endif |
| 933 | #ifdef __sparc__ | 930 | #ifdef CONFIG_SPARC32 |
| 934 | struct linux_ebus *ebus; | 931 | struct linux_ebus *ebus; |
| 935 | struct linux_ebus_device *edev; | 932 | struct linux_ebus_device *edev; |
| 936 | #ifdef __sparc_v9__ | ||
| 937 | struct sparc_isa_bridge *isa_br; | ||
| 938 | struct sparc_isa_device *isa_dev; | ||
| 939 | #endif | ||
| 940 | #else | 933 | #else |
| 941 | void *r; | 934 | void *r; |
| 942 | #ifdef RTC_IRQ | 935 | #ifdef RTC_IRQ |
| @@ -944,7 +937,7 @@ static int __init rtc_init(void) | |||
| 944 | #endif | 937 | #endif |
| 945 | #endif | 938 | #endif |
| 946 | 939 | ||
| 947 | #ifdef __sparc__ | 940 | #ifdef CONFIG_SPARC32 |
| 948 | for_each_ebus(ebus) { | 941 | for_each_ebus(ebus) { |
| 949 | for_each_ebusdev(edev, ebus) { | 942 | for_each_ebusdev(edev, ebus) { |
| 950 | if(strcmp(edev->prom_node->name, "rtc") == 0) { | 943 | if(strcmp(edev->prom_node->name, "rtc") == 0) { |
| @@ -954,17 +947,6 @@ static int __init rtc_init(void) | |||
| 954 | } | 947 | } |
| 955 | } | 948 | } |
| 956 | } | 949 | } |
| 957 | #ifdef __sparc_v9__ | ||
| 958 | for_each_isa(isa_br) { | ||
| 959 | for_each_isadev(isa_dev, isa_br) { | ||
| 960 | if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { | ||
| 961 | rtc_port = isa_dev->resource.start; | ||
| 962 | rtc_irq = isa_dev->irq; | ||
| 963 | goto found; | ||
| 964 | } | ||
| 965 | } | ||
| 966 | } | ||
| 967 | #endif | ||
| 968 | rtc_has_irq = 0; | 950 | rtc_has_irq = 0; |
| 969 | printk(KERN_ERR "rtc_init: no PC rtc found\n"); | 951 | printk(KERN_ERR "rtc_init: no PC rtc found\n"); |
| 970 | return -EIO; | 952 | return -EIO; |
| @@ -1020,7 +1002,7 @@ no_irq: | |||
| 1020 | 1002 | ||
| 1021 | #endif | 1003 | #endif |
| 1022 | 1004 | ||
| 1023 | #endif /* __sparc__ vs. others */ | 1005 | #endif /* CONFIG_SPARC32 vs. others */ |
| 1024 | 1006 | ||
| 1025 | if (misc_register(&rtc_dev)) { | 1007 | if (misc_register(&rtc_dev)) { |
| 1026 | #ifdef RTC_IRQ | 1008 | #ifdef RTC_IRQ |
| @@ -1105,7 +1087,7 @@ static void __exit rtc_exit (void) | |||
| 1105 | remove_proc_entry ("driver/rtc", NULL); | 1087 | remove_proc_entry ("driver/rtc", NULL); |
| 1106 | misc_deregister(&rtc_dev); | 1088 | misc_deregister(&rtc_dev); |
| 1107 | 1089 | ||
| 1108 | #ifdef __sparc__ | 1090 | #ifdef CONFIG_SPARC32 |
| 1109 | if (rtc_has_irq) | 1091 | if (rtc_has_irq) |
| 1110 | free_irq (rtc_irq, &rtc_port); | 1092 | free_irq (rtc_irq, &rtc_port); |
| 1111 | #else | 1093 | #else |
| @@ -1117,7 +1099,7 @@ static void __exit rtc_exit (void) | |||
| 1117 | if (rtc_has_irq) | 1099 | if (rtc_has_irq) |
| 1118 | free_irq (RTC_IRQ, NULL); | 1100 | free_irq (RTC_IRQ, NULL); |
| 1119 | #endif | 1101 | #endif |
| 1120 | #endif /* __sparc__ */ | 1102 | #endif /* CONFIG_SPARC32 */ |
| 1121 | } | 1103 | } |
| 1122 | 1104 | ||
| 1123 | module_init(rtc_init); | 1105 | module_init(rtc_init); |
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index ef0066bab2cf..61f98251feab 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c | |||
| @@ -459,6 +459,22 @@ static int vnet_nack(struct vnet_port *port, void *msgbuf) | |||
| 459 | return 0; | 459 | return 0; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static int handle_mcast(struct vnet_port *port, void *msgbuf) | ||
| 463 | { | ||
| 464 | struct vio_net_mcast_info *pkt = msgbuf; | ||
| 465 | |||
| 466 | if (pkt->tag.stype != VIO_SUBTYPE_ACK) | ||
| 467 | printk(KERN_ERR PFX "%s: Got unexpected MCAST reply " | ||
| 468 | "[%02x:%02x:%04x:%08x]\n", | ||
| 469 | port->vp->dev->name, | ||
| 470 | pkt->tag.type, | ||
| 471 | pkt->tag.stype, | ||
| 472 | pkt->tag.stype_env, | ||
| 473 | pkt->tag.sid); | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 462 | static void maybe_tx_wakeup(struct vnet *vp) | 478 | static void maybe_tx_wakeup(struct vnet *vp) |
| 463 | { | 479 | { |
| 464 | struct net_device *dev = vp->dev; | 480 | struct net_device *dev = vp->dev; |
| @@ -544,7 +560,10 @@ static void vnet_event(void *arg, int event) | |||
| 544 | err = vnet_nack(port, &msgbuf); | 560 | err = vnet_nack(port, &msgbuf); |
| 545 | } | 561 | } |
| 546 | } else if (msgbuf.tag.type == VIO_TYPE_CTRL) { | 562 | } else if (msgbuf.tag.type == VIO_TYPE_CTRL) { |
| 547 | err = vio_control_pkt_engine(vio, &msgbuf); | 563 | if (msgbuf.tag.stype_env == VNET_MCAST_INFO) |
| 564 | err = handle_mcast(port, &msgbuf); | ||
| 565 | else | ||
| 566 | err = vio_control_pkt_engine(vio, &msgbuf); | ||
| 548 | if (err) | 567 | if (err) |
| 549 | break; | 568 | break; |
| 550 | } else { | 569 | } else { |
| @@ -731,9 +750,122 @@ static int vnet_close(struct net_device *dev) | |||
| 731 | return 0; | 750 | return 0; |
| 732 | } | 751 | } |
| 733 | 752 | ||
| 753 | static struct vnet_mcast_entry *__vnet_mc_find(struct vnet *vp, u8 *addr) | ||
| 754 | { | ||
| 755 | struct vnet_mcast_entry *m; | ||
| 756 | |||
| 757 | for (m = vp->mcast_list; m; m = m->next) { | ||
| 758 | if (!memcmp(m->addr, addr, ETH_ALEN)) | ||
| 759 | return m; | ||
| 760 | } | ||
| 761 | return NULL; | ||
| 762 | } | ||
| 763 | |||
| 764 | static void __update_mc_list(struct vnet *vp, struct net_device *dev) | ||
| 765 | { | ||
| 766 | struct dev_addr_list *p; | ||
| 767 | |||
| 768 | for (p = dev->mc_list; p; p = p->next) { | ||
| 769 | struct vnet_mcast_entry *m; | ||
| 770 | |||
| 771 | m = __vnet_mc_find(vp, p->dmi_addr); | ||
| 772 | if (m) { | ||
| 773 | m->hit = 1; | ||
| 774 | continue; | ||
| 775 | } | ||
| 776 | |||
| 777 | if (!m) { | ||
| 778 | m = kzalloc(sizeof(*m), GFP_ATOMIC); | ||
| 779 | if (!m) | ||
| 780 | continue; | ||
| 781 | memcpy(m->addr, p->dmi_addr, ETH_ALEN); | ||
| 782 | m->hit = 1; | ||
| 783 | |||
| 784 | m->next = vp->mcast_list; | ||
| 785 | vp->mcast_list = m; | ||
| 786 | } | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | static void __send_mc_list(struct vnet *vp, struct vnet_port *port) | ||
| 791 | { | ||
| 792 | struct vio_net_mcast_info info; | ||
| 793 | struct vnet_mcast_entry *m, **pp; | ||
| 794 | int n_addrs; | ||
| 795 | |||
| 796 | memset(&info, 0, sizeof(info)); | ||
| 797 | |||
| 798 | info.tag.type = VIO_TYPE_CTRL; | ||
| 799 | info.tag.stype = VIO_SUBTYPE_INFO; | ||
| 800 | info.tag.stype_env = VNET_MCAST_INFO; | ||
| 801 | info.tag.sid = vio_send_sid(&port->vio); | ||
| 802 | info.set = 1; | ||
| 803 | |||
| 804 | n_addrs = 0; | ||
| 805 | for (m = vp->mcast_list; m; m = m->next) { | ||
| 806 | if (m->sent) | ||
| 807 | continue; | ||
| 808 | m->sent = 1; | ||
| 809 | memcpy(&info.mcast_addr[n_addrs * ETH_ALEN], | ||
| 810 | m->addr, ETH_ALEN); | ||
| 811 | if (++n_addrs == VNET_NUM_MCAST) { | ||
| 812 | info.count = n_addrs; | ||
| 813 | |||
| 814 | (void) vio_ldc_send(&port->vio, &info, | ||
| 815 | sizeof(info)); | ||
| 816 | n_addrs = 0; | ||
| 817 | } | ||
| 818 | } | ||
| 819 | if (n_addrs) { | ||
| 820 | info.count = n_addrs; | ||
| 821 | (void) vio_ldc_send(&port->vio, &info, sizeof(info)); | ||
| 822 | } | ||
| 823 | |||
| 824 | info.set = 0; | ||
| 825 | |||
| 826 | n_addrs = 0; | ||
| 827 | pp = &vp->mcast_list; | ||
| 828 | while ((m = *pp) != NULL) { | ||
| 829 | if (m->hit) { | ||
| 830 | m->hit = 0; | ||
| 831 | pp = &m->next; | ||
| 832 | continue; | ||
| 833 | } | ||
| 834 | |||
| 835 | memcpy(&info.mcast_addr[n_addrs * ETH_ALEN], | ||
| 836 | m->addr, ETH_ALEN); | ||
| 837 | if (++n_addrs == VNET_NUM_MCAST) { | ||
| 838 | info.count = n_addrs; | ||
| 839 | (void) vio_ldc_send(&port->vio, &info, | ||
| 840 | sizeof(info)); | ||
| 841 | n_addrs = 0; | ||
| 842 | } | ||
| 843 | |||
| 844 | *pp = m->next; | ||
| 845 | kfree(m); | ||
| 846 | } | ||
| 847 | if (n_addrs) { | ||
| 848 | info.count = n_addrs; | ||
| 849 | (void) vio_ldc_send(&port->vio, &info, sizeof(info)); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 734 | static void vnet_set_rx_mode(struct net_device *dev) | 853 | static void vnet_set_rx_mode(struct net_device *dev) |
| 735 | { | 854 | { |
| 736 | /* XXX Implement multicast support XXX */ | 855 | struct vnet *vp = netdev_priv(dev); |
| 856 | struct vnet_port *port; | ||
| 857 | unsigned long flags; | ||
| 858 | |||
| 859 | spin_lock_irqsave(&vp->lock, flags); | ||
| 860 | if (!list_empty(&vp->port_list)) { | ||
| 861 | port = list_entry(vp->port_list.next, struct vnet_port, list); | ||
| 862 | |||
| 863 | if (port->switch_port) { | ||
| 864 | __update_mc_list(vp, dev); | ||
| 865 | __send_mc_list(vp, port); | ||
| 866 | } | ||
| 867 | } | ||
| 868 | spin_unlock_irqrestore(&vp->lock, flags); | ||
| 737 | } | 869 | } |
| 738 | 870 | ||
| 739 | static int vnet_change_mtu(struct net_device *dev, int new_mtu) | 871 | static int vnet_change_mtu(struct net_device *dev, int new_mtu) |
| @@ -1070,6 +1202,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, | |||
| 1070 | switch_port = 0; | 1202 | switch_port = 0; |
| 1071 | if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL) | 1203 | if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL) |
| 1072 | switch_port = 1; | 1204 | switch_port = 1; |
| 1205 | port->switch_port = switch_port; | ||
| 1073 | 1206 | ||
| 1074 | spin_lock_irqsave(&vp->lock, flags); | 1207 | spin_lock_irqsave(&vp->lock, flags); |
| 1075 | if (switch_port) | 1208 | if (switch_port) |
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h index 7d3a0cac727b..d347a5bf24b0 100644 --- a/drivers/net/sunvnet.h +++ b/drivers/net/sunvnet.h | |||
| @@ -30,6 +30,8 @@ struct vnet_port { | |||
| 30 | 30 | ||
| 31 | struct hlist_node hash; | 31 | struct hlist_node hash; |
| 32 | u8 raddr[ETH_ALEN]; | 32 | u8 raddr[ETH_ALEN]; |
| 33 | u8 switch_port; | ||
| 34 | u8 __pad; | ||
| 33 | 35 | ||
| 34 | struct vnet *vp; | 36 | struct vnet *vp; |
| 35 | 37 | ||
| @@ -53,6 +55,13 @@ static inline unsigned int vnet_hashfn(u8 *mac) | |||
| 53 | return val & (VNET_PORT_HASH_MASK); | 55 | return val & (VNET_PORT_HASH_MASK); |
| 54 | } | 56 | } |
| 55 | 57 | ||
| 58 | struct vnet_mcast_entry { | ||
| 59 | u8 addr[ETH_ALEN]; | ||
| 60 | u8 sent; | ||
| 61 | u8 hit; | ||
| 62 | struct vnet_mcast_entry *next; | ||
| 63 | }; | ||
| 64 | |||
| 56 | struct vnet { | 65 | struct vnet { |
| 57 | /* Protects port_list and port_hash. */ | 66 | /* Protects port_list and port_hash. */ |
| 58 | spinlock_t lock; | 67 | spinlock_t lock; |
| @@ -65,6 +74,8 @@ struct vnet { | |||
| 65 | 74 | ||
| 66 | struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; | 75 | struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; |
| 67 | 76 | ||
| 77 | struct vnet_mcast_entry *mcast_list; | ||
| 78 | |||
| 68 | struct list_head list; | 79 | struct list_head list; |
| 69 | u64 local_mac; | 80 | u64 local_mac; |
| 70 | }; | 81 | }; |
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 002643392d42..2553629ec15d 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c | |||
| @@ -33,6 +33,7 @@ struct sbus_bus *sbus_root; | |||
| 33 | 33 | ||
| 34 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) | 34 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) |
| 35 | { | 35 | { |
| 36 | struct dev_archdata *sd; | ||
| 36 | unsigned long base; | 37 | unsigned long base; |
| 37 | const void *pval; | 38 | const void *pval; |
| 38 | int len, err; | 39 | int len, err; |
| @@ -67,6 +68,10 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde | |||
| 67 | 68 | ||
| 68 | sbus_fill_device_irq(sdev); | 69 | sbus_fill_device_irq(sdev); |
| 69 | 70 | ||
| 71 | sd = &sdev->ofdev.dev.archdata; | ||
| 72 | sd->prom_node = dp; | ||
| 73 | sd->op = &sdev->ofdev; | ||
| 74 | |||
| 70 | sdev->ofdev.node = dp; | 75 | sdev->ofdev.node = dp; |
| 71 | if (sdev->parent) | 76 | if (sdev->parent) |
| 72 | sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; | 77 | sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; |
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c index b45ba5392dd3..70a09a3d5af0 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c | |||
| @@ -16,9 +16,10 @@ | |||
| 16 | #include <linux/tty.h> | 16 | #include <linux/tty.h> |
| 17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
| 18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
| 19 | #include <linux/serial_core.h> | ||
| 19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 20 | 21 | ||
| 21 | #include <asm/oplib.h> | 22 | #include <asm/prom.h> |
| 22 | 23 | ||
| 23 | #include "suncore.h" | 24 | #include "suncore.h" |
| 24 | 25 | ||
| @@ -26,92 +27,60 @@ int sunserial_current_minor = 64; | |||
| 26 | 27 | ||
| 27 | EXPORT_SYMBOL(sunserial_current_minor); | 28 | EXPORT_SYMBOL(sunserial_current_minor); |
| 28 | 29 | ||
| 29 | void | 30 | int sunserial_console_match(struct console *con, struct device_node *dp, |
| 30 | sunserial_console_termios(struct console *con) | 31 | struct uart_driver *drv, int line) |
| 31 | { | 32 | { |
| 32 | char mode[16], buf[16], *s; | 33 | int off; |
| 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; | ||
| 42 | |||
| 43 | if (!serial_console) | ||
| 44 | return; | ||
| 45 | |||
| 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; | ||
| 52 | |||
| 53 | case PROMDEV_OTTYB: | ||
| 54 | mode_prop[3] = 'b'; | ||
| 55 | cd_prop[3] = 'b'; | ||
| 56 | dtr_prop[3] = 'b'; | ||
| 57 | break; | ||
| 58 | |||
| 59 | case PROMDEV_ORSC: | ||
| 60 | |||
| 61 | nd = prom_pathtoinode("rsc"); | ||
| 62 | if (!nd) { | ||
| 63 | strcpy(mode, "115200,8,n,1,-"); | ||
| 64 | goto no_options; | ||
| 65 | } | ||
| 66 | 34 | ||
| 67 | if (!prom_node_has_property(nd, ssp_console_modes_prop)) { | 35 | if (!con || of_console_device != dp) |
| 68 | strcpy(mode, "115200,8,n,1,-"); | 36 | return 0; |
| 69 | goto no_options; | ||
| 70 | } | ||
| 71 | 37 | ||
| 72 | memset(mode, 0, sizeof(mode)); | 38 | off = 0; |
| 73 | prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode)); | 39 | if (of_console_options && |
| 74 | goto no_options; | 40 | *of_console_options == 'b') |
| 41 | off = 1; | ||
| 75 | 42 | ||
| 76 | default: | 43 | if ((line & 1) != off) |
| 77 | strcpy(mode, "9600,8,n,1,-"); | 44 | return 0; |
| 78 | goto no_options; | ||
| 79 | } | ||
| 80 | 45 | ||
| 81 | topnd = prom_getchild(prom_root_node); | 46 | con->index = line; |
| 82 | nd = prom_searchsiblings(topnd, "options"); | 47 | drv->cons = con; |
| 83 | if (!nd) { | 48 | add_preferred_console(con->name, line, NULL); |
| 84 | strcpy(mode, "9600,8,n,1,-"); | ||
| 85 | goto no_options; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (!prom_node_has_property(nd, mode_prop)) { | ||
| 89 | strcpy(mode, "9600,8,n,1,-"); | ||
| 90 | goto no_options; | ||
| 91 | } | ||
| 92 | 49 | ||
| 93 | memset(mode, 0, sizeof(mode)); | 50 | return 1; |
| 94 | prom_getstring(nd, mode_prop, mode, sizeof(mode)); | 51 | } |
| 95 | 52 | EXPORT_SYMBOL(sunserial_console_match); | |
| 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 | 53 | ||
| 105 | if (prom_node_has_property(nd, dtr_prop)) { | 54 | void |
| 106 | memset(buf, 0, sizeof(buf)); | 55 | sunserial_console_termios(struct console *con) |
| 107 | prom_getstring(nd, dtr_prop, buf, sizeof(buf)); | 56 | { |
| 108 | if (!strcmp(buf, "false")) | 57 | struct device_node *dp; |
| 109 | rtsdtr = 0; | 58 | const char *od, *mode, *s; |
| 59 | char mode_prop[] = "ttyX-mode"; | ||
| 60 | int baud, bits, stop, cflag; | ||
| 61 | char parity; | ||
| 110 | 62 | ||
| 111 | /* XXX: this is unused below. */ | 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; | ||
| 72 | |||
| 73 | c = 'a'; | ||
| 74 | if (of_console_options) | ||
| 75 | c = *of_console_options; | ||
| 76 | |||
| 77 | mode_prop[3] = c; | ||
| 78 | |||
| 79 | mode = of_get_property(dp, mode_prop, NULL); | ||
| 80 | if (!mode) | ||
| 81 | mode = "9600,8,n,1,-"; | ||
| 112 | } | 82 | } |
| 113 | 83 | ||
| 114 | no_options: | ||
| 115 | cflag = CREAD | HUPCL | CLOCAL; | 84 | cflag = CREAD | HUPCL | CLOCAL; |
| 116 | 85 | ||
| 117 | s = mode; | 86 | s = mode; |
diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h index 513916a8ce37..829d7d65d6db 100644 --- a/drivers/serial/suncore.h +++ b/drivers/serial/suncore.h | |||
| @@ -24,6 +24,8 @@ extern int suncore_mouse_baud_detection(unsigned char, int); | |||
| 24 | 24 | ||
| 25 | extern int sunserial_current_minor; | 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 | extern void sunserial_console_termios(struct console *); | 29 | extern void sunserial_console_termios(struct console *); |
| 28 | 30 | ||
| 29 | #endif /* !(_SERIAL_SUN_H) */ | 31 | #endif /* !(_SERIAL_SUN_H) */ |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index d82be42ff29a..8ff900b09811 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
| @@ -520,16 +520,6 @@ static struct console sunhv_console = { | |||
| 520 | .data = &sunhv_reg, | 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 | static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) | 523 | static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) |
| 534 | { | 524 | { |
| 535 | struct uart_port *port; | 525 | struct uart_port *port; |
| @@ -582,7 +572,8 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m | |||
| 582 | sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; | 572 | sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; |
| 583 | sunserial_current_minor += 1; | 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 | err = uart_add_one_port(&sunhv_reg, port); | 578 | err = uart_add_one_port(&sunhv_reg, port); |
| 588 | if (err) | 579 | if (err) |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8a0f9e4408d4..bca57bb94939 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
| @@ -968,22 +968,6 @@ static struct console sunsab_console = { | |||
| 968 | 968 | ||
| 969 | static inline struct console *SUNSAB_CONSOLE(void) | 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 | return &sunsab_console; | 971 | return &sunsab_console; |
| 988 | } | 972 | } |
| 989 | #else | 973 | #else |
| @@ -1080,7 +1064,12 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * | |||
| 1080 | return err; | 1064 | return err; |
| 1081 | } | 1065 | } |
| 1082 | 1066 | ||
| 1067 | sunserial_console_match(SUNSAB_CONSOLE(), op->node, | ||
| 1068 | &sunsab_reg, up[0].port.line); | ||
| 1083 | uart_add_one_port(&sunsab_reg, &up[0].port); | 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 | uart_add_one_port(&sunsab_reg, &up[1].port); | 1073 | uart_add_one_port(&sunsab_reg, &up[1].port); |
| 1085 | 1074 | ||
| 1086 | dev_set_drvdata(&op->dev, &up[0]); | 1075 | dev_set_drvdata(&op->dev, &up[0]); |
| @@ -1164,7 +1153,6 @@ static int __init sunsab_init(void) | |||
| 1164 | } | 1153 | } |
| 1165 | 1154 | ||
| 1166 | sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; | 1155 | sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; |
| 1167 | sunsab_reg.cons = SUNSAB_CONSOLE(); | ||
| 1168 | sunserial_current_minor += num_channels; | 1156 | sunserial_current_minor += num_channels; |
| 1169 | } | 1157 | } |
| 1170 | 1158 | ||
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 26d720baf88c..79b13685bdfa 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
| @@ -1371,28 +1371,12 @@ static struct console sunsu_console = { | |||
| 1371 | * Register console. | 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 | return &sunsu_console; | 1376 | return &sunsu_console; |
| 1393 | } | 1377 | } |
| 1394 | #else | 1378 | #else |
| 1395 | #define SUNSU_CONSOLE(num_uart) (NULL) | 1379 | #define SUNSU_CONSOLE() (NULL) |
| 1396 | #define sunsu_serial_console_init() do { } while (0) | 1380 | #define sunsu_serial_console_init() do { } while (0) |
| 1397 | #endif | 1381 | #endif |
| 1398 | 1382 | ||
| @@ -1482,6 +1466,8 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m | |||
| 1482 | 1466 | ||
| 1483 | up->port.ops = &sunsu_pops; | 1467 | up->port.ops = &sunsu_pops; |
| 1484 | 1468 | ||
| 1469 | sunserial_console_match(SUNSU_CONSOLE(), dp, | ||
| 1470 | &sunsu_reg, up->port.line); | ||
| 1485 | err = uart_add_one_port(&sunsu_reg, &up->port); | 1471 | err = uart_add_one_port(&sunsu_reg, &up->port); |
| 1486 | if (err) | 1472 | if (err) |
| 1487 | goto out_unmap; | 1473 | goto out_unmap; |
| @@ -1572,7 +1558,6 @@ static int __init sunsu_init(void) | |||
| 1572 | return err; | 1558 | return err; |
| 1573 | sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; | 1559 | sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; |
| 1574 | sunserial_current_minor += num_uart; | 1560 | sunserial_current_minor += num_uart; |
| 1575 | sunsu_reg.cons = SUNSU_CONSOLE(num_uart); | ||
| 1576 | } | 1561 | } |
| 1577 | 1562 | ||
| 1578 | err = of_register_driver(&su_driver, &of_bus_type); | 1563 | err = of_register_driver(&su_driver, &of_bus_type); |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 0a3e10a4a35d..1d262c0c613f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
| @@ -1226,23 +1226,6 @@ static struct console sunzilog_console_ops = { | |||
| 1226 | 1226 | ||
| 1227 | static inline struct console *SUNZILOG_CONSOLE(void) | 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 | return &sunzilog_console_ops; | 1229 | return &sunzilog_console_ops; |
| 1247 | } | 1230 | } |
| 1248 | 1231 | ||
| @@ -1428,12 +1411,18 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m | |||
| 1428 | sunzilog_init_hw(&up[1]); | 1411 | sunzilog_init_hw(&up[1]); |
| 1429 | 1412 | ||
| 1430 | if (!keyboard_mouse) { | 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 | err = uart_add_one_port(&sunzilog_reg, &up[0].port); | 1417 | err = uart_add_one_port(&sunzilog_reg, &up[0].port); |
| 1432 | if (err) { | 1418 | if (err) { |
| 1433 | of_iounmap(&op->resource[0], | 1419 | of_iounmap(&op->resource[0], |
| 1434 | rp, sizeof(struct zilog_layout)); | 1420 | rp, sizeof(struct zilog_layout)); |
| 1435 | return err; | 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 | err = uart_add_one_port(&sunzilog_reg, &up[1].port); | 1426 | err = uart_add_one_port(&sunzilog_reg, &up[1].port); |
| 1438 | if (err) { | 1427 | if (err) { |
| 1439 | uart_remove_one_port(&sunzilog_reg, &up[0].port); | 1428 | uart_remove_one_port(&sunzilog_reg, &up[0].port); |
| @@ -1531,7 +1520,6 @@ static int __init sunzilog_init(void) | |||
| 1531 | goto out_free_tables; | 1520 | goto out_free_tables; |
| 1532 | 1521 | ||
| 1533 | sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; | 1522 | sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; |
| 1534 | sunzilog_reg.cons = SUNZILOG_CONSOLE(); | ||
| 1535 | 1523 | ||
| 1536 | sunserial_current_minor += uart_count; | 1524 | sunserial_current_minor += uart_count; |
| 1537 | } | 1525 | } |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 0c7bf75732ea..13990697b5c1 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -2913,10 +2913,6 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, | |||
| 2913 | int node, len, i, j, ret; | 2913 | int node, len, i, j, ret; |
| 2914 | u32 mem, chip_id; | 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 | * Map memory-mapped registers. | 2917 | * Map memory-mapped registers. |
| 2922 | */ | 2918 | */ |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index eb1a4812ad1d..b87ea21d3d78 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
| @@ -379,10 +379,6 @@ int __init igafb_init(void) | |||
| 379 | if (fb_get_options("igafb", NULL)) | 379 | if (fb_get_options("igafb", NULL)) |
| 380 | return -ENODEV; | 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 | pdev = pci_get_device(PCI_VENDOR_ID_INTERG, | 382 | pdev = pci_get_device(PCI_VENDOR_ID_INTERG, |
| 387 | PCI_DEVICE_ID_INTERG_1682, 0); | 383 | PCI_DEVICE_ID_INTERG_1682, 0); |
| 388 | if (pdev == NULL) { | 384 | if (pdev == NULL) { |
diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h index d8f9872b0e2d..4a56d84d69c4 100644 --- a/include/asm-sparc/device.h +++ b/include/asm-sparc/device.h | |||
| @@ -3,5 +3,17 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file is released under the GPLv2 | 4 | * This file is released under the GPLv2 |
| 5 | */ | 5 | */ |
| 6 | #include <asm-generic/device.h> | 6 | #ifndef _ASM_SPARC_DEVICE_H |
| 7 | #define _ASM_SPARC_DEVICE_H | ||
| 8 | |||
| 9 | struct device_node; | ||
| 10 | struct of_device; | ||
| 11 | |||
| 12 | struct dev_archdata { | ||
| 13 | struct device_node *prom_node; | ||
| 14 | struct of_device *op; | ||
| 15 | }; | ||
| 16 | |||
| 17 | #endif /* _ASM_SPARC_DEVICE_H */ | ||
| 18 | |||
| 7 | 19 | ||
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h index c7df38030992..c73ca081e1f5 100644 --- a/include/asm-sparc/fb.h +++ b/include/asm-sparc/fb.h | |||
| @@ -1,11 +1,20 @@ | |||
| 1 | #ifndef _ASM_FB_H_ | 1 | #ifndef _ASM_FB_H_ |
| 2 | #define _ASM_FB_H_ | 2 | #define _ASM_FB_H_ |
| 3 | #include <linux/fb.h> | 3 | #include <linux/fb.h> |
| 4 | #include <asm/prom.h> | ||
| 4 | 5 | ||
| 5 | #define fb_pgprotect(...) do {} while (0) | 6 | #define fb_pgprotect(...) do {} while (0) |
| 6 | 7 | ||
| 7 | static inline int fb_is_primary_device(struct fb_info *info) | 8 | static inline int fb_is_primary_device(struct fb_info *info) |
| 8 | { | 9 | { |
| 10 | struct device *dev = info->device; | ||
| 11 | struct device_node *node; | ||
| 12 | |||
| 13 | node = dev->archdata.prom_node; | ||
| 14 | if (node && | ||
| 15 | node == of_console_device) | ||
| 16 | return 1; | ||
| 17 | |||
| 9 | return 0; | 18 | return 0; |
| 10 | } | 19 | } |
| 11 | 20 | ||
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h index 91691e52c058..17ba82ee220a 100644 --- a/include/asm-sparc/oplib.h +++ b/include/asm-sparc/oplib.h | |||
| @@ -158,32 +158,6 @@ extern void prom_putchar(char character); | |||
| 158 | extern void prom_printf(char *fmt, ...); | 158 | extern void prom_printf(char *fmt, ...); |
| 159 | extern void prom_write(const char *buf, unsigned int len); | 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 | /* Multiprocessor operations... */ | 161 | /* Multiprocessor operations... */ |
| 188 | 162 | ||
| 189 | /* Start the CPU with the given device tree node, context table, and context | 163 | /* Start the CPU with the given device tree node, context table, and context |
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h index db9feb75bd86..350676c589f9 100644 --- a/include/asm-sparc/prom.h +++ b/include/asm-sparc/prom.h | |||
| @@ -85,5 +85,9 @@ static inline void of_node_put(struct device_node *node) | |||
| 85 | */ | 85 | */ |
| 86 | #include <linux/of.h> | 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 | #endif /* __KERNEL__ */ | 92 | #endif /* __KERNEL__ */ |
| 89 | #endif /* _SPARC_PROM_H */ | 93 | #endif /* _SPARC_PROM_H */ |
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h index d6cd3a175fc3..389012e5fbad 100644 --- a/include/asm-sparc64/fb.h +++ b/include/asm-sparc64/fb.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/fb.h> | 3 | #include <linux/fb.h> |
| 4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
| 5 | #include <asm/page.h> | 5 | #include <asm/page.h> |
| 6 | #include <asm/prom.h> | ||
| 6 | 7 | ||
| 7 | static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, | 8 | static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, |
| 8 | unsigned long off) | 9 | unsigned long off) |
| @@ -12,6 +13,14 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, | |||
| 12 | 13 | ||
| 13 | static inline int fb_is_primary_device(struct fb_info *info) | 14 | static inline int fb_is_primary_device(struct fb_info *info) |
| 14 | { | 15 | { |
| 16 | struct device *dev = info->device; | ||
| 17 | struct device_node *node; | ||
| 18 | |||
| 19 | node = dev->archdata.prom_node; | ||
| 20 | if (node && | ||
| 21 | node == of_console_device) | ||
| 22 | return 1; | ||
| 23 | |||
| 15 | return 0; | 24 | return 0; |
| 16 | } | 25 | } |
| 17 | 26 | ||
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h index 992f9f7a476c..3f23c5dc5f21 100644 --- a/include/asm-sparc64/oplib.h +++ b/include/asm-sparc64/oplib.h | |||
| @@ -140,32 +140,6 @@ extern void prom_putchar(char character); | |||
| 140 | extern void prom_printf(const char *fmt, ...); | 140 | extern void prom_printf(const char *fmt, ...); |
| 141 | extern void prom_write(const char *buf, unsigned int len); | 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 | /* Multiprocessor operations... */ | 143 | /* Multiprocessor operations... */ |
| 170 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
| 171 | /* Start the CPU with the given device tree node at the passed program | 145 | /* Start the CPU with the given device tree node at the passed program |
| @@ -319,6 +293,8 @@ extern int prom_inst2pkg(int); | |||
| 319 | extern int prom_service_exists(const char *service_name); | 293 | extern int prom_service_exists(const char *service_name); |
| 320 | extern void prom_sun4v_guest_soft_state(void); | 294 | extern void prom_sun4v_guest_soft_state(void); |
| 321 | 295 | ||
| 296 | extern int prom_ihandle2path(int handle, char *buffer, int bufsize); | ||
| 297 | |||
| 322 | /* Client interface level routines. */ | 298 | /* Client interface level routines. */ |
| 323 | extern void prom_set_trap_table(unsigned long tba); | 299 | extern void prom_set_trap_table(unsigned long tba); |
| 324 | extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa); | 300 | extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa); |
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index 23cc63f049a8..600afe5ae2e3 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h | |||
| @@ -8,8 +8,9 @@ | |||
| 8 | #define _ASM_SPARC64_PARPORT_H 1 | 8 | #define _ASM_SPARC64_PARPORT_H 1 |
| 9 | 9 | ||
| 10 | #include <asm/ebus.h> | 10 | #include <asm/ebus.h> |
| 11 | #include <asm/isa.h> | ||
| 12 | #include <asm/ns87303.h> | 11 | #include <asm/ns87303.h> |
| 12 | #include <asm/of_device.h> | ||
| 13 | #include <asm/prom.h> | ||
| 13 | 14 | ||
| 14 | #define PARPORT_PC_MAX_PORTS PARPORT_MAX | 15 | #define PARPORT_PC_MAX_PORTS PARPORT_MAX |
| 15 | 16 | ||
| @@ -35,8 +36,12 @@ static struct sparc_ebus_info { | |||
| 35 | unsigned int addr; | 36 | unsigned int addr; |
| 36 | unsigned int count; | 37 | unsigned int count; |
| 37 | int lock; | 38 | int lock; |
| 39 | |||
| 40 | struct parport *port; | ||
| 38 | } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS]; | 41 | } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS]; |
| 39 | 42 | ||
| 43 | static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS); | ||
| 44 | |||
| 40 | static __inline__ int request_dma(unsigned int dmanr, const char *device_id) | 45 | static __inline__ int request_dma(unsigned int dmanr, const char *device_id) |
| 41 | { | 46 | { |
| 42 | if (dmanr >= PARPORT_PC_MAX_PORTS) | 47 | if (dmanr >= PARPORT_PC_MAX_PORTS) |
| @@ -98,117 +103,145 @@ static __inline__ unsigned int get_dma_residue(unsigned int dmanr) | |||
| 98 | return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); | 103 | return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); |
| 99 | } | 104 | } |
| 100 | 105 | ||
| 101 | static int ebus_ecpp_p(struct linux_ebus_device *edev) | 106 | static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id *match) |
| 102 | { | 107 | { |
| 103 | if (!strcmp(edev->prom_node->name, "ecpp")) | 108 | unsigned long base = op->resource[0].start; |
| 104 | return 1; | 109 | unsigned long config = op->resource[1].start; |
| 105 | if (!strcmp(edev->prom_node->name, "parallel")) { | 110 | unsigned long d_base = op->resource[2].start; |
| 106 | const char *compat; | 111 | unsigned long d_len; |
| 107 | 112 | struct device_node *parent; | |
| 108 | compat = of_get_property(edev->prom_node, | 113 | struct parport *p; |
| 109 | "compatible", NULL); | 114 | int slot, err; |
| 110 | if (compat && | 115 | |
| 111 | (!strcmp(compat, "ecpp") || | 116 | parent = op->node->parent; |
| 112 | !strcmp(compat, "ns87317-ecpp") || | 117 | if (!strcmp(parent->name, "dma")) { |
| 113 | !strcmp(compat + 13, "ecpp"))) | 118 | p = parport_pc_probe_port(base, base + 0x400, |
| 114 | return 1; | 119 | op->irqs[0], PARPORT_DMA_NOFIFO, |
| 120 | op->dev.parent); | ||
| 121 | if (!p) | ||
| 122 | return -ENOMEM; | ||
| 123 | dev_set_drvdata(&op->dev, p); | ||
| 124 | return 0; | ||
| 115 | } | 125 | } |
| 126 | |||
| 127 | for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) { | ||
| 128 | if (!test_and_set_bit(slot, dma_slot_map)) | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | err = -ENODEV; | ||
| 132 | if (slot >= PARPORT_PC_MAX_PORTS) | ||
| 133 | goto out_err; | ||
| 134 | |||
| 135 | spin_lock_init(&sparc_ebus_dmas[slot].info.lock); | ||
| 136 | |||
| 137 | d_len = (op->resource[2].end - d_base) + 1UL; | ||
| 138 | sparc_ebus_dmas[slot].info.regs = | ||
| 139 | of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA"); | ||
| 140 | |||
| 141 | if (!sparc_ebus_dmas[slot].info.regs) | ||
| 142 | goto out_clear_map; | ||
| 143 | |||
| 144 | sparc_ebus_dmas[slot].info.flags = 0; | ||
| 145 | sparc_ebus_dmas[slot].info.callback = NULL; | ||
| 146 | sparc_ebus_dmas[slot].info.client_cookie = NULL; | ||
| 147 | sparc_ebus_dmas[slot].info.irq = 0xdeadbeef; | ||
| 148 | strcpy(sparc_ebus_dmas[slot].info.name, "parport"); | ||
| 149 | if (ebus_dma_register(&sparc_ebus_dmas[slot].info)) | ||
| 150 | goto out_unmap_regs; | ||
| 151 | |||
| 152 | ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1); | ||
| 153 | |||
| 154 | /* Configure IRQ to Push Pull, Level Low */ | ||
| 155 | /* Enable ECP, set bit 2 of the CTR first */ | ||
| 156 | outb(0x04, base + 0x02); | ||
| 157 | ns87303_modify(config, PCR, | ||
| 158 | PCR_EPP_ENABLE | | ||
| 159 | PCR_IRQ_ODRAIN, | ||
| 160 | PCR_ECP_ENABLE | | ||
| 161 | PCR_ECP_CLK_ENA | | ||
| 162 | PCR_IRQ_POLAR); | ||
| 163 | |||
| 164 | /* CTR bit 5 controls direction of port */ | ||
| 165 | ns87303_modify(config, PTR, | ||
| 166 | 0, PTR_LPT_REG_DIR); | ||
| 167 | |||
| 168 | p = parport_pc_probe_port(base, base + 0x400, | ||
| 169 | op->irqs[0], | ||
| 170 | slot, | ||
| 171 | op->dev.parent); | ||
| 172 | err = -ENOMEM; | ||
| 173 | if (!p) | ||
| 174 | goto out_disable_irq; | ||
| 175 | |||
| 176 | dev_set_drvdata(&op->dev, p); | ||
| 177 | |||
| 116 | return 0; | 178 | return 0; |
| 179 | |||
| 180 | out_disable_irq: | ||
| 181 | ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0); | ||
| 182 | ebus_dma_unregister(&sparc_ebus_dmas[slot].info); | ||
| 183 | |||
| 184 | out_unmap_regs: | ||
| 185 | of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len); | ||
| 186 | |||
| 187 | out_clear_map: | ||
| 188 | clear_bit(slot, dma_slot_map); | ||
| 189 | |||
| 190 | out_err: | ||
| 191 | return err; | ||
| 117 | } | 192 | } |
| 118 | 193 | ||
| 119 | static int parport_isa_probe(int count) | 194 | static int __devexit ecpp_remove(struct of_device *op) |
| 120 | { | 195 | { |
| 121 | struct sparc_isa_bridge *isa_br; | 196 | struct parport *p = dev_get_drvdata(&op->dev); |
| 122 | struct sparc_isa_device *isa_dev; | 197 | int slot = p->dma; |
| 123 | 198 | ||
| 124 | for_each_isa(isa_br) { | 199 | parport_pc_unregister_port(p); |
| 125 | for_each_isadev(isa_dev, isa_br) { | 200 | |
| 126 | struct sparc_isa_device *child; | 201 | if (slot != PARPORT_DMA_NOFIFO) { |
| 127 | unsigned long base; | 202 | unsigned long d_base = op->resource[2].start; |
| 128 | 203 | unsigned long d_len; | |
| 129 | if (strcmp(isa_dev->prom_node->name, "dma")) | 204 | |
| 130 | continue; | 205 | d_len = (op->resource[2].end - d_base) + 1UL; |
| 131 | 206 | ||
| 132 | child = isa_dev->child; | 207 | ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0); |
| 133 | while (child) { | 208 | ebus_dma_unregister(&sparc_ebus_dmas[slot].info); |
| 134 | if (!strcmp(child->prom_node->name, "parallel")) | 209 | of_iounmap(&op->resource[2], |
| 135 | break; | 210 | sparc_ebus_dmas[slot].info.regs, |
| 136 | child = child->next; | 211 | d_len); |
| 137 | } | 212 | clear_bit(slot, dma_slot_map); |
| 138 | if (!child) | ||
| 139 | continue; | ||
| 140 | |||
| 141 | base = child->resource.start; | ||
| 142 | |||
| 143 | /* No DMA, see commentary in | ||
| 144 | * asm-sparc64/floppy.h:isa_floppy_init() | ||
| 145 | */ | ||
| 146 | if (parport_pc_probe_port(base, base + 0x400, | ||
| 147 | child->irq, PARPORT_DMA_NOFIFO, | ||
| 148 | &child->bus->self->dev)) | ||
| 149 | count++; | ||
| 150 | } | ||
| 151 | } | 213 | } |
| 152 | 214 | ||
| 153 | return count; | 215 | return 0; |
| 154 | } | 216 | } |
| 155 | 217 | ||
| 156 | static int parport_pc_find_nonpci_ports (int autoirq, int autodma) | 218 | static struct of_device_id ecpp_match[] = { |
| 219 | { | ||
| 220 | .name = "ecpp", | ||
| 221 | }, | ||
| 222 | { | ||
| 223 | .name = "parallel", | ||
| 224 | .compatible = "ecpp", | ||
| 225 | }, | ||
| 226 | { | ||
| 227 | .name = "parallel", | ||
| 228 | .compatible = "ns87317-ecpp", | ||
| 229 | }, | ||
| 230 | {}, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static struct of_platform_driver ecpp_driver = { | ||
| 234 | .name = "ecpp", | ||
| 235 | .match_table = ecpp_match, | ||
| 236 | .probe = ecpp_probe, | ||
| 237 | .remove = __devexit_p(ecpp_remove), | ||
| 238 | }; | ||
| 239 | |||
| 240 | static int parport_pc_find_nonpci_ports(int autoirq, int autodma) | ||
| 157 | { | 241 | { |
| 158 | struct linux_ebus *ebus; | 242 | of_register_driver(&ecpp_driver, &of_bus_type); |
| 159 | struct linux_ebus_device *edev; | ||
| 160 | int count = 0; | ||
| 161 | |||
| 162 | for_each_ebus(ebus) { | ||
| 163 | for_each_ebusdev(edev, ebus) { | ||
| 164 | if (ebus_ecpp_p(edev)) { | ||
| 165 | unsigned long base = edev->resource[0].start; | ||
| 166 | unsigned long config = edev->resource[1].start; | ||
| 167 | unsigned long d_base = edev->resource[2].start; | ||
| 168 | unsigned long d_len; | ||
| 169 | |||
| 170 | spin_lock_init(&sparc_ebus_dmas[count].info.lock); | ||
| 171 | d_len = (edev->resource[2].end - | ||
| 172 | d_base) + 1; | ||
| 173 | sparc_ebus_dmas[count].info.regs = | ||
| 174 | ioremap(d_base, d_len); | ||
| 175 | if (!sparc_ebus_dmas[count].info.regs) | ||
| 176 | continue; | ||
| 177 | sparc_ebus_dmas[count].info.flags = 0; | ||
| 178 | sparc_ebus_dmas[count].info.callback = NULL; | ||
| 179 | sparc_ebus_dmas[count].info.client_cookie = NULL; | ||
| 180 | sparc_ebus_dmas[count].info.irq = 0xdeadbeef; | ||
| 181 | strcpy(sparc_ebus_dmas[count].info.name, "parport"); | ||
| 182 | if (ebus_dma_register(&sparc_ebus_dmas[count].info)) | ||
| 183 | continue; | ||
| 184 | ebus_dma_irq_enable(&sparc_ebus_dmas[count].info, 1); | ||
| 185 | |||
| 186 | /* Configure IRQ to Push Pull, Level Low */ | ||
| 187 | /* Enable ECP, set bit 2 of the CTR first */ | ||
| 188 | outb(0x04, base + 0x02); | ||
| 189 | ns87303_modify(config, PCR, | ||
| 190 | PCR_EPP_ENABLE | | ||
| 191 | PCR_IRQ_ODRAIN, | ||
| 192 | PCR_ECP_ENABLE | | ||
| 193 | PCR_ECP_CLK_ENA | | ||
| 194 | PCR_IRQ_POLAR); | ||
| 195 | |||
| 196 | /* CTR bit 5 controls direction of port */ | ||
| 197 | ns87303_modify(config, PTR, | ||
| 198 | 0, PTR_LPT_REG_DIR); | ||
| 199 | |||
| 200 | if (parport_pc_probe_port(base, base + 0x400, | ||
| 201 | edev->irqs[0], | ||
| 202 | count, | ||
| 203 | &ebus->self->dev)) | ||
| 204 | count++; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | } | ||
| 208 | 243 | ||
| 209 | count = parport_isa_probe(count); | 244 | return 0; |
| 210 | |||
| 211 | return count; | ||
| 212 | } | 245 | } |
| 213 | 246 | ||
| 214 | #endif /* !(_ASM_SPARC64_PARPORT_H */ | 247 | #endif /* !(_ASM_SPARC64_PARPORT_H */ |
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h index 2b9e0d795faf..31dcb92fbae0 100644 --- a/include/asm-sparc64/prom.h +++ b/include/asm-sparc64/prom.h | |||
| @@ -94,5 +94,9 @@ static inline void of_node_put(struct device_node *node) | |||
| 94 | */ | 94 | */ |
| 95 | #include <linux/of.h> | 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 | #endif /* __KERNEL__ */ | 101 | #endif /* __KERNEL__ */ |
| 98 | #endif /* _SPARC64_PROM_H */ | 102 | #endif /* _SPARC64_PROM_H */ |
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h index 409067408eec..64891cb10f05 100644 --- a/include/asm-sparc64/system.h +++ b/include/asm-sparc64/system.h | |||
| @@ -115,14 +115,8 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ | |||
| 115 | #ifndef __ASSEMBLY__ | 115 | #ifndef __ASSEMBLY__ |
| 116 | 116 | ||
| 117 | extern void sun_do_break(void); | 117 | extern void sun_do_break(void); |
| 118 | extern int serial_console; | ||
| 119 | extern int stop_a_enabled; | 118 | extern int stop_a_enabled; |
| 120 | 119 | ||
| 121 | static __inline__ int con_is_present(void) | ||
| 122 | { | ||
| 123 | return serial_console ? 0 : 1; | ||
| 124 | } | ||
| 125 | |||
| 126 | extern void synchronize_user_stack(void); | 120 | extern void synchronize_user_stack(void); |
| 127 | 121 | ||
| 128 | extern void __flushw_user(void); | 122 | extern void __flushw_user(void); |
