]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge tag 'for-linus-20121212' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowe...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 01:50:34 +0000 (17:50 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 01:50:34 +0000 (17:50 -0800)
Pull MN10300 changes from David Howells:
 "miscellaneous MN10300 arch patches.  I've based it on top of Al Viro's
  signal tree - so these patches should be pulled after that."

* tag 'for-linus-20121212' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-mn10300:
  MN10300: Use asm-generic/pci_iomap.h
  MN10300: Get rid of unused variable from ASB2305 PCI code
  MN10300: ASB2305 PCI code needs linux/irq.h
  mn10300/mm/fault.c: Port OOM changes to do_page_fault
  MN10300: Handle cacheable PCI regions in pci_iomap()
  MN10300: fix debug polling in ttySM driver
  MN10300: ttySM: clean up unnecessary casting
  MN10300: fix SMP synchronization between txdma and serial driver
  MN10300: fix serial port vdma irq setup for SMP
  MN10300: cleanup IRQ affinity setting
  MN10300: ttySM: Use memory barriers correctly in circular buffer logic

arch/mn10300/include/asm/io.h
arch/mn10300/kernel/asm-offsets.c
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/mn10300-serial-low.S
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/mn10300-serial.h
arch/mn10300/kernel/smp.c
arch/mn10300/mm/fault.c
arch/mn10300/unit-asb2305/pci-iomap.c [new file with mode: 0644]
arch/mn10300/unit-asb2305/pci.c

index 139df8c53de83374a86189a8278d91a184d3e26c..e6ed0d897ccc7c8b4f08b2f12fc97edee223de1b 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/page.h> /* I/O is all done through memory accesses */
 #include <asm/cpu-regs.h>
 #include <asm/cacheflush.h>
+#include <asm-generic/pci_iomap.h>
 
 #define mmiowb() do {} while (0)
 
@@ -258,7 +259,7 @@ static inline void __iomem *__ioremap(unsigned long offset, unsigned long size,
 
 static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 {
-       return (void __iomem *) offset;
+       return (void __iomem *)(offset & ~0x20000000);
 }
 
 /*
index 96f24fab7de6ee0e559369e195a2fa7b5120a8f2..47b3bb0c04ffc4f9db8395a6042235a5c7fab105 100644 (file)
@@ -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);
index 35932a8de8b8d299fd7aaebcf31d56eb7c6db6d3..6ab3b73efcf8d4304d0b832d4d398f94a0f332d5 100644 (file)
@@ -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 */
 
index dfc1b6f2fa9a4b70f251d8766c773c39fc7733fe..b95e76caf4fae24e0841500cde288bcd775dbc5f 100644 (file)
@@ -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
index 339cef4c82568a13ac20de767f066a6e1d95f035..81d5cb9b65695034e27a34b866d2a4c55389c673 100644 (file)
@@ -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;
 
index 6796499bf789b0136a79a066afaa44a0b901f072..01791c68ea1f1330894e71f41f1ded0131d82e93 100644 (file)
 #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 */
index e62c223e4c4594c3c06c762352d8e61a975e2d35..95983cd21e77e45a47be44ea41c82b59479b9c25 100644 (file)
@@ -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
 }
 
 /**
index 90f346f7392d68df68844fd24472f7d5af8b1bf9..d48a84fd7fae51b298ee1b03956dd823dd82ffdf 100644 (file)
@@ -123,7 +123,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
        struct mm_struct *mm;
        unsigned long page;
        siginfo_t info;
-       int write, fault;
+       int fault;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 #ifdef CONFIG_GDBSTUB
        /* handle GDB stub causing a fault */
@@ -170,6 +171,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
        if (in_atomic() || !mm)
                goto no_context;
 
+retry:
        down_read(&mm->mmap_sem);
 
        vma = find_vma(mm, address);
@@ -220,7 +222,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
  */
 good_area:
        info.si_code = SEGV_ACCERR;
-       write = 0;
        switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
        default:        /* 3: write, present */
        case MMUFCR_xFC_TYPE_WRITE:
@@ -232,7 +233,7 @@ good_area:
        case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
-               write++;
+               flags |= FAULT_FLAG_WRITE;
                break;
 
                /* read from protected page */
@@ -251,7 +252,11 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+       fault = handle_mm_fault(mm, vma, address, flags);
+
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return;
+
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
@@ -259,10 +264,22 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
-               current->maj_flt++;
-       else
-               current->min_flt++;
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (fault & VM_FAULT_MAJOR)
+                       current->maj_flt++;
+               else
+                       current->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+                        /* No need to up_read(&mm->mmap_sem) as we would
+                        * have already released it in __lock_page_or_retry
+                        * in mm/filemap.c.
+                        */
+
+                       goto retry;
+               }
+       }
 
        up_read(&mm->mmap_sem);
        return;
diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c
new file mode 100644 (file)
index 0000000..bd65dae
--- /dev/null
@@ -0,0 +1,35 @@
+/* ASB2305 PCI I/O mapping handler
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+
+/*
+ * Create a virtual mapping cookie for a PCI BAR (memory or IO)
+ */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+
+       if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) {
+               if (flags & IORESOURCE_CACHEABLE && !(flags & IORESOURCE_IO))
+                       return ioremap(start, len);
+               else
+                       return ioremap_nocache(start, len);
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
index 6dce9fc2cf3c131ce6349a291775441e0a3f5c43..e2059486d3f84b9bbee412c809aae8acfb21056e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 #include <asm/io.h>
 #include "pci-asb2305.h"
 
@@ -303,9 +304,7 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
 
 static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
 {
-       struct pci_bus_region region;
-       int i;
-       int limit;
+       int limit, i;
 
        if (dev->bus->number != 0)
                return;