From 606658292a0f8dc01f3165e741b711572af2d83f Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 31 Jul 2010 16:15:22 -0300 Subject: [PATCH] [media] saa7164: Monitor the command bus and check for inconsistencies Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7164/saa7164-bus.c | 153 ++++++++++++++++------------ drivers/media/video/saa7164/saa7164-core.c | 40 ++++++++ drivers/media/video/saa7164/saa7164-types.h | 8 +- 3 files changed, 131 insertions(+), 70 deletions(-) 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 @@ int saa7164_bus_setup(struct saa7164_dev *dev) 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 @@ void saa7164_bus_dump(struct saa7164_dev *dev) 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_dwSetWritePos = 0x%x (0x%08x)\n", + b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos)); - dprintk(DBGLVL_BUS, " .m_pdwSetReadPos = 0x%p (0x%08x)\n", - b->m_pdwSetReadPos, *b->m_pdwSetReadPos); + dprintk(DBGLVL_BUS, " .m_dwGetReadPos = 0x%x (0x%08x)\n", + b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos)); - dprintk(DBGLVL_BUS, " .m_pdwGetWritePos = 0x%p (0x%08x)\n", - b->m_pdwGetWritePos, *b->m_pdwGetWritePos); + dprintk(DBGLVL_BUS, " .m_dwGetWritePos = 0x%x (0x%08x)\n", + b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos)); - dprintk(DBGLVL_BUS, " .m_pdwGetReadPos = 0x%p (0x%08x)\n", - b->m_pdwGetReadPos, *b->m_pdwGetReadPos); +} + +/* 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 @@ void saa7164_bus_dumpmsg(struct saa7164_dev *dev, tmComResInfo_t* m, void *buf) 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 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) } 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 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 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 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 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 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 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 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 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 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, tmComResInfo_t msg_tmp; int ret = SAA_ERR_BAD_PARAMETER; + saa7164_bus_verify(dev); if (msg == 0) return ret; @@ -309,11 +330,10 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, /* 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 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, 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 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, 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 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, } 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 @@ peekout: 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 @@ static int saa7164_proc_show(struct seq_file *m, void *v) 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 @@ typedef struct { 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; -- 2.7.4