forked from Minki/linux
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Fix endless loop in cheetah_xcall_deliver(). [SERIAL] sparc: Infrastructure to fix section mismatch bugs.
This commit is contained in:
commit
da8cadb31b
@ -476,7 +476,7 @@ static inline void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpuma
|
||||
*/
|
||||
static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
|
||||
{
|
||||
u64 pstate, ver;
|
||||
u64 pstate, ver, busy_mask;
|
||||
int nack_busy_id, is_jbus, need_more;
|
||||
|
||||
if (cpus_empty(mask))
|
||||
@ -508,14 +508,20 @@ retry:
|
||||
"i" (ASI_INTR_W));
|
||||
|
||||
nack_busy_id = 0;
|
||||
busy_mask = 0;
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_cpu_mask(i, mask) {
|
||||
u64 target = (i << 14) | 0x70;
|
||||
|
||||
if (!is_jbus)
|
||||
if (is_jbus) {
|
||||
busy_mask |= (0x1UL << (i * 2));
|
||||
} else {
|
||||
target |= (nack_busy_id << 24);
|
||||
busy_mask |= (0x1UL <<
|
||||
(nack_busy_id * 2));
|
||||
}
|
||||
__asm__ __volatile__(
|
||||
"stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync\n\t"
|
||||
@ -531,15 +537,16 @@ retry:
|
||||
|
||||
/* Now, poll for completion. */
|
||||
{
|
||||
u64 dispatch_stat;
|
||||
u64 dispatch_stat, nack_mask;
|
||||
long stuck;
|
||||
|
||||
stuck = 100000 * nack_busy_id;
|
||||
nack_mask = busy_mask << 1;
|
||||
do {
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (dispatch_stat)
|
||||
: "i" (ASI_INTR_DISPATCH_STAT));
|
||||
if (dispatch_stat == 0UL) {
|
||||
if (!(dispatch_stat & (busy_mask | nack_mask))) {
|
||||
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
|
||||
: : "r" (pstate));
|
||||
if (unlikely(need_more)) {
|
||||
@ -556,12 +563,12 @@ retry:
|
||||
}
|
||||
if (!--stuck)
|
||||
break;
|
||||
} while (dispatch_stat & 0x5555555555555555UL);
|
||||
} while (dispatch_stat & busy_mask);
|
||||
|
||||
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
|
||||
: : "r" (pstate));
|
||||
|
||||
if ((dispatch_stat & ~(0x5555555555555555UL)) == 0) {
|
||||
if (dispatch_stat & busy_mask) {
|
||||
/* Busy bits will not clear, continue instead
|
||||
* of freezing up on this cpu.
|
||||
*/
|
||||
|
@ -23,11 +23,36 @@
|
||||
|
||||
#include "suncore.h"
|
||||
|
||||
int sunserial_current_minor = 64;
|
||||
static int sunserial_current_minor = 64;
|
||||
|
||||
EXPORT_SYMBOL(sunserial_current_minor);
|
||||
int sunserial_register_minors(struct uart_driver *drv, int count)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
int sunserial_console_match(struct console *con, struct device_node *dp,
|
||||
drv->minor = sunserial_current_minor;
|
||||
drv->nr += count;
|
||||
/* Register the driver on the first call */
|
||||
if (drv->nr == count)
|
||||
err = uart_register_driver(drv);
|
||||
if (err == 0) {
|
||||
sunserial_current_minor += count;
|
||||
drv->tty_driver->name_base = drv->minor - 64;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(sunserial_register_minors);
|
||||
|
||||
void sunserial_unregister_minors(struct uart_driver *drv, int count)
|
||||
{
|
||||
drv->nr -= count;
|
||||
sunserial_current_minor -= count;
|
||||
|
||||
if (drv->nr == 0)
|
||||
uart_unregister_driver(drv);
|
||||
}
|
||||
EXPORT_SYMBOL(sunserial_unregister_minors);
|
||||
|
||||
int __init sunserial_console_match(struct console *con, struct device_node *dp,
|
||||
struct uart_driver *drv, int line)
|
||||
{
|
||||
int off;
|
||||
@ -133,8 +158,6 @@ sunserial_console_termios(struct console *con)
|
||||
con->cflag = cflag;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sunserial_console_termios);
|
||||
|
||||
/* Sun serial MOUSE auto baud rate detection. */
|
||||
static struct mouse_baud_cflag {
|
||||
int baud;
|
||||
|
@ -22,7 +22,8 @@
|
||||
extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
|
||||
extern int suncore_mouse_baud_detection(unsigned char, int);
|
||||
|
||||
extern int sunserial_current_minor;
|
||||
extern int sunserial_register_minors(struct uart_driver *, int);
|
||||
extern void sunserial_unregister_minors(struct uart_driver *, int);
|
||||
|
||||
extern int sunserial_console_match(struct console *, struct device_node *,
|
||||
struct uart_driver *, int);
|
||||
|
@ -562,16 +562,10 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
|
||||
|
||||
port->dev = &op->dev;
|
||||
|
||||
sunhv_reg.minor = sunserial_current_minor;
|
||||
sunhv_reg.nr = 1;
|
||||
|
||||
err = uart_register_driver(&sunhv_reg);
|
||||
err = sunserial_register_minors(&sunhv_reg, 1);
|
||||
if (err)
|
||||
goto out_free_con_read_page;
|
||||
|
||||
sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
|
||||
sunserial_current_minor += 1;
|
||||
|
||||
sunserial_console_match(&sunhv_console, op->node,
|
||||
&sunhv_reg, port->line);
|
||||
|
||||
@ -591,8 +585,7 @@ out_remove_port:
|
||||
uart_remove_one_port(&sunhv_reg, port);
|
||||
|
||||
out_unregister_driver:
|
||||
sunserial_current_minor -= 1;
|
||||
uart_unregister_driver(&sunhv_reg);
|
||||
sunserial_unregister_minors(&sunhv_reg, 1);
|
||||
|
||||
out_free_con_read_page:
|
||||
kfree(con_read_page);
|
||||
@ -614,8 +607,7 @@ static int __devexit hv_remove(struct of_device *dev)
|
||||
|
||||
uart_remove_one_port(&sunhv_reg, port);
|
||||
|
||||
sunserial_current_minor -= 1;
|
||||
uart_unregister_driver(&sunhv_reg);
|
||||
sunserial_unregister_minors(&sunhv_reg, 1);
|
||||
|
||||
kfree(port);
|
||||
sunhv_port = NULL;
|
||||
|
@ -832,7 +832,6 @@ static struct uart_driver sunsab_reg = {
|
||||
};
|
||||
|
||||
static struct uart_sunsab_port *sunsab_ports;
|
||||
static int num_channels;
|
||||
|
||||
#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
|
||||
|
||||
@ -1102,8 +1101,8 @@ static int __init sunsab_init(void)
|
||||
{
|
||||
struct device_node *dp;
|
||||
int err;
|
||||
int num_channels = 0;
|
||||
|
||||
num_channels = 0;
|
||||
for_each_node_by_name(dp, "se")
|
||||
num_channels += 2;
|
||||
for_each_node_by_name(dp, "serial") {
|
||||
@ -1117,20 +1116,14 @@ static int __init sunsab_init(void)
|
||||
if (!sunsab_ports)
|
||||
return -ENOMEM;
|
||||
|
||||
sunsab_reg.minor = sunserial_current_minor;
|
||||
sunsab_reg.nr = num_channels;
|
||||
sunsab_reg.cons = SUNSAB_CONSOLE();
|
||||
|
||||
err = uart_register_driver(&sunsab_reg);
|
||||
err = sunserial_register_minors(&sunsab_reg, num_channels);
|
||||
if (err) {
|
||||
kfree(sunsab_ports);
|
||||
sunsab_ports = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
|
||||
sunserial_current_minor += num_channels;
|
||||
}
|
||||
|
||||
return of_register_driver(&sab_driver, &of_bus_type);
|
||||
@ -1139,9 +1132,8 @@ static int __init sunsab_init(void)
|
||||
static void __exit sunsab_exit(void)
|
||||
{
|
||||
of_unregister_driver(&sab_driver);
|
||||
if (num_channels) {
|
||||
sunserial_current_minor -= num_channels;
|
||||
uart_unregister_driver(&sunsab_reg);
|
||||
if (sunsab_reg.nr) {
|
||||
sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr);
|
||||
}
|
||||
|
||||
kfree(sunsab_ports);
|
||||
|
@ -1528,14 +1528,12 @@ static struct of_platform_driver su_driver = {
|
||||
.remove = __devexit_p(su_remove),
|
||||
};
|
||||
|
||||
static int num_uart;
|
||||
|
||||
static int __init sunsu_init(void)
|
||||
{
|
||||
struct device_node *dp;
|
||||
int err;
|
||||
int num_uart = 0;
|
||||
|
||||
num_uart = 0;
|
||||
for_each_node_by_name(dp, "su") {
|
||||
if (su_get_type(dp) == SU_PORT_PORT)
|
||||
num_uart++;
|
||||
@ -1552,26 +1550,22 @@ static int __init sunsu_init(void)
|
||||
}
|
||||
|
||||
if (num_uart) {
|
||||
sunsu_reg.minor = sunserial_current_minor;
|
||||
sunsu_reg.nr = num_uart;
|
||||
err = uart_register_driver(&sunsu_reg);
|
||||
err = sunserial_register_minors(&sunsu_reg, num_uart);
|
||||
if (err)
|
||||
return err;
|
||||
sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
|
||||
sunserial_current_minor += num_uart;
|
||||
}
|
||||
|
||||
err = of_register_driver(&su_driver, &of_bus_type);
|
||||
if (err && num_uart)
|
||||
uart_unregister_driver(&sunsu_reg);
|
||||
sunserial_unregister_minors(&sunsu_reg, num_uart);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit sunsu_exit(void)
|
||||
{
|
||||
if (num_uart)
|
||||
uart_unregister_driver(&sunsu_reg);
|
||||
if (sunsu_reg.nr)
|
||||
sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr);
|
||||
}
|
||||
|
||||
module_init(sunsu_init);
|
||||
|
@ -63,10 +63,6 @@
|
||||
readb(&((__channel)->control))
|
||||
#endif
|
||||
|
||||
static int num_sunzilog;
|
||||
#define NUM_SUNZILOG num_sunzilog
|
||||
#define NUM_CHANNELS (NUM_SUNZILOG * 2)
|
||||
|
||||
#define ZS_CLOCK 4915200 /* Zilog input clock rate. */
|
||||
#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
|
||||
|
||||
@ -1031,18 +1027,19 @@ static struct uart_driver sunzilog_reg = {
|
||||
.major = TTY_MAJOR,
|
||||
};
|
||||
|
||||
static int __init sunzilog_alloc_tables(void)
|
||||
static int __init sunzilog_alloc_tables(int num_sunzilog)
|
||||
{
|
||||
struct uart_sunzilog_port *up;
|
||||
unsigned long size;
|
||||
int num_channels = num_sunzilog * 2;
|
||||
int i;
|
||||
|
||||
size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port);
|
||||
size = num_channels * sizeof(struct uart_sunzilog_port);
|
||||
sunzilog_port_table = kzalloc(size, GFP_KERNEL);
|
||||
if (!sunzilog_port_table)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
for (i = 0; i < num_channels; i++) {
|
||||
up = &sunzilog_port_table[i];
|
||||
|
||||
spin_lock_init(&up->port.lock);
|
||||
@ -1050,13 +1047,13 @@ static int __init sunzilog_alloc_tables(void)
|
||||
if (i == 0)
|
||||
sunzilog_irq_chain = up;
|
||||
|
||||
if (i < NUM_CHANNELS - 1)
|
||||
if (i < num_channels - 1)
|
||||
up->next = up + 1;
|
||||
else
|
||||
up->next = NULL;
|
||||
}
|
||||
|
||||
size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *);
|
||||
size = num_sunzilog * sizeof(struct zilog_layout __iomem *);
|
||||
sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
|
||||
if (!sunzilog_chip_regs) {
|
||||
kfree(sunzilog_port_table);
|
||||
@ -1496,34 +1493,28 @@ static int __init sunzilog_init(void)
|
||||
struct device_node *dp;
|
||||
int err, uart_count;
|
||||
int num_keybms;
|
||||
int num_sunzilog = 0;
|
||||
|
||||
NUM_SUNZILOG = 0;
|
||||
num_keybms = 0;
|
||||
for_each_node_by_name(dp, "zs") {
|
||||
NUM_SUNZILOG++;
|
||||
num_sunzilog++;
|
||||
if (of_find_property(dp, "keyboard", NULL))
|
||||
num_keybms++;
|
||||
}
|
||||
|
||||
uart_count = 0;
|
||||
if (NUM_SUNZILOG) {
|
||||
if (num_sunzilog) {
|
||||
int uart_count;
|
||||
|
||||
err = sunzilog_alloc_tables();
|
||||
err = sunzilog_alloc_tables(num_sunzilog);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms);
|
||||
uart_count = (num_sunzilog * 2) - (2 * num_keybms);
|
||||
|
||||
sunzilog_reg.nr = uart_count;
|
||||
sunzilog_reg.minor = sunserial_current_minor;
|
||||
err = uart_register_driver(&sunzilog_reg);
|
||||
err = sunserial_register_minors(&sunzilog_reg, uart_count);
|
||||
if (err)
|
||||
goto out_free_tables;
|
||||
|
||||
sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
|
||||
|
||||
sunserial_current_minor += uart_count;
|
||||
}
|
||||
|
||||
err = of_register_driver(&zs_driver, &of_bus_type);
|
||||
@ -1557,8 +1548,8 @@ out_unregister_driver:
|
||||
of_unregister_driver(&zs_driver);
|
||||
|
||||
out_unregister_uart:
|
||||
if (NUM_SUNZILOG) {
|
||||
uart_unregister_driver(&sunzilog_reg);
|
||||
if (num_sunzilog) {
|
||||
sunserial_unregister_minors(&sunzilog_reg, num_sunzilog);
|
||||
sunzilog_reg.cons = NULL;
|
||||
}
|
||||
|
||||
@ -1590,8 +1581,8 @@ static void __exit sunzilog_exit(void)
|
||||
zilog_irq = -1;
|
||||
}
|
||||
|
||||
if (NUM_SUNZILOG) {
|
||||
uart_unregister_driver(&sunzilog_reg);
|
||||
if (sunzilog_reg.nr) {
|
||||
sunserial_unregister_minors(&sunzilog_reg, sunzilog_reg.nr);
|
||||
sunzilog_free_tables();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user