[media] saa7164: buffer crc checks and ensure we use the memcpy func
Buffer crc checks and ensure we use the correct PCIe IO memcpy func Signed-off-by: Steven Toth <stoth@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
46eeb8dd30
commit
12d3203e39
@@ -113,6 +113,7 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
|
|||||||
buf->flags = SAA7164_BUFFER_FREE;
|
buf->flags = SAA7164_BUFFER_FREE;
|
||||||
buf->pos = 0;
|
buf->pos = 0;
|
||||||
buf->actual_size = params->pitch * params->numberoflines;
|
buf->actual_size = params->pitch * params->numberoflines;
|
||||||
|
buf->crc = 0;
|
||||||
/* TODO: arg len is being ignored */
|
/* TODO: arg len is being ignored */
|
||||||
buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
|
buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
|
||||||
buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
|
buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
|
||||||
@@ -129,8 +130,9 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
|
|||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
/* init the buffers to a known pattern, easier during debugging */
|
/* init the buffers to a known pattern, easier during debugging */
|
||||||
memset(buf->cpu, 0xff, buf->pci_size);
|
memset_io(buf->cpu, 0xff, buf->pci_size);
|
||||||
memset(buf->pt_cpu, 0xff, buf->pt_size);
|
buf->crc = crc32(0, buf->cpu, buf->actual_size);
|
||||||
|
memset_io(buf->pt_cpu, 0xff, buf->pt_size);
|
||||||
|
|
||||||
dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n",
|
dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n",
|
||||||
__func__, buf);
|
__func__, buf);
|
||||||
@@ -296,6 +298,7 @@ struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u
|
|||||||
|
|
||||||
buf->actual_size = len;
|
buf->actual_size = len;
|
||||||
buf->pos = 0;
|
buf->pos = 0;
|
||||||
|
buf->crc = 0;
|
||||||
|
|
||||||
dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n",
|
dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n",
|
||||||
__func__, buf);
|
__func__, buf);
|
||||||
|
@@ -217,28 +217,28 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
|
|||||||
dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
|
dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
|
||||||
|
|
||||||
/* Split the msg into pieces as the ring wraps */
|
/* Split the msg into pieces as the ring wraps */
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
|
memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
|
||||||
memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
|
memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
|
||||||
sizeof(*msg) - space_rem);
|
sizeof(*msg) - space_rem);
|
||||||
|
|
||||||
memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
|
memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
|
||||||
buf, msg->size);
|
buf, msg->size);
|
||||||
|
|
||||||
} else if (space_rem == sizeof(*msg)) {
|
} else if (space_rem == sizeof(*msg)) {
|
||||||
dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
|
dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
|
||||||
|
|
||||||
/* Additional data at the beginning of the ring */
|
/* Additional data at the beginning of the ring */
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
||||||
memcpy(bus->m_pdwSetRing, buf, msg->size);
|
memcpy_toio(bus->m_pdwSetRing, buf, msg->size);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Additional data wraps around the ring */
|
/* Additional data wraps around the ring */
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
||||||
if (msg->size > 0) {
|
if (msg->size > 0) {
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp +
|
memcpy_toio(bus->m_pdwSetRing + curr_swp +
|
||||||
sizeof(*msg), buf, space_rem -
|
sizeof(*msg), buf, space_rem -
|
||||||
sizeof(*msg));
|
sizeof(*msg));
|
||||||
memcpy(bus->m_pdwSetRing, (u8 *)buf +
|
memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
|
||||||
space_rem - sizeof(*msg),
|
space_rem - sizeof(*msg),
|
||||||
bytes_to_write - space_rem);
|
bytes_to_write - space_rem);
|
||||||
}
|
}
|
||||||
@@ -250,8 +250,8 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
|
|||||||
dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
|
dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
|
||||||
|
|
||||||
/* The ring buffer doesn't wrap, two simple copies */
|
/* The ring buffer doesn't wrap, two simple copies */
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
|
||||||
memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
|
memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
|
||||||
msg->size);
|
msg->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,19 +343,19 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
|
|||||||
new_grp -= bus->m_dwSizeGetRing;
|
new_grp -= bus->m_dwSizeGetRing;
|
||||||
space_rem = bus->m_dwSizeGetRing - curr_grp;
|
space_rem = bus->m_dwSizeGetRing - curr_grp;
|
||||||
|
|
||||||
memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
|
memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
|
||||||
memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
|
memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
|
||||||
bytes_to_read - space_rem);
|
bytes_to_read - space_rem);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* No wrapping */
|
/* No wrapping */
|
||||||
memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
|
memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No need to update the read positions, because this was a peek */
|
/* No need to update the read positions, because this was a peek */
|
||||||
/* If the caller specifically want to peek, return */
|
/* If the caller specifically want to peek, return */
|
||||||
if (peekonly) {
|
if (peekonly) {
|
||||||
memcpy(msg, &msg_tmp, sizeof(*msg));
|
memcpy_fromio(msg, &msg_tmp, sizeof(*msg));
|
||||||
goto peekout;
|
goto peekout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,24 +401,24 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
|
|||||||
|
|
||||||
if (space_rem < sizeof(*msg)) {
|
if (space_rem < sizeof(*msg)) {
|
||||||
/* msg wraps around the ring */
|
/* msg wraps around the ring */
|
||||||
memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
|
memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem);
|
||||||
memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
|
memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing,
|
||||||
sizeof(*msg) - space_rem);
|
sizeof(*msg) - space_rem);
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
|
memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
|
||||||
space_rem, buf_size);
|
space_rem, buf_size);
|
||||||
|
|
||||||
} else if (space_rem == sizeof(*msg)) {
|
} else if (space_rem == sizeof(*msg)) {
|
||||||
memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy(buf, bus->m_pdwGetRing, buf_size);
|
memcpy(buf, bus->m_pdwGetRing, buf_size);
|
||||||
} else {
|
} else {
|
||||||
/* Additional data wraps around the ring */
|
/* Additional data wraps around the ring */
|
||||||
memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
||||||
if (buf) {
|
if (buf) {
|
||||||
memcpy(buf, bus->m_pdwGetRing + curr_grp +
|
memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
|
||||||
sizeof(*msg), space_rem - sizeof(*msg));
|
sizeof(*msg), space_rem - sizeof(*msg));
|
||||||
memcpy(buf + space_rem - sizeof(*msg),
|
memcpy_fromio(buf + space_rem - sizeof(*msg),
|
||||||
bus->m_pdwGetRing, bytes_to_read -
|
bus->m_pdwGetRing, bytes_to_read -
|
||||||
space_rem);
|
space_rem);
|
||||||
}
|
}
|
||||||
@@ -427,9 +427,9 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* No wrapping */
|
/* No wrapping */
|
||||||
memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
|
||||||
if (buf)
|
if (buf)
|
||||||
memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
|
memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
|
||||||
buf_size);
|
buf_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,6 +72,28 @@ LIST_HEAD(saa7164_devlist);
|
|||||||
|
|
||||||
#define INT_SIZE 16
|
#define INT_SIZE 16
|
||||||
|
|
||||||
|
void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 tmp[16];
|
||||||
|
memset(&tmp[0], 0xff, sizeof(tmp));
|
||||||
|
|
||||||
|
printk(KERN_INFO "--------------------> "
|
||||||
|
"00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 16) {
|
||||||
|
if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) {
|
||||||
|
printk(KERN_INFO " [0x%08x] "
|
||||||
|
"%02x %02x %02x %02x %02x %02x %02x %02x "
|
||||||
|
"%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
|
||||||
|
*(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
|
||||||
|
*(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
|
||||||
|
*(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
|
||||||
|
*(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void saa7164_ts_verifier(struct saa7164_buffer *buf)
|
static void saa7164_ts_verifier(struct saa7164_buffer *buf)
|
||||||
{
|
{
|
||||||
struct saa7164_port *port = buf->port;
|
struct saa7164_port *port = buf->port;
|
||||||
@@ -216,6 +238,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
|
|||||||
struct saa7164_user_buffer *ubuf;
|
struct saa7164_user_buffer *ubuf;
|
||||||
struct list_head *c, *n;
|
struct list_head *c, *n;
|
||||||
int wp, rp, i = 0;
|
int wp, rp, i = 0;
|
||||||
|
u32 crc, ok = 0;
|
||||||
u8 *p;
|
u8 *p;
|
||||||
|
|
||||||
port->last_svc_msecs_diff = port->last_svc_msecs;
|
port->last_svc_msecs_diff = port->last_svc_msecs;
|
||||||
@@ -277,10 +300,19 @@ static void saa7164_work_enchandler(struct work_struct *w)
|
|||||||
saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
|
saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buf->idx == wp) {
|
||||||
|
/* Ignore this, it's being updated currently by the dma engine */
|
||||||
|
} else
|
||||||
if (buf->idx == rp) {
|
if (buf->idx == rp) {
|
||||||
|
|
||||||
|
crc = crc32(0, buf->cpu, buf->actual_size);
|
||||||
|
if (crc != port->shadow_crc[rp])
|
||||||
|
printk(KERN_ERR "%s crc didn't match shadow was 0x%x now 0x%x\n",
|
||||||
|
__func__, port->shadow_crc[rp], crc);
|
||||||
|
|
||||||
/* Found the buffer, deal with it */
|
/* Found the buffer, deal with it */
|
||||||
dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",
|
dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d crc32: 0x%x\n",
|
||||||
__func__, wp, rp);
|
__func__, wp, rp, buf->crc);
|
||||||
|
|
||||||
/* Validate the incoming buffer content */
|
/* Validate the incoming buffer content */
|
||||||
if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
|
if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
|
||||||
@@ -293,9 +325,23 @@ static void saa7164_work_enchandler(struct work_struct *w)
|
|||||||
ubuf = list_first_entry(&port->list_buf_free.list,
|
ubuf = list_first_entry(&port->list_buf_free.list,
|
||||||
struct saa7164_user_buffer, list);
|
struct saa7164_user_buffer, list);
|
||||||
|
|
||||||
if (ubuf->actual_size == buf->actual_size) {
|
if (ubuf->actual_size >= buf->actual_size) {
|
||||||
memcpy(ubuf->data, buf->cpu,
|
memcpy(ubuf->data, port->shadow_buf[rp], 312 * 188);
|
||||||
ubuf->actual_size);
|
|
||||||
|
/* Throw a new checksum on the read buffer */
|
||||||
|
ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
|
||||||
|
|
||||||
|
if ((crc == port->shadow_crc[rp]) && (crc == ubuf->crc))
|
||||||
|
ok = 1;
|
||||||
|
else
|
||||||
|
ok = 0;
|
||||||
|
|
||||||
|
if (ok == 0)
|
||||||
|
printk(KERN_ERR
|
||||||
|
"rp: %d dmacrc: 0x%08x shadcrc: 0x%08x ubufcrc: 0x%08x %s\n",
|
||||||
|
rp, buf->crc, port->shadow_crc[rp], ubuf->crc,
|
||||||
|
ok ? "crcgood" : "crcbad");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "buf %p actual fails match\n", buf);
|
printk(KERN_ERR "buf %p actual fails match\n", buf);
|
||||||
}
|
}
|
||||||
@@ -315,9 +361,21 @@ static void saa7164_work_enchandler(struct work_struct *w)
|
|||||||
/* Ensure offset into buffer remains 0, fill buffer
|
/* Ensure offset into buffer remains 0, fill buffer
|
||||||
* with known bad data. */
|
* with known bad data. */
|
||||||
saa7164_buffer_zero_offsets(port, rp);
|
saa7164_buffer_zero_offsets(port, rp);
|
||||||
memset(buf->cpu, 0xff, buf->pci_size);
|
memset_io(buf->cpu, 0xff, buf->pci_size);
|
||||||
|
buf->crc = crc32(0, buf->cpu, buf->actual_size);
|
||||||
|
|
||||||
|
// break;
|
||||||
|
} else {
|
||||||
|
/* Validate all other checksums, on previous buffers - they should never change */
|
||||||
|
crc = crc32(0, buf->cpu, buf->actual_size);
|
||||||
|
if (crc != buf->crc) {
|
||||||
|
printk(KERN_ERR "buf[%d].crc became invalid, was 0x%x became 0x%x rp: %d wp: %d\n",
|
||||||
|
buf->idx, buf->crc, crc, rp, wp);
|
||||||
|
//saa7164_dumphex16FF(dev, (u8 *)buf->cpu, buf->actual_size);
|
||||||
|
saa7164_dumphex16FF(dev, (u8 *)buf->cpu, 256);
|
||||||
|
buf->crc = crc;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -332,7 +390,6 @@ static void saa7164_work_enchandler(struct work_struct *w)
|
|||||||
print_histogram = 64 + port->nr;
|
print_histogram = 64 + port->nr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void saa7164_work_cmdhandler(struct work_struct *w)
|
static void saa7164_work_cmdhandler(struct work_struct *w)
|
||||||
{
|
{
|
||||||
struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
|
struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
|
||||||
@@ -354,7 +411,11 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
|
|||||||
static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
|
static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
|
||||||
{
|
{
|
||||||
struct saa7164_dev *dev = port->dev;
|
struct saa7164_dev *dev = port->dev;
|
||||||
int wp, rp;
|
struct saa7164_buffer *buf;
|
||||||
|
struct saa7164_user_buffer *ubuf;
|
||||||
|
struct list_head *c, *n;
|
||||||
|
int wp, rp, i = 0;
|
||||||
|
u8 *p;
|
||||||
|
|
||||||
/* Find the current write point from the hardware */
|
/* Find the current write point from the hardware */
|
||||||
wp = saa7164_readl(port->bufcounter);
|
wp = saa7164_readl(port->bufcounter);
|
||||||
@@ -400,7 +461,48 @@ static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
|
|||||||
port->last_irq_wp,
|
port->last_irq_wp,
|
||||||
port->last_irq_rp
|
port->last_irq_rp
|
||||||
);
|
);
|
||||||
|
/* Find the used buffer, shadow copy it before we've
|
||||||
|
* acked the interrupt.
|
||||||
|
*/
|
||||||
|
// mutex_lock(&port->dmaqueue_lock);
|
||||||
|
list_for_each_safe(c, n, &port->dmaqueue.list) {
|
||||||
|
|
||||||
|
buf = list_entry(c, struct saa7164_buffer, list);
|
||||||
|
if (i++ > port->hwcfg.buffercount) {
|
||||||
|
printk(KERN_ERR "%s() illegal i count %d\n",
|
||||||
|
__func__, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (u8 *)buf->cpu;
|
||||||
|
if ( (*(p + buf->actual_size + 0) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 1) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 2) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 3) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 0x10) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 0x11) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 0x12) != 0xff) ||
|
||||||
|
(*(p + buf->actual_size + 0x13) != 0xff) )
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "buf %p failed guard check\n", buf);
|
||||||
|
saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf->idx == rp) {
|
||||||
|
|
||||||
|
memcpy_fromio(port->shadow_buf[rp], buf->cpu, 312 * 188);
|
||||||
|
port->shadow_crc[rp] = crc32(0, port->shadow_buf[rp], 312 * 188);
|
||||||
|
|
||||||
|
buf->crc = crc32(0, buf->cpu, 312 * 188);
|
||||||
|
|
||||||
|
if (port->shadow_crc[rp] != buf->crc)
|
||||||
|
printk(KERN_ERR "%s() crc check failed 0x%x vs 0x%x\n",
|
||||||
|
__func__, port->shadow_crc[rp], buf->crc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// mutex_unlock(&port->dmaqueue_lock);
|
||||||
schedule_work(&port->workenc);
|
schedule_work(&port->workenc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -693,10 +795,10 @@ static void saa7164_dump_busdesc(struct saa7164_dev *dev)
|
|||||||
*/
|
*/
|
||||||
static void saa7164_get_descriptors(struct saa7164_dev *dev)
|
static void saa7164_get_descriptors(struct saa7164_dev *dev)
|
||||||
{
|
{
|
||||||
memcpy(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t));
|
memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t));
|
||||||
memcpy(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t),
|
memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t),
|
||||||
sizeof(tmComResInterfaceDescr_t));
|
sizeof(tmComResInterfaceDescr_t));
|
||||||
memcpy(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
|
memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
|
||||||
sizeof(tmComResBusDescr_t));
|
sizeof(tmComResBusDescr_t));
|
||||||
|
|
||||||
if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) {
|
if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) {
|
||||||
@@ -742,6 +844,7 @@ static int get_resources(struct saa7164_dev *dev)
|
|||||||
static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
|
static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
|
||||||
{
|
{
|
||||||
struct saa7164_port *port = 0;
|
struct saa7164_port *port = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
|
if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
|
||||||
BUG();
|
BUG();
|
||||||
@@ -780,6 +883,18 @@ static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
|
|||||||
saa7164_histogram_reset(&port->poll_interval,
|
saa7164_histogram_reset(&port->poll_interval,
|
||||||
"encoder poll() intervals");
|
"encoder poll() intervals");
|
||||||
|
|
||||||
|
if (port->type == SAA7164_MPEG_ENCODER) {
|
||||||
|
for (i = 0; i < 8; i ++) {
|
||||||
|
port->shadow_buf[i] = kzalloc(312 * 188, GFP_KERNEL);
|
||||||
|
if (port->shadow_buf[i] == 0)
|
||||||
|
printk(KERN_ERR "%s() shadow_buf ENOMEM\n", __func__);
|
||||||
|
else {
|
||||||
|
memset(port->shadow_buf[i], 0xff, 312 * 188);
|
||||||
|
port->shadow_crc[i] = crc32(0, port->shadow_buf[i], 312 * 188);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,6 +1172,8 @@ static void saa7164_shutdown(struct saa7164_dev *dev)
|
|||||||
static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
|
static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
|
||||||
{
|
{
|
||||||
struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
|
struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
|
||||||
|
struct saa7164_port *port;
|
||||||
|
int i;
|
||||||
|
|
||||||
saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
|
saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
|
||||||
&dev->ports[ SAA7164_PORT_ENC1 ].irq_interval);
|
&dev->ports[ SAA7164_PORT_ENC1 ].irq_interval);
|
||||||
@@ -1071,6 +1188,22 @@ static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
|
|||||||
|
|
||||||
saa7164_shutdown(dev);
|
saa7164_shutdown(dev);
|
||||||
|
|
||||||
|
port = &dev->ports[ SAA7164_PORT_ENC1 ];
|
||||||
|
if (port->type == SAA7164_MPEG_ENCODER) {
|
||||||
|
for (i = 0; i < 8; i ++) {
|
||||||
|
kfree(port->shadow_buf[i]);
|
||||||
|
port->shadow_buf[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port = &dev->ports[ SAA7164_PORT_ENC2 ];
|
||||||
|
if (port->type == SAA7164_MPEG_ENCODER) {
|
||||||
|
for (i = 0; i < 8; i ++) {
|
||||||
|
kfree(port->shadow_buf[i]);
|
||||||
|
port->shadow_buf[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
|
if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
|
||||||
saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]);
|
saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]);
|
||||||
|
|
||||||
|
@@ -865,6 +865,7 @@ static int saa7164_encoder_start_streaming(struct saa7164_port *port)
|
|||||||
|
|
||||||
/* Configure the encoder with any cache values */
|
/* Configure the encoder with any cache values */
|
||||||
saa7164_api_set_encoder(port);
|
saa7164_api_set_encoder(port);
|
||||||
|
saa7164_api_get_encoder(port);
|
||||||
|
|
||||||
saa7164_buffer_cfg_port(port);
|
saa7164_buffer_cfg_port(port);
|
||||||
|
|
||||||
@@ -1006,11 +1007,19 @@ struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
|
|||||||
{
|
{
|
||||||
struct saa7164_user_buffer *buf = 0;
|
struct saa7164_user_buffer *buf = 0;
|
||||||
struct saa7164_dev *dev = port->dev;
|
struct saa7164_dev *dev = port->dev;
|
||||||
|
u32 crc;
|
||||||
|
|
||||||
mutex_lock(&port->dmaqueue_lock);
|
mutex_lock(&port->dmaqueue_lock);
|
||||||
if (!list_empty(&port->list_buf_used.list)) {
|
if (!list_empty(&port->list_buf_used.list)) {
|
||||||
buf = list_first_entry(&port->list_buf_used.list,
|
buf = list_first_entry(&port->list_buf_used.list,
|
||||||
struct saa7164_user_buffer, list);
|
struct saa7164_user_buffer, list);
|
||||||
|
|
||||||
|
crc = crc32(0, buf->data, buf->actual_size);
|
||||||
|
if (crc != buf->crc) {
|
||||||
|
printk(KERN_ERR "%s() buf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
|
||||||
|
buf, buf->crc, crc);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&port->dmaqueue_lock);
|
mutex_unlock(&port->dmaqueue_lock);
|
||||||
|
|
||||||
|
@@ -50,6 +50,7 @@
|
|||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/crc32.h>
|
||||||
|
|
||||||
#include <media/tuner.h>
|
#include <media/tuner.h>
|
||||||
#include <media/tveeprom.h>
|
#include <media/tveeprom.h>
|
||||||
@@ -194,6 +195,8 @@ struct saa7164_user_buffer {
|
|||||||
u8 *data;
|
u8 *data;
|
||||||
u32 pos;
|
u32 pos;
|
||||||
u32 actual_size;
|
u32 actual_size;
|
||||||
|
|
||||||
|
u32 crc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct saa7164_fw_status {
|
struct saa7164_fw_status {
|
||||||
@@ -282,12 +285,13 @@ struct saa7164_buffer {
|
|||||||
|
|
||||||
/* A block of page align PCI memory */
|
/* A block of page align PCI memory */
|
||||||
u32 pci_size; /* PCI allocation size in bytes */
|
u32 pci_size; /* PCI allocation size in bytes */
|
||||||
u64 *cpu; /* Virtual address */
|
u64 __iomem *cpu; /* Virtual address */
|
||||||
dma_addr_t dma; /* Physical address */
|
dma_addr_t dma; /* Physical address */
|
||||||
|
u32 crc; /* Checksum for the entire buffer data */
|
||||||
|
|
||||||
/* A page table that splits the block into a number of entries */
|
/* A page table that splits the block into a number of entries */
|
||||||
u32 pt_size; /* PCI allocation size in bytes */
|
u32 pt_size; /* PCI allocation size in bytes */
|
||||||
u64 *pt_cpu; /* Virtual address */
|
u64 __iomem *pt_cpu; /* Virtual address */
|
||||||
dma_addr_t pt_dma; /* Physical address */
|
dma_addr_t pt_dma; /* Physical address */
|
||||||
|
|
||||||
/* Encoder fops */
|
/* Encoder fops */
|
||||||
@@ -386,6 +390,9 @@ struct saa7164_port {
|
|||||||
u32 a_cc_errors;
|
u32 a_cc_errors;
|
||||||
u8 last_v_cc;
|
u8 last_v_cc;
|
||||||
u8 last_a_cc;
|
u8 last_a_cc;
|
||||||
|
|
||||||
|
u8 *shadow_buf[8];
|
||||||
|
u32 shadow_crc[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct saa7164_dev {
|
struct saa7164_dev {
|
||||||
@@ -536,7 +543,6 @@ extern struct saa7164_user_buffer *saa7164_buffer_alloc_user(
|
|||||||
extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
|
extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
|
||||||
extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
|
extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
/* saa7164-encoder.c */
|
/* saa7164-encoder.c */
|
||||||
int saa7164_encoder_register(struct saa7164_port *port);
|
int saa7164_encoder_register(struct saa7164_port *port);
|
||||||
|
Reference in New Issue
Block a user