diff options
author | Steven Toth <stoth@kernellabs.com> | 2010-07-31 14:49:28 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 05:54:59 -0400 |
commit | cfbaf33733b99d214d5616dcb48a690630c19d65 (patch) | |
tree | cc5c1f8e94e6ed2773d02b4224462baf61f44771 /drivers/media/video/saa7164/saa7164-core.c | |
parent | b31f1222990c02bccb73805648493b5e132a52f9 (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.c | 252 |
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 | ||
242 | static void saa7164_work_enchandler(struct work_struct *w) | 242 | static 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); | 314 | static 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 | |||
402 | static void saa7164_work_cmdhandler(struct work_struct *w) | 391 | static 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) | |||
420 | static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port) | 409 | static 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 | ||