All of lore.kernel.org
 help / color / mirror / Atom feed
From: dillon min <dillon.minfei@gmail.com>
To: Johan Hovold <johan@kernel.org>
Cc: Greg KH <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre TORGUE <alexandre.torgue@foss.st.com>,
	kernel test robot <lkp@intel.com>,
	Gerald Baeza <gerald.baeza@foss.st.com>,
	Erwan LE-RAY - foss <erwan.leray@foss.st.com>,
	linux-serial@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com,
	Linux ARM <linux-arm-kernel@lists.infradead.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	kbuild-all@lists.01.org, clang-built-linux@googlegroups.com
Subject: Re: [PATCH v3] serial: stm32: optimize spin lock usage
Date: Sat, 17 Apr 2021 21:07:55 +0800	[thread overview]
Message-ID: <CAL9mu0Kxny5JOGDk67ByMCVAJFOCF44rEOjbt68VxHz_2gZHrg@mail.gmail.com> (raw)
In-Reply-To: <YHma7H3RoLyeH650@hovoldconsulting.com>

Hi Johan,

On Fri, Apr 16, 2021 at 10:10 PM Johan Hovold <johan@kernel.org> wrote:
>
> On Fri, Apr 16, 2021 at 06:10:41PM +0800, dillon.minfei@gmail.com wrote:
> > From: dillon min <dillon.minfei@gmail.com>
> >
> > This patch aims to fix two potential bug:
> > - no lock to protect uart register in this case
> >
> >   stm32_usart_threaded_interrupt()
> >      spin_lock(&port->lock);
> >      ...
> >      stm32_usart_receive_chars()
> >        uart_handle_sysrq_char();
> >        sysrq_function();
> >        printk();
> >          stm32_usart_console_write();
> >            locked = 0; //since port->sysrq is not zero,
> >                          no lock to protect forward register
> >                          access.
> >
> > - if add spin_trylock_irqsave() to protect uart register for sysrq = 1 case,
> >   that might got recursive locking under UP.
> >   So, use uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq()
> >   move sysrq handler position to irq/thread_d handler, just record
> >   sysrq_ch in stm32_usart_receive_chars() by uart_prepare_sysrq_char()
> >   delay the sysrq process to next interrupt handler.
> >
> >   new flow:
> >
> >   stm32_usart_threaded_interrupt()/stm32_usart_interrupt()
> >   spin_lock_irqsave(&port->lock);
> >   ...
> >   uart_unlock_and_check_sysrq();
> >      spin_unlock_irqrestore();
> >      handle_sysrq(sysrq_ch);
> >   stm32_usart_threaded_interrupt()//stm32_usart_interrupt() return
> >
> > Cc: Johan Hovold <johan@kernel.org>
> > Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
> > Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > Cc: Gerald Baeza <gerald.baeza@foss.st.com>
> > Cc: Erwan Le Ray <erwan.leray@foss.st.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: dillon min <dillon.minfei@gmail.com>
> > ---
> > v3: add uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq() to move
> >     sysrq handler inside interrupt routinei to avoid recursive locking,
> >     according to Johan Hovold suggestion, thanks.
> >
> >  drivers/tty/serial/stm32-usart.c | 24 +++++++++++-------------
> >  1 file changed, 11 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
> > index b3675cf25a69..981f50ec784e 100644
> > --- a/drivers/tty/serial/stm32-usart.c
> > +++ b/drivers/tty/serial/stm32-usart.c
> > @@ -271,7 +271,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
> >                       }
> >               }
> >
> > -             if (uart_handle_sysrq_char(port, c))
> > +             if (uart_prepare_sysrq_char(port, c))
> >                       continue;
> >               uart_insert_char(port, sr, USART_SR_ORE, c, flag);
> >       }
> > @@ -457,9 +457,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> >       const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
> > +     unsigned long flags;
> >       u32 sr;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
> >
> >       sr = readl_relaxed(port->membase + ofs->isr);
> >
> > @@ -477,7 +478,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
> >               stm32_usart_transmit_chars(port);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       if (stm32_port->rx_ch)
> >               return IRQ_WAKE_THREAD;
> > @@ -489,13 +490,14 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
> >  {
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> > +     unsigned long flags;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
>
> This essentially turns the threaded handler into a non-threaded one,
> which is a bad idea.
This change is only to adapt for uart_unlock_and_check_sysrq() need flags.
Found your patch has removed this parameter from
uart_unlock_and_check_sysrq(), so this changes should be removed.

>
> >       if (stm32_port->rx_ch)
> >               stm32_usart_receive_chars(port, true);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       return IRQ_HANDLED;
> >  }
>
> You also didn't base this patch on tty-next, which has a number of
> updates to this driver. Before noting that myself, I had fixed a couple
> of deadlocks in this driver which turned out to have been incidentally
> fixed by an unrelated path in -next.
Yes, my submission is based on linux-5.12. based on the component's
next branch is a good idea , to avoid conflict. thanks.
>
> I'll be posting a series that should fix up all of this.
Thanks
>
> Johan

