diff options
Diffstat (limited to 'arch/mn10300/kernel')
-rw-r--r-- | arch/mn10300/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/mn10300/kernel/entry.S | 7 | ||||
-rw-r--r-- | arch/mn10300/kernel/irq.c | 50 | ||||
-rw-r--r-- | arch/mn10300/kernel/mn10300-serial-low.S | 9 | ||||
-rw-r--r-- | arch/mn10300/kernel/mn10300-serial.c | 213 | ||||
-rw-r--r-- | arch/mn10300/kernel/mn10300-serial.h | 10 | ||||
-rw-r--r-- | arch/mn10300/kernel/process.c | 33 | ||||
-rw-r--r-- | arch/mn10300/kernel/smp.c | 10 |
8 files changed, 176 insertions, 158 deletions
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c index 96f24fab7de..47b3bb0c04f 100644 --- a/arch/mn10300/kernel/asm-offsets.c +++ b/arch/mn10300/kernel/asm-offsets.c @@ -96,7 +96,7 @@ void foo(void) OFFSET(__rx_outp, mn10300_serial_port, rx_outp); OFFSET(__uart_state, mn10300_serial_port, uart.state); OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar); - OFFSET(__tx_break, mn10300_serial_port, tx_break); + OFFSET(__tx_flags, mn10300_serial_port, tx_flags); OFFSET(__intr_flags, mn10300_serial_port, intr_flags); OFFSET(__rx_icr, mn10300_serial_port, rx_icr); OFFSET(__tx_icr, mn10300_serial_port, tx_icr); diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 0c631d34c8d..68fcab8f8f6 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread) mov (REG_D0,fp),d0 mov (REG_A0,fp),a0 calls (a0) - jmp sys_exit - -ENTRY(ret_from_kernel_execve) - add -12,d0 /* pt_regs -> frame */ - mov d0,sp - GET_THREAD_INFO a2 clr d0 + mov d0,(REG_D0,fp) jmp syscall_exit ############################################################################### diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 35932a8de8b..6ab3b73efcf 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -142,57 +142,11 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask, bool force) { unsigned long flags; - int err; flags = arch_local_cli_save(); - - /* check irq no */ - switch (d->irq) { - case TMJCIRQ: - case RESCHEDULE_IPI: - case CALL_FUNC_SINGLE_IPI: - case LOCAL_TIMER_IPI: - case FLUSH_CACHE_IPI: - case CALL_FUNCTION_NMI_IPI: - case DEBUGGER_NMI_IPI: -#ifdef CONFIG_MN10300_TTYSM0 - case SC0RXIRQ: - case SC0TXIRQ: -#ifdef CONFIG_MN10300_TTYSM0_TIMER8 - case TM8IRQ: -#elif CONFIG_MN10300_TTYSM0_TIMER2 - case TM2IRQ: -#endif /* CONFIG_MN10300_TTYSM0_TIMER8 */ -#endif /* CONFIG_MN10300_TTYSM0 */ - -#ifdef CONFIG_MN10300_TTYSM1 - case SC1RXIRQ: - case SC1TXIRQ: -#ifdef CONFIG_MN10300_TTYSM1_TIMER12 - case TM12IRQ: -#elif defined(CONFIG_MN10300_TTYSM1_TIMER9) - case TM9IRQ: -#elif defined(CONFIG_MN10300_TTYSM1_TIMER3) - case TM3IRQ: -#endif /* CONFIG_MN10300_TTYSM1_TIMER12 */ -#endif /* CONFIG_MN10300_TTYSM1 */ - -#ifdef CONFIG_MN10300_TTYSM2 - case SC2RXIRQ: - case SC2TXIRQ: - case TM10IRQ: -#endif /* CONFIG_MN10300_TTYSM2 */ - err = -1; - break; - - default: - set_bit(d->irq, irq_affinity_request); - err = 0; - break; - } - + set_bit(d->irq, irq_affinity_request); arch_local_irq_restore(flags); - return err; + return 0; } #endif /* CONFIG_SMP */ diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S index dfc1b6f2fa9..b95e76caf4f 100644 --- a/arch/mn10300/kernel/mn10300-serial-low.S +++ b/arch/mn10300/kernel/mn10300-serial-low.S @@ -118,8 +118,8 @@ ENTRY(mn10300_serial_vdma_tx_handler) movbu d2,(e3) # ACK the interrupt movhu (e3),d2 # flush - btst 0x01,(__tx_break,a3) # handle transmit break request - bne mnsc_vdma_tx_break + btst 0xFF,(__tx_flags,a3) # handle transmit flags + bne mnsc_vdma_tx_flags movbu (SCxSTR,e2),d2 # don't try and transmit a char if the # buffer is not empty @@ -171,10 +171,13 @@ mnsc_vdma_tx_empty: bset MNSCx_TX_EMPTY,(__intr_flags,a3) bra mnsc_vdma_tx_done -mnsc_vdma_tx_break: +mnsc_vdma_tx_flags: + btst MNSCx_TX_STOP,(__tx_flags,a3) + bne mnsc_vdma_tx_stop movhu (SCxCTR,e2),d2 # turn on break mode or SC01CTR_BKE,d2 movhu d2,(SCxCTR,e2) +mnsc_vdma_tx_stop: mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 movhu d2,(e3) # disable transmit interrupts on this # channel diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 339cef4c825..81d5cb9b656 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -408,6 +408,34 @@ static struct irq_chip mn10300_serial_pic = { .irq_unmask = mn10300_serial_nop, }; +static void mn10300_serial_low_mask(struct irq_data *d) +{ + unsigned long flags; + u16 tmp; + + flags = arch_local_cli_save(); + GxICR(d->irq) = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); + tmp = GxICR(d->irq); /* flush write buffer */ + arch_local_irq_restore(flags); +} + +static void mn10300_serial_low_unmask(struct irq_data *d) +{ + unsigned long flags; + u16 tmp; + + flags = arch_local_cli_save(); + GxICR(d->irq) = + NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; + tmp = GxICR(d->irq); /* flush write buffer */ + arch_local_irq_restore(flags); +} + +static struct irq_chip mn10300_serial_low_pic = { + .name = "mnserial-low", + .irq_mask = mn10300_serial_low_mask, + .irq_unmask = mn10300_serial_low_unmask, +}; /* * serial virtual DMA interrupt jump table @@ -416,25 +444,53 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS]; static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) { - unsigned long flags; + int retries = 100; u16 x; - flags = arch_local_cli_save(); - *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); - x = *port->tx_icr; - arch_local_irq_restore(flags); + /* nothing to do if irq isn't set up */ + if (!mn10300_serial_int_tbl[port->tx_irq].port) + return; + + port->tx_flags |= MNSCx_TX_STOP; + mb(); + + /* + * Here we wait for the irq to be disabled. Either it already is + * disabled or we wait some number of retries for the VDMA handler + * to disable it. The retries give the VDMA handler enough time to + * run to completion if it was already in progress. If the VDMA IRQ + * is enabled but the handler is not yet running when arrive here, + * the STOP flag will prevent the handler from conflicting with the + * driver code following this loop. + */ + while ((*port->tx_icr & GxICR_ENABLE) && retries-- > 0) + ; + if (retries <= 0) { + *port->tx_icr = + NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); + x = *port->tx_icr; + } } static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) { - unsigned long flags; u16 x; - flags = arch_local_cli_save(); + /* nothing to do if irq isn't set up */ + if (!mn10300_serial_int_tbl[port->tx_irq].port) + return; + + /* stop vdma irq if not already stopped */ + if (!(port->tx_flags & MNSCx_TX_STOP)) + mn10300_serial_dis_tx_intr(port); + + port->tx_flags &= ~MNSCx_TX_STOP; + mb(); + *port->tx_icr = - NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; + NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | + GxICR_ENABLE | GxICR_REQUEST | GxICR_DETECT; x = *port->tx_icr; - arch_local_irq_restore(flags); } static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) @@ -487,16 +543,17 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port) try_again: /* pull chars out of the hat */ - ix = port->rx_outp; - if (ix == port->rx_inp) { + ix = ACCESS_ONCE(port->rx_outp); + if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) { if (push && !tty->low_latency) tty_flip_buffer_push(tty); return; } + smp_read_barrier_depends(); ch = port->rx_buffer[ix++]; st = port->rx_buffer[ix++]; - smp_rmb(); + smp_mb(); port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); port->uart.icount.rx++; @@ -778,8 +835,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port) struct mn10300_serial_port *port = container_of(_port, struct mn10300_serial_port, uart); - u16 x; - _enter("%s{%lu}", port->name, CIRC_CNT(&port->uart.state->xmit.head, @@ -787,14 +842,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port) UART_XMIT_SIZE)); /* kick the virtual DMA controller */ - arch_local_cli(); - x = *port->tx_icr; - x |= GxICR_ENABLE; - - if (*port->_status & SC01STR_TBF) - x &= ~(GxICR_REQUEST | GxICR_DETECT); - else - x |= GxICR_REQUEST | GxICR_DETECT; + mn10300_serial_en_tx_intr(port); _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", *port->_control, *port->_intr, *port->_status, @@ -802,10 +850,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port) (port->div_timer == MNSCx_DIV_TIMER_8BIT) ? *(volatile u8 *)port->_tmxbr : *port->_tmxbr, *port->tx_icr); - - *port->tx_icr = x; - x = *port->tx_icr; - arch_local_sti(); } /* @@ -815,13 +859,17 @@ static void mn10300_serial_send_xchar(struct uart_port *_port, char ch) { struct mn10300_serial_port *port = container_of(_port, struct mn10300_serial_port, uart); + unsigned long flags; _enter("%s,%02x", port->name, ch); if (likely(port->gdbstub)) { port->tx_xchar = ch; - if (ch) + if (ch) { + spin_lock_irqsave(&port->uart.lock, flags); mn10300_serial_en_tx_intr(port); + spin_unlock_irqrestore(&port->uart.lock, flags); + } } } @@ -882,18 +930,21 @@ static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl) { struct mn10300_serial_port *port = container_of(_port, struct mn10300_serial_port, uart); + unsigned long flags; _enter("%s,%d", port->name, ctl); + spin_lock_irqsave(&port->uart.lock, flags); if (ctl) { /* tell the virtual DMA handler to assert BREAK */ - port->tx_break = 1; + port->tx_flags |= MNSCx_TX_BREAK; mn10300_serial_en_tx_intr(port); } else { - port->tx_break = 0; + port->tx_flags &= ~MNSCx_TX_BREAK; *port->_control &= ~SC01CTR_BKE; mn10300_serial_en_tx_intr(port); } + spin_unlock_irqrestore(&port->uart.lock, flags); } /* @@ -916,6 +967,7 @@ static int mn10300_serial_startup(struct uart_port *_port) return -ENOMEM; port->rx_inp = port->rx_outp = 0; + port->tx_flags = 0; /* finally, enable the device */ *port->_intr = SC01ICR_TI; @@ -928,22 +980,23 @@ static int mn10300_serial_startup(struct uart_port *_port) pint->port = port; pint->vdma = mn10300_serial_vdma_tx_handler; - set_intr_level(port->rx_irq, - NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); - set_intr_level(port->tx_irq, - NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)); + irq_set_chip(port->rx_irq, &mn10300_serial_low_pic); + irq_set_chip(port->tx_irq, &mn10300_serial_low_pic); irq_set_chip(port->tm_irq, &mn10300_serial_pic); if (request_irq(port->rx_irq, mn10300_serial_interrupt, - IRQF_DISABLED, port->rx_name, port) < 0) + IRQF_DISABLED | IRQF_NOBALANCING, + port->rx_name, port) < 0) goto error; if (request_irq(port->tx_irq, mn10300_serial_interrupt, - IRQF_DISABLED, port->tx_name, port) < 0) + IRQF_DISABLED | IRQF_NOBALANCING, + port->tx_name, port) < 0) goto error2; if (request_irq(port->tm_irq, mn10300_serial_interrupt, - IRQF_DISABLED, port->tm_name, port) < 0) + IRQF_DISABLED | IRQF_NOBALANCING, + port->tm_name, port) < 0) goto error3; mn10300_serial_mask_ack(port->tm_irq); @@ -964,14 +1017,22 @@ error: */ static void mn10300_serial_shutdown(struct uart_port *_port) { + unsigned long flags; u16 x; struct mn10300_serial_port *port = container_of(_port, struct mn10300_serial_port, uart); _enter("%s", port->name); + spin_lock_irqsave(&_port->lock, flags); + mn10300_serial_dis_tx_intr(port); + + *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); + x = *port->rx_icr; + port->tx_flags = 0; + spin_unlock_irqrestore(&_port->lock, flags); + /* disable the serial port and its baud rate timer */ - port->tx_break = 0; *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE); *port->_tmxmd = 0; @@ -986,12 +1047,8 @@ static void mn10300_serial_shutdown(struct uart_port *_port) free_irq(port->rx_irq, port); free_irq(port->tx_irq, port); - arch_local_cli(); - *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); - x = *port->rx_icr; - *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); - x = *port->tx_icr; - arch_local_sti(); + mn10300_serial_int_tbl[port->tx_irq].port = NULL; + mn10300_serial_int_tbl[port->rx_irq].port = NULL; } /* @@ -1317,7 +1374,8 @@ timer_okay: if ((new->c_cflag & CREAD) == 0) port->uart.ignore_status_mask |= (1 << TTY_NORMAL); - scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE); + scxctr |= SC01CTR_TXE | SC01CTR_RXE; + scxctr |= *port->_control & SC01CTR_BKE; *port->_control = scxctr; spin_unlock_irqrestore(&port->uart.lock, flags); @@ -1519,17 +1577,24 @@ static void mn10300_serial_console_write(struct console *co, { struct mn10300_serial_port *port; unsigned i; - u16 scxctr, txicr, tmp; + u16 scxctr; u8 tmxmd; + unsigned long flags; + int locked = 1; port = mn10300_serial_ports[co->index]; + local_irq_save(flags); + if (port->uart.sysrq) { + /* mn10300_serial_interrupt() already took the lock */ + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&port->uart.lock); + } else + spin_lock(&port->uart.lock); + /* firstly hijack the serial port from the "virtual DMA" controller */ - arch_local_cli(); - txicr = *port->tx_icr; - *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); - tmp = *port->tx_icr; - arch_local_sti(); + mn10300_serial_dis_tx_intr(port); /* the transmitter may be disabled */ scxctr = *port->_control; @@ -1565,12 +1630,12 @@ static void mn10300_serial_console_write(struct console *co, while (*port->_status & SC01STR_TBF) continue; - *(u8 *) port->_txb = ch; + *port->_txb = ch; if (ch == 0x0a) { while (*port->_status & SC01STR_TBF) continue; - *(u8 *) port->_txb = 0xd; + *port->_txb = 0xd; } } @@ -1583,10 +1648,11 @@ static void mn10300_serial_console_write(struct console *co, if (!(scxctr & SC01CTR_TXE)) *port->_control = scxctr; - arch_local_cli(); - *port->tx_icr = txicr; - tmp = *port->tx_icr; - arch_local_sti(); + mn10300_serial_en_tx_intr(port); + + if (locked) + spin_unlock(&port->uart.lock); + local_irq_restore(flags); } /* @@ -1655,18 +1721,29 @@ static int mn10300_serial_poll_get_char(struct uart_port *_port) _enter("%s", port->name); - do { - /* pull chars out of the hat */ - ix = port->rx_outp; - if (ix == port->rx_inp) - return NO_POLL_CHAR; + if (mn10300_serial_int_tbl[port->rx_irq].port != NULL) { + do { + /* pull chars out of the hat */ + ix = ACCESS_ONCE(port->rx_outp); + if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) + return NO_POLL_CHAR; - ch = port->rx_buffer[ix++]; - st = port->rx_buffer[ix++]; - smp_rmb(); - port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); + smp_read_barrier_depends(); + ch = port->rx_buffer[ix++]; + st = port->rx_buffer[ix++]; + smp_mb(); + port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); - } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)); + } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)); + } else { + do { + st = *port->_status; + if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)) + continue; + } while (!(st & SC01STR_RBF)); + + ch = *port->_rxb; + } return ch; } @@ -1693,12 +1770,12 @@ static void mn10300_serial_poll_put_char(struct uart_port *_port, tmp = *port->_intr; if (ch == 0x0a) { - *(u8 *) port->_txb = 0x0d; + *port->_txb = 0x0d; while (*port->_status & SC01STR_TBF) continue; } - *(u8 *) port->_txb = ch; + *port->_txb = ch; while (*port->_status & SC01STR_TBF) continue; diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h index 6796499bf78..01791c68ea1 100644 --- a/arch/mn10300/kernel/mn10300-serial.h +++ b/arch/mn10300/kernel/mn10300-serial.h @@ -29,6 +29,10 @@ #define MNSCx_TX_SPACE 0x04 #define MNSCx_TX_EMPTY 0x08 +/* tx_flags bits */ +#define MNSCx_TX_BREAK 0x01 +#define MNSCx_TX_STOP 0x02 + #ifndef __ASSEMBLY__ struct mn10300_serial_port { @@ -36,7 +40,7 @@ struct mn10300_serial_port { unsigned rx_inp; /* pointer to rx input offset */ unsigned rx_outp; /* pointer to rx output offset */ u8 tx_xchar; /* high-priority XON/XOFF buffer */ - u8 tx_break; /* transmit break request */ + u8 tx_flags; /* transmit break/stop request */ u8 intr_flags; /* interrupt flags */ volatile u16 *rx_icr; /* Rx interrupt control register */ volatile u16 *tx_icr; /* Tx interrupt control register */ @@ -54,8 +58,8 @@ struct mn10300_serial_port { volatile u16 *_control; /* control register pointer */ volatile u8 *_status; /* status register pointer */ volatile u8 *_intr; /* interrupt register pointer */ - volatile void *_rxb; /* receive buffer register pointer */ - volatile void *_txb; /* transmit buffer register pointer */ + volatile u8 *_rxb; /* receive buffer register pointer */ + volatile u8 *_txb; /* transmit buffer register pointer */ volatile u16 *_tmicr; /* timer interrupt control register */ volatile u8 *_tmxmd; /* baud rate timer mode register */ volatile u16 *_tmxbr; /* baud rate timer base register */ diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index d0c671b6d9f..eb09f5a552f 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -206,7 +206,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) */ int copy_thread(unsigned long clone_flags, unsigned long c_usp, unsigned long ustk_size, - struct task_struct *p, struct pt_regs *kregs) + struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct pt_regs *c_regs; @@ -227,7 +227,7 @@ int copy_thread(unsigned long clone_flags, p->thread.wchan = p->thread.pc; p->thread.usp = c_usp; - if (unlikely(!kregs)) { + if (unlikely(p->flags & PF_KTHREAD)) { memset(c_regs, 0, sizeof(struct pt_regs)); c_regs->a0 = c_usp; /* function */ c_regs->d0 = ustk_size; /* argument */ @@ -236,8 +236,9 @@ int copy_thread(unsigned long clone_flags, p->thread.pc = (unsigned long) ret_from_kernel_thread; return 0; } - *c_regs = *kregs; - c_regs->sp = c_usp; + *c_regs = *current_pt_regs(); + if (c_usp) + c_regs->sp = c_usp; c_regs->epsw &= ~EPSW_FE; /* my FPU */ /* the new TLS pointer is passed in as arg #5 to sys_clone() */ @@ -249,30 +250,6 @@ int copy_thread(unsigned long clone_flags, return 0; } -/* - * clone a process - * - tlsptr is retrieved by copy_thread() from current_frame()->d3 - */ -asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int __user *child_tidptr, - int __user *tlsptr) -{ - return do_fork(clone_flags, newsp ?: current_frame()->sp, - current_frame(), 0, parent_tidptr, child_tidptr); -} - -asmlinkage long sys_fork(void) -{ - return do_fork(SIGCHLD, current_frame()->sp, - current_frame(), 0, NULL, NULL); -} - -asmlinkage long sys_vfork(void) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp, - current_frame(), 0, NULL, NULL); -} - unsigned long get_wchan(struct task_struct *p) { return p->thread.wchan; diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index e62c223e4c4..95983cd21e7 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -130,10 +130,12 @@ static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id); static struct irqaction reschedule_ipi = { .handler = smp_reschedule_interrupt, + .flags = IRQF_NOBALANCING, .name = "smp reschedule IPI" }; static struct irqaction call_function_ipi = { .handler = smp_call_function_interrupt, + .flags = IRQF_NOBALANCING, .name = "smp call function IPI" }; @@ -141,7 +143,7 @@ static struct irqaction call_function_ipi = { static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); static struct irqaction local_timer_ipi = { .handler = smp_ipi_timer_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NOBALANCING, .name = "smp local timer IPI" }; #endif @@ -180,6 +182,7 @@ static void init_ipi(void) #ifdef CONFIG_MN10300_CACHE_ENABLED /* set up the cache flush IPI */ + irq_set_chip(FLUSH_CACHE_IPI, &mn10300_ipi_type); flags = arch_local_cli_save(); __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV), mn10300_low_ipi_handler); @@ -189,6 +192,7 @@ static void init_ipi(void) #endif /* set up the NMI call function IPI */ + irq_set_chip(CALL_FUNCTION_NMI_IPI, &mn10300_ipi_type); flags = arch_local_cli_save(); GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT; tmp16 = GxICR(CALL_FUNCTION_NMI_IPI); @@ -199,6 +203,10 @@ static void init_ipi(void) __set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV), mn10300_low_ipi_handler); arch_local_irq_restore(flags); + +#ifdef CONFIG_KERNEL_DEBUGGER + irq_set_chip(DEBUGGER_NMI_IPI, &mn10300_ipi_type); +#endif } /** |