aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7164/saa7164-core.c
diff options
context:
space:
mode:
authorSteven Toth <stoth@kernellabs.com>2010-07-31 14:49:28 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:54:59 -0400
commitcfbaf33733b99d214d5616dcb48a690630c19d65 (patch)
treecc5c1f8e94e6ed2773d02b4224462baf61f44771 /drivers/media/video/saa7164/saa7164-core.c
parentb31f1222990c02bccb73805648493b5e132a52f9 (diff)
[media] saa7164: irqhandler cleanup and helper function added
Signed-off-by: Steven Toth <stoth@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7164/saa7164-core.c')
-rw-r--r--drivers/media/video/saa7164/saa7164-core.c252
1 files changed, 78 insertions, 174 deletions
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index 09f7a64f538b..eb9c3459bb10 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -239,54 +239,15 @@ static void saa7164_histogram_print(struct saa7164_port *port,
239 printk(KERN_ERR "Total: %d\n", entries); 239 printk(KERN_ERR "Total: %d\n", entries);
240} 240}
241 241
242static void saa7164_work_enchandler(struct work_struct *w) 242static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
243{ 243{
244 struct saa7164_port *port =
245 container_of(w, struct saa7164_port, workenc);
246 struct saa7164_dev *dev = port->dev; 244 struct saa7164_dev *dev = port->dev;
247 struct saa7164_buffer *buf; 245 struct saa7164_buffer *buf = 0;
248 struct saa7164_user_buffer *ubuf; 246 struct saa7164_user_buffer *ubuf = 0;
249 struct list_head *c, *n; 247 struct list_head *c, *n;
250 int wp, rp, i = 0; 248 int i = 0;
251 u32 crc, ok = 0;
252 u8 *p;
253
254 port->last_svc_msecs_diff = port->last_svc_msecs;
255 port->last_svc_msecs = jiffies_to_msecs(jiffies);
256 port->last_svc_wp = saa7164_readl(port->bufcounter);
257 port->last_svc_rp = port->last_irq_rp;
258 wp = port->last_svc_wp;
259 rp = port->last_svc_rp;
260
261
262 port->last_svc_msecs_diff = port->last_svc_msecs -
263 port->last_svc_msecs_diff;
264
265 saa7164_histogram_update(&port->svc_interval,
266 port->last_svc_msecs_diff);
267
268 port->last_irq_svc_msecs_diff = port->last_svc_msecs -
269 port->last_irq_msecs;
270
271 saa7164_histogram_update(&port->irq_svc_interval,
272 port->last_irq_svc_msecs_diff);
273
274 dprintk(DBGLVL_IRQ,
275 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
276 __func__,
277 port->last_svc_msecs_diff,
278 port->last_irq_svc_msecs_diff,
279 port->last_svc_wp,
280 port->last_svc_rp
281 );
282
283 if ((rp < 0) || (rp > 7)) {
284 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
285 return;
286 }
287 249
288 mutex_lock(&port->dmaqueue_lock); 250 mutex_lock(&port->dmaqueue_lock);
289
290 list_for_each_safe(c, n, &port->dmaqueue.list) { 251 list_for_each_safe(c, n, &port->dmaqueue.list) {
291 252
292 buf = list_entry(c, struct saa7164_buffer, list); 253 buf = list_entry(c, struct saa7164_buffer, list);
@@ -296,33 +257,10 @@ static void saa7164_work_enchandler(struct work_struct *w)
296 break; 257 break;
297 } 258 }
298 259
299 p = (u8 *)buf->cpu; 260 if (buf->idx == bufnr) {
300 if ( (*(p + buf->actual_size + 0) != 0xff) ||
301 (*(p + buf->actual_size + 1) != 0xff) ||
302 (*(p + buf->actual_size + 2) != 0xff) ||
303 (*(p + buf->actual_size + 3) != 0xff) ||
304 (*(p + buf->actual_size + 0x10) != 0xff) ||
305 (*(p + buf->actual_size + 0x11) != 0xff) ||
306 (*(p + buf->actual_size + 0x12) != 0xff) ||
307 (*(p + buf->actual_size + 0x13) != 0xff) )
308 {
309 printk(KERN_ERR "%s() buf %p failed guard check\n", __func__, buf);
310 saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
311 }
312
313 if (buf->idx == wp) {
314 /* Ignore this, it's being updated currently by the dma engine */
315 } else
316 if (buf->idx == rp) {
317
318 crc = crc32(0, buf->cpu, buf->actual_size);
319// if (crc != port->shadow_crc[rp])
320// printk(KERN_ERR "%s crc didn't match shadow was 0x%x now 0x%x\n",
321// __func__, port->shadow_crc[rp], crc);
322 261
323 /* Found the buffer, deal with it */ 262 /* Found the buffer, deal with it */
324 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d crc32: 0x%x\n", 263 dprintk(DBGLVL_IRQ, "%s() rp: %d\n", __func__, bufnr);
325 __func__, wp, rp, buf->crc);
326 264
327 /* Validate the incoming buffer content */ 265 /* Validate the incoming buffer content */
328 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) 266 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
@@ -339,17 +277,12 @@ static void saa7164_work_enchandler(struct work_struct *w)
339 277
340 if (buf->actual_size <= ubuf->actual_size) { 278 if (buf->actual_size <= ubuf->actual_size) {
341 279
342 memcpy_fromio(ubuf->data, port->shadow_buf[rp], 280 memcpy_fromio(ubuf->data, buf->cpu,
343 ubuf->actual_size); 281 ubuf->actual_size);
344 282
345 /* Throw a new checksum on the read buffer */ 283 /* Throw a new checksum on the read buffer */
346 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size); 284 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
347 285
348 if ((crc == port->shadow_crc[rp]) && (crc == ubuf->crc))
349 ok = 1;
350 else
351 ok = 0;
352
353 /* Requeue the buffer on the free list */ 286 /* Requeue the buffer on the free list */
354 ubuf->pos = 0; 287 ubuf->pos = 0;
355 288
@@ -369,26 +302,81 @@ static void saa7164_work_enchandler(struct work_struct *w)
369 /* Ensure offset into buffer remains 0, fill buffer 302 /* Ensure offset into buffer remains 0, fill buffer
370 * with known bad data. We check for this data at a later point 303 * with known bad data. We check for this data at a later point
371 * in time. */ 304 * in time. */
372 saa7164_buffer_zero_offsets(port, rp); 305 saa7164_buffer_zero_offsets(port, bufnr);
373 memset_io(buf->cpu, 0xff, buf->pci_size); 306 memset_io(buf->cpu, 0xff, buf->pci_size);
374 buf->crc = crc32(0, buf->cpu, buf->actual_size);
375 307
376 break; 308 break;
377 } else { 309 }
378 /* Validate all other checksums, on previous buffers - they should never change */ 310 }
379 crc = crc32(0, buf->cpu, buf->actual_size); 311 mutex_unlock(&port->dmaqueue_lock);
380 if (crc != buf->crc) { 312}
381 printk(KERN_ERR "buf[%d].crc became invalid, was 0x%x became 0x%x rp: %d wp: %d\n", 313
382 buf->idx, buf->crc, crc, rp, wp); 314static void saa7164_work_enchandler(struct work_struct *w)
383 //saa7164_dumphex16FF(dev, (u8 *)buf->cpu, buf->actual_size); 315{
384 saa7164_dumphex16FF(dev, (u8 *)buf->cpu, 256); 316 struct saa7164_port *port =
385 buf->crc = crc; 317 container_of(w, struct saa7164_port, workenc);
386 } 318 struct saa7164_dev *dev = port->dev;
319
320 u32 wp, mcb, rp, cnt = 0;
387 321
322 port->last_svc_msecs_diff = port->last_svc_msecs;
323 port->last_svc_msecs = jiffies_to_msecs(jiffies);
324
325 port->last_svc_msecs_diff = port->last_svc_msecs -
326 port->last_svc_msecs_diff;
327
328 saa7164_histogram_update(&port->svc_interval,
329 port->last_svc_msecs_diff);
330
331 port->last_irq_svc_msecs_diff = port->last_svc_msecs -
332 port->last_irq_msecs;
333
334 saa7164_histogram_update(&port->irq_svc_interval,
335 port->last_irq_svc_msecs_diff);
336
337 dprintk(DBGLVL_IRQ,
338 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
339 __func__,
340 port->last_svc_msecs_diff,
341 port->last_irq_svc_msecs_diff,
342 port->last_svc_wp,
343 port->last_svc_rp
344 );
345
346 /* Current write position */
347 wp = saa7164_readl(port->bufcounter);
348 if (wp > (port->hwcfg.buffercount - 1)) {
349 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
350 return;
351 }
352
353 /* Most current complete buffer */
354 if (wp == 0)
355 mcb = 7;
356 else
357 mcb = wp - 1;
358
359 while (1) {
360 rp = (port->last_svc_rp + 1) % 8;
361
362 if ((rp < 0) || (rp > 7)) {
363 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
364 break;
388 } 365 }
389 366
367 /* Process a buffer */
368 if (port->nr == SAA7164_PORT_ENC1)
369 printk(KERN_ERR "Port enc1 processing buffer %d\n", rp);
370 saa7164_work_enchandler_helper(port, rp);
371 port->last_svc_rp = rp;
372 cnt++;
373
374 if (rp == mcb)
375 break;
390 } 376 }
391 mutex_unlock(&port->dmaqueue_lock); 377
378 if (port->nr == SAA7164_PORT_ENC1)
379 printk(KERN_ERR "Enc1 processed %d buffers for port %p\n", cnt, port);
392 380
393 if (print_histogram == port->nr) { 381 if (print_histogram == port->nr) {
394 saa7164_histogram_print(port, &port->irq_interval); 382 saa7164_histogram_print(port, &port->irq_interval);
@@ -399,6 +387,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
399 print_histogram = 64 + port->nr; 387 print_histogram = 64 + port->nr;
400 } 388 }
401} 389}
390
402static void saa7164_work_cmdhandler(struct work_struct *w) 391static void saa7164_work_cmdhandler(struct work_struct *w)
403{ 392{
404 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd); 393 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
@@ -420,49 +409,12 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
420static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port) 409static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
421{ 410{
422 struct saa7164_dev *dev = port->dev; 411 struct saa7164_dev *dev = port->dev;
423 struct saa7164_buffer *buf;
424 struct list_head *c, *n;
425 int wp, rp, i = 0;
426 u8 *p;
427 u32 *up, j;
428
429 /* Find the current write point from the hardware */
430 wp = saa7164_readl(port->bufcounter);
431 if (wp > (port->hwcfg.buffercount - 1)) {
432 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
433 return 0;
434 }
435
436 printk(KERN_ERR "port %p wp = %d\n", port, wp);
437
438 /* Find the previous buffer to the current write point */
439 if (wp == 0)
440 rp = 7;
441 else
442 rp = wp - 1;
443
444 if ((rp < 0) || (rp > 7)) {
445 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
446 return 0;
447 }
448
449 if (rp == port->last_irq_rp) {
450 printk(KERN_ERR "%s() Duplicate rp = %d port %p\n",
451 __func__, rp, port);
452 }
453
454 if (rp != ((port->last_irq_rp + 1) % 8)) {
455 printk(KERN_ERR "%s() Multiple bufs on interrupt, port %p\n",
456 __func__, port);
457 }
458 412
459 /* Store old time */ 413 /* Store old time */
460 port->last_irq_msecs_diff = port->last_irq_msecs; 414 port->last_irq_msecs_diff = port->last_irq_msecs;
461 415
462 /* Collect new stats */ 416 /* Collect new stats */
463 port->last_irq_msecs = jiffies_to_msecs(jiffies); 417 port->last_irq_msecs = jiffies_to_msecs(jiffies);
464 port->last_irq_wp = wp;
465 port->last_irq_rp = rp;
466 418
467 /* Calculate stats */ 419 /* Calculate stats */
468 port->last_irq_msecs_diff = port->last_irq_msecs - 420 port->last_irq_msecs_diff = port->last_irq_msecs -
@@ -471,58 +423,10 @@ static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
471 saa7164_histogram_update(&port->irq_interval, 423 saa7164_histogram_update(&port->irq_interval,
472 port->last_irq_msecs_diff); 424 port->last_irq_msecs_diff);
473 425
474 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed wp: %d rp: %d\n", 426 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
475 __func__, 427 port->last_irq_msecs_diff);
476 port->last_irq_msecs_diff,
477 port->last_irq_wp,
478 port->last_irq_rp
479 );
480 /* Find the used buffer, shadow copy it before we've
481 * acked the interrupt.
482 */
483// mutex_lock(&port->dmaqueue_lock);
484 list_for_each_safe(c, n, &port->dmaqueue.list) {
485
486 buf = list_entry(c, struct saa7164_buffer, list);
487 if (i++ > port->hwcfg.buffercount) {
488 printk(KERN_ERR "%s() illegal i count %d\n",
489 __func__, i);
490 break;
491 }
492
493 p = (u8 *)buf->cpu;
494 if ( (*(p + buf->actual_size + 0) != 0xff) ||
495 (*(p + buf->actual_size + 1) != 0xff) ||
496 (*(p + buf->actual_size + 2) != 0xff) ||
497 (*(p + buf->actual_size + 3) != 0xff) ||
498 (*(p + buf->actual_size + 0x10) != 0xff) ||
499 (*(p + buf->actual_size + 0x11) != 0xff) ||
500 (*(p + buf->actual_size + 0x12) != 0xff) ||
501 (*(p + buf->actual_size + 0x13) != 0xff) )
502 {
503 printk(KERN_ERR "buf %p failed guard check\n", buf);
504 saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
505 }
506
507 if (buf->idx == rp) {
508 up = (u32 *)port->shadow_buf[rp];
509 for (j = 0 ; j < (buf->actual_size / sizeof(u32)); j++) {
510 *(up + j) = (rp << 28) | port->counter++;
511 }
512 port->shadow_crc[rp] = crc32(0, port->shadow_buf[rp], buf->actual_size);
513
514 buf->crc = crc32(0, buf->cpu, buf->actual_size);
515
516// if (port->shadow_crc[rp] != buf->crc)
517// printk(KERN_ERR "%s() crc check failed 0x%x vs 0x%x\n",
518// __func__, port->shadow_crc[rp], buf->crc);
519 break;
520 }
521 428
522 }
523// mutex_unlock(&port->dmaqueue_lock);
524 schedule_work(&port->workenc); 429 schedule_work(&port->workenc);
525
526 return 0; 430 return 0;
527} 431}
528 432