[media] saa7164: Monitor the command bus and check for inconsistencies

Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
index ccc6100..8848687 100644
--- a/drivers/media/video/saa7164/saa7164-bus.c
+++ b/drivers/media/video/saa7164/saa7164-bus.c
@@ -43,17 +43,11 @@
 
 	b->m_dwSizeGetRing	= SAA_DEVICE_BUFFERBLOCKSIZE;
 
-	b->m_pdwSetWritePos	= (u32 *)((u8 *)(dev->bmmio +
-		((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64))));
+	b->m_dwSetWritePos	= ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64));
+	b->m_dwSetReadPos	= b->m_dwSetWritePos + (1 * sizeof(u32));
 
-	b->m_pdwSetReadPos	= (u32 *)((u8 *)b->m_pdwSetWritePos +
-		1 * sizeof(u32));
-
-	b->m_pdwGetWritePos	= (u32 *)((u8 *)b->m_pdwSetWritePos +
-		2 * sizeof(u32));
-
-	b->m_pdwGetReadPos	= (u32 *)((u8 *)b->m_pdwSetWritePos +
-		3 * sizeof(u32));
+	b->m_dwGetWritePos	= b->m_dwSetWritePos + (2 * sizeof(u32));
+	b->m_dwGetReadPos	= b->m_dwSetWritePos + (3 * sizeof(u32));
 
 	return 0;
 }
@@ -71,17 +65,44 @@
 	dprintk(DBGLVL_BUS, " .m_pdwGetRing     = 0x%p\n", b->m_pdwGetRing);
 	dprintk(DBGLVL_BUS, " .m_dwSizeGetRing  = 0x%x\n", b->m_dwSizeGetRing);
 
-	dprintk(DBGLVL_BUS, " .m_pdwSetWritePos = 0x%p (0x%08x)\n",
-		b->m_pdwSetWritePos, *b->m_pdwSetWritePos);
+	dprintk(DBGLVL_BUS, " .m_dwSetReadPos   = 0x%x (0x%08x)\n",
+		b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
 
-	dprintk(DBGLVL_BUS, " .m_pdwSetReadPos  = 0x%p (0x%08x)\n",
-		b->m_pdwSetReadPos, *b->m_pdwSetReadPos);
+	dprintk(DBGLVL_BUS, " .m_dwSetWritePos  = 0x%x (0x%08x)\n",
+		b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
 
-	dprintk(DBGLVL_BUS, " .m_pdwGetWritePos = 0x%p (0x%08x)\n",
-		b->m_pdwGetWritePos, *b->m_pdwGetWritePos);
+	dprintk(DBGLVL_BUS, " .m_dwGetReadPos   = 0x%x (0x%08x)\n",
+		b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
 
-	dprintk(DBGLVL_BUS, " .m_pdwGetReadPos  = 0x%p (0x%08x)\n",
-		b->m_pdwGetReadPos, *b->m_pdwGetReadPos);
+	dprintk(DBGLVL_BUS, " .m_dwGetWritePos  = 0x%x (0x%08x)\n",
+		b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
+
+}
+
+/* Intensionally throw a BUG() if the state of the message bus looks corrupt */
+void saa7164_bus_verify(struct saa7164_dev *dev)
+{
+	tmComResBusInfo_t *b = &dev->bus;
+	int bug = 0, debug;
+
+	if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing)
+		bug++;
+
+	if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing)
+		bug++;
+
+	if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing)
+		bug++;
+
+	if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing)
+		bug++;
+
+	if (bug) {
+		debug = 0xffff; /* Ensure we get the bus dump */
+		saa7164_bus_dump(dev);
+		debug = 1024; /* Ensure we get the bus dump */
+		BUG();
+	}
 }
 
 void saa7164_bus_dumpmsg(struct saa7164_dev *dev, tmComResInfo_t* m, void *buf)
@@ -111,7 +132,7 @@
 int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
 {
 	tmComResBusInfo_t *bus = &dev->bus;
-	u32 bytes_to_write, read_distance, timeout, curr_srp, curr_swp;
+	u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
 	u32 new_swp, space_rem;
 	int ret = SAA_ERR_BAD_PARAMETER;
 
@@ -121,6 +142,7 @@
 	}
 
 	dprintk(DBGLVL_BUS, "%s()\n", __func__);
+	saa7164_bus_verify(dev);
 
 	msg->size = cpu_to_le16(msg->size);
 	msg->command = cpu_to_le16(msg->command);
