From: Peter Hurley <peter@hurleysoftware.com>
To: Orson Zhai <orsonzhai@gmail.com>,
Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Cc: gregkh@linuxfoundation.org, mark.rutland@arm.com, arnd@arndb.de,
gnomes@lxorguk.ukuu.org.uk, broonie@kernel.org,
robh+dt@kernel.org, pawel.moll@arm.com,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
will.deacon@arm.com, catalin.marinas@arm.com, jslaby@suse.cz,
jason@lakedaemon.net, heiko@sntech.de, florian.vaussard@epfl.ch,
andrew@lunn.ch, rrichter@cavium.com, hytszk@gmail.com,
grant.likely@linaro.org, antonynpavlov@gmail.com,
Joel.Schopp@amd.com, Suravee.Suthikulpanit@amd.com,
shawn.guo@linaro.org, lea.yan@linaro.org,
jorge.ramirez-ortiz@linaro.org, lee.jones@linaro.org,
geng.ren@spreadtrum.com, zhizhou.zhang@spreadtrum.com,
lanqing.liu@spreadtrum.com, zhang.lyra@gmail.com,
wei.qiao@spreadtrum.com, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-serial@vger.kernel.org
Subject: Re: [PATCH v5 5/5] tty/serial: Add Spreadtrum sc9836-uart driver support
Date: Tue, 20 Jan 2015 08:39:25 -0500 [thread overview]
Message-ID: <54BE5A8D.6090303@hurleysoftware.com> (raw)
In-Reply-To: <54BE45EA.3030308@gmail.com>
On 01/20/2015 07:11 AM, Orson Zhai wrote:
> Hi, Peter,
>
> Thank you for reviewing our code!
> Some discussion below.
>
> On 2015年01月16日 23:20, Peter Hurley wrote:
>> On 01/16/2015 05:00 AM, Chunyan Zhang wrote:
>>> Add a full sc9836-uart driver for SC9836 SoC which is based on the
>>> spreadtrum sharkl64 platform.
>>> This driver also support earlycon.
>>> This patch also replaced the spaces between the macros and their
>>> values with the tabs in serial_core.h
>> The locking doesn't look correct. Specific notations below.
>>> +static inline void sprd_tx(int irq, void *dev_id)
>>> +{
>>> + struct uart_port *port = dev_id;
>>> + struct circ_buf *xmit = &port->state->xmit;
>>> + int count;
>>> +
>>> + if (port->x_char) {
>>> + serial_out(port, SPRD_TXD, port->x_char);
>>> + port->icount.tx++;
>>> + port->x_char = 0;
>>> + return;
>>> + }
>>> +
>>> + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
>>> + sprd_stop_tx(port);
>>> + return;
>>> + }
>>> +
>>> + count = THLD_TX_EMPTY;
>>> + do {
>>> + serial_out(port, SPRD_TXD, xmit->buf[xmit->tail]);
>>> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>> + port->icount.tx++;
>>> + if (uart_circ_empty(xmit))
>>> + break;
>>> + } while (--count > 0);
>>> +
>>> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
>>> + uart_write_wakeup(port);
>>> +
>>> + if (uart_circ_empty(xmit))
>>> + sprd_stop_tx(port);
>>> +}
>>> +
>>> +/* this handles the interrupt from one port */
>>> +static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
>>> +{
>>> + struct uart_port *port = (struct uart_port *)dev_id;
>>> + unsigned int ims;
>> Why does your isr not have to take port->lock ?
>
> The original consideration is the registers are accessed by isr only.
> Interrupt will not be nested because of gic chip driver protection.
> So there is not other thread will race on it.
> Does this make sense?
The xmit->buf[] and its indexes could be accessed concurrently.
For example,
CPU 0 | CPU 1
|
sprd_handle_irq | uart_flush_buffer
sprd_tx | spin_lock_irqsave
... |
count = 64 |
do { | xmit->tail = 0
serial_out(xmit->buf[xmit->tail]) |
whoops - what byte did this just output?
I'm sure there's many more possible races, perhaps with worse
outcomes than just 1 bad byte output.
>>
>>> + ims = serial_in(port, SPRD_IMSR);
>>> +
>>> + if (!ims)
>>> + return IRQ_NONE;
>>> +
>>> + serial_out(port, SPRD_ICLR, ~0);
>>> +
>>> + if (ims & (SPRD_IMSR_RX_FIFO_FULL |
>>> + SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT))
>>> + sprd_rx(irq, port);
>>> +
>>> + if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
>>> + sprd_tx(irq, port);
>>> +
>>> + return IRQ_HANDLED;
>>> +}
[...]
>>> +static void sprd_console_putchar(struct uart_port *port, int ch)
>>> +{
>>> + wait_for_xmitr(port);
>>> + serial_out(port, SPRD_TXD, ch);
>>> +}
>>> +
>>> +static void sprd_console_write(struct console *co, const char *s,
>>> + unsigned int count)
>>> +{
>>> + struct uart_port *port = &sprd_port[co->index]->port;
>>> + int ien;
>>> + int locked = 1;
>>> +
>>> + if (oops_in_progress)
>>> + locked = spin_trylock(&port->lock);
>>> + else
>>> + spin_lock(&port->lock);
>> If you do need to take the port->lock in your isr, then you need to
>> disable local irq here.
>
> You mean to use spin_lock_irqsave()?
>
> We do disable irq below....
But not before an irq could happen with the spin_lock already taken.
printk
...
sprd_console_write
spin_lock
<IRQ>
sprd_handle_irq
spin_lock
** DEADLOCK **
[
Note: some drivers assume that console->write() will always be
called with local interrupts disabled. This is a bad idea and I
have warned those driver authors when this has come up before.
]
Also, since you handle sysrq in your isr the above needs to check
for non-zero port->sysrq and _not_ attempt the spinlock because
the isr will already have it; for example,
<IRQ>
sprd_handle_irq
spin_lock
sprd_rx
...
uart_handle_syrq_char
handle_sysrq
__handle_sysrq
printk
...
sprd_console_write
spin_lock
** DEADLOCK **
Regards,
Peter Hurley
>>
>>> + /* save the IEN then disable the interrupts */
>>> + ien = serial_in(port, SPRD_IEN);
>>> + serial_out(port, SPRD_IEN, 0x0);
>
> Here, we disable port IEN register.
>
>>> +
>>> + uart_console_write(port, s, count, sprd_console_putchar);
>>> +
>>> + /* wait for transmitter to become empty and restore the IEN */
>>> + wait_for_xmitr(port);
>>> + serial_out(port, SPRD_IEN, ien);
>>> + if (locked)
>>> + spin_unlock(&port->lock);
>>> +}
WARNING: multiple messages have this Message-ID (diff)
From: peter@hurleysoftware.com (Peter Hurley)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v5 5/5] tty/serial: Add Spreadtrum sc9836-uart driver support
Date: Tue, 20 Jan 2015 08:39:25 -0500 [thread overview]
Message-ID: <54BE5A8D.6090303@hurleysoftware.com> (raw)
In-Reply-To: <54BE45EA.3030308@gmail.com>
On 01/20/2015 07:11 AM, Orson Zhai wrote:
> Hi, Peter,
>
> Thank you for reviewing our code!
> Some discussion below.
>
> On 2015?01?16? 23:20, Peter Hurley wrote:
>> On 01/16/2015 05:00 AM, Chunyan Zhang wrote:
>>> Add a full sc9836-uart driver for SC9836 SoC which is based on the
>>> spreadtrum sharkl64 platform.
>>> This driver also support earlycon.
>>> This patch also replaced the spaces between the macros and their
>>> values with the tabs in serial_core.h
>> The locking doesn't look correct. Specific notations below.
>>> +static inline void sprd_tx(int irq, void *dev_id)
>>> +{
>>> + struct uart_port *port = dev_id;
>>> + struct circ_buf *xmit = &port->state->xmit;
>>> + int count;
>>> +
>>> + if (port->x_char) {
>>> + serial_out(port, SPRD_TXD, port->x_char);
>>> + port->icount.tx++;
>>> + port->x_char = 0;
>>> + return;
>>> + }
>>> +
>>> + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
>>> + sprd_stop_tx(port);
>>> + return;
>>> + }
>>> +
>>> + count = THLD_TX_EMPTY;
>>> + do {
>>> + serial_out(port, SPRD_TXD, xmit->buf[xmit->tail]);
>>> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>> + port->icount.tx++;
>>> + if (uart_circ_empty(xmit))
>>> + break;
>>> + } while (--count > 0);
>>> +
>>> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
>>> + uart_write_wakeup(port);
>>> +
>>> + if (uart_circ_empty(xmit))
>>> + sprd_stop_tx(port);
>>> +}
>>> +
>>> +/* this handles the interrupt from one port */
>>> +static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
>>> +{
>>> + struct uart_port *port = (struct uart_port *)dev_id;
>>> + unsigned int ims;
>> Why does your isr not have to take port->lock ?
>
> The original consideration is the registers are accessed by isr only.
> Interrupt will not be nested because of gic chip driver protection.
> So there is not other thread will race on it.
> Does this make sense?
The xmit->buf[] and its indexes could be accessed concurrently.
For example,
CPU 0 | CPU 1
|
sprd_handle_irq | uart_flush_buffer
sprd_tx | spin_lock_irqsave
... |
count = 64 |
do { | xmit->tail = 0
serial_out(xmit->buf[xmit->tail]) |
whoops - what byte did this just output?
I'm sure there's many more possible races, perhaps with worse
outcomes than just 1 bad byte output.
>>
>>> + ims = serial_in(port, SPRD_IMSR);
>>> +
>>> + if (!ims)
>>> + return IRQ_NONE;
>>> +
>>> + serial_out(port, SPRD_ICLR, ~0);
>>> +
>>> + if (ims & (SPRD_IMSR_RX_FIFO_FULL |
>>> + SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT))
>>> + sprd_rx(irq, port);
>>> +
>>> + if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
>>> + sprd_tx(irq, port);
>>> +
>>> + return IRQ_HANDLED;
>>> +}
[...]
>>> +static void sprd_console_putchar(struct uart_port *port, int ch)
>>> +{
>>> + wait_for_xmitr(port);
>>> + serial_out(port, SPRD_TXD, ch);
>>> +}
>>> +
>>> +static void sprd_console_write(struct console *co, const char *s,
>>> + unsigned int count)
>>> +{
>>> + struct uart_port *port = &sprd_port[co->index]->port;
>>> + int ien;
>>> + int locked = 1;
>>> +
>>> + if (oops_in_progress)
>>> + locked = spin_trylock(&port->lock);
>>> + else
>>> + spin_lock(&port->lock);
>> If you do need to take the port->lock in your isr, then you need to
>> disable local irq here.
>
> You mean to use spin_lock_irqsave()?
>
> We do disable irq below....
But not before an irq could happen with the spin_lock already taken.
printk
...
sprd_console_write
spin_lock
<IRQ>
sprd_handle_irq
spin_lock
** DEADLOCK **
[
Note: some drivers assume that console->write() will always be
called with local interrupts disabled. This is a bad idea and I
have warned those driver authors when this has come up before.
]
Also, since you handle sysrq in your isr the above needs to check
for non-zero port->sysrq and _not_ attempt the spinlock because
the isr will already have it; for example,
<IRQ>
sprd_handle_irq
spin_lock
sprd_rx
...
uart_handle_syrq_char
handle_sysrq
__handle_sysrq
printk
...
sprd_console_write
spin_lock
** DEADLOCK **
Regards,
Peter Hurley
>>
>>> + /* save the IEN then disable the interrupts */
>>> + ien = serial_in(port, SPRD_IEN);
>>> + serial_out(port, SPRD_IEN, 0x0);
>
> Here, we disable port IEN register.
>
>>> +
>>> + uart_console_write(port, s, count, sprd_console_putchar);
>>> +
>>> + /* wait for transmitter to become empty and restore the IEN */
>>> + wait_for_xmitr(port);
>>> + serial_out(port, SPRD_IEN, ien);
>>> + if (locked)
>>> + spin_unlock(&port->lock);
>>> +}
next prev parent reply other threads:[~2015-01-20 13:39 UTC|newest]
Thread overview: 81+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <sc9836-v5>
2015-01-16 10:00 ` [PATCH v5 0/5] Add Spreadtrum Sharkl64 Platform support Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` [PATCH v5 1/5] Documentation: DT: Renamed of-serial.txt to 8250.txt Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
[not found] ` <1421402411-3479-2-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
2015-01-16 14:11 ` Rob Herring
2015-01-16 14:11 ` Rob Herring
2015-01-16 14:11 ` Rob Herring
2015-01-16 10:00 ` [PATCH v5 2/5] Documentation: DT: Add bindings for Spreadtrum SoC Platform Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
[not found] ` <1421402411-3479-3-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
2015-01-16 10:21 ` Mark Rutland
2015-01-16 10:21 ` Mark Rutland
2015-01-16 10:21 ` Mark Rutland
2015-01-16 12:53 ` Lyra Zhang
2015-01-16 12:53 ` Lyra Zhang
2015-01-16 12:53 ` Lyra Zhang
[not found] ` <CAAfSe-teDdPzRUnvzM+NErfZwmqM04yUMgic--hyZL8-Jjd8jw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-16 14:11 ` Mark Rutland
2015-01-16 14:11 ` Mark Rutland
2015-01-16 14:11 ` Mark Rutland
2015-01-17 8:10 ` Orson Zhai
2015-01-17 8:10 ` Orson Zhai
2015-01-17 8:10 ` Orson Zhai
2015-01-16 10:00 ` [PATCH v5 3/5] arm64: dts: Add support for Spreadtrum SC9836 SoC in dts and Makefile Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
[not found] ` <1421402411-3479-4-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
2015-01-16 10:35 ` Mark Rutland
2015-01-16 10:35 ` Mark Rutland
2015-01-16 10:35 ` Mark Rutland
2015-01-16 12:49 ` Orson Zhai
2015-01-16 12:49 ` Orson Zhai
2015-01-16 12:49 ` Orson Zhai
2015-01-16 14:09 ` Mark Rutland
2015-01-16 14:09 ` Mark Rutland
2015-01-16 14:09 ` Mark Rutland
2015-01-17 8:47 ` Orson Zhai
2015-01-17 8:47 ` Orson Zhai
2015-01-17 8:47 ` Orson Zhai
2015-01-16 10:00 ` [PATCH v5 4/5] arm64: Add support for Spreadtrum's Sharkl64 Platform in Kconfig and defconfig Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
[not found] ` <1421402411-3479-5-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
2015-01-16 10:48 ` Mark Rutland
2015-01-16 10:48 ` Mark Rutland
2015-01-16 10:48 ` Mark Rutland
2015-01-16 11:50 ` Lyra Zhang
2015-01-16 11:50 ` Lyra Zhang
2015-01-16 11:50 ` Lyra Zhang
2015-01-16 10:00 ` [PATCH v5 5/5] tty/serial: Add Spreadtrum sc9836-uart driver support Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:00 ` Chunyan Zhang
2015-01-16 10:26 ` Arnd Bergmann
2015-01-16 10:26 ` Arnd Bergmann
[not found] ` <1421402411-3479-6-git-send-email-chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
2015-01-16 11:02 ` Baruch Siach
2015-01-16 11:02 ` Baruch Siach
2015-01-16 11:02 ` Baruch Siach
2015-01-16 15:20 ` Peter Hurley
2015-01-16 15:20 ` Peter Hurley
2015-01-16 15:20 ` Peter Hurley
2015-01-20 12:11 ` Orson Zhai
2015-01-20 12:11 ` Orson Zhai
2015-01-20 13:39 ` Peter Hurley [this message]
2015-01-20 13:39 ` Peter Hurley
2015-01-16 16:41 ` Rob Herring
2015-01-16 16:41 ` Rob Herring
2015-01-16 16:41 ` Rob Herring
[not found] ` <CAL_JsqJg=BtanmR_rhYthCUhKbErs8viZ7MMMXr-PmPjUV4BRQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-19 9:55 ` Lyra Zhang
2015-01-19 9:55 ` Lyra Zhang
2015-01-19 9:55 ` Lyra Zhang
2015-01-19 14:11 ` Rob Herring
2015-01-19 14:11 ` Rob Herring
2015-01-19 14:11 ` Rob Herring
2015-01-20 7:37 ` Lyra Zhang
2015-01-20 7:37 ` Lyra Zhang
2015-01-20 7:37 ` Lyra Zhang
[not found] ` <CAAfSe-tAwURc_P+-0+m22ao9r+Fud6Ae89JF8FGsWgg_49Mdhg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-20 8:41 ` Orson Zhai
2015-01-20 8:41 ` Orson Zhai
2015-01-20 8:41 ` Orson Zhai
2015-01-20 20:17 ` Rob Herring
2015-01-20 20:17 ` Rob Herring
2015-01-20 20:17 ` Rob Herring
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=54BE5A8D.6090303@hurleysoftware.com \
--to=peter@hurleysoftware.com \
--cc=Joel.Schopp@amd.com \
--cc=Suravee.Suthikulpanit@amd.com \
--cc=andrew@lunn.ch \
--cc=antonynpavlov@gmail.com \
--cc=arnd@arndb.de \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=chunyan.zhang@spreadtrum.com \
--cc=florian.vaussard@epfl.ch \
--cc=galak@codeaurora.org \
--cc=geng.ren@spreadtrum.com \
--cc=gnomes@lxorguk.ukuu.org.uk \
--cc=grant.likely@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=heiko@sntech.de \
--cc=hytszk@gmail.com \
--cc=ijc+devicetree@hellion.org.uk \
--cc=jason@lakedaemon.net \
--cc=jorge.ramirez-ortiz@linaro.org \
--cc=jslaby@suse.cz \
--cc=lanqing.liu@spreadtrum.com \
--cc=lea.yan@linaro.org \
--cc=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=orsonzhai@gmail.com \
--cc=pawel.moll@arm.com \
--cc=robh+dt@kernel.org \
--cc=rrichter@cavium.com \
--cc=shawn.guo@linaro.org \
--cc=wei.qiao@spreadtrum.com \
--cc=will.deacon@arm.com \
--cc=zhang.lyra@gmail.com \
--cc=zhizhou.zhang@spreadtrum.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.