[PATCH 4/5] omap_hdq: handle case where isr sees a 0 status byte.

From: NeilBrown
Date: Thu Dec 29 2011 - 21:48:15 EST


According to the documentation, when an isr happens one of the
3 bits in INT_STATUS must be set to say why.
But I sometimes see a value of zero.

The only explanation I can think of is that someone else reads the
register and so clears the bits. But I cannot find that someone.

So until we do, intuit what must have caused the interrupt.
If we were trying to write, assume it completed.
If we were trying to read and go something other than 0xFF,
assume the read completed.
If we read 0xFF, assume the read timed-out.

Signed-off-by: NeilBrown <neilb@xxxxxxx>
---

drivers/w1/masters/omap_hdq.c | 26 +++++++++++++++++++++++++-
1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 848399b..6b82469 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -211,9 +211,33 @@ static irqreturn_t hdq_isr(int irq, void *_hdq)
{
struct hdq_data *hdq_data = _hdq;
unsigned long irqflags;
+ u8 status;

spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
- hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ status = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ if (!status) {
+ /* I sometimes see a zero status even though the read
+ * seems to have been successful. Very strange.
+ * But we did get an interrupt, so figure out what
+ * must have happened.
+ */
+ u8 ctrl = hdq_reg_in(hdq_data, OMAP_HDQ_CTRL_STATUS);
+ dev_dbg(hdq_data->dev, "hdr_isr: INT=0! CTRL=0x%02x\n", ctrl);
+ if (!(ctrl & OMAP_HDQ_CTRL_STATUS_GO)) {
+ /* It has definitely finished.. */
+ if (ctrl & OMAP_HDQ_CTRL_STATUS_DIR) {
+ /* A read finished or timed-out */
+ u8 data = hdq_reg_in(hdq_data,
+ OMAP_HDQ_RX_DATA);
+ if (data == 0xFF)
+ status = OMAP_HDQ_INT_STATUS_TIMEOUT;
+ else
+ status = OMAP_HDQ_INT_STATUS_RXCOMPLETE;
+ } else
+ status = OMAP_HDQ_INT_STATUS_TXCOMPLETE;
+ }
+ }
+ hdq_data->hdq_irqstatus = status;
spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus);



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