@@ -141,30 +163,30 @@
 	mutex_lock(&bus->lock);
 
 	bytes_to_write = sizeof(*msg) + msg->size;
-	read_distance = 0;
+	free_write_space = 0;
 	timeout = SAA_BUS_TIMEOUT;
-	curr_srp = le32_to_cpu(*bus->m_pdwSetReadPos);
-	curr_swp = le32_to_cpu(*bus->m_pdwSetWritePos);
+	curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
+	curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
 
 	/* Deal with ring wrapping issues */
 	if (curr_srp > curr_swp)
-		/* The ring has not wrapped yet */
-		read_distance = curr_srp - curr_swp;
-	else
 		/* Deal with the wrapped ring */
-		read_distance = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
+		free_write_space = curr_srp - curr_swp;
+	else
+		/* The ring has not wrapped yet */
+		free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
 
 	dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__,
 		bytes_to_write);
 
-	dprintk(DBGLVL_BUS, "%s() read_distance = %d\n", __func__,
-		read_distance);
+	dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__,
+		free_write_space);
 
 	dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp);
 	dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp);
 
 	/* Process the msg and write the content onto the bus */
-	while (bytes_to_write >= read_distance) {
+	while (bytes_to_write >= free_write_space) {
 
 		if (timeout-- == 0) {
 			printk(KERN_ERR "%s() bus timeout\n", __func__);
@@ -177,15 +199,15 @@
 		mdelay(1);
 
 		/* Check the space usage again */
-		curr_srp = le32_to_cpu(*bus->m_pdwSetReadPos);
+		curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
 
 		/* Deal with ring wrapping issues */
 		if (curr_srp > curr_swp)
-			/* Read didn't wrap around the buffer */
-			read_distance = curr_srp - curr_swp;
-		else
 			/* Deal with the wrapped ring */
-			read_distance = (curr_srp + bus->m_dwSizeSetRing) -
+			free_write_space = curr_srp - curr_swp;
+		else
+			/* Read didn't wrap around the buffer */
+			free_write_space = (curr_srp + bus->m_dwSizeSetRing) -
 				curr_swp;
 
 	}
@@ -217,28 +239,28 @@
 			dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
 
 			/* Split the msg into pieces as the ring wraps */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
-			memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
+			memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
 				sizeof(*msg) - space_rem);
 
-			memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
+			memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
 				buf, msg->size);
 
 		} else if (space_rem == sizeof(*msg)) {
 			dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
 
 			/* Additional data at the beginning of the ring */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-			memcpy_toio(bus->m_pdwSetRing, buf, msg->size);
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+			memcpy(bus->m_pdwSetRing, buf, msg->size);
 
 		} else {
 			/* Additional data wraps around the ring */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
 			if (msg->size > 0) {
-				memcpy_toio(bus->m_pdwSetRing + curr_swp +
+				memcpy(bus->m_pdwSetRing + curr_swp +
 					sizeof(*msg), buf, space_rem -
 					sizeof(*msg));
-				memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
+				memcpy(bus->m_pdwSetRing, (u8 *)buf +
 					space_rem - sizeof(*msg),
 					bytes_to_write - space_rem);
 			}
@@ -250,23 +272,21 @@
 		dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
 
 		/* The ring buffer doesn't wrap, two simple copies */
-		memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-		memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
+		memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+		memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
 			msg->size);
 	}
 
 	dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
 
-	/* TODO: Convert all of the direct PCI writes into
-	 * saa7164_writel/b calls for consistency.
-	 */
-
 	/* Update the bus write position */
-	*bus->m_pdwSetWritePos = cpu_to_le32(new_swp);
+	saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
 	ret = SAA_OK;
 
 out:
+	saa7164_bus_dump(dev);
 	mutex_unlock(&bus->lock);
+	saa7164_bus_verify(dev);
 	return ret;
 }
 
@@ -288,6 +308,7 @@
 	tmComResInfo_t msg_tmp;
 	int ret = SAA_ERR_BAD_PARAMETER;
 
+	saa7164_bus_verify(dev);
 	if (msg == 0)
 		return ret;
 
@@ -309,11 +330,10 @@
 	/* Peek the bus to see if a msg exists, if it's not what we're expecting
 	 * then return cleanly else read the message from the bus.
 	 */
-	curr_gwp = le32_to_cpu(*bus->m_pdwGetWritePos);
-	curr_grp = le32_to_cpu(*bus->m_pdwGetReadPos);
+	curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
+	curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
 
 	if (curr_gwp == curr_grp) {
-		dprintk(DBGLVL_BUS, "%s() No message on the bus\n", __func__);
 		ret = SAA_ERR_EMPTY;
 		goto out;
 	}
