diff options
Diffstat (limited to 'drivers/media/platform/s5p-mfc/s5p_mfc.c')
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc.c | 88 |
1 files changed, 37 insertions, 51 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 379f57433711..681bc6ba149d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -412,62 +412,48 @@ leave_handle_frame: | |||
412 | } | 412 | } |
413 | 413 | ||
414 | /* Error handling for interrupt */ | 414 | /* Error handling for interrupt */ |
415 | static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, | 415 | static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, |
416 | unsigned int reason, unsigned int err) | 416 | struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) |
417 | { | 417 | { |
418 | struct s5p_mfc_dev *dev; | ||
419 | unsigned long flags; | 418 | unsigned long flags; |
420 | 419 | ||
421 | /* If no context is available then all necessary | ||
422 | * processing has been done. */ | ||
423 | if (ctx == NULL) | ||
424 | return; | ||
425 | |||
426 | dev = ctx->dev; | ||
427 | mfc_err("Interrupt Error: %08x\n", err); | 420 | mfc_err("Interrupt Error: %08x\n", err); |
428 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
429 | wake_up_dev(dev, reason, err); | ||
430 | 421 | ||
431 | /* Error recovery is dependent on the state of context */ | 422 | if (ctx != NULL) { |
432 | switch (ctx->state) { | 423 | /* Error recovery is dependent on the state of context */ |
433 | case MFCINST_INIT: | 424 | switch (ctx->state) { |
434 | /* This error had to happen while acquireing instance */ | 425 | case MFCINST_RES_CHANGE_INIT: |
435 | case MFCINST_GOT_INST: | 426 | case MFCINST_RES_CHANGE_FLUSH: |
436 | /* This error had to happen while parsing the header */ | 427 | case MFCINST_RES_CHANGE_END: |
437 | case MFCINST_HEAD_PARSED: | 428 | case MFCINST_FINISHING: |
438 | /* This error had to happen while setting dst buffers */ | 429 | case MFCINST_FINISHED: |
439 | case MFCINST_RETURN_INST: | 430 | case MFCINST_RUNNING: |
440 | /* This error had to happen while releasing instance */ | 431 | /* It is higly probable that an error occured |
441 | clear_work_bit(ctx); | 432 | * while decoding a frame */ |
442 | wake_up_ctx(ctx, reason, err); | 433 | clear_work_bit(ctx); |
443 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 434 | ctx->state = MFCINST_ERROR; |
444 | BUG(); | 435 | /* Mark all dst buffers as having an error */ |
445 | s5p_mfc_clock_off(); | 436 | spin_lock_irqsave(&dev->irqlock, flags); |
446 | ctx->state = MFCINST_ERROR; | 437 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
447 | break; | 438 | &ctx->dst_queue, &ctx->vq_dst); |
448 | case MFCINST_FINISHING: | 439 | /* Mark all src buffers as having an error */ |
449 | case MFCINST_FINISHED: | 440 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
450 | case MFCINST_RUNNING: | 441 | &ctx->src_queue, &ctx->vq_src); |
451 | /* It is higly probable that an error occured | 442 | spin_unlock_irqrestore(&dev->irqlock, flags); |
452 | * while decoding a frame */ | 443 | wake_up_ctx(ctx, reason, err); |
453 | clear_work_bit(ctx); | 444 | break; |
454 | ctx->state = MFCINST_ERROR; | 445 | default: |
455 | /* Mark all dst buffers as having an error */ | 446 | clear_work_bit(ctx); |
456 | spin_lock_irqsave(&dev->irqlock, flags); | 447 | ctx->state = MFCINST_ERROR; |
457 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, | 448 | wake_up_ctx(ctx, reason, err); |
458 | &ctx->vq_dst); | 449 | break; |
459 | /* Mark all src buffers as having an error */ | 450 | } |
460 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, | ||
461 | &ctx->vq_src); | ||
462 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
463 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
464 | BUG(); | ||
465 | s5p_mfc_clock_off(); | ||
466 | break; | ||
467 | default: | ||
468 | mfc_err("Encountered an error interrupt which had not been handled\n"); | ||
469 | break; | ||
470 | } | 451 | } |
452 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
453 | BUG(); | ||
454 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
455 | s5p_mfc_clock_off(); | ||
456 | wake_up_dev(dev, reason, err); | ||
471 | return; | 457 | return; |
472 | } | 458 | } |
473 | 459 | ||
@@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) | |||
632 | dev->warn_start) | 618 | dev->warn_start) |
633 | s5p_mfc_handle_frame(ctx, reason, err); | 619 | s5p_mfc_handle_frame(ctx, reason, err); |
634 | else | 620 | else |
635 | s5p_mfc_handle_error(ctx, reason, err); | 621 | s5p_mfc_handle_error(dev, ctx, reason, err); |
636 | clear_bit(0, &dev->enter_suspend); | 622 | clear_bit(0, &dev->enter_suspend); |
637 | break; | 623 | break; |
638 | 624 | ||