cregit-Linux how code gets into the kernel

Release 4.13 drivers/media/platform/s5p-mfc/s5p_mfc.c

/*
 * Samsung S5P Multi Format Codec v 5.1
 *
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 * Kamil Debski, <k.debski@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/v4l2-event.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_reserved_mem.h>
#include <media/videobuf2-v4l2.h>
#include "s5p_mfc_common.h"
#include "s5p_mfc_ctrl.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_dec.h"
#include "s5p_mfc_enc.h"
#include "s5p_mfc_intr.h"
#include "s5p_mfc_iommu.h"
#include "s5p_mfc_opr.h"
#include "s5p_mfc_cmd.h"
#include "s5p_mfc_pm.h"


#define S5P_MFC_DEC_NAME	"s5p-mfc-dec"

#define S5P_MFC_ENC_NAME	"s5p-mfc-enc"


int mfc_debug_level;
module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");


static char *mfc_mem_size;
module_param_named(mem, mfc_mem_size, charp, 0644);
MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers");

/* Helper functions for interrupt processing */

/* Remove from hw execution round robin */

void clear_work_bit(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; spin_lock(&dev->condlock); __clear_bit(ctx->num, &dev->ctx_work_bits); spin_unlock(&dev->condlock); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski2655.32%150.00%
Andrzej Hajda2144.68%150.00%
Total47100.00%2100.00%

/* Add to hw execution round robin */
void set_work_bit(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; spin_lock(&dev->condlock); __set_bit(ctx->num, &dev->ctx_work_bits); spin_unlock(&dev->condlock); }

Contributors

PersonTokensPropCommitsCommitProp
Andrzej Hajda2757.45%150.00%
Kamil Debski2042.55%150.00%
Total47100.00%2100.00%

/* Remove from hw execution round robin */
void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; spin_lock_irqsave(&dev->condlock, flags); __clear_bit(ctx->num, &dev->ctx_work_bits); spin_unlock_irqrestore(&dev->condlock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Andrzej Hajda55100.00%1100.00%
Total55100.00%1100.00%

/* Add to hw execution round robin */
void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; spin_lock_irqsave(&dev->condlock, flags); __set_bit(ctx->num, &dev->ctx_work_bits); spin_unlock_irqrestore(&dev->condlock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Andrzej Hajda55100.00%1100.00%
Total55100.00%1100.00%


int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) { unsigned long flags; int ctx; spin_lock_irqsave(&dev->condlock, flags); ctx = dev->curr_ctx; do { ctx = (ctx + 1) % MFC_NUM_CONTEXTS; if (ctx == dev->curr_ctx) { if (!test_bit(ctx, &dev->ctx_work_bits)) ctx = -EAGAIN; break; } } while (!test_bit(ctx, &dev->ctx_work_bits)); spin_unlock_irqrestore(&dev->condlock, flags); return ctx; }

Contributors

PersonTokensPropCommitsCommitProp
Andrzej Hajda102100.00%1100.00%
Total102100.00%1100.00%

/* Wake up context wait_queue */
static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { ctx->int_cond = 1; ctx->int_type = reason; ctx->int_err = err; wake_up(&ctx->queue); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski45100.00%1100.00%
Total45100.00%1100.00%

/* Wake up device wait_queue */
static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason, unsigned int err) { dev->int_cond = 1; dev->int_type = reason; dev->int_err = err; wake_up(&dev->queue); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski45100.00%1100.00%
Total45100.00%1100.00%


void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq) { struct s5p_mfc_buf *b; int i; while (!list_empty(lh)) { b = list_entry(lh->next, struct s5p_mfc_buf, list); for (i = 0; i < b->b->vb2_buf.num_planes; i++) vb2_set_plane_payload(&b->b->vb2_buf, i, 0); vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR); list_del(&b->list); } }

Contributors

PersonTokensPropCommitsCommitProp
Andrzej Hajda100100.00%1100.00%
Total100100.00%1100.00%


static void s5p_mfc_watchdog(unsigned long arg) { struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg; if (test_bit(0, &dev->hw_lock)) atomic_inc(&dev->watchdog_cnt); if (atomic_read(&dev->watchdog_cnt) >= MFC_WATCHDOG_CNT) { /* This means that hw is busy and no interrupts were * generated by hw for the Nth time of running this * watchdog timer. This usually means a serious hw * error. Now it is time to kill all instances and * reset the MFC. */ mfc_err("Time out during waiting for HW\n"); schedule_work(&dev->watchdog_work); } dev->watchdog_timer.expires = jiffies + msecs_to_jiffies(MFC_WATCHDOG_INTERVAL); add_timer(&dev->watchdog_timer); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski8997.80%133.33%
Bhaktipriya Shridhar11.10%133.33%
Sachin Kamat11.10%133.33%
Total91100.00%3100.00%


static void s5p_mfc_watchdog_worker(struct work_struct *work) { struct s5p_mfc_dev *dev; struct s5p_mfc_ctx *ctx; unsigned long flags; int mutex_locked; int i, ret; dev = container_of(work, struct s5p_mfc_dev, watchdog_work); mfc_err("Driver timeout error handling\n"); /* Lock the mutex that protects open and release. * This is necessary as they may load and unload firmware. */ mutex_locked = mutex_trylock(&dev->mfc_mutex); if (!mutex_locked) mfc_err("Error: some instance may be closing/opening\n"); spin_lock_irqsave(&dev->irqlock, flags); s5p_mfc_clock_off(); for (i = 0; i < MFC_NUM_CONTEXTS; i++) { ctx = dev->ctx[i]; if (!ctx) continue; ctx->state = MFCINST_ERROR; s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); clear_work_bit(ctx); wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0); } clear_bit(0, &dev->hw_lock); spin_unlock_irqrestore(&dev->irqlock, flags); /* De-init MFC */ s5p_mfc_deinit_hw(dev); /* Double check if there is at least one instance running. * If no instance is in memory than no firmware should be present */ if (dev->num_inst > 0) { ret = s5p_mfc_load_firmware(dev); if (ret) { mfc_err("Failed to reload FW\n"); goto unlock; } s5p_mfc_clock_on(); ret = s5p_mfc_init_hw(dev); s5p_mfc_clock_off(); if (ret) mfc_err("Failed to reinit FW\n"); } unlock: if (mutex_locked) mutex_unlock(&dev->mfc_mutex); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski24194.88%116.67%
Arun Mankuzhi62.36%116.67%
Marek Szyprowski31.18%116.67%
Andrzej Hajda20.79%116.67%
Arun Kumar K20.79%233.33%
Total254100.00%6100.00%


static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_buf *dst_buf; struct s5p_mfc_dev *dev = ctx->dev; ctx->state = MFCINST_FINISHED; ctx->sequence++; while (!list_empty(&ctx->dst_queue)) { dst_buf = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); mfc_debug(2, "Cleaning up buffer: %d\n", dst_buf->b->vb2_buf.index); vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0); vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0); list_del(&dst_buf->list); dst_buf->flags |= MFC_BUF_FLAG_EOS; ctx->dst_queue_cnt--; dst_buf->b->sequence = (ctx->sequence++); if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) == s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx)) dst_buf->b->field = V4L2_FIELD_NONE; else dst_buf->b->field = V4L2_FIELD_INTERLACED; dst_buf->b->flags |= V4L2_BUF_FLAG_LAST; ctx->dec_dst_flag &= ~(1 << dst_buf->b->vb2_buf.index); vb2_buffer_done(&dst_buf->b->vb2_buf, VB2_BUF_STATE_DONE); } }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski17077.98%120.00%
Arun Kumar K2310.55%120.00%
Junghak Sung115.05%120.00%
Philipp Zabel83.67%120.00%
Andrzej Hajda62.75%120.00%
Total218100.00%5100.00%


