aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Osciak <posciak@chromium.org>2014-10-21 07:07:01 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-10-28 13:50:33 -0400
commit9a7bc6b0c456bdc642269659fb13f29a8c13815b (patch)
tree6868dd6da411436b2ac64c312c1c6bdd54d2658f
parent5932f74a116cf14b69b9b3e23dcaf8698151976e (diff)
[media] s5p-mfc: Don't crash the kernel if the watchdog kicks in
If the software watchdog kicks in, the watchdog worker is not synchronized with hardware interrupts and does not block other instances. It's possible for it to clear the hw_lock, making other instances trigger a BUG() on hw_lock checks. Since it's not fatal to clear the hw_lock to zero twice, just WARN in those cases for now. We should not explode, as firmware will return errors as needed for other instances after it's reloaded, or they will time out. A clean fix should involve killing other instances when watchdog kicks in, but requires a major redesign of locking in the driver. Signed-off-by: Pawel Osciak <posciak@chromium.org> Signed-off-by: Kiran AVND <avnd.kiran@samsung.com> Signed-off-by: Arun Kumar K <arun.kk@samsung.com> Signed-off-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c21
1 files changed, 7 insertions, 14 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index eb710554cb2d..8620236200b7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -342,8 +342,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
342 ctx->state = MFCINST_RES_CHANGE_INIT; 342 ctx->state = MFCINST_RES_CHANGE_INIT;
343 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); 343 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
344 wake_up_ctx(ctx, reason, err); 344 wake_up_ctx(ctx, reason, err);
345 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 345 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
346 BUG();
347 s5p_mfc_clock_off(); 346 s5p_mfc_clock_off();
348 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); 347 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
349 return; 348 return;
@@ -415,8 +414,7 @@ leave_handle_frame:
415 clear_work_bit(ctx); 414 clear_work_bit(ctx);
416 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); 415 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
417 wake_up_ctx(ctx, reason, err); 416 wake_up_ctx(ctx, reason, err);
418 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 417 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
419 BUG();
420 s5p_mfc_clock_off(); 418 s5p_mfc_clock_off();
421 /* if suspending, wake up device and do not try_run again*/ 419 /* if suspending, wake up device and do not try_run again*/
422 if (test_bit(0, &dev->enter_suspend)) 420 if (test_bit(0, &dev->enter_suspend))
@@ -463,8 +461,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
463 break; 461 break;
464 } 462 }
465 } 463 }
466 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 464 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
467 BUG();
468 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); 465 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
469 s5p_mfc_clock_off(); 466 s5p_mfc_clock_off();
470 wake_up_dev(dev, reason, err); 467 wake_up_dev(dev, reason, err);
@@ -518,8 +515,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
518 } 515 }
519 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); 516 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
520 clear_work_bit(ctx); 517 clear_work_bit(ctx);
521 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 518 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
522 BUG();
523 s5p_mfc_clock_off(); 519 s5p_mfc_clock_off();
524 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); 520 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
525 wake_up_ctx(ctx, reason, err); 521 wake_up_ctx(ctx, reason, err);
@@ -557,16 +553,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
557 } else { 553 } else {
558 ctx->dpb_flush_flag = 0; 554 ctx->dpb_flush_flag = 0;
559 } 555 }
560 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 556 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
561 BUG();
562 557
563 s5p_mfc_clock_off(); 558 s5p_mfc_clock_off();
564 559
565 wake_up(&ctx->queue); 560 wake_up(&ctx->queue);
566 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); 561 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
567 } else { 562 } else {
568 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 563 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
569 BUG();
570 564
571 s5p_mfc_clock_off(); 565 s5p_mfc_clock_off();
572 566
@@ -643,8 +637,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
643 mfc_err("post_frame_start() failed\n"); 637 mfc_err("post_frame_start() failed\n");
644 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); 638 s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
645 wake_up_ctx(ctx, reason, err); 639 wake_up_ctx(ctx, reason, err);
646 if (test_and_clear_bit(0, &dev->hw_lock) == 0) 640 WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
647 BUG();
648 s5p_mfc_clock_off(); 641 s5p_mfc_clock_off();
649 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); 642 s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
650 } else { 643 } else {