Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Peter Hurley
On 08/17/2015 12:00 PM, Anirudha Sarangi wrote:
>> From: Peter Hurley [mailto:pe...@hurleysoftware.com]
>> On 08/17/2015 03:22 AM, Michal Simek wrote:
>>> From: Anirudha Sarangi 
>>>
>>> The existing interrupt handling logic has followins issues.
>>> - Upon a parity error with default configuration, the control
>>>   never comes out of the ISR thereby hanging Linux.
>>> - The error handling logic around framing and parity error are buggy.
>>>   There are chances that the errors will never be captured.
>>> - The existing ISR is just too long.
>>> This patch fixes all these concerns.
>>
>> This patch is unreviewable. Please break this down into multiple patches.
>>
> Thanks. Let me give a shot. It is just breaking the single big ISR that has 
> both Rx and Tx in a single function into smaller ones.
> Not sure how I will create smaller patches, but I will try and get back.

I would start with a refactor patch that splits up the ISR but
makes no other functional changes. Then add the bug fix patches.

Regards,
Peter Hurley

ps - The email signature below is not appropriate for lkml.

> 
> This email and any attachments are intended for the sole use of the named 
> recipient(s) and contain(s) confidential information that may be proprietary, 
> privileged or copyrighted under applicable law. If you are not the intended 
> recipient, do not read, copy, or forward this email message or any 
> attachments. Delete this email message and any attachments immediately.
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Anirudha Sarangi
Hi,

> -Original Message-
> From: Peter Hurley [mailto:pe...@hurleysoftware.com]
> Sent: Monday, August 17, 2015 9:26 PM
> To: Michal Simek
> Cc: linux-kernel@vger.kernel.org; mon...@monstr.eu; Anirudha Sarangi; Soren
> Brinkmann; Jiri Slaby; linux-ser...@vger.kernel.org; Greg Kroah-Hartman; 
> linux-
> arm-ker...@lists.infradead.org
> Subject: Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic
>
> On 08/17/2015 03:22 AM, Michal Simek wrote:
> > From: Anirudha Sarangi 
> >
> > The existing interrupt handling logic has followins issues.
> > - Upon a parity error with default configuration, the control
> >   never comes out of the ISR thereby hanging Linux.
> > - The error handling logic around framing and parity error are buggy.
> >   There are chances that the errors will never be captured.
> > - The existing ISR is just too long.
> > This patch fixes all these concerns.
>
> This patch is unreviewable. Please break this down into multiple patches.
>
Thanks. Let me give a shot. It is just breaking the single big ISR that has 
both Rx and Tx in a single function into smaller ones.
Not sure how I will create smaller patches, but I will try and get back.

Regards
Anirudha

