Commit 9a7bc6b0 authored by Pawel Osciak's avatar Pawel Osciak Committed by Mauro Carvalho Chehab

[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: default avatarPawel Osciak <posciak@chromium.org>
Signed-off-by: default avatarKiran AVND <avnd.kiran@samsung.com>
Signed-off-by: default avatarArun Kumar K <arun.kk@samsung.com>
Signed-off-by: default avatarKamil Debski <k.debski@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 5932f74a
...@@ -342,8 +342,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, ...@@ -342,8 +342,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
ctx->state = MFCINST_RES_CHANGE_INIT; ctx->state = MFCINST_RES_CHANGE_INIT;
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err); wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
return; return;
...@@ -415,8 +414,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, ...@@ -415,8 +414,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
clear_work_bit(ctx); clear_work_bit(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err); wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
/* if suspending, wake up device and do not try_run again*/ /* if suspending, wake up device and do not try_run again*/
if (test_bit(0, &dev->enter_suspend)) if (test_bit(0, &dev->enter_suspend))
...@@ -463,8 +461,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, ...@@ -463,8 +461,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
break; break;
} }
} }
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
s5p_mfc_clock_off(); s5p_mfc_clock_off();
wake_up_dev(dev, reason, err); wake_up_dev(dev, reason, err);
...@@ -518,8 +515,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, ...@@ -518,8 +515,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
} }
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
clear_work_bit(ctx); clear_work_bit(ctx);
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
wake_up_ctx(ctx, reason, err); wake_up_ctx(ctx, reason, err);
...@@ -557,16 +553,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, ...@@ -557,16 +553,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
} else { } else {
ctx->dpb_flush_flag = 0; ctx->dpb_flush_flag = 0;
} }
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
wake_up(&ctx->queue); wake_up(&ctx->queue);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
} else { } else {
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
...@@ -643,8 +637,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) ...@@ -643,8 +637,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
mfc_err("post_frame_start() failed\n"); mfc_err("post_frame_start() failed\n");
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err); wake_up_ctx(ctx, reason, err);
if (test_and_clear_bit(0, &dev->hw_lock) == 0) WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
BUG();
s5p_mfc_clock_off(); s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment