From: Johannes Reif <reif@corscience.de>
To: spi-devel-general@lists.sourceforge.net,
linux-serial@vger.kernel.org, manuel.stahl@iis.fraunhofer.de
Subject: sc16is7x2 driver bug (fix)
Date: Fri, 17 Dec 2010 16:22:18 +0100 [thread overview]
Message-ID: <4D0B802A.1090002@corscience.de> (raw)
Hi,
I'm using the sc16is7x2 driver (SPI<-> 2x UART) written by Manuel Stahl.
While operating one UART channel everything seems fine. But if I use
both channels the driver runs into an "unresponsive state" after some time.
In this state I figured out that the /IRQ pin of the chip stays low
(active) although the IIR of both channels indicates that there is no
interrupt pending.
Can someone reproduce this bug?
I want to make clear that there are 2 interrupt handler which share one
IRQ. So i.e. let's say the following happens:
- RX-timeout interrupt on channel 2
- IRQ Pin high -> low (active)
- kernel gets notice of IRQ and starts thread(s)
- work thread ch. 1 starting
- work thread ch. 2 starting
- work thread ch. 1 reads IIR over SPI and figures out that ch. 1 has no
interrupt
- work thread ch. 2 reads IIR over SPI, sees that ch
- work thread ch. 1 finished (returns IRQ_HANDLED)
- work thread ch. 2 reads out RX data --> IIR gets cleared (also IRQ pin
goes high)
(what happens when ch. 1 gets data now and generates an IRQ before
worker of ch. 2 has finished)
- work thread ch. 2. finished /returns IRQ_HANDLED)
Is it possible that last IRQ_HANDLED makes the Kernel wait for /IRQ pin
going high and low again, because the Kernel thinks that the first
IRQ_HANDLED managed the IRQ and the second one that of ch. 1 which didn't?
For those who don't have the driver right now here's the work routine.
static irqreturn_t sc16is7x2_work(int irq, void *data)
{
struct sc16is7x2_channel *chan = data;
struct sc16is7x2_chip *ts = chan->chip;
struct spi_message *m = &(chan->fifo_message);
unsigned ch = (chan == ts->channel) ? 0 : 1;
bool rx, tx;
dev_dbg(&ts->spi->dev, "%s (%i)\n", __func__, ch);
sc16is7x2_read_status(ts, ch);
while ((chan->iir & UART_IIR_NO_INT) == 0x00
&& !ts->force_end_work) {
sc16is7x2_handle_modem(ts, ch);
spi_message_init(m);
rx = sc16is7x2_msg_add_fifo_rx(ts, ch);
tx = sc16is7x2_msg_add_fifo_tx(ts, ch);
if (rx || tx)
spi_sync(ts->spi, m);
if (rx)
sc16is7x2_handle_fifo_rx(chan);
if (tx)
sc16is7x2_handle_fifo_tx(chan);
sc16is7x2_read_status(ts, ch);
}
dev_dbg(&ts->spi->dev, "%s finished (iir = 0x%02x)\n",
__func__, chan->iir);
return IRQ_HANDLED;
}
The following patch is a workaround for that bug which does also check
the gpio pin of the IRQ line.
--- a/drivers/serial/sc16is7x2.c
+++ b/drivers/serial/sc16is7x2.c
@@ -1042,7 +1042,7 @@ static irqreturn_t sc16is7x2_work(int irq, void *data)
sc16is7x2_read_status(ts, ch);
- while ((chan->iir & UART_IIR_NO_INT) == 0x00
+ while (((chan->iir & UART_IIR_NO_INT) == 0x00 ||
gpio_get_value(irq_to_gpio(ts->spi->irq)) == 0)
&& !ts->force_end_work) {
sc16is7x2_handle_modem(ts, ch);
Johannes Reif
next reply other threads:[~2010-12-17 15:22 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-17 15:22 Johannes Reif [this message]
2010-12-17 15:36 ` sc16is7x2 driver bug (fix) Manuel Stahl
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=4D0B802A.1090002@corscience.de \
--to=reif@corscience.de \
--cc=linux-serial@vger.kernel.org \
--cc=manuel.stahl@iis.fraunhofer.de \
--cc=spi-devel-general@lists.sourceforge.net \
/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.