WARNING: multiple messages have this Message-ID (diff)
From: dillon min <dillon.minfei@gmail.com>
To: Johan Hovold <johan@kernel.org>
Cc: Greg KH <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>,
	 Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre TORGUE <alexandre.torgue@foss.st.com>,
	 kernel test robot <lkp@intel.com>,
	Gerald Baeza <gerald.baeza@foss.st.com>,
	 Erwan LE-RAY - foss <erwan.leray@foss.st.com>,
	linux-serial@vger.kernel.org,
	 linux-stm32@st-md-mailman.stormreply.com,
	 Linux ARM <linux-arm-kernel@lists.infradead.org>,
	 Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	kbuild-all@lists.01.org, clang-built-linux@googlegroups.com
Subject: Re: [PATCH v3] serial: stm32: optimize spin lock usage
Date: Sat, 17 Apr 2021 21:07:55 +0800	[thread overview]
Message-ID: <CAL9mu0Kxny5JOGDk67ByMCVAJFOCF44rEOjbt68VxHz_2gZHrg@mail.gmail.com> (raw)
In-Reply-To: <YHma7H3RoLyeH650@hovoldconsulting.com>

Hi Johan,

On Fri, Apr 16, 2021 at 10:10 PM Johan Hovold <johan@kernel.org> wrote:
>
> On Fri, Apr 16, 2021 at 06:10:41PM +0800, dillon.minfei@gmail.com wrote:
> > From: dillon min <dillon.minfei@gmail.com>
> >
> > This patch aims to fix two potential bug:
> > - no lock to protect uart register in this case
> >
> >   stm32_usart_threaded_interrupt()
> >      spin_lock(&port->lock);
> >      ...
> >      stm32_usart_receive_chars()
> >        uart_handle_sysrq_char();
> >        sysrq_function();
> >        printk();
> >          stm32_usart_console_write();
> >            locked = 0; //since port->sysrq is not zero,
> >                          no lock to protect forward register
> >                          access.
> >
> > - if add spin_trylock_irqsave() to protect uart register for sysrq = 1 case,
> >   that might got recursive locking under UP.
> >   So, use uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq()
> >   move sysrq handler position to irq/thread_d handler, just record
> >   sysrq_ch in stm32_usart_receive_chars() by uart_prepare_sysrq_char()
> >   delay the sysrq process to next interrupt handler.
> >
> >   new flow:
> >
> >   stm32_usart_threaded_interrupt()/stm32_usart_interrupt()
> >   spin_lock_irqsave(&port->lock);
> >   ...
> >   uart_unlock_and_check_sysrq();
> >      spin_unlock_irqrestore();
> >      handle_sysrq(sysrq_ch);
> >   stm32_usart_threaded_interrupt()//stm32_usart_interrupt() return
> >
> > Cc: Johan Hovold <johan@kernel.org>
> > Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
> > Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > Cc: Gerald Baeza <gerald.baeza@foss.st.com>
> > Cc: Erwan Le Ray <erwan.leray@foss.st.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: dillon min <dillon.minfei@gmail.com>
> > ---
> > v3: add uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq() to move
> >     sysrq handler inside interrupt routinei to avoid recursive locking,
> >     according to Johan Hovold suggestion, thanks.
> >
> >  drivers/tty/serial/stm32-usart.c | 24 +++++++++++-------------
> >  1 file changed, 11 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
> > index b3675cf25a69..981f50ec784e 100644
> > --- a/drivers/tty/serial/stm32-usart.c
> > +++ b/drivers/tty/serial/stm32-usart.c
> > @@ -271,7 +271,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
> >                       }
> >               }
> >
> > -             if (uart_handle_sysrq_char(port, c))
> > +             if (uart_prepare_sysrq_char(port, c))
> >                       continue;
> >               uart_insert_char(port, sr, USART_SR_ORE, c, flag);
> >       }
> > @@ -457,9 +457,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> >       const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
> > +     unsigned long flags;
> >       u32 sr;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
> >
> >       sr = readl_relaxed(port->membase + ofs->isr);
> >
> > @@ -477,7 +478,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
> >               stm32_usart_transmit_chars(port);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       if (stm32_port->rx_ch)
> >               return IRQ_WAKE_THREAD;
> > @@ -489,13 +490,14 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
> >  {
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> > +     unsigned long flags;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
>
> This essentially turns the threaded handler into a non-threaded one,
> which is a bad idea.
This change is only to adapt for uart_unlock_and_check_sysrq() need flags.
Found your patch has removed this parameter from
uart_unlock_and_check_sysrq(), so this changes should be removed.

>
> >       if (stm32_port->rx_ch)
> >               stm32_usart_receive_chars(port, true);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       return IRQ_HANDLED;
> >  }
>
> You also didn't base this patch on tty-next, which has a number of
> updates to this driver. Before noting that myself, I had fixed a couple
> of deadlocks in this driver which turned out to have been incidentally
> fixed by an unrelated path in -next.
Yes, my submission is based on linux-5.12. based on the component's
next branch is a good idea , to avoid conflict. thanks.
>
> I'll be posting a series that should fix up all of this.
Thanks
>
> Johan

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: dillon min <dillon.minfei@gmail.com>
To: kbuild-all@lists.01.org
Subject: Re: [PATCH v3] serial: stm32: optimize spin lock usage
Date: Sat, 17 Apr 2021 21:07:55 +0800	[thread overview]
Message-ID: <CAL9mu0Kxny5JOGDk67ByMCVAJFOCF44rEOjbt68VxHz_2gZHrg@mail.gmail.com> (raw)
In-Reply-To: <YHma7H3RoLyeH650@hovoldconsulting.com>