static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *dst_buf, *src_buf; size_t dec_y_addr; unsigned int frame_type; /* Make sure we actually have a new frame before continuing. */ frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) return; dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev); /* Copy timestamp / timecode from decoded src to dst and set appropriate flags. */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) == dec_y_addr) { dst_buf->b->timecode = src_buf->b->timecode; dst_buf->b->vb2_buf.timestamp = src_buf->b->vb2_buf.timestamp; dst_buf->b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf->b->flags |= src_buf->b->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; switch (frame_type) { case S5P_FIMV_DECODE_FRAME_I_FRAME: dst_buf->b->flags |= V4L2_BUF_FLAG_KEYFRAME; break; case S5P_FIMV_DECODE_FRAME_P_FRAME: dst_buf->b->flags |= V4L2_BUF_FLAG_PFRAME; break; case S5P_FIMV_DECODE_FRAME_B_FRAME: dst_buf->b->flags |= V4L2_BUF_FLAG_BFRAME; break; default: /* Don't know how to handle S5P_FIMV_DECODE_FRAME_OTHER_FRAME. */ mfc_debug(2, "Unexpected frame type: %d\n", frame_type); } break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski14264.84%225.00%
Sakari Ailus2310.50%112.50%
Arun Kumar K2310.50%112.50%
Ilja Friedel2310.50%112.50%
Junghak Sung73.20%225.00%
Marek Szyprowski10.46%112.50%
Total219100.00%8100.00%


static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *dst_buf; size_t dspl_y_addr; unsigned int frame_type; dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); if (IS_MFCV6_PLUS(dev)) frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_disp_frame_type, ctx); else frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); /* If frame is same as previous then skip and do not dequeue */ if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { if (!ctx->after_packed_pb) ctx->sequence++; ctx->after_packed_pb = 0; return; } ctx->sequence++; /* The MFC returns address of the buffer, now we have to * check which videobuf does it correspond to */ list_for_each_entry(dst_buf, &ctx->dst_queue, list) { /* Check if this is the buffer we're looking for */ if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) == dspl_y_addr) { list_del(&dst_buf->list); ctx->dst_queue_cnt--; dst_buf->b->sequence = ctx->sequence; if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) == s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx)) dst_buf->b->field = V4L2_FIELD_NONE; else dst_buf->b->field = V4L2_FIELD_INTERLACED; vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, ctx->luma_size); vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, ctx->chroma_size); clear_bit(dst_buf->b->vb2_buf.index, &ctx->dec_dst_flag); vb2_buffer_done(&dst_buf->b->vb2_buf, err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski20072.73%116.67%
Arun Kumar K4014.55%233.33%
Sjoerd Simons217.64%116.67%
Junghak Sung134.73%116.67%
Marek Szyprowski10.36%116.67%
Total275100.00%6100.00%

/* Handle frame decoding interrupt */
static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { struct s5p_mfc_dev *dev = ctx->dev; unsigned int dst_frame_status; unsigned int dec_frame_status; struct s5p_mfc_buf *src_buf; unsigned int res_change; dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; dec_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dec_status, dev) & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK) >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT; mfc_debug(2, "Frame Status: %x\n", dst_frame_status); if (ctx->state == MFCINST_RES_CHANGE_INIT) ctx->state = MFCINST_RES_CHANGE_FLUSH; if (res_change == S5P_FIMV_RES_INCREASE || res_change == S5P_FIMV_RES_DECREASE) { ctx->state = MFCINST_RES_CHANGE_INIT; s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); return; } if (ctx->dpb_flush_flag) ctx->dpb_flush_flag = 0; /* All frames remaining in the buffer have been extracted */ if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) { if (ctx->state == MFCINST_RES_CHANGE_FLUSH) { static const struct v4l2_event ev_src_ch = { .type = V4L2_EVENT_SOURCE_CHANGE, .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, }; s5p_mfc_handle_frame_all_extracted(ctx); ctx->state = MFCINST_RES_CHANGE_END; v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); goto leave_handle_frame; } else { s5p_mfc_handle_frame_all_extracted(ctx); } } if (dec_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) s5p_mfc_handle_frame_copy_time(ctx); /* A frame has been decoded and is in the buffer */ if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY || dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) { s5p_mfc_handle_frame_new(ctx, err); } else { mfc_debug(2, "No frame decode\n"); } /* Mark source buffer as complete */ if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY && !list_empty(&ctx->src_queue)) { src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, dev); if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC && ctx->consumed_stream + STUFF_BYTE < src_buf->b->vb2_buf.planes[0].bytesused) { /* Run MFC again on the same buffer */ mfc_debug(2, "Running again the same buffer\n"); ctx->after_packed_pb = 1; } else { mfc_debug(2, "MFC needs next buffer\n"); ctx->consumed_stream = 0; if (src_buf->flags & MFC_BUF_FLAG_EOS) ctx->state = MFCINST_FINISHING; list_del(&src_buf->list); ctx->src_queue_cnt--; if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0) vb2_buffer_done(&src_buf->b->vb2_buf, VB2_BUF_STATE_ERROR); else vb2_buffer_done(&src_buf->b->vb2_buf, VB2_BUF_STATE_DONE); } } leave_handle_frame: if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) || ctx->dst_queue_cnt < ctx->pb_count) clear_work_bit(ctx); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); /* if suspending, wake up device and do not try_run again*/ if (test_bit(0, &dev->enter_suspend)) wake_up_dev(dev, reason, err); else s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski42270.81%216.67%
Pawel Osciak6510.91%433.33%
Arun Kumar K6310.57%216.67%
Prathyush K233.86%18.33%
Jeongtae Park101.68%18.33%
Junghak Sung91.51%18.33%
Andrzej Hajda40.67%18.33%
Total596100.00%12100.00%

