linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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);
>>> +}

  reply	other threads:[~2015-01-20 13:39 UTC|newest]

Thread overview: 25+ 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   ` [PATCH v5 1/5] Documentation: DT: Renamed of-serial.txt to 8250.txt 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 10:00   ` [PATCH v5 2/5] Documentation: DT: Add bindings for Spreadtrum SoC Platform 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 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-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
     [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:00   ` [PATCH v5 4/5] arm64: Add support for Spreadtrum's Sharkl64 Platform in Kconfig and defconfig 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 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: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 15:20       ` Peter Hurley
2015-01-20 12:11         ` Orson Zhai
2015-01-20 13:39           ` Peter Hurley [this message]
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 14:11             ` Rob Herring
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 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).