[-- Attachment #1: Type: text/plain, Size: 4990 bytes --]

Hi Johan,

On Fri, Apr 16, 2021 at 10:10 PM Johan Hovold <johan@kernel.org> wrote:
>
> On Fri, Apr 16, 2021 at 06:10:41PM +0800, dillon.minfei(a)gmail.com wrote:
> > From: dillon min <dillon.minfei@gmail.com>
> >
> > This patch aims to fix two potential bug:
> > - no lock to protect uart register in this case
> >
> >   stm32_usart_threaded_interrupt()
> >      spin_lock(&port->lock);
> >      ...
> >      stm32_usart_receive_chars()
> >        uart_handle_sysrq_char();
> >        sysrq_function();
> >        printk();
> >          stm32_usart_console_write();
> >            locked = 0; //since port->sysrq is not zero,
> >                          no lock to protect forward register
> >                          access.
> >
> > - if add spin_trylock_irqsave() to protect uart register for sysrq = 1 case,
> >   that might got recursive locking under UP.
> >   So, use uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq()
> >   move sysrq handler position to irq/thread_d handler, just record
> >   sysrq_ch in stm32_usart_receive_chars() by uart_prepare_sysrq_char()
> >   delay the sysrq process to next interrupt handler.
> >
> >   new flow:
> >
> >   stm32_usart_threaded_interrupt()/stm32_usart_interrupt()
> >   spin_lock_irqsave(&port->lock);
> >   ...
> >   uart_unlock_and_check_sysrq();
> >      spin_unlock_irqrestore();
> >      handle_sysrq(sysrq_ch);
> >   stm32_usart_threaded_interrupt()//stm32_usart_interrupt() return
> >
> > Cc: Johan Hovold <johan@kernel.org>
> > Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
> > Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > Cc: Gerald Baeza <gerald.baeza@foss.st.com>
> > Cc: Erwan Le Ray <erwan.leray@foss.st.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: dillon min <dillon.minfei@gmail.com>
> > ---
> > v3: add uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq() to move
> >     sysrq handler inside interrupt routinei to avoid recursive locking,
> >     according to Johan Hovold suggestion, thanks.
> >
> >  drivers/tty/serial/stm32-usart.c | 24 +++++++++++-------------
> >  1 file changed, 11 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
> > index b3675cf25a69..981f50ec784e 100644
> > --- a/drivers/tty/serial/stm32-usart.c
> > +++ b/drivers/tty/serial/stm32-usart.c
> > @@ -271,7 +271,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
> >                       }
> >               }
> >
> > -             if (uart_handle_sysrq_char(port, c))
> > +             if (uart_prepare_sysrq_char(port, c))
> >                       continue;
> >               uart_insert_char(port, sr, USART_SR_ORE, c, flag);
> >       }
> > @@ -457,9 +457,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> >       const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
> > +     unsigned long flags;
> >       u32 sr;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
> >
> >       sr = readl_relaxed(port->membase + ofs->isr);
> >
> > @@ -477,7 +478,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
> >       if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
> >               stm32_usart_transmit_chars(port);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       if (stm32_port->rx_ch)
> >               return IRQ_WAKE_THREAD;
> > @@ -489,13 +490,14 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
> >  {
> >       struct uart_port *port = ptr;
> >       struct stm32_port *stm32_port = to_stm32_port(port);
> > +     unsigned long flags;
> >
> > -     spin_lock(&port->lock);
> > +     spin_lock_irqsave(&port->lock, flags);
>
> This essentially turns the threaded handler into a non-threaded one,
> which is a bad idea.
This change is only to adapt for uart_unlock_and_check_sysrq() need flags.
Found your patch has removed this parameter from
uart_unlock_and_check_sysrq(), so this changes should be removed.

>
> >       if (stm32_port->rx_ch)
> >               stm32_usart_receive_chars(port, true);
> >
> > -     spin_unlock(&port->lock);
> > +     uart_unlock_and_check_sysrq(port, flags);
> >
> >       return IRQ_HANDLED;
> >  }
>
> You also didn't base this patch on tty-next, which has a number of
> updates to this driver. Before noting that myself, I had fixed a couple
> of deadlocks in this driver which turned out to have been incidentally
> fixed by an unrelated path in -next.
Yes, my submission is based on linux-5.12. based on the component's
next branch is a good idea , to avoid conflict. thanks.
>
> I'll be posting a series that should fix up all of this.
Thanks
>
> Johan

  reply	other threads:[~2021-04-17 13:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16 10:10 [PATCH v3] serial: stm32: optimize spin lock usage dillon.minfei
2021-04-16 10:10 ` dillon.minfei
2021-04-16 10:10 ` dillon.minfei
2021-04-16 14:10 ` Johan Hovold
2021-04-16 14:10   ` Johan Hovold
2021-04-16 14:10   ` Johan Hovold
2021-04-17 13:07   ` dillon min [this message]
2021-04-17 13:07     ` dillon min
2021-04-17 13:07     ` dillon min

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=CAL9mu0Kxny5JOGDk67ByMCVAJFOCF44rEOjbt68VxHz_2gZHrg@mail.gmail.com \
    --to=dillon.minfei@gmail.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=clang-built-linux@googlegroups.com \
    --cc=erwan.leray@foss.st.com \
    --cc=gerald.baeza@foss.st.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=johan@kernel.org \
    --cc=kbuild-all@lists.01.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=lkp@intel.com \
    --cc=mcoquelin.stm32@gmail.com \
    /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.