/* Error handling for interrupt */
static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { mfc_err("Interrupt Error: %08x\n", err); if (ctx != NULL) { /* Error recovery is dependent on the state of context */ switch (ctx->state) { case MFCINST_RES_CHANGE_INIT: case MFCINST_RES_CHANGE_FLUSH: case MFCINST_RES_CHANGE_END: case MFCINST_FINISHING: case MFCINST_FINISHED: case MFCINST_RUNNING: /* It is highly probable that an error occurred * while decoding a frame */ clear_work_bit(ctx); ctx->state = MFCINST_ERROR; /* Mark all dst buffers as having an error */ s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); /* Mark all src buffers as having an error */ s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); wake_up_ctx(ctx, reason, err); break; default: clear_work_bit(ctx); ctx->state = MFCINST_ERROR; wake_up_ctx(ctx, reason, err); break; } } WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_clock_off(); wake_up_dev(dev, reason, err); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski16996.02%233.33%
Pawel Osciak31.70%116.67%
Andrzej Hajda31.70%233.33%
Jonathan McCrohan10.57%116.67%
Total176100.00%6100.00%

/* Header parsing interrupt handling */
static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { struct s5p_mfc_dev *dev; if (ctx == NULL) return; dev = ctx->dev; if (ctx->c_ops->post_seq_start) { if (ctx->c_ops->post_seq_start(ctx)) mfc_err("post_seq_start() failed\n"); } else { ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width, dev); ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height, dev); s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, dev); ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count, dev); if (ctx->img_width == 0 || ctx->img_height == 0) ctx->state = MFCINST_ERROR; else ctx->state = MFCINST_HEAD_PARSED; if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) && !list_empty(&ctx->src_queue)) { struct s5p_mfc_buf *src_buf; src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, dev) < src_buf->b->vb2_buf.planes[0].bytesused) ctx->head_processed = 0; else ctx->head_processed = 1; } else { ctx->head_processed = 1; } } s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); clear_work_bit(ctx); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); wake_up_ctx(ctx, reason, err); }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski14947.45%110.00%
Jeongtae Park10834.39%110.00%
Arun Kumar K4614.65%330.00%
Andrzej Hajda30.96%110.00%
Junghak Sung30.96%110.00%
Pawel Osciak30.96%110.00%
Julia Lawall10.32%110.00%
Sachin Kamat10.32%110.00%
Total314100.00%10100.00%

/* Header parsing interrupt handling */
static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { struct s5p_mfc_buf *src_buf; struct s5p_mfc_dev *dev; if (ctx == NULL) return; dev = ctx->dev; s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); ctx