diff options
Diffstat (limited to 'drivers')
| -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 3afe879d54d7..5448ad1ea248 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 | ||
