Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe59d297 authored by Linus Torvalds's avatar Linus Torvalds
Browse files


Pull TTY fixes from Greg Kroah-Hartman:
 "Here are 2 tiny patches for a serial driver to resolve issues that
  people have reported with the 3.6-rc tree.

  Both of these have been in the linux-next tree for a while now.

  Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org&gt;">

* tag 'tty-3.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: serial: imx: don't reinit clock in imx_setup_ufcr()
  tty: serial: imx: console write routing is unsafe on SMP
parents f2378e38 7be0670f
Loading
Loading
Loading
Loading
+15 −15
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@
#define  UCR4_OREN  	 (1<<1)  /* Receiver overrun interrupt enable */
#define  UCR4_DREN  	 (1<<0)  /* Recv data ready interrupt enable */
#define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
#define  UFCR_DCEDTE	 (1<<6)  /* DCE/DTE mode select */
#define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
#define  UFCR_RFDIV_REG(x)	(((x) < 7 ? 6 - (x) : 6) << 7)
#define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
@@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
{
	unsigned int val;
	unsigned int ufcr_rfdiv;

	/* set receiver / transmitter trigger level.
	 * RFDIV is set such way to satisfy requested uartclk value
	 */
	val = TXTL << 10 | RXTL;
	ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2)
			/ sport->port.uartclk;

	if(!ufcr_rfdiv)
		ufcr_rfdiv = 1;

	val |= UFCR_RFDIV_REG(ufcr_rfdiv);

	/* set receiver / transmitter trigger level */
	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
	val |= TXTL << UFCR_TXTL_SHF | RXTL;
	writel(val, sport->port.membase + UFCR);

	return 0;
}

@@ -754,6 +744,7 @@ static int imx_startup(struct uart_port *port)
		}
	}

	spin_lock_irqsave(&sport->port.lock, flags);
	/*
	 * Finally, clear and enable interrupts
	 */
@@ -807,7 +798,6 @@ static int imx_startup(struct uart_port *port)
	/*
	 * Enable modem status interrupts
	 */
	spin_lock_irqsave(&sport->port.lock,flags);
	imx_enable_ms(&sport->port);
	spin_unlock_irqrestore(&sport->port.lock,flags);

@@ -837,10 +827,13 @@ static void imx_shutdown(struct uart_port *port)
{
	struct imx_port *sport = (struct imx_port *)port;
	unsigned long temp;
	unsigned long flags;

	spin_lock_irqsave(&sport->port.lock, flags);
	temp = readl(sport->port.membase + UCR2);
	temp &= ~(UCR2_TXEN);
	writel(temp, sport->port.membase + UCR2);
	spin_unlock_irqrestore(&sport->port.lock, flags);

	if (USE_IRDA(sport)) {
		struct imxuart_platform_data *pdata;
@@ -869,12 +862,14 @@ static void imx_shutdown(struct uart_port *port)
	 * Disable all interrupts, port and break condition.
	 */

	spin_lock_irqsave(&sport->port.lock, flags);
	temp = readl(sport->port.membase + UCR1);
	temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
	if (USE_IRDA(sport))
		temp &= ~(UCR1_IREN);

	writel(temp, sport->port.membase + UCR1);
	spin_unlock_irqrestore(&sport->port.lock, flags);
}

static void
@@ -1217,6 +1212,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
	struct imx_port *sport = imx_ports[co->index];
	struct imx_port_ucrs old_ucr;
	unsigned int ucr1;
	unsigned long flags;

	spin_lock_irqsave(&sport->port.lock, flags);

	/*
	 *	First, save UCR1/2/3 and then disable interrupts
@@ -1242,6 +1240,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
	while (!(readl(sport->port.membase + USR2) & USR2_TXDC));

	imx_port_ucrs_restore(&sport->port, &old_ucr);

	spin_unlock_irqrestore(&sport->port.lock, flags);
}

/*