MN10300 changes 2012-12-12
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIVAwUAUMi2WhOxKuMESys7AQK2bxAApJQL2x6/k4swH933rhdVooA2TiMVST3l XSy6yil6Qeqz82RDnVMfxQ069N8iP5x93fE918V6UzeIrUmKEL8xD2UJCZzjW6B9 vmBNrD6VUGdiBhTcGY7er4EtlnRf1XJgUPmfdIEAJoZ8VMkKyYAGkckW2I8hiYbZ gyF+ONc+CHxspqS1CzNUmmbP84T6rij2fydqLaSNNnQYnEfICt7dciv73KBQYMtn AsCLcmWW4DkZ37VL6Bg8yvgRaxbNlZpS0Rl5oKS65rYX9azt/SvujSta0UEv+uYF m/2HqExwgo8HZHKyIEpRgBLqfOfekJATbSLEq3jEgA73MLdzw2DTgpJQOmWCjtjN 7bROv2O57e8ttxb81x10YyInzOTYOd18XEb2Qa6O4wbB5TS8MxZywfuTfL+sdfsN pquqyKNgxD7HqqxIcWSNKGxkPPZ/Xk/JmgcQFVCjpvvdCizsFTwWeiAd81Jz0Dn+ SLL345nlDJPVukgIiDiwm9UvkyG0Pg03K5k6+7QOWB/5AdPqgRUeOi6gqQE7ZQ9G GK8/2xX4xFJ8LLPqfh2X+1PUesa8Dhph4NorsW4comJtPcLuh30XbwIKTjpBF90y 7OILeZeQ+qFu8S9lLSQOr6zxs3/9uKP8ADoOAnFmUEE2PkzvZqMrnrlezAyqtNht LkVa/IR/z50= =ex0l -----END PGP SIGNATURE----- Merge tag 'for-linus-20121212' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-mn10300 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
This commit is contained in:
Коммит
e37aa63e87
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче