From e2afca6988c335d2ec7b66f2fadcd63286570bf8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 13:40:31 +0100 Subject: [PATCH 1/3] serial: sh-sci: Fix warnings due to improper casts and printk formats Use the %zu and %pad printk specifiers to print size_t and dma_addr_t variables, and cast pointers to uintptr_t instead of unsigned int where applicable. This fixes warnings on platforms where pointers and/or dma_addr_t have a different size than int. Cc: linux-serial@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 7d8103cd3e2e..6e5ce628b4eb 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -557,7 +557,7 @@ static inline int sci_rxd_in(struct uart_port *port) return 1; /* Cast for ARM damage */ - return !!__raw_readb((void __iomem *)s->cfg->port_reg); + return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg); } /* ********************************************************************** * @@ -1309,7 +1309,7 @@ static int sci_dma_rx_push(struct sci_port *s, size_t count) } if (room < count) - dev_warn(port->dev, "Rx overrun: dropping %u bytes\n", + dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n", count - room); if (!room) return room; @@ -1442,7 +1442,7 @@ static void work_fn_rx(struct work_struct *work) int count; chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); - dev_dbg(port->dev, "Read %u bytes with cookie %d\n", + dev_dbg(port->dev, "Read %zu bytes with cookie %d\n", sh_desc->partial, sh_desc->cookie); spin_lock_irqsave(&port->lock, flags); @@ -1691,16 +1691,17 @@ static void sci_request_dma(struct uart_port *port) s->chan_tx = chan; sg_init_table(&s->sg_tx, 1); /* UART circular tx buffer is an aligned page. */ - BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); + BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK); sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf), - UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK); + UART_XMIT_SIZE, + (uintptr_t)port->state->xmit.buf & ~PAGE_MASK); nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE); if (!nent) sci_tx_dma_release(s, false); else - dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, - sg_dma_len(&s->sg_tx), - port->state->xmit.buf, sg_dma_address(&s->sg_tx)); + dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, + sg_dma_len(&s->sg_tx), port->state->xmit.buf, + &sg_dma_address(&s->sg_tx)); s->sg_len_tx = nent; @@ -1740,7 +1741,7 @@ static void sci_request_dma(struct uart_port *port) sg_init_table(sg, 1); sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, - (int)buf[i] & ~PAGE_MASK); + (uintptr_t)buf[i] & ~PAGE_MASK); sg_dma_address(sg) = dma[i]; } From caec70381b469d6ed1bd3d0441a19aa6de0bbff3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 18:11:45 +0100 Subject: [PATCH 2/3] serial: sh-sci: Don't enable/disable port from within break timer The break timer accesses hardware registers and thus requires the port to be enabled. It currently ensures this by enabling the port at the beginning of the timer handler, and disabling it at the end. However, the enable/disable operations call the runtime PM sync functions, which are not allowed in atomic context. The current situation is thus broken. This change relies on non-atomic code to enable/disable the port. The break timer will only be started from the IRQ handler, which already runs with the port enabled. We just need to ensure that the port won't be disabled with the timer running, and that's easily done by just cancelling the timer in the port disable function. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 6e5ce628b4eb..1ebac3e9e53a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -431,6 +431,14 @@ static void sci_port_disable(struct sci_port *sci_port) if (!sci_port->port.dev) return; + /* Cancel the break timer to ensure that the timer handler will not try + * to access the hardware with clocks and power disabled. Reset the + * break flag to make the break debouncing state machine ready for the + * next break. + */ + del_timer_sync(&sci_port->break_timer); + sci_port->break_flag = 0; + clk_disable(sci_port->fclk); clk_disable(sci_port->iclk); @@ -733,8 +741,6 @@ static void sci_break_timer(unsigned long data) { struct sci_port *port = (struct sci_port *)data; - sci_port_enable(port); - if (sci_rxd_in(&port->port) == 0) { port->break_flag = 1; sci_schedule_break_timer(port); @@ -744,8 +750,6 @@ static void sci_break_timer(unsigned long data) sci_schedule_break_timer(port); } else port->break_flag = 0; - - sci_port_disable(port); } static int sci_handle_errors(struct uart_port *port) From b016b646e8676858f39ea9be760494b04b9ee0af Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 18:11:46 +0100 Subject: [PATCH 3/3] serial: sh-sci: Convert to clk_prepare/unprepare Turn clk_enable() and clk_disable() calls into clk_prepare_enable() and clk_disable_unprepare() to get ready for the migration to the common clock framework. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 1ebac3e9e53a..1a3fc7a2e4db 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -421,9 +421,9 @@ static void sci_port_enable(struct sci_port *sci_port) pm_runtime_get_sync(sci_port->port.dev); - clk_enable(sci_port->iclk); + clk_prepare_enable(sci_port->iclk); sci_port->port.uartclk = clk_get_rate(sci_port->iclk); - clk_enable(sci_port->fclk); + clk_prepare_enable(sci_port->fclk); } static void sci_port_disable(struct sci_port *sci_port) @@ -439,8 +439,8 @@ static void sci_port_disable(struct sci_port *sci_port) del_timer_sync(&sci_port->break_timer); sci_port->break_flag = 0; - clk_disable(sci_port->fclk); - clk_disable(sci_port->iclk); + clk_disable_unprepare(sci_port->fclk); + clk_disable_unprepare(sci_port->iclk); pm_runtime_put_sync(sci_port->port.dev); }