> Regards,
> Peter Hurley
>
> > It separates out the Tx and Rx
> > hanling logic into separate functions. It ensures that the status
> > registers are cleared on all cases so that a hang situation never
> > arises.
> >
> > Signed-off-by: Anirudha Sarangi 
> > Signed-off-by: Michal Simek 
> > ---
> >
> >  drivers/tty/serial/xilinx_uartps.c | 194
> > -
> >  1 file changed, 104 insertions(+), 90 deletions(-)
> >
> > diff --git a/drivers/tty/serial/xilinx_uartps.c
> > b/drivers/tty/serial/xilinx_uartps.c
> > index 2dc26e5f1384..c771dbbf6161 100644
> > --- a/drivers/tty/serial/xilinx_uartps.c
> > +++ b/drivers/tty/serial/xilinx_uartps.c
> > @@ -173,61 +173,86 @@ struct cdns_uart {
> > clk_rate_change_nb);
> >
> >  /**
> > - * cdns_uart_isr - Interrupt handler
> > - * @irq: Irq number
> > - * @dev_id: Id of the port
> > - *
> > - * Return: IRQHANDLED
> > + * cdns_uart_handle_tx - Handle the bytes to be Txed.
> > + * @dev_id: Id of the UART port
> > + * Return: None
> >   */
> > -static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
> > +static void cdns_uart_handle_tx(void *dev_id)
> >  {
> > struct uart_port *port = (struct uart_port *)dev_id;
> > -   unsigned long flags;
> > -   unsigned int isrstatus, numbytes;
> > -   unsigned int data;
> > -   char status = TTY_NORMAL;
> > +   unsigned int numbytes;
> >
> > -   spin_lock_irqsave(>lock, flags);
> > +   if (uart_circ_empty(>state->xmit)) {
> > +   writel(CDNS_UART_IXR_TXEMPTY, port->membase +
> > +  CDNS_UART_IDR_OFFSET);
> > +   } else {
> > +   numbytes = port->fifosize;
> > +   /* Break if no more data available in the UART buffer */
> > +   while (numbytes--) {
> > +   if (uart_circ_empty(>state->xmit))
> > +   break;
> > +   /*
> > +* Get the data from the UART circular buffer
> > +* and write it to the cdns_uart's TX_FIFO
> > +* register.
> > +*/
> > +   writel(port->state->xmit.buf[port->state->xmit.tail],
> > +  port->membase + CDNS_UART_FIFO_OFFSET);
> >
> > -   /* Read the interrupt status register to determine which
> > -* interrupt(s) is/are active.
> > -*/
> > -   isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET);
> > +   port->icount.tx++;
> >
> > -   /*
> > -* There is no hardware break detection, so we interpret framing
> > -* error with all-zeros data as a break sequence. Most of the time,
> > -* there's another non-zero byte at the end of the sequence.
> > -*/
> > -   if (isrstatus & CDNS_UART_IXR_FRAMING) {
> > -   while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
> > -   CDNS_UART_SR_RXEMPTY)) {
> > -   if (!readl(port->membase + CDNS_UART_FIFO_OFFSET))
> {
> > -   port->read_status_mask |=
> CDNS_UART_IXR_BRK;
> > -   isrstatus &= ~CDNS_UART_IXR_FRAMING;
> > -   }
> 

Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Peter Hurley
On 08/17/2015 03:22 AM, Michal Simek wrote:
> From: Anirudha Sarangi 
> 
> The existing interrupt handling logic has followins issues.
> - Upon a parity error with default configuration, the control
>   never comes out of the ISR thereby hanging Linux.
> - The error handling logic around framing and parity error are buggy.
>   There are chances that the errors will never be captured.
> - The existing ISR is just too long.
> This patch fixes all these concerns.

This patch is unreviewable. Please break this down into multiple patches.

Regards,
Peter Hurley

> It separates out the Tx and Rx
> hanling logic into separate functions. It ensures that the status
> registers are cleared on all cases so that a hang situation never
> arises.
> 
> Signed-off-by: Anirudha Sarangi 
> Signed-off-by: Michal Simek 
> ---
> 
>  drivers/tty/serial/xilinx_uartps.c | 194 
> -
>  1 file changed, 104 insertions(+), 90 deletions(-)
> 
> diff --git a/drivers/tty/serial/xilinx_uartps.c 
> b/drivers/tty/serial/xilinx_uartps.c
> index 2dc26e5f1384..c771dbbf6161 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -173,61 +173,86 @@ struct cdns_uart {
>   clk_rate_change_nb);
>  
>  /**
> - * cdns_uart_isr - Interrupt handler
> - * @irq: Irq number
> - * @dev_id: Id of the port
> - *
> - * Return: IRQHANDLED
> + * cdns_uart_handle_tx - Handle the bytes to be Txed.
> + * @dev_id: Id of the UART port
> + * Return: None
>   */
> -static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
> +static void cdns_uart_handle_tx(void *dev_id)
>  {
>   struct uart_port *port = (struct uart_port *)dev_id;
> - unsigned long flags;
> - unsigned int isrstatus, numbytes;
> - unsigned int data;
> - char status = TTY_NORMAL;
> + unsigned int numbytes;
>  
> - spin_lock_irqsave(>lock, flags);
> + if (uart_circ_empty(>state->xmit)) {
> + writel(CDNS_UART_IXR_TXEMPTY, port->membase +
> +CDNS_UART_IDR_OFFSET);
> + } else {
> + numbytes = port->fifosize;
> + /* Break if no more data available in the UART buffer */
> + while (numbytes--) {
> + if (uart_circ_empty(>state->xmit))
> + break;
> + /*
> +  * Get the data from the UART circular buffer
> +  * and write it to the cdns_uart's TX_FIFO
> +  * register.
> +  */
> + writel(port->state->xmit.buf[port->state->xmit.tail],
> +port->membase + CDNS_UART_FIFO_OFFSET);
>  
> - /* Read the interrupt status register to determine which
> -  * interrupt(s) is/are active.
> -  */
> - isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET);
> + port->icount.tx++;
>  
> - /*
> -  * There is no hardware break detection, so we interpret framing
> -  * error with all-zeros data as a break sequence. Most of the time,
> -  * there's another non-zero byte at the end of the sequence.
> -  */
> - if (isrstatus & CDNS_UART_IXR_FRAMING) {
> - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
> - CDNS_UART_SR_RXEMPTY)) {
> - if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) {
> - port->read_status_mask |= CDNS_UART_IXR_BRK;
> - isrstatus &= ~CDNS_UART_IXR_FRAMING;
> - }
> + /*
> +  * Adjust the tail of the UART buffer and wrap
> +  * the buffer if it reaches limit.
> +  */
> + port->state->xmit.tail =
> + (port->state->xmit.tail + 1) &
> + (UART_XMIT_SIZE - 1);
>   }
> - writel(CDNS_UART_IXR_FRAMING,
> - port->membase + CDNS_UART_ISR_OFFSET);
> - }
>  
> - /* drop byte with parity error if IGNPAR specified */
> - if (isrstatus & port->ignore_status_mask & CDNS_UART_IXR_PARITY)
> - isrstatus &= ~(CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT);
> + if (uart_circ_chars_pending(
> + >state->xmit) < WAKEUP_CHARS)
> + uart_write_wakeup(port);
> + }
> +}
>  
> - isrstatus &= port->read_status_mask;
> - isrstatus &= ~port->ignore_status_mask;
> +/**
> + * cdns_uart_handle_rx - Handle the received bytes along with Rx errors.
> + * @dev_id: Id of the UART port
> + * @isrstatus: The interrupt status register value as read
> + * Return: None
> + */
> +static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
> +{
> + struct uart_port *port = (struct uart_port *)dev_id;
> + unsigned int data;
> + unsigned int framerrprocessed = 

Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Peter Hurley
On 08/17/2015 03:22 AM, Michal Simek wrote:
 From: Anirudha Sarangi anirudha.sara...@xilinx.com
 
 The existing interrupt handling logic has followins issues.
 - Upon a parity error with default configuration, the control
   never comes out of the ISR thereby hanging Linux.
 - The error handling logic around framing and parity error are buggy.
   There are chances that the errors will never be captured.
 - The existing ISR is just too long.
 This patch fixes all these concerns.

This patch is unreviewable. Please break this down into multiple patches.

Regards,
Peter Hurley

 It separates out the Tx and Rx
 hanling logic into separate functions. It ensures that the status
 registers are cleared on all cases so that a hang situation never
 arises.
 
 Signed-off-by: Anirudha Sarangi anir...@xilinx.com
 Signed-off-by: Michal Simek michal.si...@xilinx.com
 ---
 
  drivers/tty/serial/xilinx_uartps.c | 194 
 -
  1 file changed, 104 insertions(+), 90 deletions(-)
 
 diff --git a/drivers/tty/serial/xilinx_uartps.c 
 b/drivers/tty/serial/xilinx_uartps.c
 index 2dc26e5f1384..c771dbbf6161 100644
 --- a/drivers/tty/serial/xilinx_uartps.c
 +++ b/drivers/tty/serial/xilinx_uartps.c
 @@ -173,61 +173,86 @@ struct cdns_uart {
   clk_rate_change_nb);
  
  /**
 - * cdns_uart_isr - Interrupt handler
 - * @irq: Irq number
 - * @dev_id: Id of the port
 - *
 - * Return: IRQHANDLED
 + * cdns_uart_handle_tx - Handle the bytes to be Txed.
 + * @dev_id: Id of the UART port
 + * Return: None
   */
 -static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
 +static void cdns_uart_handle_tx(void *dev_id)
  {
   struct uart_port *port = (struct uart_port *)dev_id;
 - unsigned long flags;
 - unsigned int isrstatus, numbytes;
 - unsigned int data;
 - char status = TTY_NORMAL;
 + unsigned int numbytes;
  
 - spin_lock_irqsave(port-lock, flags);
 + if (uart_circ_empty(port-state-xmit)) {
 + writel(CDNS_UART_IXR_TXEMPTY, port-membase +
 +CDNS_UART_IDR_OFFSET);
 + } else {
 + numbytes = port-fifosize;
 + /* Break if no more data available in the UART buffer */
 + while (numbytes--) {
 + if (uart_circ_empty(port-state-xmit))
 + break;
 + /*
 +  * Get the data from the UART circular buffer
 +  * and write it to the cdns_uart's TX_FIFO
 +  * register.
 +  */
 + writel(port-state-xmit.buf[port-state-xmit.tail],
 +port-membase + CDNS_UART_FIFO_OFFSET);
  
 - /* Read the interrupt status register to determine which
 -  * interrupt(s) is/are active.
 -  */
 - isrstatus = readl(port-membase + CDNS_UART_ISR_OFFSET);
 + port-icount.tx++;
  
 - /*
 -  * There is no hardware break detection, so we interpret framing
 -  * error with all-zeros data as a break sequence. Most of the time,
 -  * there's another non-zero byte at the end of the sequence.
 -  */
 - if (isrstatus  CDNS_UART_IXR_FRAMING) {
 - while (!(readl(port-membase + CDNS_UART_SR_OFFSET) 
 - CDNS_UART_SR_RXEMPTY)) {
 - if (!readl(port-membase + CDNS_UART_FIFO_OFFSET)) {
 - port-read_status_mask |= CDNS_UART_IXR_BRK;
 - isrstatus = ~CDNS_UART_IXR_FRAMING;
 - }
 + /*
 +  * Adjust the tail of the UART buffer and wrap
 +  * the buffer if it reaches limit.
 +  */
 + port-state-xmit.tail =
 + (port-state-xmit.tail + 1) 
 + (UART_XMIT_SIZE - 1);
   }
 - writel(CDNS_UART_IXR_FRAMING,
 - port-membase + CDNS_UART_ISR_OFFSET);
 - }
  
 - /* drop byte with parity error if IGNPAR specified */
 - if (isrstatus  port-ignore_status_mask  CDNS_UART_IXR_PARITY)
 - isrstatus = ~(CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT);
 + if (uart_circ_chars_pending(
 + port-state-xmit)  WAKEUP_CHARS)
 + uart_write_wakeup(port);
 + }
 +}
  
 - isrstatus = port-read_status_mask;
 - isrstatus = ~port-ignore_status_mask;
 +/**
 + * cdns_uart_handle_rx - Handle the received bytes along with Rx errors.
 + * @dev_id: Id of the UART port
 + * @isrstatus: The interrupt status register value as read
 + * Return: None
 + */
 +static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
 +{
 + struct uart_port *port = (struct uart_port *)dev_id;
 + unsigned int data;
 + unsigned int framerrprocessed = 0;
 + char status = TTY_NORMAL;
  
 - if ((isrstatus  

Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Peter Hurley
On 08/17/2015 12:00 PM, Anirudha Sarangi wrote:
 From: Peter Hurley [mailto:pe...@hurleysoftware.com]
 On 08/17/2015 03:22 AM, Michal Simek wrote:
 From: Anirudha Sarangi anirudha.sara...@xilinx.com

 The existing interrupt handling logic has followins issues.
 - Upon a parity error with default configuration, the control
   never comes out of the ISR thereby hanging Linux.
 - The error handling logic around framing and parity error are buggy.
   There are chances that the errors will never be captured.
 - The existing ISR is just too long.
 This patch fixes all these concerns.

 This patch is unreviewable. Please break this down into multiple patches.

 Thanks. Let me give a shot. It is just breaking the single big ISR that has 
 both Rx and Tx in a single function into smaller ones.
 Not sure how I will create smaller patches, but I will try and get back.

I would start with a refactor patch that splits up the ISR but
makes no other functional changes. Then add the bug fix patches.

Regards,
Peter Hurley

ps - The email signature below is not appropriate for lkml.

 
 This email and any attachments are intended for the sole use of the named 
 recipient(s) and contain(s) confidential information that may be proprietary, 
 privileged or copyrighted under applicable law. If you are not the intended 
 recipient, do not read, copy, or forward this email message or any 
 attachments. Delete this email message and any attachments immediately.
 

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

2015-08-17 Thread Anirudha Sarangi
Hi,

 -Original Message-
 From: Peter Hurley [mailto:pe...@hurleysoftware.com]
 Sent: Monday, August 17, 2015 9:26 PM
 To: Michal Simek
 Cc: linux-kernel@vger.kernel.org; mon...@monstr.eu; Anirudha Sarangi; Soren
 Brinkmann; Jiri Slaby; linux-ser...@vger.kernel.org; Greg Kroah-Hartman; 
 linux-
 arm-ker...@lists.infradead.org
 Subject: Re: [PATCH 4/4] serial: xuartps: Rewrite the interrupt handling logic

 On 08/17/2015 03:22 AM, Michal Simek wrote:
  From: Anirudha Sarangi anirudha.sara...@xilinx.com
 
  The existing interrupt handling logic has followins issues.
  - Upon a parity error with default configuration, the control
never comes out of the ISR thereby hanging Linux.
  - The error handling logic around framing and parity error are buggy.
There are chances that the errors will never be captured.
  - The existing ISR is just too long.
  This patch fixes all these concerns.

 This patch is unreviewable. Please break this down into multiple patches.

Thanks. Let me give a shot. It is just breaking the single big ISR that has 
both Rx and Tx in a single function into smaller ones.
Not sure how I will create smaller patches, but I will try and get back.

Regards
Anirudha

 Regards,
 Peter Hurley

  It separates out the Tx and Rx
  hanling logic into separate functions. It ensures that the status
  registers are cleared on all cases so that a hang situation never
  arises.
 
  Signed-off-by: Anirudha Sarangi anir...@xilinx.com
  Signed-off-by: Michal Simek michal.si...@xilinx.com
  ---
 
   drivers/tty/serial/xilinx_uartps.c | 194
  -
   1 file changed, 104 insertions(+), 90 deletions(-)
 
  diff --git a/drivers/tty/serial/xilinx_uartps.c
  b/drivers/tty/serial/xilinx_uartps.c
  index 2dc26e5f1384..c771dbbf6161 100644
  --- a/drivers/tty/serial/xilinx_uartps.c
  +++ b/drivers/tty/serial/xilinx_uartps.c
  @@ -173,61 +173,86 @@ struct cdns_uart {
  clk_rate_change_nb);
 
   /**
  - * cdns_uart_isr - Interrupt handler
  - * @irq: Irq number
  - * @dev_id: Id of the port
  - *
  - * Return: IRQHANDLED
  + * cdns_uart_handle_tx - Handle the bytes to be Txed.
  + * @dev_id: Id of the UART port
  + * Return: None
*/
  -static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
  +static void cdns_uart_handle_tx(void *dev_id)
   {
  struct uart_port *port = (struct uart_port *)dev_id;
  -   unsigned long flags;
  -   unsigned int isrstatus, numbytes;
  -   unsigned int data;
  -   char status = TTY_NORMAL;
  +   unsigned int numbytes;
 
  -   spin_lock_irqsave(port-lock, flags);
  +   if (uart_circ_empty(port-state-xmit)) {
  +   writel(CDNS_UART_IXR_TXEMPTY, port-membase +
  +  CDNS_UART_IDR_OFFSET);
  +   } else {
  +   numbytes = port-fifosize;
  +   /* Break if no more data available in the UART buffer */
  +   while (numbytes--) {
  +   if (uart_circ_empty(port-state-xmit))
  +   break;
  +   /*
  +* Get the data from the UART circular buffer
  +* and write it to the cdns_uart's TX_FIFO
  +* register.
  +*/
  +   writel(port-state-xmit.buf[port-state-xmit.tail],
  +  port-membase + CDNS_UART_FIFO_OFFSET);
 
  -   /* Read the interrupt status register to determine which
  -* interrupt(s) is/are active.
  -*/
  -   isrstatus = readl(port-membase + CDNS_UART_ISR_OFFSET);
  +   port-icount.tx++;
 
  -   /*
  -* There is no hardware break detection, so we interpret framing
  -* error with all-zeros data as a break sequence. Most of the time,
  -* there's another non-zero byte at the end of the sequence.
  -*/
  -   if (isrstatus  CDNS_UART_IXR_FRAMING) {
  -   while (!(readl(port-membase + CDNS_UART_SR_OFFSET) 
  -   CDNS_UART_SR_RXEMPTY)) {
  -   if (!readl(port-membase + CDNS_UART_FIFO_OFFSET))
 {
  -   port-read_status_mask |=
 CDNS_UART_IXR_BRK;
  -   isrstatus = ~CDNS_UART_IXR_FRAMING;
  -   }
  +   /*
  +* Adjust the tail of the UART buffer and wrap
  +* the buffer if it reaches limit.
  +*/
  +   port-state-xmit.tail =
  +   (port-state-xmit.tail + 1) 
  +   (UART_XMIT_SIZE - 1);
  }
  -   writel(CDNS_UART_IXR_FRAMING,
  -   port-membase + CDNS_UART_ISR_OFFSET);
  -   }
 
  -   /* drop byte with parity error if IGNPAR specified */
  -   if (isrstatus  port-ignore_status_mask  CDNS_UART_IXR_PARITY)
  -   isrstatus = ~(CDNS_UART_IXR_RXTRIG |
 CDNS_UART_IXR_TOUT);
  +   if (uart_circ_chars_pending(
  +   port-state-xmit)  WAKEUP_CHARS