@@ -343,19 +363,19 @@
 		new_grp -= bus->m_dwSizeGetRing;
 		space_rem = bus->m_dwSizeGetRing - curr_grp;
 
-		memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
-		memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
+		memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
+		memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
 			bytes_to_read - space_rem);
 
 	} else {
 		/* No wrapping */
-		memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
+		memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
 	}
 
 	/* No need to update the read positions, because this was a peek */
 	/* If the caller specifically want to peek, return */
 	if (peekonly) {
-		memcpy_fromio(msg, &msg_tmp, sizeof(*msg));
+		memcpy(msg, &msg_tmp, sizeof(*msg));
 		goto peekout;
 	}
 
@@ -401,24 +421,24 @@
 
 		if (space_rem < sizeof(*msg)) {
 			/* msg wraps around the ring */
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem);
-			memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing,
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
+			memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
 				sizeof(*msg) - space_rem);
 			if (buf)
-				memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
+				memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
 					space_rem, buf_size);
 
 		} else if (space_rem == sizeof(*msg)) {
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 			if (buf)
 				memcpy(buf, bus->m_pdwGetRing, buf_size);
 		} else {
 			/* Additional data wraps around the ring */
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 			if (buf) {
-				memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
+				memcpy(buf, bus->m_pdwGetRing + curr_grp +
 					sizeof(*msg), space_rem - sizeof(*msg));
-				memcpy_fromio(buf + space_rem - sizeof(*msg),
+				memcpy(buf + space_rem - sizeof(*msg),
 					bus->m_pdwGetRing, bytes_to_read -
 					space_rem);
 			}
@@ -427,14 +447,14 @@
 
 	} else {
 		/* No wrapping */
-		memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+		memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 		if (buf)
-			memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
+			memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
 				buf_size);
 	}
 
 	/* Update the read positions, adjusting the ring */
-	*bus->m_pdwGetReadPos = cpu_to_le32(new_grp);
+	saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
 
 peekout:
 	msg->size = le16_to_cpu(msg->size);
@@ -443,6 +463,7 @@
 	ret = SAA_OK;
 out:
 	mutex_unlock(&bus->lock);
+	saa7164_bus_verify(dev);
 	return ret;
 }
 
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index 545eeff..fcbb9d5 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -1122,6 +1122,46 @@
 		b = &dev->bus;
 		mutex_lock(&b->lock);
 
+		seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n",
+			b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
+
+		seq_printf(m, " .m_pdwSetReadPos  = 0x%x (0x%08x)\n",
+			b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
+
+		seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n",
+			b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
+
+		seq_printf(m, " .m_pdwGetReadPos  = 0x%x (0x%08x)\n",
+			b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
+		c = 0;
+		seq_printf(m, "\n  Set Ring:\n");
+		seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+		for (i = 0; i < b->m_dwSizeSetRing; i++) {
+			if (c == 0)
+				seq_printf(m, " %04x:", i);
+
+			seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
+
+			if (++c == 16) {
+				seq_printf(m, "\n");
+				c = 0;
+			}
+		}
+
+		c = 0;
+		seq_printf(m, "\n  Get Ring:\n");
+		seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+		for (i = 0; i < b->m_dwSizeGetRing; i++) {
+			if (c == 0)
+				seq_printf(m, " %04x:", i);
+
+			seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
+
+			if (++c == 16) {
+				seq_printf(m, "\n");
+				c = 0;
+			}
+		}
 
 		mutex_unlock(&b->lock);
 
diff --git a/drivers/media/video/saa7164/saa7164-types.h b/drivers/media/video/saa7164/saa7164-types.h
index 3406a95..ea245ba 100644
--- a/drivers/media/video/saa7164/saa7164-types.h
+++ b/drivers/media/video/saa7164/saa7164-types.h
@@ -82,10 +82,10 @@
 	u32	m_dwSizeSetRing;
 	u8	*m_pdwGetRing;
 	u32	m_dwSizeGetRing;
-	u32	*m_pdwSetWritePos;
-	u32	*m_pdwSetReadPos;
-	u32	*m_pdwGetWritePos;
-	u32	*m_pdwGetReadPos;
+	u32	m_dwSetWritePos;
+	u32	m_dwSetReadPos;
+	u32	m_dwGetWritePos;
+	u32	m_dwGetReadPos;
 
 	/* All access is protected */
 	struct mutex lock;