aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Toth <stoth@kernellabs.com>2010-07-31 14:13:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:54:54 -0400
commit12d3203e39db306f56611b3f47ba425ca6a409f9 (patch)
tree3e7eba22186a7015be6529abd2c3ee3659b0b77c
parent46eeb8dd30d3651e6ea55c2e60594206cd591d79 (diff)
[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>
-rw-r--r--drivers/media/video/saa7164/saa7164-buffer.c7
-rw-r--r--drivers/media/video/saa7164/saa7164-bus.c46
-rw-r--r--drivers/media/video/saa7164/saa7164-core.c157
-rw-r--r--drivers/media/video/saa7164/saa7164-encoder.c9
-rw-r--r--drivers/media/video/saa7164/saa7164.h12
5 files changed, 191 insertions, 40 deletions
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
index 0760891d5fa8..b75157d411dd 100644
--- a/drivers/media/video/saa7164/saa7164-buffer.c
+++ b/drivers/media/video/saa7164/saa7164-buffer.c
@@ -113,6 +113,7 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
113 buf->flags = SAA7164_BUFFER_FREE; 113 buf->flags = SAA7164_BUFFER_FREE;
114 buf->pos = 0; 114 buf->pos = 0;
115 buf->actual_size = params->pitch * params->numberoflines; 115 buf->actual_size = params->pitch * params->numberoflines;
116 buf->crc = 0;
116 /* TODO: arg len is being ignored */ 117 /* TODO: arg len is being ignored */
117 buf->pci_size = SAA7164_PT_ENTRIES * 0x1000; 118 buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
118 buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000; 119 buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
@@ -129,8 +130,9 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
129 goto fail2; 130 goto fail2;
130 131
131 /* init the buffers to a known pattern, easier during debugging */ 132 /* init the buffers to a known pattern, easier during debugging */
132 memset(buf->cpu, 0xff, buf->pci_size); 133 memset_io(buf->cpu, 0xff, buf->pci_size);
133 memset(buf->pt_cpu, 0xff, buf->pt_size); 134 buf->crc = crc32(0, buf->cpu, buf->actual_size);
135 memset_io(buf->pt_cpu, 0xff, buf->pt_size);
134 136
135 dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n", 137 dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n",
136 __func__, buf); 138 __func__, buf);
@@ -296,6 +298,7 @@ struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u
296 298
297 buf->actual_size = len; 299 buf->actual_size = len;
298 buf->pos = 0; 300 buf->pos = 0;
301 buf->crc = 0;
299 302
300 dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n", 303 dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n",
301 __func__, buf); 304 __func__, buf);
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
index 49414c814859..ccc61007f33a 100644
--- a/drivers/media/video/saa7164/saa7164-bus.c
+++ b/drivers/media/video/saa7164/saa7164-bus.c
@@ -217,28 +217,28 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
217 dprintk(DBGLVL_BUS, "%s() tr4\n", __func__); 217 dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
218 218
219 /* Split the msg into pieces as the ring wraps */ 219 /* Split the msg into pieces as the ring wraps */
220 memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem); 220 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
221 memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem, 221 memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
222 sizeof(*msg) - space_rem); 222 sizeof(*msg) - space_rem);
223 223
224 memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem, 224 memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
225 buf, msg->size); 225 buf, msg->size);
226 226
227 } else if (space_rem == sizeof(*msg)) { 227 } else if (space_rem == sizeof(*msg)) {
228 dprintk(DBGLVL_BUS, "%s() tr5\n", __func__); 228 dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
229 229
230 /* Additional data at the beginning of the ring */ 230 /* Additional data at the beginning of the ring */
231 memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 231 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
232 memcpy(bus->m_pdwSetRing, buf, msg->size); 232 memcpy_toio(bus->m_pdwSetRing, buf, msg->size);
233 233
234 } else { 234 } else {
235 /* Additional data wraps around the ring */ 235 /* Additional data wraps around the ring */
236 memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 236 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
237 if (msg->size > 0) { 237 if (msg->size > 0) {
238 memcpy(bus->m_pdwSetRing + curr_swp + 238 memcpy_toio(bus->m_pdwSetRing + curr_swp +
239 sizeof(*msg), buf, space_rem - 239 sizeof(*msg), buf, space_rem -
240 sizeof(*msg)); 240 sizeof(*msg));
241 memcpy(bus->m_pdwSetRing, (u8 *)buf + 241 memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
242 space_rem - sizeof(*msg), 242 space_rem - sizeof(*msg),
243 bytes_to_write - space_rem); 243 bytes_to_write - space_rem);
244 } 244 }
@@ -250,8 +250,8 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
250 dprintk(DBGLVL_BUS, "%s() tr6\n", __func__); 250 dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
251 251
252 /* The ring buffer doesn't wrap, two simple copies */ 252 /* The ring buffer doesn't wrap, two simple copies */
253 memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 253 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
254 memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf, 254 memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
255 msg->size); 255 msg->size);
256 } 256 }
257 257
@@ -343,19 +343,19 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
343 new_grp -= bus->m_dwSizeGetRing; 343 new_grp -= bus->m_dwSizeGetRing;
344 space_rem = bus->m_dwSizeGetRing - curr_grp; 344 space_rem = bus->m_dwSizeGetRing - curr_grp;
345 345
346 memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem); 346 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
347 memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing, 347 memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
348 bytes_to_read - space_rem); 348 bytes_to_read - space_rem);
349 349
350 } else { 350 } else {
351 /* No wrapping */ 351 /* No wrapping */
352 memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read); 352 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
353 } 353 }
354 354
355 /* No need to update the read positions, because this was a peek */ 355 /* No need to update the read positions, because this was a peek */
356 /* If the caller specifically want to peek, return */ 356 /* If the caller specifically want to peek, return */
357 if (peekonly) { 357 if (peekonly) {
358 memcpy(msg, &msg_tmp, sizeof(*msg)); 358 memcpy_fromio(msg, &msg_tmp, sizeof(*msg));
359 goto peekout; 359 goto peekout;
360 } 360 }
361 361
@@ -401,24 +401,24 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
401 401
402 if (space_rem < sizeof(*msg)) { 402 if (space_rem < sizeof(*msg)) {
403 /* msg wraps around the ring */ 403 /* msg wraps around the ring */
404 memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem); 404 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem);
405 memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing, 405 memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing,
406 sizeof(*msg) - space_rem); 406 sizeof(*msg) - space_rem);
407 if (buf) 407 if (buf)
408 memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) - 408 memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
409 space_rem, buf_size); 409 space_rem, buf_size);
410 410
411 } else if (space_rem == sizeof(*msg)) { 411 } else if (space_rem == sizeof(*msg)) {
412 memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 412 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
413 if (buf) 413 if (buf)
414 memcpy(buf, bus->m_pdwGetRing, buf_size); 414 memcpy(buf, bus->m_pdwGetRing, buf_size);
415 } else { 415 } else {
416 /* Additional data wraps around the ring */ 416 /* Additional data wraps around the ring */
417 memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 417 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
418 if (buf) { 418 if (buf) {
419 memcpy(buf, bus->m_pdwGetRing + curr_grp + 419 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
420 sizeof(*msg), space_rem - sizeof(*msg)); 420 sizeof(*msg), space_rem - sizeof(*msg));
421 memcpy(buf + space_rem - sizeof(*msg), 421 memcpy_fromio(buf + space_rem - sizeof(*msg),
422 bus->m_pdwGetRing, bytes_to_read - 422 bus->m_pdwGetRing, bytes_to_read -
423 space_rem); 423 space_rem);
424 } 424 }
@@ -427,9 +427,9 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
427 427
428 } else { 428 } else {
429 /* No wrapping */ 429 /* No wrapping */
430 memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 430 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
431 if (buf) 431 if (buf)
432 memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), 432 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
433 buf_size); 433 buf_size);
434 } 434 }
435 435
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index e96bbe4698b9..79e1a2ee7e9e 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -72,6 +72,28 @@ LIST_HEAD(saa7164_devlist);
72 72
73#define INT_SIZE 16 73#define INT_SIZE 16
74 74
75void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len)
76{
77 int i;
78 u8 tmp[16];
79 memset(&tmp[0], 0xff, sizeof(tmp));
80
81 printk(KERN_INFO "--------------------> "
82 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
83
84 for (i = 0; i < len; i += 16) {
85 if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) {
86 printk(KERN_INFO " [0x%08x] "
87 "%02x %02x %02x %02x %02x %02x %02x %02x "
88 "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
89 *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
90 *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
91 *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
92 *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
93 }
94 }
95}
96
75static void saa7164_ts_verifier(struct saa7164_buffer *buf) 97static void saa7164_ts_verifier(struct saa7164_buffer *buf)
76{ 98{
77 struct saa7164_port *port = buf->port; 99 struct saa7164_port *port = buf->port;
@@ -216,6 +238,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
216 struct saa7164_user_buffer *ubuf; 238 struct saa7164_user_buffer *ubuf;
217 struct list_head *c, *n; 239 struct list_head *c, *n;
218 int wp, rp, i = 0; 240 int wp, rp, i = 0;
241 u32 crc, ok = 0;
219 u8 *p; 242 u8 *p;
220 243
221 port->last_svc_msecs_diff = port->last_svc_msecs; 244 port->last_svc_msecs_diff = port->last_svc_msecs;
@@ -277,10 +300,19 @@ static void saa7164_work_enchandler(struct work_struct *w)
277 saa7164_dumphex16(dev, p + buf->actual_size - 32, 64); 300 saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
278 } 301 }
279 302
303 if (buf->idx == wp) {
304 /* Ignore this, it's being updated currently by the dma engine */
305 } else
280 if (buf->idx == rp) { 306 if (buf->idx == rp) {
307
308 crc = crc32(0, buf->cpu, buf->actual_size);
309 if (crc != port->shadow_crc[rp])
310 printk(KERN_ERR "%s crc didn't match shadow was 0x%x now 0x%x\n",
311 __func__, port->shadow_crc[rp], crc);
312
281 /* Found the buffer, deal with it */ 313 /* Found the buffer, deal with it */
282 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n", 314 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d crc32: 0x%x\n",
283 __func__, wp, rp); 315 __func__, wp, rp, buf->crc);
284 316
285 /* Validate the incoming buffer content */ 317 /* Validate the incoming buffer content */
286 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) 318 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)
293 ubuf = list_first_entry(&port->list_buf_free.list, 325 ubuf = list_first_entry(&port->list_buf_free.list,
294 struct saa7164_user_buffer, list); 326 struct saa7164_user_buffer, list);
295 327
296 if (ubuf->actual_size == buf->actual_size) { 328 if (ubuf->actual_size >= buf->actual_size) {
297 memcpy(ubuf->data, buf->cpu, 329 memcpy(ubuf->data, port->shadow_buf[rp], 312 * 188);
298 ubuf->actual_size); 330
331 /* Throw a new checksum on the read buffer */
332 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
333
334 if ((crc == port->shadow_crc[rp]) && (crc == ubuf->crc))
335 ok = 1;
336 else
337 ok = 0;
338
339 if (ok == 0)
340 printk(KERN_ERR
341 "rp: %d dmacrc: 0x%08x shadcrc: 0x%08x ubufcrc: 0x%08x %s\n",
342 rp, buf->crc, port->shadow_crc[rp], ubuf->crc,
343 ok ? "crcgood" : "crcbad");
344
299 } else { 345 } else {
300 printk(KERN_ERR "buf %p actual fails match\n", buf); 346 printk(KERN_ERR "buf %p actual fails match\n", buf);
301 } 347 }
@@ -315,9 +361,21 @@ static void saa7164_work_enchandler(struct work_struct *w)
315 /* Ensure offset into buffer remains 0, fill buffer 361 /* Ensure offset into buffer remains 0, fill buffer
316 * with known bad data. */ 362 * with known bad data. */
317 saa7164_buffer_zero_offsets(port, rp); 363 saa7164_buffer_zero_offsets(port, rp);
318 memset(buf->cpu, 0xff, buf->pci_size); 364 memset_io(buf->cpu, 0xff, buf->pci_size);
365 buf->crc = crc32(0, buf->cpu, buf->actual_size);
366
367// break;
368 } else {
369 /* Validate all other checksums, on previous buffers - they should never change */
370 crc = crc32(0, buf->cpu, buf->actual_size);
371 if (crc != buf->crc) {
372 printk(KERN_ERR "buf[%d].crc became invalid, was 0x%x became 0x%x rp: %d wp: %d\n",
373 buf->idx, buf->crc, crc, rp, wp);
374 //saa7164_dumphex16FF(dev, (u8 *)buf->cpu, buf->actual_size);
375 saa7164_dumphex16FF(dev, (u8 *)buf->cpu, 256);
376 buf->crc = crc;
377 }
319 378
320 break;
321 } 379 }
322 380
323 } 381 }
@@ -332,7 +390,6 @@ static void saa7164_work_enchandler(struct work_struct *w)
332 print_histogram = 64 + port->nr; 390 print_histogram = 64 + port->nr;
333 } 391 }
334} 392}
335
336static void saa7164_work_cmdhandler(struct work_struct *w) 393static void saa7164_work_cmdhandler(struct work_struct *w)
337{ 394{
338 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd); 395 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
@@ -354,7 +411,11 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
354static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port) 411static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
355{ 412{
356 struct saa7164_dev *dev = port->dev; 413 struct saa7164_dev *dev = port->dev;
357 int wp, rp; 414 struct saa7164_buffer *buf;
415 struct saa7164_user_buffer *ubuf;
416 struct list_head *c, *n;
417 int wp, rp, i = 0;
418 u8 *p;
358 419
359 /* Find the current write point from the hardware */ 420 /* Find the current write point from the hardware */
360 wp = saa7164_readl(port->bufcounter); 421 wp = saa7164_readl(port->bufcounter);
@@ -400,7 +461,48 @@ static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
400 port->last_irq_wp, 461 port->last_irq_wp,
401 port->last_irq_rp 462 port->last_irq_rp
402 ); 463 );
464 /* Find the used buffer, shadow copy it before we've
465 * acked the interrupt.
466 */
467// mutex_lock(&port->dmaqueue_lock);
468 list_for_each_safe(c, n, &port->dmaqueue.list) {
469
470 buf = list_entry(c, struct saa7164_buffer, list);
471 if (i++ > port->hwcfg.buffercount) {
472 printk(KERN_ERR "%s() illegal i count %d\n",
473 __func__, i);
474 break;
475 }
476
477 p = (u8 *)buf->cpu;
478 if ( (*(p + buf->actual_size + 0) != 0xff) ||
479 (*(p + buf->actual_size + 1) != 0xff) ||
480 (*(p + buf->actual_size + 2) != 0xff) ||
481 (*(p + buf->actual_size + 3) != 0xff) ||
482 (*(p + buf->actual_size + 0x10) != 0xff) ||
483 (*(p + buf->actual_size + 0x11) != 0xff) ||
484 (*(p + buf->actual_size + 0x12) != 0xff) ||
485 (*(p + buf->actual_size + 0x13) != 0xff) )
486 {
487 printk(KERN_ERR "buf %p failed guard check\n", buf);
488 saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
489 }
490
491 if (buf->idx == rp) {
492
493 memcpy_fromio(port->shadow_buf[rp], buf->cpu, 312 * 188);
494 port->shadow_crc[rp] = crc32(0, port->shadow_buf[rp], 312 * 188);
403 495
496 buf->crc = crc32(0, buf->cpu, 312 * 188);
497
498 if (port->shadow_crc[rp] != buf->crc)
499 printk(KERN_ERR "%s() crc check failed 0x%x vs 0x%x\n",
500 __func__, port->shadow_crc[rp], buf->crc);
501 break;
502 }
503
504 }
505// mutex_unlock(&port->dmaqueue_lock);
404 schedule_work(&port->workenc); 506 schedule_work(&port->workenc);
405 507
406 return 0; 508 return 0;
@@ -693,10 +795,10 @@ static void saa7164_dump_busdesc(struct saa7164_dev *dev)
693 */ 795 */
694static void saa7164_get_descriptors(struct saa7164_dev *dev) 796static void saa7164_get_descriptors(struct saa7164_dev *dev)
695{ 797{
696 memcpy(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t)); 798 memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t));
697 memcpy(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t), 799 memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t),
698 sizeof(tmComResInterfaceDescr_t)); 800 sizeof(tmComResInterfaceDescr_t));
699 memcpy(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation, 801 memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
700 sizeof(tmComResBusDescr_t)); 802 sizeof(tmComResBusDescr_t));
701 803
702 if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) { 804 if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) {
@@ -742,6 +844,7 @@ static int get_resources(struct saa7164_dev *dev)
742static int saa7164_port_init(struct saa7164_dev *dev, int portnr) 844static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
743{ 845{
744 struct saa7164_port *port = 0; 846 struct saa7164_port *port = 0;
847 int i;
745 848
746 if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS)) 849 if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
747 BUG(); 850 BUG();
@@ -780,6 +883,18 @@ static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
780 saa7164_histogram_reset(&port->poll_interval, 883 saa7164_histogram_reset(&port->poll_interval,
781 "encoder poll() intervals"); 884 "encoder poll() intervals");
782 885
886 if (port->type == SAA7164_MPEG_ENCODER) {
887 for (i = 0; i < 8; i ++) {
888 port->shadow_buf[i] = kzalloc(312 * 188, GFP_KERNEL);
889 if (port->shadow_buf[i] == 0)
890 printk(KERN_ERR "%s() shadow_buf ENOMEM\n", __func__);
891 else {
892 memset(port->shadow_buf[i], 0xff, 312 * 188);
893 port->shadow_crc[i] = crc32(0, port->shadow_buf[i], 312 * 188);
894 }
895 }
896 }
897
783 return 0; 898 return 0;
784} 899}
785 900
@@ -1057,6 +1172,8 @@ static void saa7164_shutdown(struct saa7164_dev *dev)
1057static void __devexit saa7164_finidev(struct pci_dev *pci_dev) 1172static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
1058{ 1173{
1059 struct saa7164_dev *dev = pci_get_drvdata(pci_dev); 1174 struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
1175 struct saa7164_port *port;
1176 int i;
1060 1177
1061 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ], 1178 saa7164_histogram_print(&dev->ports[ SAA7164_PORT_ENC1 ],
1062 &dev->ports[ SAA7164_PORT_ENC1 ].irq_interval); 1179 &dev->ports[ SAA7164_PORT_ENC1 ].irq_interval);
@@ -1071,6 +1188,22 @@ static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
1071 1188
1072 saa7164_shutdown(dev); 1189 saa7164_shutdown(dev);
1073 1190
1191 port = &dev->ports[ SAA7164_PORT_ENC1 ];
1192 if (port->type == SAA7164_MPEG_ENCODER) {
1193 for (i = 0; i < 8; i ++) {
1194 kfree(port->shadow_buf[i]);
1195 port->shadow_buf[i] = 0;
1196 }
1197 }
1198 port = &dev->ports[ SAA7164_PORT_ENC2 ];
1199 if (port->type == SAA7164_MPEG_ENCODER) {
1200 for (i = 0; i < 8; i ++) {
1201 kfree(port->shadow_buf[i]);
1202 port->shadow_buf[i] = 0;
1203 }
1204 }
1205
1206
1074 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) 1207 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
1075 saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]); 1208 saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]);
1076 1209
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c
index c61907d0efb9..f3ecdc93e20e 100644
--- a/drivers/media/video/saa7164/saa7164-encoder.c
+++ b/drivers/media/video/saa7164/saa7164-encoder.c
@@ -865,6 +865,7 @@ static int saa7164_encoder_start_streaming(struct saa7164_port *port)
865 865
866 /* Configure the encoder with any cache values */ 866 /* Configure the encoder with any cache values */
867 saa7164_api_set_encoder(port); 867 saa7164_api_set_encoder(port);
868 saa7164_api_get_encoder(port);
868 869
869 saa7164_buffer_cfg_port(port); 870 saa7164_buffer_cfg_port(port);
870 871
@@ -1006,11 +1007,19 @@ struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
1006{ 1007{
1007 struct saa7164_user_buffer *buf = 0; 1008 struct saa7164_user_buffer *buf = 0;
1008 struct saa7164_dev *dev = port->dev; 1009 struct saa7164_dev *dev = port->dev;
1010 u32 crc;
1009 1011
1010 mutex_lock(&port->dmaqueue_lock); 1012 mutex_lock(&port->dmaqueue_lock);
1011 if (!list_empty(&port->list_buf_used.list)) { 1013 if (!list_empty(&port->list_buf_used.list)) {
1012 buf = list_first_entry(&port->list_buf_used.list, 1014 buf = list_first_entry(&port->list_buf_used.list,
1013 struct saa7164_user_buffer, list); 1015 struct saa7164_user_buffer, list);
1016
1017 crc = crc32(0, buf->data, buf->actual_size);
1018 if (crc != buf->crc) {
1019 printk(KERN_ERR "%s() buf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
1020 buf, buf->crc, crc);
1021 }
1022
1014 } 1023 }
1015 mutex_unlock(&port->dmaqueue_lock); 1024 mutex_unlock(&port->dmaqueue_lock);
1016 1025
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
index 796d21df52b2..a8a29e56b2ce 100644
--- a/drivers/media/video/saa7164/saa7164.h
+++ b/drivers/media/video/saa7164/saa7164.h
@@ -50,6 +50,7 @@
50#include <linux/kdev_t.h> 50#include <linux/kdev_t.h>
51#include <linux/version.h> 51#include <linux/version.h>
52#include <linux/mutex.h> 52#include <linux/mutex.h>
53#include <linux/crc32.h>
53 54
54#include <media/tuner.h> 55#include <media/tuner.h>
55#include <media/tveeprom.h> 56#include <media/tveeprom.h>
@@ -194,6 +195,8 @@ struct saa7164_user_buffer {
194 u8 *data; 195 u8 *data;
195 u32 pos; 196 u32 pos;
196 u32 actual_size; 197 u32 actual_size;
198
199 u32 crc;
197}; 200};
198 201
199struct saa7164_fw_status { 202struct saa7164_fw_status {
@@ -282,12 +285,13 @@ struct saa7164_buffer {
282 285
283 /* A block of page align PCI memory */ 286 /* A block of page align PCI memory */
284 u32 pci_size; /* PCI allocation size in bytes */ 287 u32 pci_size; /* PCI allocation size in bytes */
285 u64 *cpu; /* Virtual address */ 288 u64 __iomem *cpu; /* Virtual address */
286 dma_addr_t dma; /* Physical address */ 289 dma_addr_t dma; /* Physical address */
290 u32 crc; /* Checksum for the entire buffer data */
287 291
288 /* A page table that splits the block into a number of entries */ 292 /* A page table that splits the block into a number of entries */
289 u32 pt_size; /* PCI allocation size in bytes */ 293 u32 pt_size; /* PCI allocation size in bytes */
290 u64 *pt_cpu; /* Virtual address */ 294 u64 __iomem *pt_cpu; /* Virtual address */
291 dma_addr_t pt_dma; /* Physical address */ 295 dma_addr_t pt_dma; /* Physical address */
292 296
293 /* Encoder fops */ 297 /* Encoder fops */
@@ -386,6 +390,9 @@ struct saa7164_port {
386 u32 a_cc_errors; 390 u32 a_cc_errors;
387 u8 last_v_cc; 391 u8 last_v_cc;
388 u8 last_a_cc; 392 u8 last_a_cc;
393
394 u8 *shadow_buf[8];
395 u32 shadow_crc[8];
389}; 396};
390 397
391struct saa7164_dev { 398struct saa7164_dev {
@@ -536,7 +543,6 @@ extern struct saa7164_user_buffer *saa7164_buffer_alloc_user(
536extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf); 543extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
537extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i); 544extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
538 545
539
540/* ----------------------------------------------------------- */ 546/* ----------------------------------------------------------- */
541/* saa7164-encoder.c */ 547/* saa7164-encoder.c */
542int saa7164_encoder_register(struct saa7164_port *port); 548int saa7164_encoder_register(struct saa7164_port *port);