diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 17:35:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 17:35:25 -0700 |
commit | c2e68052429fdf87702fccd272951282bef1c60a (patch) | |
tree | b9f3bf3918526af068ed264190a85fb18dd3d8b0 /arch | |
parent | d6f410bdbcb435c744c4f8259d6659ae2c6e447a (diff) | |
parent | 1256efd5519a8eca2dfa6039ce5cf58f44d1626d (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
[SPARC64]: fix section mismatch warning in mdesc.c
[SPARC64]: fix section mismatch warning in pci_sunv4
[SPARC64]: Stop using drivers/char/rtc.c
[SPARC64]: Convert parport to of_platform_driver.
[SPARC]: Implement fb_is_primary_device().
[SPARC64]: Fix virq decomposition.
[SPARC64]: Use KERN_ERR in IRQ manipulation error printks.
[SPARC64]: Do not flood log with failed DS messages.
[SPARC64]: Add proper multicast support to VNET driver.
[SPARC64]: Handle multiple domain-services-port nodes properly.
[SPARC64]: Improve VIO device naming further.
[SPARC]: Make sure dev_archdata is filled in for all devices.
[SPARC]: Define minimal struct dev_archdata, similarly to sparc64.
[SPARC]: Fix serial console device detection.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc/kernel/ebus.c | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/of_device.c | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/prom.c | 131 | ||||
-rw-r--r-- | arch/sparc/kernel/setup.c | 65 | ||||
-rw-r--r-- | arch/sparc/prom/console.c | 116 | ||||
-rw-r--r-- | arch/sparc/prom/misc.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/ds.c | 249 | ||||
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 72 | ||||
-rw-r--r-- | arch/sparc64/kernel/isa.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/mdesc.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/of_device.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/power.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 56 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 70 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 79 | ||||
-rw-r--r-- | arch/sparc64/kernel/vio.c | 35 | ||||
-rw-r--r-- | arch/sparc64/prom/console.c | 85 | ||||
-rw-r--r-- | arch/sparc64/prom/misc.c | 4 | ||||
-rw-r--r-- | arch/sparc64/prom/tree.c | 8 |
24 files changed, 529 insertions, 497 deletions
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 7bb86b9cdaa..ac352eb6dff 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 { const struct linux_prom_registers *regs; struct linux_ebus_child *child; + struct dev_archdata *sd; const int *irqs; int i, n, len; unsigned long baseaddr; @@ -234,6 +235,10 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d } } + sd = &dev->ofdev.dev.archdata; + sd->prom_node = dp; + sd->op = &dev->ofdev; + dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 7176040caba..36383f73d68 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, { struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); const struct linux_prom_irqs *intr; + struct dev_archdata *sd; int len, i; if (!op) return NULL; + sd = &op->dev.archdata; + sd->prom_node = dp; + sd->op = op; + op->node = dp; op->clock_freq = of_getintprop_default(dp, "clock-frequency", diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 8c37f8f5adb..33f7a3ddb10 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -39,6 +39,7 @@ #include <asm/processor.h> #include <asm/psr.h> #include <asm/elf.h> +#include <asm/prom.h> #include <asm/unistd.h> /* @@ -150,7 +151,7 @@ void machine_halt(void) local_irq_enable(); mdelay(8); local_irq_disable(); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); prom_halt(); panic("Halt failed!"); @@ -166,7 +167,7 @@ void machine_restart(char * cmd) p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); if (cmd) prom_reboot(cmd); @@ -179,7 +180,8 @@ void machine_restart(char * cmd) void machine_power_off(void) { #ifdef CONFIG_SUN_AUXIO - if (auxio_power_register && (!serial_console || scons_pwroff)) + if (auxio_power_register && + (strcmp(of_console_device->type, "serial") || scons_pwroff)) *auxio_power_register |= AUXIO_POWER_OFF; #endif machine_halt(); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 012f98346bc..e3a537650db 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 return dp; } +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +extern void restore_current(void); + +static void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + unsigned long flags; + const char *type; + phandle node; + int skip, fd; + + of_console_path = prom_early_alloc(256); + + switch (prom_vers) { + case PROM_V0: + case PROM_SUN4: + skip = 0; + switch (*romvec->pv_stdout) { + case PROMDEV_SCREEN: + type = "display"; + break; + + case PROMDEV_TTYB: + skip = 1; + /* FALLTHRU */ + + case PROMDEV_TTYA: + type = "serial"; + break; + + default: + prom_printf("Invalid PROM_V0 stdout value %u\n", + *romvec->pv_stdout); + prom_halt(); + } + + for_each_node_by_type(dp, type) { + if (!skip--) + break; + } + if (!dp) { + prom_printf("Cannot find PROM_V0 console node.\n"); + prom_halt(); + } + of_console_device = dp; + + strcpy(of_console_path, dp->full_name); + if (!strcmp(type, "serial")) { + strcat(of_console_path, + (skip ? ":b" : ":a")); + } + break; + + default: + case PROM_V2: + case PROM_V3: + fd = *romvec->pv_v2bootargs.fd_stdout; + + spin_lock_irqsave(&prom_lock, flags); + node = (*romvec->pv_v2devops.v2_inst2pkg)(fd); + restore_current(); + spin_unlock_irqrestore(&prom_lock, flags); + + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", fd); + prom_halt(); + } + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + + if (!type) { + prom_printf("Console stdout lacks " + "device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + if (prom_vers == PROM_V2) { + strcpy(of_console_path, dp->full_name); + switch (*romvec->pv_stdout) { + case PROMDEV_TTYA: + strcat(of_console_path, ":a"); + break; + case PROMDEV_TTYB: + strcat(of_console_path, ":b"); + break; + } + } else { + const char *path; + + dp = of_find_node_by_path("/"); + path = of_get_property(dp, "stdout-path", NULL); + if (!path) { + prom_printf("No stdout-path in root node.\n"); + prom_halt(); + } + strcpy(of_console_path, path); + } + break; + } + + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + prom_printf(msg, of_console_path); + printk(msg, of_console_path); +} + void __init prom_build_devicetree(void) { struct device_node **nextp; @@ -409,6 +538,8 @@ void __init prom_build_devicetree(void) allnodes->child = build_tree(allnodes, prom_getchild(allnodes->node), &nextp); + of_console_init(); + printk("PROM: Built device tree with %u bytes of memory.\n", prom_early_allocated); } diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 64c0ed98820..f8228383895 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -146,31 +146,6 @@ static void __init process_switch(char c) } } -static void __init process_console(char *commands) -{ - serial_console = 0; - commands += 8; - /* Linux-style serial */ - if (!strncmp(commands, "ttyS", 4)) - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; - else if (!strncmp(commands, "tty", 3)) { - char c = *(commands + 3); - /* Solaris-style serial */ - if (c == 'a' || c == 'b') - serial_console = c - 'a' + 1; - /* else Linux-style fbcon, not serial */ - } -#if defined(CONFIG_PROM_CONSOLE) - if (!strncmp(commands, "prom", 4)) { - char *p; - - for (p = commands - 8; *p && *p != ' '; p++) - *p = ' '; - conswitchp = &prom_con; - } -#endif -} - static void __init boot_flags_init(char *commands) { while (*commands) { @@ -187,9 +162,7 @@ static void __init boot_flags_init(char *commands) process_switch(*commands++); continue; } - if (!strncmp(commands, "console=", 8)) { - process_console(commands); - } else if (!strncmp(commands, "mem=", 4)) { + if (!strncmp(commands, "mem=", 4)) { /* * "mem=XXX[kKmM] overrides the PROM-reported * memory size. @@ -341,41 +314,6 @@ void __init setup_arch(char **cmdline_p) smp_setup_cpu_possible_map(); } -static int __init set_preferred_console(void) -{ - int idev, odev; - - /* The user has requested a console so this is already set up. */ - if (serial_console >= 0) - return -EBUSY; - - idev = prom_query_input_device(); - odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) { - prom_printf("MrCoffee ttya\n"); - serial_console = 1; - } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) { - serial_console = 0; - prom_printf("MrCoffee keyboard\n"); - } else { - prom_printf("Confusing console (idev %d, odev %d)\n", - idev, odev); - serial_console = 1; - } - - if (serial_console) - return add_preferred_console("ttyS", serial_console - 1, NULL); - - return -ENODEV; -} -console_initcall(set_preferred_console); - extern char *sparc_cpu_type; extern char *sparc_fpu_type; @@ -461,7 +399,6 @@ void sun_do_break(void) prom_cmdline(); } -int serial_console = -1; int stop_a_enabled = 1; static int __init topology_init(void) diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index 4e6e41d3291..8d1cfb0d506 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c @@ -102,119 +102,3 @@ prom_putchar(char c) while(prom_nbputchar(c) == -1) ; return; } - -/* Query for input device type */ -enum prom_input_device -prom_query_input_device(void) -{ - unsigned long flags; - int st_p; - char propb[64]; - char *p; - int propl; - - switch(prom_vers) { - case PROM_V0: - case PROM_V2: - case PROM_SUN4: - default: - switch(*romvec->pv_stdin) { - case PROMDEV_KBD: return PROMDEV_IKBD; - case PROMDEV_TTYA: return PROMDEV_ITTYA; - case PROMDEV_TTYB: return PROMDEV_ITTYB; - default: - return PROMDEV_I_UNK; - }; - case PROM_V3: - spin_lock_irqsave(&prom_lock, flags); - st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - if(prom_node_has_property(st_p, "keyboard")) - return PROMDEV_IKBD; - if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) { - if(strncmp(propb, "keyboard", sizeof("serial")) == 0) - return PROMDEV_IKBD; - } - if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) { - if(strncmp(propb, "serial", sizeof("serial"))) - return PROMDEV_I_UNK; - } - propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb)); - if(propl > 2) { - p = propb; - while(*p) p++; p -= 2; - if(p[0] == ':') { - if(p[1] == 'a') - return PROMDEV_ITTYA; - else if(p[1] == 'b') - return PROMDEV_ITTYB; - } - } - return PROMDEV_I_UNK; - } -} - -/* Query for output device type */ - -enum prom_output_device -prom_query_output_device(void) -{ - unsigned long flags; - int st_p; - char propb[64]; - char *p; - int propl; - - switch(prom_vers) { - case PROM_V0: - case PROM_SUN4: - switch(*romvec->pv_stdin) { - case PROMDEV_SCREEN: return PROMDEV_OSCREEN; - case PROMDEV_TTYA: return PROMDEV_OTTYA; - case PROMDEV_TTYB: return PROMDEV_OTTYB; - }; - break; - case PROM_V2: - case PROM_V3: - spin_lock_irqsave(&prom_lock, flags); - st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); - if (propl == sizeof("display") && - strncmp("display", propb, sizeof("display")) == 0) - { - return PROMDEV_OSCREEN; - } - if(prom_vers == PROM_V3) { - if(propl >= 0 && - strncmp("serial", propb, sizeof("serial")) != 0) - return PROMDEV_O_UNK; - propl = prom_getproperty(prom_root_node, "stdout-path", - propb, sizeof(propb)); - if(propl == CON_SIZE_JMC && - strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0) - return PROMDEV_OTTYA; - if(propl > 2) { - p = propb; - while(*p) p++; p-= 2; - if(p[0]==':') { - if(p[1] == 'a') - return PROMDEV_OTTYA; - else if(p[1] == 'b') - return PROMDEV_OTTYB; - } - } - } else { - switch(*romvec->pv_stdin) { - case PROMDEV_TTYA: return PROMDEV_OTTYA; - case PROMDEV_TTYB: return PROMDEV_OTTYB; - }; - } - break; - default: - ; - }; - return PROMDEV_O_UNK; -} diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c index 1942c7c05cb..37cff5f5470 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc.c @@ -58,7 +58,7 @@ prom_cmdline(void) extern void install_linux_ticker(void); unsigned long flags; - if(!serial_console && prom_palette) + if (prom_palette) prom_palette (1); spin_lock_irqsave(&prom_lock, flags); install_obp_ticker(); @@ -69,7 +69,7 @@ prom_cmdline(void) #ifdef CONFIG_SUN_AUXIO set_auxio(AUXIO_LED, 0); #endif - if(!serial_console && prom_palette) + if (prom_palette) prom_palette (0); } diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index 1a2062ecb0b..9f472a79d37 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c @@ -124,10 +124,11 @@ struct ds_data_nack { __u64 result; }; +struct ds_info; struct ds_cap_state { __u64 handle; - void (*data)(struct ldc_channel *lp, + void (*data)(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); @@ -139,27 +140,27 @@ struct ds_cap_state { #define CAP_STATE_REGISTERED 0x02 }; -static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp, +static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); -static void domain_shutdown_data(struct ldc_channel *lp, +static void domain_shutdown_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); -static void domain_panic_data(struct ldc_channel *lp, +static void domain_panic_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); #ifdef CONFIG_HOTPLUG_CPU -static void dr_cpu_data(struct ldc_channel *lp, +static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); #endif -static void ds_pri_data(struct ldc_channel *lp, +static void ds_pri_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); -static void ds_var_data(struct ldc_channel *lp, +static void ds_var_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len); -struct ds_cap_state ds_states[] = { +struct ds_cap_state ds_states_template[] = { { .service_id = "md-update", .data = md_update_data, @@ -200,30 +201,38 @@ struct ds_info { #define DS_HS_START 0x01 #define DS_HS_DONE 0x02 + u64 id; + void *rcv_buf; int rcv_buf_len; + + struct ds_cap_state *ds_states; + int num_ds_states; + + struct ds_info *next; }; -static struct ds_info *ds_info; +static struct ds_info *ds_info_list; -static struct ds_cap_state *find_cap(u64 handle) +static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle) { unsigned int index = handle >> 32; - if (index >= ARRAY_SIZE(ds_states)) + if (index >= dp->num_ds_states) return NULL; - return &ds_states[index]; + return &dp->ds_states[index]; } -static struct ds_cap_state *find_cap_by_string(const char *name) +static struct ds_cap_state *find_cap_by_string(struct ds_info *dp, + const char *name) { int i; - for (i = 0; i < ARRAY_SIZE(ds_states); i++) { - if (strcmp(ds_states[i].service_id, name)) + for (i = 0; i < dp->num_ds_states; i++) { + if (strcmp(dp->ds_states[i].service_id, name)) continue; - return &ds_states[i]; + return &dp->ds_states[i]; } return NULL; } @@ -264,10 +273,11 @@ struct ds_md_update_res { __u32 result; }; -static void md_update_data(struct ldc_channel *lp, - struct ds_cap_state *dp, +static void md_update_data(struct ds_info *dp, + struct ds_cap_state *cp, void *buf, int len) { + struct ldc_channel *lp = dp->lp; struct ds_data *dpkt = buf; struct ds_md_update_req *rp; struct { @@ -277,14 +287,14 @@ static void md_update_data(struct ldc_channel *lp, rp = (struct ds_md_update_req *) (dpkt + 1); - printk(KERN_INFO PFX "Machine description update.\n"); + printk(KERN_INFO "ds-%lu: Machine description update.\n", dp->id); mdesc_update(); memset(&pkt, 0, sizeof(pkt)); pkt.data.tag.type = DS_DATA; pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); - pkt.data.handle = dp->handle; + pkt.data.handle = cp->handle; pkt.res.req_num = rp->req_num; pkt.res.result = DS_OK; @@ -302,10 +312,11 @@ struct ds_shutdown_res { char reason[1]; }; -static void domain_shutdown_data(struct ldc_channel *lp, - struct ds_cap_state *dp, +static void domain_shutdown_data(struct ds_info *dp, + struct ds_cap_state *cp, void *buf, int len) { + struct ldc_channel *lp = dp->lp; struct ds_data *dpkt = buf; struct ds_shutdown_req *rp; struct { @@ -315,13 +326,13 @@ static void domain_shutdown_data(struct ldc_channel *lp, rp = (struct ds_shutdown_req *) (dpkt + 1); - printk(KERN_ALERT PFX "Shutdown request from " - "LDOM manager received.\n"); + printk(KERN_ALERT "ds-%lu: Shutdown request from " + "LDOM manager received.\n", dp->id); memset(&pkt, 0, sizeof(pkt)); pkt.data.tag.type = DS_DATA; pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); - pkt.data.handle = dp->handle; + pkt.data.handle = cp->handle; pkt.res.req_num = rp->req_num; pkt.res.result = DS_OK; pkt.res.reason[0] = 0; @@ -341,10 +352,11 @@ struct ds_panic_res { char reason[1]; }; -static void domain_panic_data(struct ldc_channel *lp, - struct ds_cap_state *dp, +static void domain_panic_data(struct ds_info *dp, + struct ds_cap_state *cp, void *buf, int len) { + struct ldc_channel *lp = dp->lp; struct ds_data *dpkt = buf; struct ds_panic_req *rp; struct { @@ -354,13 +366,13 @@ static void domain_panic_data(struct ldc_channel *lp, rp = (struct ds_panic_req *) (dpkt + 1); - printk(KERN_ALERT PFX "Panic request from " - "LDOM manager received.\n"); + printk(KERN_ALERT "ds-%lu: Panic request from " + "LDOM manager received.\n", dp->id); memset(&pkt, 0, sizeof(pkt)); pkt.data.tag.type = DS_DATA; pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); - pkt.data.handle = dp->handle; + pkt.data.handle = cp->handle; pkt.res.req_num = rp->req_num; pkt.res.result = DS_OK; pkt.res.reason[0] = 0; @@ -403,10 +415,11 @@ struct dr_cpu_resp_entry { __u32 str_off; }; -static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) +static void __dr_cpu_send_error(struct ds_info *dp, + struct ds_cap_state *cp, + struct ds_data *data) { struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); - struct ds_info *dp = ds_info; struct { struct ds_data data; struct dr_cpu_tag tag; @@ -428,12 +441,14 @@ static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) __ds_send(dp->lp, &pkt, msg_len); } -static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) +static void dr_cpu_send_error(struct ds_info *dp, + struct ds_cap_state *cp, + struct ds_data *data) { unsigned long flags; spin_lock_irqsave(&ds_lock, flags); - __dr_cpu_send_error(cp, data); + __dr_cpu_send_error(dp, cp, data); spin_unlock_irqrestore(&ds_lock, flags); } @@ -511,7 +526,9 @@ static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus, } } -static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, +static int dr_cpu_configure(struct ds_info *dp, + struct ds_cap_state *cp, + u64 req_num, cpumask_t *mask) { struct ds_data *resp; @@ -533,7 +550,8 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, for_each_cpu_mask(cpu, *mask) { int err; - printk(KERN_INFO PFX "Starting cpu %d...\n", cpu); + printk(KERN_INFO "ds-%lu: Starting cpu %d...\n", + dp->id, cpu); err = cpu_up(cpu); if (err) { __u32 res = DR_CPU_RES_FAILURE; @@ -548,14 +566,14 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, res = DR_CPU_RES_CPU_NOT_RESPONDING; } - printk(KERN_INFO PFX "CPU startup failed err=%d\n", - err); + printk(KERN_INFO "ds-%lu: CPU startup failed err=%d\n", + dp->id, err); dr_cpu_mark(resp, cpu, ncpus, res, stat); } } spin_lock_irqsave(&ds_lock, flags); - __ds_send(ds_info->lp, resp, resp_len); + __ds_send(dp->lp, resp, resp_len); spin_unlock_irqrestore(&ds_lock, flags); kfree(resp); @@ -566,7 +584,9 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, return 0; } -static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, +static int dr_cpu_unconfigure(struct ds_info *dp, + struct ds_cap_state *cp, + u64 req_num, cpumask_t *mask) { struct ds_data *resp; @@ -586,8 +606,8 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, for_each_cpu_mask(cpu, *mask) { int err; - printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n", - smp_processor_id(), cpu); + printk(KERN_INFO "ds-%lu: Shutting down cpu %d...\n", + dp->id, cpu); err = cpu_down(cpu); if (err) dr_cpu_mark(resp, cpu, ncpus, @@ -596,7 +616,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, } spin_lock_irqsave(&ds_lock, flags); - __ds_send(ds_info->lp, resp, resp_len); + __ds_send(dp->lp, resp, resp_len); spin_unlock_irqrestore(&ds_lock, flags); kfree(resp); @@ -604,7 +624,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, return 0; } -static void dr_cpu_data(struct ldc_channel *lp, +static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len) { @@ -623,7 +643,7 @@ static void dr_cpu_data(struct ldc_channel *lp, break; default: - dr_cpu_send_error(cp, data); + dr_cpu_send_error(dp, cp, data); return; } @@ -639,12 +659,12 @@ static void dr_cpu_data(struct ldc_channel *lp, } if (tag->type == DR_CPU_CONFIGURE) - err = dr_cpu_configure(cp, req_num, &mask); + err = dr_cpu_configure(dp, cp, req_num, &mask); else - err = dr_cpu_unconfigure(cp, req_num, &mask); + err = dr_cpu_unconfigure(dp, cp, req_num, &mask); if (err) - dr_cpu_send_error(cp, data); + dr_cpu_send_error(dp, cp, data); } #endif /* CONFIG_HOTPLUG_CPU */ @@ -656,8 +676,8 @@ struct ds_pri_msg { #define DS_PRI_UPDATE 0x02 }; -static void ds_pri_data(struct ldc_channel *lp, - struct ds_cap_state *dp, +static void ds_pri_data(struct ds_info *dp, + struct ds_cap_state *cp, void *buf, int len) { struct ds_data *dpkt = buf; @@ -665,8 +685,8 @@ static void ds_pri_data(struct ldc_channel *lp, rp = (struct ds_pri_msg *) (dpkt + 1); - printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n", - rp->req_num, rp->type, len); + printk(KERN_INFO "ds-%lu: PRI REQ [%lx:%lx], len=%d\n", + dp->id, rp->req_num, rp->type, len); } struct ds_var_hdr { @@ -701,8 +721,8 @@ static DEFINE_MUTEX(ds_var_mutex); static int ds_var_doorbell; static int ds_var_response; -static void ds_var_data(struct ldc_channel *lp, - struct ds_cap_state *dp, +static void ds_var_data(struct ds_info *dp, + struct ds_cap_state *cp, void *buf, int len) { struct ds_data *dpkt = buf; @@ -721,14 +741,35 @@ static void ds_var_data(struct ldc_channel *lp, void ldom_set_var(const char *var, const char *value) { - struct ds_info *dp = ds_info; struct ds_cap_state *cp; + struct ds_info *dp; + unsigned long flags; + + spin_lock_irqsave(&ds_lock, flags); + cp = NULL; + for (dp = ds_info_list; dp; dp = dp->next) { + struct ds_cap_state *tmp; + + tmp = find_cap_by_string(dp, "var-config"); + if (tmp && tmp->state == CAP_STATE_REGISTERED) { + cp = tmp; + break; + } + } + if (!cp) { + for (dp = ds_info_list; dp; dp = dp->next) { + struct ds_cap_state *tmp; - cp = find_cap_by_string("var-config"); - if (cp->state != CAP_STATE_REGISTERED) - cp = find_cap_by_string("var-config-backup"); + tmp = find_cap_by_string(dp, "var-config-backup"); + if (tmp && tmp->state == CAP_STATE_REGISTERED) { + cp = tmp; + break; + } + } + } + spin_unlock_irqrestore(&ds_lock, flags); - if (cp->state == CAP_STATE_REGISTERED) { + if (cp) { union { struct { struct ds_data data; @@ -736,7 +777,6 @@ void ldom_set_var(const char *var, const char *value) } header; char all[512]; } pkt; - unsigned long flags; char *base, *p; int msg_len, loops; @@ -777,9 +817,9 @@ void ldom_set_var(const char *var, const char *value) if (ds_var_doorbell == 0 || ds_var_response != DS_VAR_SUCCESS) - printk(KERN_ERR PFX "var-config [%s:%s] " + printk(KERN_ERR "ds-%lu: var-config [%s:%s] " "failed, response(%d).\n", - var, value, + dp->id, var, value, ds_var_response); } else { printk(KERN_ERR PFX "var-config not registered so " @@ -811,8 +851,8 @@ void ldom_power_off(void) static void ds_conn_reset(struct ds_info *dp) { - printk(KERN_ERR PFX "ds_conn_reset() from %p\n", - __builtin_return_address(0)); + printk(KERN_ERR "ds-%lu: ds_conn_reset() from %p\n", + dp->id, __builtin_return_address(0)); } static int register_services(struct ds_info *dp) @@ -820,12 +860,12 @@ static int register_services(struct ds_info *dp) struct ldc_channel *lp = dp->lp; int i; - for (i = 0; i < ARRAY_SIZE(ds_states); i++) { + for (i = 0; i < dp->num_ds_states; i++) { struct { struct ds_reg_req req; u8 id_buf[256]; } pbuf; - struct ds_cap_state *cp = &ds_states[i]; + struct ds_cap_state *cp = &dp->ds_states[i]; int err, msg_len; u64 new_count; @@ -870,28 +910,26 @@ static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt) if (pkt->type == DS_REG_ACK) { struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt; - struct ds_cap_state *cp = find_cap(ap->handle); + struct ds_cap_state *cp = find_cap(dp, ap->handle); if (!cp) { - printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n", - ap->handle); + printk(KERN_ERR "ds-%lu: REG ACK for unknown " + "handle %lx\n", dp->id, ap->handle); return 0; } - printk(KERN_INFO PFX "Registered %s service.\n", - cp->service_id); + printk(KERN_INFO "ds-%lu: Registered %s service.\n", + dp->id, cp->service_id); cp->state = CAP_STATE_REGISTERED; } else if (pkt->type == DS_REG_NACK) { struct ds_reg_nack *np = (struct ds_reg_nack *) pkt; - struct ds_cap_state *cp = find_cap(np->handle); + struct ds_cap_state *cp = find_cap(dp, np->handle); if (!cp) { - printk(KERN_ERR PFX "REG NACK for " + printk(KERN_ERR "ds-%lu: REG NACK for " "unknown handle %lx\n", - np->handle); + dp->id, np->handle); return 0; } - printk(KERN_INFO PFX "Could not register %s service\n", - cp->service_id); cp->state = CAP_STATE_UNKNOWN; } @@ -922,6 +960,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ds_wait); struct ds_queue_entry { struct list_head list; + struct ds_info *dp; int req_len; int __pad; u64 req[0]; @@ -930,7 +969,6 @@ struct ds_queue_entry { static void process_ds_work(void) { struct ds_queue_entry *qp, *tmp; - static struct ds_info *dp; unsigned long flags; LIST_HEAD(todo); @@ -939,22 +977,22 @@ static void process_ds_work(void) INIT_LIST_HEAD(&ds_work_list); spin_unlock_irqrestore(&ds_lock, flags); - dp = ds_info; - list_for_each_entry_safe(qp, tmp, &todo, list) { struct ds_data *dpkt = (struct ds_data *) qp->req; - struct ds_cap_state *cp = find_cap(dpkt->handle); + struct ds_info *dp = qp->dp; + struct ds_cap_state *cp = find_cap(dp, dpkt->handle); int req_len = qp->req_len; if (!cp) { - printk(KERN_ERR PFX "Data for unknown handle %lu\n", - dpkt->handle); + printk(KERN_ERR "ds-%lu: Data for unknown " + "handle %lu\n", + dp->id, dpkt->handle); spin_lock_irqsave(&ds_lock, flags); __send_ds_nack(dp, dpkt->handle); spin_unlock_irqrestore(&ds_lock, flags); } else { - cp->data(dp->lp, cp, dpkt, req_len); + cp->data(dp, cp, dpkt, req_len); } list_del(&qp->list); @@ -990,6 +1028,7 @@ static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len) if (!qp) { __send_ds_nack(dp, dpkt->handle); } else { + qp->dp = dp; memcpy(&qp->req, pkt, len); list_add_tail(&qp->list, &ds_work_list); wake_up(&ds_wait); @@ -1019,8 +1058,8 @@ static void ds_reset(struct ds_info *dp) dp->hs_state = 0; - for (i = 0; i < ARRAY_SIZE(ds_states); i++) { - struct ds_cap_state *cp = &ds_states[i]; + for (i = 0; i < dp->num_ds_states; i++) { + struct ds_cap_state *cp = &dp->ds_states[i]; cp->state = CAP_STATE_UNKNOWN; } @@ -1048,7 +1087,8 @@ static void ds_event(void *arg, int event) } if (event != LDC_EVENT_DATA_READY) { - printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); + printk(KERN_WARNING "ds-%lu: Unexpected LDC event %d\n", + dp->id, event); spin_unlock_irqrestore(&ds_lock, flags); return; } @@ -1099,9 +1139,11 @@ static int __devinit ds_probe(struct vio_dev *vdev, .mtu = 4096, .mode = LDC_MODE_STREAM, }; + struct mdesc_handle *hp; struct ldc_channel *lp; struct ds_info *dp; - int err; + const u64 *val; + int err, i; if (ds_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -1111,19 +1153,37 @@ static int __devinit ds_probe(struct vio_dev *vdev, if (!dp) goto out_err; + hp = mdesc_grab(); + val = mdesc_get_property(hp, vdev->mp, "id", NULL); + if (val) + dp->id = *val; + mdesc_release(hp); + dp->rcv_buf = kzalloc(4096, GFP_KERNEL); if (!dp->rcv_buf) goto out_free_dp; dp->rcv_buf_len = 4096; + dp->ds_states = kzalloc(sizeof(ds_states_template), + GFP_KERNEL); + if (!dp->ds_states) + goto out_free_rcv_buf; + + memcpy(dp->ds_states, ds_states_template, + sizeof(ds_states_template)); + dp->num_ds_states = ARRAY_SIZE(ds_states_template); + + for (i = 0; i < dp->num_ds_states; i++) + dp->ds_states[i].handle = ((u64)i << 32); + ds_cfg.tx_irq = vdev->tx_irq; ds_cfg.rx_irq = vdev->rx_irq; lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); if (IS_ERR(lp)) { err = PTR_ERR(lp); - goto out_free_rcv_buf; + goto out_free_ds_states; } dp->lp = lp; @@ -1131,13 +1191,19 @@ static int __devinit ds_probe(struct vio_dev *vdev, if (err) goto out_free_ldc; - ds_info = dp; + spin_lock_irq(&ds_lock); + dp->next = ds_info_list; + ds_info_list = dp; + spin_unlock_irq(&ds_lock); return err; out_free_ldc: ldc_free(dp->lp); +out_free_ds_states: + kfree(dp->ds_states); + out_free_rcv_buf: kfree(dp->rcv_buf); @@ -1172,11 +1238,6 @@ static struct vio_driver ds_driver = { static int __init ds_init(void) { - int i; - - for (i = 0; i < ARRAY_SIZE(ds_states); i++) - ds_states[i].handle = ((u64)i << 32); - kthread_run(ds_thread, NULL, "kldomd"); return vio_register_driver(&ds_driver); diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index ad55a9bb50d..6d2956179cd 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) static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { struct linux_ebus_child *child; + struct dev_archdata *sd; struct of_device *op; int i, len; @@ -387,6 +388,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de dev->irqs[i] = op->irqs[i]; } + sd = &dev->ofdev.dev.archdata; + sd->prom_node = dp; + sd->op = &dev->ofdev; + dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index c72795666a6..db31bf6b42d 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 */ #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) -static unsigned int virt_to_real_irq_table[NR_IRQS]; +static struct { + unsigned int irq; + unsigned int dev_handle; + unsigned int dev_ino; +} virt_to_real_irq_table[NR_IRQS]; static unsigned char virt_irq_alloc(unsigned int real_irq) { @@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) BUILD_BUG_ON(NR_IRQS >= 256); for (ent = 1; ent < NR_IRQS; ent++) { - if (!virt_to_real_irq_table[ent]) + if (!virt_to_real_irq_table[ent].irq) break; } if (ent >= NR_IRQS) { @@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) return 0; } - virt_to_real_irq_table[ent] = real_irq; + virt_to_real_irq_table[ent].irq = real_irq; return ent; } @@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq) if (virt_irq >= NR_IRQS) return; - real_irq = virt_to_real_irq_table[virt_irq]; - virt_to_real_irq_table[virt_irq] = 0; + real_irq = virt_to_real_irq_table[virt_irq].irq; + virt_to_real_irq_table[virt_irq].irq = 0; __bucket(real_irq)->virt_irq = 0; } @@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq) static unsigned int virt_to_real_irq(unsigned char virt_irq) { - return virt_to_real_irq_table[virt_irq]; + return virt_to_real_irq_table[virt_irq].irq; } /* @@ -336,15 +340,15 @@ static void sun4v_irq_enable(unsigned int virt_irq) err = sun4v_intr_settarget(ino, cpuid); if (err != HV_EOK) - printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", - ino, cpuid, err); + printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " + "err(%d)\n", ino, cpuid, err); err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); if (err != HV_EOK) - printk("sun4v_intr_setstate(%x): " + printk(KERN_ERR "sun4v_intr_setstate(%x): " "err(%d)\n", ino, err); err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): err(%d)\n", + printk(KERN_ERR "sun4v_intr_setenabled(%x): err(%d)\n", ino, err); } } @@ -362,8 +366,8 @@ static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask) err = sun4v_intr_settarget(ino, cpuid); if (err != HV_EOK) - printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", - ino, cpuid, err); + printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " + "err(%d)\n", ino, cpuid, err); } } @@ -377,7 +381,7 @@ static void sun4v_irq_disable(unsigned int virt_irq) err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): " + printk(KERN_ERR "sun4v_intr_setenabled(%x): " "err(%d)\n", ino, err); } } @@ -410,7 +414,7 @@ static void sun4v_irq_end(unsigned int virt_irq) err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); if (err != HV_EOK) - printk("sun4v_intr_setstate(%x): " + printk(KERN_ERR "sun4v_intr_setstate(%x): " "err(%d)\n", ino, err); } } @@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq) static void sun4v_virq_enable(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; if (likely(bucket)) { unsigned long cpuid, dev_handle, dev_ino; @@ -426,24 +429,24 @@ static void sun4v_virq_enable(unsigned int virt_irq) cpuid = irq_choose_cpu(virt_irq); - dev_handle = ino & IMAP_IGN; - dev_ino = ino & IMAP_INO; + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); if (err != HV_EOK) - printk("sun4v_vintr_set_target(%lx,%lx,%lu): " + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " "err(%d)\n", dev_handle, dev_ino, cpuid, err); err = sun4v_vintr_set_state(dev_handle, dev_ino, HV_INTR_STATE_IDLE); if (err != HV_EOK) - printk("sun4v_vintr_set_state(%lx,%lx," + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," "HV_INTR_STATE_IDLE): err(%d)\n", dev_handle, dev_ino, err); err = sun4v_vintr_set_valid(dev_handle, dev_ino, HV_INTR_ENABLED); if (err != HV_EOK) - printk("sun4v_vintr_set_state(%lx,%lx," + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," "HV_INTR_ENABLED): err(%d)\n", dev_handle, dev_ino, err); } @@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq) static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; if (likely(bucket)) { unsigned long cpuid, dev_handle, dev_ino; @@ -460,12 +462,12 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) cpuid = irq_choose_cpu(virt_irq); - dev_handle = ino & IMAP_IGN; - dev_ino = ino & IMAP_INO; + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); if (err != HV_EOK) - printk("sun4v_vintr_set_target(%lx,%lx,%lu): " + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " "err(%d)\n", dev_handle, dev_ino, cpuid, err); } @@ -474,19 +476,18 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) static void sun4v_virq_disable(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; if (likely(bucket)) { unsigned long dev_handle, dev_ino; int err; - dev_handle = ino & IMAP_IGN; - dev_ino = ino & IMAP_INO; + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; err = sun4v_vintr_set_valid(dev_handle, dev_ino, HV_INTR_DISABLED); if (err != HV_EOK) - printk("sun4v_vintr_set_state(%lx,%lx," + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," "HV_INTR_DISABLED): err(%d)\n", dev_handle, dev_ino, err); } @@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq) static void sun4v_virq_end(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; struct irq_desc *desc = irq_desc + virt_irq; if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -505,13 +505,13 @@ static void sun4v_virq_end(unsigned int virt_irq) unsigned long dev_handle, dev_ino; int err; - dev_handle = ino & IMAP_IGN; - dev_ino = ino & IMAP_INO; + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; err = sun4v_vintr_set_state(dev_handle, dev_ino, HV_INTR_STATE_IDLE); if (err != HV_EOK) - printk("sun4v_vintr_set_state(%lx,%lx," + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," "HV_INTR_STATE_IDLE): err(%d)\n", dev_handle, dev_ino, err); } @@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) { unsigned long sysino, hv_err; + unsigned int virq; BUG_ON(devhandle & devino); @@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) prom_halt(); } - return sun4v_build_common(sysino, &sun4v_virq); + virq = sun4v_build_common(sysino, &sun4v_virq); + + virt_to_real_irq_table[virq].dev_handle = devhandle; + virt_to_real_irq_table[virq].dev_ino = devino; + + return virq; } #ifdef CONFIG_PCI_MSI diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 6a6882e57ff..1a1043fcf97 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) while (dp) { struct sparc_isa_device *isa_dev; + struct dev_archdata *sd; isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { @@ -86,6 +87,10 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) return; } + sd = &isa_dev->ofdev.dev.archdata; + sd->prom_node = dp; + sd->op = &isa_dev->ofdev; + isa_dev->ofdev.node = dp; isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; isa_dev->ofdev.dev.bus = &isa_bus_type; diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 13a79fe5115..cce4d0ddf5d 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, hp->handle_size = handle_size; } -static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size) +static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size) { struct mdesc_handle *hp; unsigned int handle_size, alloc_size; @@ -123,7 +123,7 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp) } } -static struct mdesc_mem_ops bootmem_mdesc_memops = { +static struct mdesc_mem_ops bootmem_mdesc_ops = { .alloc = mdesc_bootmem_alloc, .free = mdesc_bootmem_free, }; @@ -860,7 +860,7 @@ void __init sun4v_mdesc_init(void) printk("MDESC: Size is %lu bytes.\n", len); - hp = mdesc_alloc(len, &bootmem_mdesc_memops); + hp = mdesc_alloc(len, &bootmem_mdesc_ops); if (hp == NULL) { prom_printf("MDESC: alloc of %lu bytes failed.\n", len); prom_halt(); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 7b0dce9604e..4cc77485f53 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, { struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); const unsigned int *irq; + struct dev_archdata *sd; int len, i; if (!op) return NULL; + sd = &op->dev.archdata; + sd->prom_node = dp; + sd->op = op; + op->node = dp; 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 6b3fe2c1d65..639cf06ca37 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) } #endif /* !(CONFIG_PCI_MSI) */ -static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) +static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; @@ -1163,7 +1163,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_sun4v_msi_init(pbm); } -void sun4v_pci_init(struct device_node *dp, char *model_name) +void __init sun4v_pci_init(struct device_node *dp, char *model_name) { static int hvapi_negotiated = 0; struct pci_controller_info *p; diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index b00feb01c16..881a09ee4c4 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; void machine_power_off(void) { sstate_poweroff(); - if (!serial_console || scons_pwroff) { + if (strcmp(of_console_device->type, "serial") || scons_pwroff) { if (power_reg) { /* Both register bits seem to have the * same effect, so until I figure out diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 93557507ec9..fd7899ba1d7 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -119,7 +119,7 @@ extern void (*prom_keyboard)(void); void machine_halt(void) { sstate_halt(); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); if (prom_keyboard) prom_keyboard(); @@ -130,7 +130,7 @@ void machine_halt(void) void machine_alt_power_off(void) { sstate_poweroff(); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette(1); if (prom_keyboard) prom_keyboard(); @@ -145,7 +145,7 @@ void machine_restart(char * cmd) sstate_reboot(); p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (!serial_console && prom_palette) + if (prom_palette) prom_palette (1); if (prom_keyboard) prom_keyboard(); diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 2b2017ce226..f4e0a9ad9be 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) smp_fill_in_sib_core_maps(); } +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +static void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + const char *type; + phandle node; + + of_console_path = prom_early_alloc(256); + if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) { + prom_printf("Cannot obtain path of stdout.\n"); + prom_halt(); + } + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + node = prom_inst2pkg(prom_stdout); + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", prom_stdout); + prom_halt(); + } + + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + if (!type) { + prom_printf("Console stdout lacks device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + prom_printf(msg, of_console_path); + printk(msg, of_console_path); +} + void __init prom_build_devicetree(void) { struct device_node **nextp; @@ -1658,6 +1712,8 @@ void __init prom_build_devicetree(void) allnodes->child = build_tree(allnodes, prom_getchild(allnodes->node), &nextp); + of_console_init(); + printk("PROM: Built device tree with %u bytes of memory.\n", prom_early_allocated); diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index aafde3dd9fd..0f5be828ee9 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -133,33 +133,6 @@ static void __init process_switch(char c) } } -static void __init process_console(char *commands) -{ - serial_console = 0; - commands += 8; - /* Linux-style serial */ - if (!strncmp(commands, "ttyS", 4)) - serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; - else if (!strncmp(commands, "tty", 3)) { - char c = *(commands + 3); - /* Solaris-style serial */ - if (c == 'a' || c == 'b') { - serial_console = c - 'a' + 1; - prom_printf ("Using /dev/tty%c as console.\n", c); - } - /* else Linux-style fbcon, not serial */ - } -#if defined(CONFIG_PROM_CONSOLE) - if (!strncmp(commands, "prom", 4)) { - char *p; - - for (p = commands - 8; *p && *p != ' '; p++) - *p = ' '; - conswitchp = &prom_con; - } -#endif -} - static void __init boot_flags_init(char *commands) { while (*commands) { @@ -176,9 +149,7 @@ static void __init boot_flags_init(char *commands) process_switch(*commands++); continue; } - if (!strncmp(commands, "console=", 8)) { - process_console(commands); - } else if (!strncmp(commands, "mem=", 4)) { + if (!strncmp(commands, "mem=", 4)) { /* * "mem=XXX[kKmM]" overrides the PROM-reported * memory size. @@ -378,44 +349,6 @@ void __init setup_arch(char **cmdline_p) paging_init(); } -static int __init set_preferred_console(void) -{ - int idev, odev; - - /* The user has requested a console so this is already set up. */ - if (serial_console >= 0) - return -EBUSY; - - idev = prom_query_input_device(); - odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { - serial_console = 3; - } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) { - /* sunhv_console_init() doesn't check the serial_console - * value anyways... - */ - serial_console = 4; - return add_preferred_console("ttyHV", 0, NULL); - } else { - prom_printf("Inconsistent console: " - "input %d, output %d\n", - idev, odev); - prom_halt(); - } - - if (serial_console) - return add_preferred_console("ttyS", serial_console - 1, NULL); - - return -ENODEV; -} -console_initcall(set_preferred_console); - /* BUFFER is PAGE_SIZE bytes long. */ extern char *sparc_cpu_type; @@ -508,5 +441,4 @@ void sun_do_break(void) prom_cmdline(); } -int serial_console = -1; int stop_a_enabled = 1; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 719d676c2dd..7d36531aa5b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -330,7 +330,6 @@ EXPORT_SYMBOL(VISenter); /* for input/keybdev */ EXPORT_SYMBOL(sun_do_break); -EXPORT_SYMBOL(serial_console); EXPORT_SYMBOL(stop_a_enabled); #ifdef CONFIG_DEBUG_BUGVERBOSE diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 592ffcd5760..e340eb401fb 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) return 0; } + +static void cmos_get_rtc_time(struct rtc_time *rtc_tm) +{ + unsigned char ctrl; + + rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); + rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); + rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); + rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); + rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); + rtc_tm->tm_year = CMOS_READ(RTC_YEAR); + rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); + + ctrl = CMOS_READ(RTC_CONTROL); + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(rtc_tm->tm_sec); + BCD_TO_BIN(rtc_tm->tm_min); + BCD_TO_BIN(rtc_tm->tm_hour); + BCD_TO_BIN(rtc_tm->tm_mday); + BCD_TO_BIN(rtc_tm->tm_mon); + BCD_TO_BIN(rtc_tm->tm_year); + BCD_TO_BIN(rtc_tm->tm_wday); + } + + if (rtc_tm->tm_year <= 69) + rtc_tm->tm_year += 100; + + rtc_tm->tm_mon--; +} + +static int cmos_set_rtc_time(struct rtc_time *rtc_tm) +{ + unsigned char mon, day, hrs, min, sec; + unsigned char save_control, save_freq_select; + unsigned int yrs; + + yrs = rtc_tm->tm_year; + mon = rtc_tm->tm_mon + 1; + day = rtc_tm->tm_mday; + hrs = rtc_tm->tm_hour; + min = rtc_tm->tm_min; + sec = rtc_tm->tm_sec; + + if (yrs >= 100) + yrs -= 100; + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + } + + save_control = CMOS_READ(RTC_CONTROL); + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DAY_OF_MONTH); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); + + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return 0; +} #endif /* CONFIG_PCI */ struct mini_rtc_ops { @@ -1456,6 +1528,11 @@ static struct mini_rtc_ops bq4802_rtc_ops = { .get_rtc_time = bq4802_get_rtc_time, .set_rtc_time = bq4802_set_rtc_time, }; + +static struct mini_rtc_ops cmos_rtc_ops = { + .get_rtc_time = cmos_get_rtc_time, + .set_rtc_time = cmos_set_rtc_time, +}; #endif /* CONFIG_PCI */ static struct mini_rtc_ops *mini_rtc_ops; @@ -1583,6 +1660,8 @@ static int __init rtc_mini_init(void) #ifdef CONFIG_PCI else if (bq4802_regs) mini_rtc_ops = &bq4802_rtc_ops; + else if (ds1287_regs) + mini_rtc_ops = &cmos_rtc_ops; #endif /* CONFIG_PCI */ else return -ENODEV; diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 491223a6628..3685daf5157 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, struct device_node *dp; struct vio_dev *vdev; int err, tlen, clen; - const u64 *id; + const u64 *id, *cfg_handle; + u64 a; type = mdesc_get_property(hp, mp, "device-type", &tlen); if (!type) { @@ -221,26 +222,18 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, return NULL; } - if (!strcmp(type, "vdc-port")) { - u64 a; + id = mdesc_get_property(hp, mp, "id", NULL); - id = NULL; - mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { - u64 target; + cfg_handle = NULL; + mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { + u64 target; - target = mdesc_arc_target(hp, a); - id = mdesc_get_property(hp, target, + target = mdesc_arc_target(hp, a); + cfg_handle = mdesc_get_property(hp, target, "cfg-handle", NULL); - if (id) - break; - } - if (!id) { - printk(KERN_ERR "VIO: vdc-port lacks parent " - "cfg-handle.\n"); - return NULL; - } - } else - id = mdesc_get_property(hp, mp, "id", NULL); + if (cfg_handle) + break; + } bus_id_name = type; if (!strcmp(type, "domain-services-port")) @@ -285,10 +278,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", bus_id_name); vdev->dev_no = ~(u64)0; - } else { + } else if (!cfg_handle) { snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", bus_id_name, *id); vdev->dev_no = *id; + } else { + snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu", + bus_id_name, *cfg_handle, *id); + vdev->dev_no = *cfg_handle; } vdev->dev.parent = parent; diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c index 7c25c54cefd..3fafa9a8b50 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc64/prom/console.c @@ -73,88 +73,3 @@ prom_puts(const char *s, int len) P1275_INOUT(3,1), prom_stdout, s, P1275_SIZE(len)); } - -/* Query for input device type */ -enum prom_input_device -prom_query_input_device(void) -{ - int st_p; - char propb[64]; - - st_p = prom_inst2pkg(prom_stdin); - if(prom_node_has_property(st_p, "keyboard")) - return PROMDEV_IKBD; - prom_getproperty(st_p, "device_type", propb, sizeof(propb)); - if(strncmp(propb, "serial", 6)) - return PROMDEV_I_UNK; - /* FIXME: Is there any better way how to find out? */ - memset(propb, 0, sizeof(propb)); - st_p = prom_finddevice ("/options"); - prom_getproperty(st_p, "input-device", propb, sizeof(propb)); - - /* - * If we get here with propb == 'keyboard', we are on ttya, as - * the PROM defaulted to this due to 'no input device'. - */ - if (!strncmp(propb, "keyboard", 8)) - return PROMDEV_ITTYA; - - if (!strncmp (propb, "rsc", 3)) - return PROMDEV_IRSC; - - if (!strncmp (propb, "virtual-console", 3)) - return PROMDEV_IVCONS; - - if (strncmp (propb, "tty", 3) || !propb[3]) - return PROMDEV_I_UNK; - - switch (propb[3]) { - case 'a': return PROMDEV_ITTYA; - case 'b': return PROMDEV_ITTYB; - default: return PROMDEV_I_UNK; - } -} - -/* Query for output device type */ - -enum prom_output_device -prom_query_output_device(void) -{ - int st_p; - char propb[64]; - int propl; - - st_p = prom_inst2pkg(prom_stdout); - propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); - if (propl >= 0 && propl == sizeof("display") && - strncmp("display", propb, sizeof("display")) == 0) - return PROMDEV_OSCREEN; - if(strncmp("serial", propb, 6)) - return PROMDEV_O_UNK; - /* FIXME: Is there any better way how to find out? */ - memset(propb, 0, sizeof(propb)); - st_p = prom_finddevice ("/options"); - prom_getproperty(st_p, "output-device", propb, sizeof(propb)); - - /* - * If we get here with propb == 'screen', we are on ttya, as - * the PROM defaulted to this due to 'no input device'. - */ - if (!strncmp(propb, "screen", 6)) - return PROMDEV_OTTYA; - - if (!strncmp (propb, "rsc", 3)) - return PROMDEV_ORSC; - - if (!strncmp (propb, "virtual-console", 3)) - return PROMDEV_OVCONS; - - if (strncmp (propb, "tty", 3) || !propb[3]) - return PROMDEV_O_UNK; - - switch (propb[3]) { - case 'a': return PROMDEV_OTTYA; - case 'b': return PROMDEV_OTTYB; - default: return PROMDEV_O_UNK; - } -} diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index 33c5b7da31e..68c83ad04ad 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c @@ -72,7 +72,7 @@ void prom_cmdline(void) local_irq_save(flags); - if (!serial_console && prom_palette) + if (prom_palette) prom_palette(1); #ifdef CONFIG_SMP @@ -85,7 +85,7 @@ void prom_cmdline(void) smp_release(); #endif - if (!serial_console && prom_palette) + if (prom_palette) prom_palette(0); local_irq_restore(flags); diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c index 17b7ecfe7ca..b2c5b12c981 100644 --- a/arch/sparc64/prom/tree.c +++ b/arch/sparc64/prom/tree.c @@ -304,3 +304,11 @@ prom_pathtoinode(const char *path) if (node == -1) return 0; return node; } + +int prom_ihandle2path(int handle, char *buffer, int bufsize) +{ + return p1275_cmd("instance-to-path", + P1275_ARG(1,P1275_ARG_OUT_BUF)| + P1275_INOUT(3, 1), + handle, buffer, P1275_SIZE(bufsize)); +} |