forked from Minki/linux
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.
This commit is contained in:
commit
c2e6805242
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
cp = find_cap_by_string("var-config");
|
||||
if (cp->state != CAP_STATE_REGISTERED)
|
||||
cp = find_cap_by_string("var-config-backup");
|
||||
spin_lock_irqsave(&ds_lock, flags);
|
||||
cp = NULL;
|
||||
for (dp = ds_info_list; dp; dp = dp->next) {
|
||||
struct ds_cap_state *tmp;
|
||||
|
||||
if (cp->state == CAP_STATE_REGISTERED) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ config NVRAM
|
||||
|
||||
config RTC
|
||||
tristate "Enhanced Real Time Clock Support"
|
||||
depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390
|
||||
depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC64 && (!SPARC32 || PCI) && !FRV && !ARM && !SUPERH && !S390
|
||||
---help---
|
||||
If you say Y here and create a character special file /dev/rtc with
|
||||
major number 10 and minor number 135 using mknod ("man mknod"), you
|
||||
|
@ -86,12 +86,9 @@
|
||||
#include <asm/hpet.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
#include <linux/pci.h>
|
||||
#include <asm/ebus.h>
|
||||
#ifdef __sparc_v9__
|
||||
#include <asm/isa.h>
|
||||
#endif
|
||||
|
||||
static unsigned long rtc_port;
|
||||
static int rtc_irq = PCI_IRQ_NONE;
|
||||
@ -930,13 +927,9 @@ static int __init rtc_init(void)
|
||||
unsigned int year, ctrl;
|
||||
char *guess = NULL;
|
||||
#endif
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev;
|
||||
#ifdef __sparc_v9__
|
||||
struct sparc_isa_bridge *isa_br;
|
||||
struct sparc_isa_device *isa_dev;
|
||||
#endif
|
||||
#else
|
||||
void *r;
|
||||
#ifdef RTC_IRQ
|
||||
@ -944,7 +937,7 @@ static int __init rtc_init(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
if(strcmp(edev->prom_node->name, "rtc") == 0) {
|
||||
@ -954,17 +947,6 @@ static int __init rtc_init(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __sparc_v9__
|
||||
for_each_isa(isa_br) {
|
||||
for_each_isadev(isa_dev, isa_br) {
|
||||
if (strcmp(isa_dev->prom_node->name, "rtc") == 0) {
|
||||
rtc_port = isa_dev->resource.start;
|
||||
rtc_irq = isa_dev->irq;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rtc_has_irq = 0;
|
||||
printk(KERN_ERR "rtc_init: no PC rtc found\n");
|
||||
return -EIO;
|
||||
@ -1020,7 +1002,7 @@ no_irq:
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __sparc__ vs. others */
|
||||
#endif /* CONFIG_SPARC32 vs. others */
|
||||
|
||||
if (misc_register(&rtc_dev)) {
|
||||
#ifdef RTC_IRQ
|
||||
@ -1105,7 +1087,7 @@ static void __exit rtc_exit (void)
|
||||
remove_proc_entry ("driver/rtc", NULL);
|
||||
misc_deregister(&rtc_dev);
|
||||
|
||||
#ifdef __sparc__
|
||||
#ifdef CONFIG_SPARC32
|
||||
if (rtc_has_irq)
|
||||
free_irq (rtc_irq, &rtc_port);
|
||||
#else
|
||||
@ -1117,7 +1099,7 @@ static void __exit rtc_exit (void)
|
||||
if (rtc_has_irq)
|
||||
free_irq (RTC_IRQ, NULL);
|
||||
#endif
|
||||
#endif /* __sparc__ */
|
||||
#endif /* CONFIG_SPARC32 */
|
||||
}
|
||||
|
||||
module_init(rtc_init);
|
||||
|
@ -459,6 +459,22 @@ static int vnet_nack(struct vnet_port *port, void *msgbuf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_mcast(struct vnet_port *port, void *msgbuf)
|
||||
{
|
||||
struct vio_net_mcast_info *pkt = msgbuf;
|
||||
|
||||
if (pkt->tag.stype != VIO_SUBTYPE_ACK)
|
||||
printk(KERN_ERR PFX "%s: Got unexpected MCAST reply "
|
||||
"[%02x:%02x:%04x:%08x]\n",
|
||||
port->vp->dev->name,
|
||||
pkt->tag.type,
|
||||
pkt->tag.stype,
|
||||
pkt->tag.stype_env,
|
||||
pkt->tag.sid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void maybe_tx_wakeup(struct vnet *vp)
|
||||
{
|
||||
struct net_device *dev = vp->dev;
|
||||
@ -544,7 +560,10 @@ static void vnet_event(void *arg, int event)
|
||||
err = vnet_nack(port, &msgbuf);
|
||||
}
|
||||
} else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
|
||||
err = vio_control_pkt_engine(vio, &msgbuf);
|
||||
if (msgbuf.tag.stype_env == VNET_MCAST_INFO)
|
||||
err = handle_mcast(port, &msgbuf);
|
||||
else
|
||||
err = vio_control_pkt_engine(vio, &msgbuf);
|
||||
if (err)
|
||||
break;
|
||||
} else {
|
||||
@ -731,9 +750,122 @@ static int vnet_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vnet_mcast_entry *__vnet_mc_find(struct vnet *vp, u8 *addr)
|
||||
{
|
||||
struct vnet_mcast_entry *m;
|
||||
|
||||
for (m = vp->mcast_list; m; m = m->next) {
|
||||
if (!memcmp(m->addr, addr, ETH_ALEN))
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __update_mc_list(struct vnet *vp, struct net_device *dev)
|
||||
{
|
||||
struct dev_addr_list *p;
|
||||
|
||||
for (p = dev->mc_list; p; p = p->next) {
|
||||
struct vnet_mcast_entry *m;
|
||||
|
||||
m = __vnet_mc_find(vp, p->dmi_addr);
|
||||
if (m) {
|
||||
m->hit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m) {
|
||||
m = kzalloc(sizeof(*m), GFP_ATOMIC);
|
||||
if (!m)
|
||||
continue;
|
||||
memcpy(m->addr, p->dmi_addr, ETH_ALEN);
|
||||
m->hit = 1;
|
||||
|
||||
m->next = vp->mcast_list;
|
||||
vp->mcast_list = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __send_mc_list(struct vnet *vp, struct vnet_port *port)
|
||||
{
|
||||
struct vio_net_mcast_info info;
|
||||
struct vnet_mcast_entry *m, **pp;
|
||||
int n_addrs;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
info.tag.type = VIO_TYPE_CTRL;
|
||||
info.tag.stype = VIO_SUBTYPE_INFO;
|
||||
info.tag.stype_env = VNET_MCAST_INFO;
|
||||
info.tag.sid = vio_send_sid(&port->vio);
|
||||
info.set = 1;
|
||||
|
||||
n_addrs = 0;
|
||||
for (m = vp->mcast_list; m; m = m->next) {
|
||||
if (m->sent)
|
||||
continue;
|
||||
m->sent = 1;
|
||||
memcpy(&info.mcast_addr[n_addrs * ETH_ALEN],
|
||||
m->addr, ETH_ALEN);
|
||||
if (++n_addrs == VNET_NUM_MCAST) {
|
||||
info.count = n_addrs;
|
||||
|
||||
(void) vio_ldc_send(&port->vio, &info,
|
||||
sizeof(info));
|
||||
n_addrs = 0;
|
||||
}
|
||||
}
|
||||
if (n_addrs) {
|
||||
info.count = n_addrs;
|
||||
(void) vio_ldc_send(&port->vio, &info, sizeof(info));
|
||||
}
|
||||
|
||||
info.set = 0;
|
||||
|
||||
n_addrs = 0;
|
||||
pp = &vp->mcast_list;
|
||||
while ((m = *pp) != NULL) {
|
||||
if (m->hit) {
|
||||
m->hit = 0;
|
||||
pp = &m->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&info.mcast_addr[n_addrs * ETH_ALEN],
|
||||
m->addr, ETH_ALEN);
|
||||
if (++n_addrs == VNET_NUM_MCAST) {
|
||||
info.count = n_addrs;
|
||||
(void) vio_ldc_send(&port->vio, &info,
|
||||
sizeof(info));
|
||||
n_addrs = 0;
|
||||
}
|
||||
|
||||
*pp = m->next;
|
||||
kfree(m);
|
||||
}
|
||||
if (n_addrs) {
|
||||
info.count = n_addrs;
|
||||
(void) vio_ldc_send(&port->vio, &info, sizeof(info));
|
||||
}
|
||||
}
|
||||
|
||||
static void vnet_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
/* XXX Implement multicast support XXX */
|
||||
struct vnet *vp = netdev_priv(dev);
|
||||
struct vnet_port *port;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vp->lock, flags);
|
||||
if (!list_empty(&vp->port_list)) {
|
||||
port = list_entry(vp->port_list.next, struct vnet_port, list);
|
||||
|
||||
if (port->switch_port) {
|
||||
__update_mc_list(vp, dev);
|
||||
__send_mc_list(vp, port);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&vp->lock, flags);
|
||||
}
|
||||
|
||||
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,
|
||||
switch_port = 0;
|
||||
if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL)
|
||||
switch_port = 1;
|
||||
port->switch_port = switch_port;
|
||||
|
||||
spin_lock_irqsave(&vp->lock, flags);
|
||||
if (switch_port)
|
||||
|
@ -30,6 +30,8 @@ struct vnet_port {
|
||||
|
||||
struct hlist_node hash;
|
||||
u8 raddr[ETH_ALEN];
|
||||
u8 switch_port;
|
||||
u8 __pad;
|
||||
|
||||
struct vnet *vp;
|
||||
|
||||
@ -53,6 +55,13 @@ static inline unsigned int vnet_hashfn(u8 *mac)
|
||||
return val & (VNET_PORT_HASH_MASK);
|
||||
}
|
||||
|
||||
struct vnet_mcast_entry {
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 sent;
|
||||
u8 hit;
|
||||
struct vnet_mcast_entry *next;
|
||||
};
|
||||
|
||||
struct vnet {
|
||||
/* Protects port_list and port_hash. */
|
||||
spinlock_t lock;
|
||||
@ -65,6 +74,8 @@ struct vnet {
|
||||
|
||||
struct hlist_head port_hash[VNET_PORT_HASH_SIZE];
|
||||
|
||||
struct vnet_mcast_entry *mcast_list;
|
||||
|
||||
struct list_head list;
|
||||
u64 local_mac;
|
||||
};
|
||||
|
@ -33,6 +33,7 @@ struct sbus_bus *sbus_root;
|
||||
|
||||
static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
|
||||
{
|
||||
struct dev_archdata *sd;
|
||||
unsigned long base;
|
||||
const void *pval;
|
||||
int len, err;
|
||||
@ -67,6 +68,10 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde
|
||||
|
||||
sbus_fill_device_irq(sdev);
|
||||
|
||||
sd = &sdev->ofdev.dev.archdata;
|
||||
sd->prom_node = dp;
|
||||
sd->op = &sdev->ofdev;
|
||||
|
||||
sdev->ofdev.node = dp;
|
||||
if (sdev->parent)
|
||||
sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev;
|
||||
|
@ -16,9 +16,10 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#include "suncore.h"
|
||||
|
||||
@ -26,92 +27,60 @@ int sunserial_current_minor = 64;
|
||||
|
||||
EXPORT_SYMBOL(sunserial_current_minor);
|
||||
|
||||
int sunserial_console_match(struct console *con, struct device_node *dp,
|
||||
struct uart_driver *drv, int line)
|
||||
{
|
||||
int off;
|
||||
|
||||
if (!con || of_console_device != dp)
|
||||
return 0;
|
||||
|
||||
off = 0;
|
||||
if (of_console_options &&
|
||||
*of_console_options == 'b')
|
||||
off = 1;
|
||||
|
||||
if ((line & 1) != off)
|
||||
return 0;
|
||||
|
||||
con->index = line;
|
||||
drv->cons = con;
|
||||
add_preferred_console(con->name, line, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(sunserial_console_match);
|
||||
|
||||
void
|
||||
sunserial_console_termios(struct console *con)
|
||||
{
|
||||
char mode[16], buf[16], *s;
|
||||
struct device_node *dp;
|
||||
const char *od, *mode, *s;
|
||||
char mode_prop[] = "ttyX-mode";
|
||||
char cd_prop[] = "ttyX-ignore-cd";
|
||||
char dtr_prop[] = "ttyX-rts-dtr-off";
|
||||
char *ssp_console_modes_prop = "ssp-console-modes";
|
||||
int baud, bits, stop, cflag;
|
||||
char parity;
|
||||
int carrier = 0;
|
||||
int rtsdtr = 1;
|
||||
int topnd, nd;
|
||||
|
||||
if (!serial_console)
|
||||
return;
|
||||
dp = of_find_node_by_path("/options");
|
||||
od = of_get_property(dp, "output-device", NULL);
|
||||
if (!strcmp(od, "rsc")) {
|
||||
mode = of_get_property(of_console_device,
|
||||
"ssp-console-modes", NULL);
|
||||
if (!mode)
|
||||
mode = "115200,8,n,1,-";
|
||||
} else {
|
||||
char c;
|
||||
|
||||
switch (serial_console) {
|
||||
case PROMDEV_OTTYA:
|
||||
mode_prop[3] = 'a';
|
||||
cd_prop[3] = 'a';
|
||||
dtr_prop[3] = 'a';
|
||||
break;
|
||||
c = 'a';
|
||||
if (of_console_options)
|
||||
c = *of_console_options;
|
||||
|
||||
case PROMDEV_OTTYB:
|
||||
mode_prop[3] = 'b';
|
||||
cd_prop[3] = 'b';
|
||||
dtr_prop[3] = 'b';
|
||||
break;
|
||||
mode_prop[3] = c;
|
||||
|
||||
case PROMDEV_ORSC:
|
||||
|
||||
nd = prom_pathtoinode("rsc");
|
||||
if (!nd) {
|
||||
strcpy(mode, "115200,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
|
||||
strcpy(mode, "115200,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
memset(mode, 0, sizeof(mode));
|
||||
prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
|
||||
goto no_options;
|
||||
|
||||
default:
|
||||
strcpy(mode, "9600,8,n,1,-");
|
||||
goto no_options;
|
||||
mode = of_get_property(dp, mode_prop, NULL);
|
||||
if (!mode)
|
||||
mode = "9600,8,n,1,-";
|
||||
}
|
||||
|
||||
topnd = prom_getchild(prom_root_node);
|
||||
nd = prom_searchsiblings(topnd, "options");
|
||||
if (!nd) {
|
||||
strcpy(mode, "9600,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
if (!prom_node_has_property(nd, mode_prop)) {
|
||||
strcpy(mode, "9600,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
memset(mode, 0, sizeof(mode));
|
||||
prom_getstring(nd, mode_prop, mode, sizeof(mode));
|
||||
|
||||
if (prom_node_has_property(nd, cd_prop)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
prom_getstring(nd, cd_prop, buf, sizeof(buf));
|
||||
if (!strcmp(buf, "false"))
|
||||
carrier = 1;
|
||||
|
||||
/* XXX: this is unused below. */
|
||||
}
|
||||
|
||||
if (prom_node_has_property(nd, dtr_prop)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
prom_getstring(nd, dtr_prop, buf, sizeof(buf));
|
||||
if (!strcmp(buf, "false"))
|
||||
rtsdtr = 0;
|
||||
|
||||
/* XXX: this is unused below. */
|
||||
}
|
||||
|
||||
no_options:
|
||||
cflag = CREAD | HUPCL | CLOCAL;
|
||||
|
||||
s = mode;
|
||||
|
@ -24,6 +24,8 @@ extern int suncore_mouse_baud_detection(unsigned char, int);
|
||||
|
||||
extern int sunserial_current_minor;
|
||||
|
||||
extern int sunserial_console_match(struct console *, struct device_node *,
|
||||
struct uart_driver *, int);
|
||||
extern void sunserial_console_termios(struct console *);
|
||||
|
||||
#endif /* !(_SERIAL_SUN_H) */
|
||||
|
@ -520,16 +520,6 @@ static struct console sunhv_console = {
|
||||
.data = &sunhv_reg,
|
||||
};
|
||||
|
||||
static inline struct console *SUNHV_CONSOLE(void)
|
||||
{
|
||||
if (con_is_present())
|
||||
return NULL;
|
||||
|
||||
sunhv_console.index = 0;
|
||||
|
||||
return &sunhv_console;
|
||||
}
|
||||
|
||||
static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct uart_port *port;
|
||||
@ -582,7 +572,8 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
|
||||
sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
|
||||
sunserial_current_minor += 1;
|
||||
|
||||
sunhv_reg.cons = SUNHV_CONSOLE();
|
||||
sunserial_console_match(&sunhv_console, op->node,
|
||||
&sunhv_reg, port->line);
|
||||
|
||||
err = uart_add_one_port(&sunhv_reg, port);
|
||||
if (err)
|
||||
|
@ -968,22 +968,6 @@ static struct console sunsab_console = {
|
||||
|
||||
static inline struct console *SUNSAB_CONSOLE(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (con_is_present())
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < num_channels; i++) {
|
||||
int this_minor = sunsab_reg.minor + i;
|
||||
|
||||
if ((this_minor - 64) == (serial_console - 1))
|
||||
break;
|
||||
}
|
||||
if (i == num_channels)
|
||||
return NULL;
|
||||
|
||||
sunsab_console.index = i;
|
||||
|
||||
return &sunsab_console;
|
||||
}
|
||||
#else
|
||||
@ -1080,7 +1064,12 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
|
||||
return err;
|
||||
}
|
||||
|
||||
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
||||
&sunsab_reg, up[0].port.line);
|
||||
uart_add_one_port(&sunsab_reg, &up[0].port);
|
||||
|
||||
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
||||
&sunsab_reg, up[1].port.line);
|
||||
uart_add_one_port(&sunsab_reg, &up[1].port);
|
||||
|
||||
dev_set_drvdata(&op->dev, &up[0]);
|
||||
@ -1164,7 +1153,6 @@ static int __init sunsab_init(void)
|
||||
}
|
||||
|
||||
sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
|
||||
sunsab_reg.cons = SUNSAB_CONSOLE();
|
||||
sunserial_current_minor += num_channels;
|
||||
}
|
||||
|
||||
|
@ -1371,28 +1371,12 @@ static struct console sunsu_console = {
|
||||
* Register console.
|
||||
*/
|
||||
|
||||
static inline struct console *SUNSU_CONSOLE(int num_uart)
|
||||
static inline struct console *SUNSU_CONSOLE(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (con_is_present())
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < num_uart; i++) {
|
||||
int this_minor = sunsu_reg.minor + i;
|
||||
|
||||
if ((this_minor - 64) == (serial_console - 1))
|
||||
break;
|
||||
}
|
||||
if (i == num_uart)
|
||||
return NULL;
|
||||
|
||||
sunsu_console.index = i;
|
||||
|
||||
return &sunsu_console;
|
||||
}
|
||||
#else
|
||||
#define SUNSU_CONSOLE(num_uart) (NULL)
|
||||
#define SUNSU_CONSOLE() (NULL)
|
||||
#define sunsu_serial_console_init() do { } while (0)
|
||||
#endif
|
||||
|
||||
@ -1482,6 +1466,8 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
|
||||
|
||||
up->port.ops = &sunsu_pops;
|
||||
|
||||
sunserial_console_match(SUNSU_CONSOLE(), dp,
|
||||
&sunsu_reg, up->port.line);
|
||||
err = uart_add_one_port(&sunsu_reg, &up->port);
|
||||
if (err)
|
||||
goto out_unmap;
|
||||
@ -1572,7 +1558,6 @@ static int __init sunsu_init(void)
|
||||
return err;
|
||||
sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
|
||||
sunserial_current_minor += num_uart;
|
||||
sunsu_reg.cons = SUNSU_CONSOLE(num_uart);
|
||||
}
|
||||
|
||||
err = of_register_driver(&su_driver, &of_bus_type);
|
||||
|
@ -1226,23 +1226,6 @@ static struct console sunzilog_console_ops = {
|
||||
|
||||
static inline struct console *SUNZILOG_CONSOLE(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (con_is_present())
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
int this_minor = sunzilog_reg.minor + i;
|
||||
|
||||
if ((this_minor - 64) == (serial_console - 1))
|
||||
break;
|
||||
}
|
||||
if (i == NUM_CHANNELS)
|
||||
return NULL;
|
||||
|
||||
sunzilog_console_ops.index = i;
|
||||
sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
|
||||
|
||||
return &sunzilog_console_ops;
|
||||
}
|
||||
|
||||
@ -1428,12 +1411,18 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
|
||||
sunzilog_init_hw(&up[1]);
|
||||
|
||||
if (!keyboard_mouse) {
|
||||
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
|
||||
&sunzilog_reg, up[0].port.line))
|
||||
up->flags |= SUNZILOG_FLAG_IS_CONS;
|
||||
err = uart_add_one_port(&sunzilog_reg, &up[0].port);
|
||||
if (err) {
|
||||
of_iounmap(&op->resource[0],
|
||||
rp, sizeof(struct zilog_layout));
|
||||
return err;
|
||||
}
|
||||
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
|
||||
&sunzilog_reg, up[1].port.line))
|
||||
up->flags |= SUNZILOG_FLAG_IS_CONS;
|
||||
err = uart_add_one_port(&sunzilog_reg, &up[1].port);
|
||||
if (err) {
|
||||
uart_remove_one_port(&sunzilog_reg, &up[0].port);
|
||||
@ -1531,7 +1520,6 @@ static int __init sunzilog_init(void)
|
||||
goto out_free_tables;
|
||||
|
||||
sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
|
||||
sunzilog_reg.cons = SUNZILOG_CONSOLE();
|
||||
|
||||
sunserial_current_minor += uart_count;
|
||||
}
|
||||
|
@ -2913,10 +2913,6 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||
int node, len, i, j, ret;
|
||||
u32 mem, chip_id;
|
||||
|
||||
/* Do not attach when we have a serial console. */
|
||||
if (!con_is_present())
|
||||
return -ENXIO;
|
||||
|
||||
/*
|
||||
* Map memory-mapped registers.
|
||||
*/
|
||||
|
@ -379,10 +379,6 @@ int __init igafb_init(void)
|
||||
if (fb_get_options("igafb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
/* Do not attach when we have a serial console. */
|
||||
if (!con_is_present())
|
||||
return -ENXIO;
|
||||
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
|
||||
PCI_DEVICE_ID_INTERG_1682, 0);
|
||||
if (pdev == NULL) {
|
||||
|
@ -3,5 +3,17 @@
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*/
|
||||
#include <asm-generic/device.h>
|
||||
#ifndef _ASM_SPARC_DEVICE_H
|
||||
#define _ASM_SPARC_DEVICE_H
|
||||
|
||||
struct device_node;
|
||||
struct of_device;
|
||||
|
||||
struct dev_archdata {
|
||||
struct device_node *prom_node;
|
||||
struct of_device *op;
|
||||
};
|
||||
|
||||
#endif /* _ASM_SPARC_DEVICE_H */
|
||||
|
||||
|
||||
|
@ -1,11 +1,20 @@
|
||||
#ifndef _ASM_FB_H_
|
||||
#define _ASM_FB_H_
|
||||
#include <linux/fb.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#define fb_pgprotect(...) do {} while (0)
|
||||
|
||||
static inline int fb_is_primary_device(struct fb_info *info)
|
||||
{
|
||||
struct device *dev = info->device;
|
||||
struct device_node *node;
|
||||
|
||||
node = dev->archdata.prom_node;
|
||||
if (node &&
|
||||
node == of_console_device)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -158,32 +158,6 @@ extern void prom_putchar(char character);
|
||||
extern void prom_printf(char *fmt, ...);
|
||||
extern void prom_write(const char *buf, unsigned int len);
|
||||
|
||||
/* Query for input device type */
|
||||
|
||||
enum prom_input_device {
|
||||
PROMDEV_IKBD, /* input from keyboard */
|
||||
PROMDEV_ITTYA, /* input from ttya */
|
||||
PROMDEV_ITTYB, /* input from ttyb */
|
||||
PROMDEV_IRSC, /* input from rsc */
|
||||
PROMDEV_IVCONS, /* input from virtual-console */
|
||||
PROMDEV_I_UNK,
|
||||
};
|
||||
|
||||
extern enum prom_input_device prom_query_input_device(void);
|
||||
|
||||
/* Query for output device type */
|
||||
|
||||
enum prom_output_device {
|
||||
PROMDEV_OSCREEN, /* to screen */
|
||||
PROMDEV_OTTYA, /* to ttya */
|
||||
PROMDEV_OTTYB, /* to ttyb */
|
||||
PROMDEV_ORSC, /* to rsc */
|
||||
PROMDEV_OVCONS, /* to virtual-console */
|
||||
PROMDEV_O_UNK,
|
||||
};
|
||||
|
||||
extern enum prom_output_device prom_query_output_device(void);
|
||||
|
||||
/* Multiprocessor operations... */
|
||||
|
||||
/* Start the CPU with the given device tree node, context table, and context
|
||||
|
@ -85,5 +85,9 @@ static inline void of_node_put(struct device_node *node)
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
|
||||
extern struct device_node *of_console_device;
|
||||
extern char *of_console_path;
|
||||
extern char *of_console_options;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _SPARC_PROM_H */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <linux/fb.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
|
||||
unsigned long off)
|
||||
@ -12,6 +13,14 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
|
||||
|
||||
static inline int fb_is_primary_device(struct fb_info *info)
|
||||
{
|
||||
struct device *dev = info->device;
|
||||
struct device_node *node;
|
||||
|
||||
node = dev->archdata.prom_node;
|
||||
if (node &&
|
||||
node == of_console_device)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -140,32 +140,6 @@ extern void prom_putchar(char character);
|
||||
extern void prom_printf(const char *fmt, ...);
|
||||
extern void prom_write(const char *buf, unsigned int len);
|
||||
|
||||
/* Query for input device type */
|
||||
|
||||
enum prom_input_device {
|
||||
PROMDEV_IKBD, /* input from keyboard */
|
||||
PROMDEV_ITTYA, /* input from ttya */
|
||||
PROMDEV_ITTYB, /* input from ttyb */
|
||||
PROMDEV_IRSC, /* input from rsc */
|
||||
PROMDEV_IVCONS, /* input from virtual-console */
|
||||
PROMDEV_I_UNK,
|
||||
};
|
||||
|
||||
extern enum prom_input_device prom_query_input_device(void);
|
||||
|
||||
/* Query for output device type */
|
||||
|
||||
enum prom_output_device {
|
||||
PROMDEV_OSCREEN, /* to screen */
|
||||
PROMDEV_OTTYA, /* to ttya */
|
||||
PROMDEV_OTTYB, /* to ttyb */
|
||||
PROMDEV_ORSC, /* to rsc */
|
||||
PROMDEV_OVCONS, /* to virtual-console */
|
||||
PROMDEV_O_UNK,
|
||||
};
|
||||
|
||||
extern enum prom_output_device prom_query_output_device(void);
|
||||
|
||||
/* Multiprocessor operations... */
|
||||
#ifdef CONFIG_SMP
|
||||
/* Start the CPU with the given device tree node at the passed program
|
||||
@ -319,6 +293,8 @@ extern int prom_inst2pkg(int);
|
||||
extern int prom_service_exists(const char *service_name);
|
||||
extern void prom_sun4v_guest_soft_state(void);
|
||||
|
||||
extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
|
||||
|
||||
/* Client interface level routines. */
|
||||
extern void prom_set_trap_table(unsigned long tba);
|
||||
extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa);
|
||||
|
@ -8,8 +8,9 @@
|
||||
#define _ASM_SPARC64_PARPORT_H 1
|
||||
|
||||
#include <asm/ebus.h>
|
||||
#include <asm/isa.h>
|
||||
#include <asm/ns87303.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#define PARPORT_PC_MAX_PORTS PARPORT_MAX
|
||||
|
||||
@ -35,8 +36,12 @@ static struct sparc_ebus_info {
|
||||
unsigned int addr;
|
||||
unsigned int count;
|
||||
int lock;
|
||||
|
||||
struct parport *port;
|
||||
} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
|
||||
|
||||
static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
|
||||
|
||||
static __inline__ int request_dma(unsigned int dmanr, const char *device_id)
|
||||
{
|
||||
if (dmanr >= PARPORT_PC_MAX_PORTS)
|
||||
@ -98,117 +103,145 @@ static __inline__ unsigned int get_dma_residue(unsigned int dmanr)
|
||||
return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
|
||||
}
|
||||
|
||||
static int ebus_ecpp_p(struct linux_ebus_device *edev)
|
||||
static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
if (!strcmp(edev->prom_node->name, "ecpp"))
|
||||
return 1;
|
||||
if (!strcmp(edev->prom_node->name, "parallel")) {
|
||||
const char *compat;
|
||||
unsigned long base = op->resource[0].start;
|
||||
unsigned long config = op->resource[1].start;
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
struct device_node *parent;
|
||||
struct parport *p;
|
||||
int slot, err;
|
||||
|
||||
compat = of_get_property(edev->prom_node,
|
||||
"compatible", NULL);
|
||||
if (compat &&
|
||||
(!strcmp(compat, "ecpp") ||
|
||||
!strcmp(compat, "ns87317-ecpp") ||
|
||||
!strcmp(compat + 13, "ecpp")))
|
||||
return 1;
|
||||
parent = op->node->parent;
|
||||
if (!strcmp(parent->name, "dma")) {
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->irqs[0], PARPORT_DMA_NOFIFO,
|
||||
op->dev.parent);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
|
||||
if (!test_and_set_bit(slot, dma_slot_map))
|
||||
break;
|
||||
}
|
||||
err = -ENODEV;
|
||||
if (slot >= PARPORT_PC_MAX_PORTS)
|
||||
goto out_err;
|
||||
|
||||
spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
sparc_ebus_dmas[slot].info.regs =
|
||||
of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
|
||||
|
||||
if (!sparc_ebus_dmas[slot].info.regs)
|
||||
goto out_clear_map;
|
||||
|
||||
sparc_ebus_dmas[slot].info.flags = 0;
|
||||
sparc_ebus_dmas[slot].info.callback = NULL;
|
||||
sparc_ebus_dmas[slot].info.client_cookie = NULL;
|
||||
sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
|
||||
strcpy(sparc_ebus_dmas[slot].info.name, "parport");
|
||||
if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
|
||||
goto out_unmap_regs;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
|
||||
|
||||
/* Configure IRQ to Push Pull, Level Low */
|
||||
/* Enable ECP, set bit 2 of the CTR first */
|
||||
outb(0x04, base + 0x02);
|
||||
ns87303_modify(config, PCR,
|
||||
PCR_EPP_ENABLE |
|
||||
PCR_IRQ_ODRAIN,
|
||||
PCR_ECP_ENABLE |
|
||||
PCR_ECP_CLK_ENA |
|
||||
PCR_IRQ_POLAR);
|
||||
|
||||
/* CTR bit 5 controls direction of port */
|
||||
ns87303_modify(config, PTR,
|
||||
0, PTR_LPT_REG_DIR);
|
||||
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->irqs[0],
|
||||
slot,
|
||||
op->dev.parent);
|
||||
err = -ENOMEM;
|
||||
if (!p)
|
||||
goto out_disable_irq;
|
||||
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_irq:
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
|
||||
|
||||
out_clear_map:
|
||||
clear_bit(slot, dma_slot_map);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit ecpp_remove(struct of_device *op)
|
||||
{
|
||||
struct parport *p = dev_get_drvdata(&op->dev);
|
||||
int slot = p->dma;
|
||||
|
||||
parport_pc_unregister_port(p);
|
||||
|
||||
if (slot != PARPORT_DMA_NOFIFO) {
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
of_iounmap(&op->resource[2],
|
||||
sparc_ebus_dmas[slot].info.regs,
|
||||
d_len);
|
||||
clear_bit(slot, dma_slot_map);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parport_isa_probe(int count)
|
||||
static struct of_device_id ecpp_match[] = {
|
||||
{
|
||||
.name = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ns87317-ecpp",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct of_platform_driver ecpp_driver = {
|
||||
.name = "ecpp",
|
||||
.match_table = ecpp_match,
|
||||
.probe = ecpp_probe,
|
||||
.remove = __devexit_p(ecpp_remove),
|
||||
};
|
||||
|
||||
static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
|
||||
{
|
||||
struct sparc_isa_bridge *isa_br;
|
||||
struct sparc_isa_device *isa_dev;
|
||||
of_register_driver(&ecpp_driver, &of_bus_type);
|
||||
|
||||
for_each_isa(isa_br) {
|
||||
for_each_isadev(isa_dev, isa_br) {
|
||||
struct sparc_isa_device *child;
|
||||
unsigned long base;
|
||||
|
||||
if (strcmp(isa_dev->prom_node->name, "dma"))
|
||||
continue;
|
||||
|
||||
child = isa_dev->child;
|
||||
while (child) {
|
||||
if (!strcmp(child->prom_node->name, "parallel"))
|
||||
break;
|
||||
child = child->next;
|
||||
}
|
||||
if (!child)
|
||||
continue;
|
||||
|
||||
base = child->resource.start;
|
||||
|
||||
/* No DMA, see commentary in
|
||||
* asm-sparc64/floppy.h:isa_floppy_init()
|
||||
*/
|
||||
if (parport_pc_probe_port(base, base + 0x400,
|
||||
child->irq, PARPORT_DMA_NOFIFO,
|
||||
&child->bus->self->dev))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
|
||||
{
|
||||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev;
|
||||
int count = 0;
|
||||
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
if (ebus_ecpp_p(edev)) {
|
||||
unsigned long base = edev->resource[0].start;
|
||||
unsigned long config = edev->resource[1].start;
|
||||
unsigned long d_base = edev->resource[2].start;
|
||||
unsigned long d_len;
|
||||
|
||||
spin_lock_init(&sparc_ebus_dmas[count].info.lock);
|
||||
d_len = (edev->resource[2].end -
|
||||
d_base) + 1;
|
||||
sparc_ebus_dmas[count].info.regs =
|
||||
ioremap(d_base, d_len);
|
||||
if (!sparc_ebus_dmas[count].info.regs)
|
||||
continue;
|
||||
sparc_ebus_dmas[count].info.flags = 0;
|
||||
sparc_ebus_dmas[count].info.callback = NULL;
|
||||
sparc_ebus_dmas[count].info.client_cookie = NULL;
|
||||
sparc_ebus_dmas[count].info.irq = 0xdeadbeef;
|
||||
strcpy(sparc_ebus_dmas[count].info.name, "parport");
|
||||
if (ebus_dma_register(&sparc_ebus_dmas[count].info))
|
||||
continue;
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[count].info, 1);
|
||||
|
||||
/* Configure IRQ to Push Pull, Level Low */
|
||||
/* Enable ECP, set bit 2 of the CTR first */
|
||||
outb(0x04, base + 0x02);
|
||||
ns87303_modify(config, PCR,
|
||||
PCR_EPP_ENABLE |
|
||||
PCR_IRQ_ODRAIN,
|
||||
PCR_ECP_ENABLE |
|
||||
PCR_ECP_CLK_ENA |
|
||||
PCR_IRQ_POLAR);
|
||||
|
||||
/* CTR bit 5 controls direction of port */
|
||||
ns87303_modify(config, PTR,
|
||||
0, PTR_LPT_REG_DIR);
|
||||
|
||||
if (parport_pc_probe_port(base, base + 0x400,
|
||||
edev->irqs[0],
|
||||
count,
|
||||
&ebus->self->dev))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = parport_isa_probe(count);
|
||||
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !(_ASM_SPARC64_PARPORT_H */
|
||||
|
@ -94,5 +94,9 @@ static inline void of_node_put(struct device_node *node)
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
|
||||
extern struct device_node *of_console_device;
|
||||
extern char *of_console_path;
|
||||
extern char *of_console_options;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _SPARC64_PROM_H */
|
||||
|
@ -115,14 +115,8 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern void sun_do_break(void);
|
||||
extern int serial_console;
|
||||
extern int stop_a_enabled;
|
||||
|
||||
static __inline__ int con_is_present(void)
|
||||
{
|
||||
return serial_console ? 0 : 1;
|
||||
}
|
||||
|
||||
extern void synchronize_user_stack(void);
|
||||
|
||||
extern void __flushw_user(void);
|
||||
|
Loading…
Reference in New Issue
Block a user