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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux