All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ian Campbell <Ian.Campbell@citrix.com>
To: vijay.kilari@gmail.com
Cc: Keir Fraser <keir@xen.org>,
	stefano.stabellini@eu.citrix.com,
	Prasun.Kapoor@caviumnetworks.com,
	manish.jaggi@caviumnetworks.com, julien.grall@linaro.org,
	tim@xen.org, xen-devel@lists.xen.org,
	stefano.stabellini@citrix.com,
	Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Subject: Re: [PATCH v1] xen/arm: Manage pl011 uart TX interrupt correctly
Date: Thu, 11 Dec 2014 12:24:32 +0000	[thread overview]
Message-ID: <1418300672.10394.35.camel@citrix.com> (raw)
In-Reply-To: <1418099995-22777-1-git-send-email-vijay.kilari@gmail.com>

On Tue, 2014-12-09 at 10:09 +0530, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> In pl011.c, when TX interrupt is received
> serial_tx_interrupt() is called to push next
> characters. If TX buffer is empty, serial_tx_interrupt()
> does not disable TX interrupt and hence pl011 UART
> irq handler pl011_interrupt() always sees TX interrupt
> status set in MIS register and cpu does not come out of
> UART irq handler.
> 
> With this patch, mask TX interrupt by writing 0 to
> IMSC register when TX buffer is empty and unmask by
> writing 1 to IMSC register before sending characters.
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
>  xen/drivers/char/pl011.c  |   16 ++++++++++++++++
>  xen/drivers/char/serial.c |   34 ++++++++++++++++++++++++++++++++++
>  xen/include/xen/serial.h  |    4 ++++

These last two changes require that you cc the common serial maintainer,
not just the ARM maintainers. In this case that means Keir, who I have
CCd.

./scripts/get_maintainers.pl can help automate this.

>  3 files changed, 54 insertions(+)
> 
> diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
> index dd19ce8..57274d9 100644
> --- a/xen/drivers/char/pl011.c
> +++ b/xen/drivers/char/pl011.c
> @@ -197,6 +197,20 @@ static const struct vuart_info *pl011_vuart(struct serial_port *port)
>      return &uart->vuart;
>  }
>  
> +static void pl011_tx_stop(struct serial_port *port)
> +{
> +    struct pl011 *uart = port->uart;
> +
> +    pl011_write(uart, IMSC, pl011_read(uart, IMSC) & ~(TXI));
> +}
> +
> +static void pl011_tx_start(struct serial_port *port)
> +{
> +    struct pl011 *uart = port->uart;
> +
> +    pl011_write(uart, IMSC, pl011_read(uart, IMSC) | (TXI));
> +}
> +
>  static struct uart_driver __read_mostly pl011_driver = {
>      .init_preirq  = pl011_init_preirq,
>      .init_postirq = pl011_init_postirq,
> @@ -207,6 +221,8 @@ static struct uart_driver __read_mostly pl011_driver = {
>      .putc         = pl011_putc,
>      .getc         = pl011_getc,
>      .irq          = pl011_irq,
> +    .start_tx     = pl011_tx_start,
> +    .stop_tx      = pl011_tx_stop,
>      .vuart_info   = pl011_vuart,
>  };
>  
> diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
> index 44026b1..c583a48 100644
> --- a/xen/drivers/char/serial.c
> +++ b/xen/drivers/char/serial.c
> @@ -31,6 +31,18 @@ static struct serial_port com[SERHND_IDX + 1] = {
>  
>  static bool_t __read_mostly post_irq;
>  
> +static inline void serial_start_tx(struct serial_port *port)
> +{
> +    if ( port->driver->start_tx != NULL )
> +        port->driver->start_tx(port);
> +}
> +
> +static inline void serial_stop_tx(struct serial_port *port)
> +{
> +    if ( port->driver->stop_tx != NULL )
> +        port->driver->stop_tx(port);
> +}
> +
>  void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
>  {
>      char c;
> @@ -76,6 +88,18 @@ void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
>          cpu_relax();
>      }
>  
> +    if ( port->txbufc == port->txbufp )
> +    {
> +        /* Disable TX. nothing to send */
> +        serial_stop_tx(port);
> +        spin_unlock(&port->tx_lock);
> +        goto out;
> +    }
> +    else
> +    {
> +        if ( port->driver->tx_ready(port) )
> +            serial_start_tx(port);
> +    }
>      for ( i = 0, n = port->driver->tx_ready(port); i < n; i++ )
>      {
>          if ( port->txbufc == port->txbufp )
> @@ -117,6 +141,8 @@ static void __serial_putc(struct serial_port *port, char c)
>                      cpu_relax();
>                  if ( n > 0 )
>                  {
> +                    /* Enable TX before sending chars */
> +                    serial_start_tx(port);
>                      while ( n-- )
>                          port->driver->putc(
>                              port,
> @@ -135,6 +161,8 @@ static void __serial_putc(struct serial_port *port, char c)
>          if ( ((port->txbufp - port->txbufc) == 0) &&
>               port->driver->tx_ready(port) > 0 )
>          {
> +            /* Enable TX before sending chars */
> +            serial_start_tx(port);
>              /* Buffer and UART FIFO are both empty, and port is available. */
>              port->driver->putc(port, c);
>          }
> @@ -152,11 +180,16 @@ static void __serial_putc(struct serial_port *port, char c)
>          while ( !(n = port->driver->tx_ready(port)) )
>              cpu_relax();
>          if ( n > 0 )
> +        {
> +            /* Enable TX before sending chars */
> +            serial_start_tx(port);
>              port->driver->putc(port, c);
> +        }
>      }
>      else
>      {
>          /* Simple synchronous transmitter. */
> +        serial_start_tx(port);
>          port->driver->putc(port, c);
>      }
>  }
> @@ -404,6 +437,7 @@ void serial_start_sync(int handle)
>                  /* port is unavailable and might not come up until reenabled by
>                     dom0, we can't really do proper sync */
>                  break;
> +            serial_start_tx(port);
>              port->driver->putc(
>                  port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
>          }
> diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
> index 9f4451b..71e6ade 100644
> --- a/xen/include/xen/serial.h
> +++ b/xen/include/xen/serial.h
> @@ -81,6 +81,10 @@ struct uart_driver {
>      int  (*getc)(struct serial_port *, char *);
>      /* Get IRQ number for this port's serial line: returns -1 if none. */
>      int  (*irq)(struct serial_port *);
> +    /* Unmask TX interrupt */
> +    void  (*start_tx)(struct serial_port *);
> +    /* Mask TX interrupt */
> +    void  (*stop_tx)(struct serial_port *);
>      /* Get serial information */
>      const struct vuart_info *(*vuart_info)(struct serial_port *);
>  };

  parent reply	other threads:[~2014-12-11 12:24 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-09  4:39 [PATCH v1] xen/arm: Manage pl011 uart TX interrupt correctly vijay.kilari
2014-12-11 12:15 ` Tim Deegan
2015-01-08 14:59   ` Ian Campbell
2015-01-20 14:46     ` Ian Campbell
2014-12-11 12:24 ` Ian Campbell [this message]
2014-12-15 12:09   ` Julien Grall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1418300672.10394.35.camel@citrix.com \
    --to=ian.campbell@citrix.com \
    --cc=Prasun.Kapoor@caviumnetworks.com \
    --cc=Vijaya.Kumar@caviumnetworks.com \
    --cc=julien.grall@linaro.org \
    --cc=keir@xen.org \
    --cc=manish.jaggi@caviumnetworks.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=tim@xen.org \
    --cc=vijay.kilari@gmail.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.