diff options
author | Steven Toth <stoth@kernellabs.com> | 2010-07-31 14:13:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 05:54:54 -0400 |
commit | 12d3203e39db306f56611b3f47ba425ca6a409f9 (patch) | |
tree | 3e7eba22186a7015be6529abd2c3ee3659b0b77c | |
parent | 46eeb8dd30d3651e6ea55c2e60594206cd591d79 (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.c | 7 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164-bus.c | 46 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164-core.c | 157 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164-encoder.c | 9 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164.h | 12 |
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 | ||
75 | void 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 | |||
75 | static void saa7164_ts_verifier(struct saa7164_buffer *buf) | 97 | static 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 | |||
336 | static void saa7164_work_cmdhandler(struct work_struct *w) | 393 | static 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) | |||
354 | static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port) | 411 | static 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 | */ |
694 | static void saa7164_get_descriptors(struct saa7164_dev *dev) | 796 | static 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) | |||
742 | static int saa7164_port_init(struct saa7164_dev *dev, int portnr) | 844 | static 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) | |||
1057 | static void __devexit saa7164_finidev(struct pci_dev *pci_dev) | 1172 | static 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 | ||
199 | struct saa7164_fw_status { | 202 | struct 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 | ||
391 | struct saa7164_dev { | 398 | struct saa7164_dev { |
@@ -536,7 +543,6 @@ extern struct saa7164_user_buffer *saa7164_buffer_alloc_user( | |||
536 | extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf); | 543 | extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf); |
537 | extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i); | 544 | extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i); |
538 | 545 | ||
539 | |||
540 | /* ----------------------------------------------------------- */ | 546 | /* ----------------------------------------------------------- */ |
541 | /* saa7164-encoder.c */ | 547 | /* saa7164-encoder.c */ |
542 | int saa7164_encoder_register(struct saa7164_port *port); | 548 | int saa7164_encoder_register(struct saa7164_port *port); |