From fe4ded7117ef043f26b6d3cb1397c7833cfd744a Mon Sep 17 00:00:00 2001 From: Zhou Peng Date: Fri, 16 Apr 2021 18:49:24 +0800 Subject: [PATCH] arm64: imx8mx: vpu: integrate vsi 20210416 release MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit - M865SW-738: VSI V4L2 Engineer release package 20210416 M865SW-636: [VPU/V4L2] H264 decoder: Resolution change stream seek hang M865SW-696: [VPU/V4L2] VC8000E: Flush encoder then get V4L2_EVENT_CODEC_ERROR event M865SW-730: [VPU/V4L2] encoder: Android poll() waiting timeout at beginning M865SW-734: [VPU/V4L2] decoder: daemon occurs error when running unit test M865SW-697: [VPU/V4L2] encoder: the bitrate of encoding vp8 is not accurate M865SW-726: [VPU/V4L2] 8MM/8MP HEVC 10bit decoder: cannot play on Android Signed-off-by: Zhou Peng (cherry picked from commit ddf936035cb532689a9442529089e648729ac378) --- drivers/mxc/hantro_v4l2/vsi-v4l2-config.c | 51 ++++++++++++----------- drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c | 13 +++--- drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c | 10 ++--- drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h | 6 ++- drivers/mxc/hantro_v4l2/vsi-v4l2.c | 14 +++---- drivers/mxc/hantro_v4l2/vsi-v4l2.h | 4 +- drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c | 23 +++++----- 7 files changed, 63 insertions(+), 58 deletions(-) diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2-config.c b/drivers/mxc/hantro_v4l2/vsi-v4l2-config.c index f4dd17f43507..e29d8ca071eb 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2-config.c +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2-config.c @@ -975,10 +975,11 @@ static int get_fmtprofile(struct vsi_v4l2_mediacfg *pcfg) } } -static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int width, int height, int planeno, int pixelWidth) +static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int width, int height, int planeno, int bdecoder) { int totalsize = 0; int basesize = width * height, extsize = 0, quadsize = 0; + int padsize = 0; if (braw) { if (enc_isRGBformat(pixelformat)) { @@ -998,6 +999,8 @@ static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int case V4L2_PIX_FMT_411SP: extsize = basesize / 2; quadsize = basesize / 4; + if (bdecoder) + padsize = quadsize + 32; break; case V4L2_PIX_FMT_NV16: extsize = basesize; @@ -1019,7 +1022,7 @@ static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int } } if (planeno == 1) { - totalsize = basesize + extsize; + totalsize = basesize + extsize + padsize; psize[0] = max_t(int, PAGE_ALIGN(totalsize), psize[0]); } else if (planeno == 2) { psize[0] = basesize; @@ -1148,7 +1151,7 @@ static int vsiv4l2_setfmt_enc(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt) if (fmt->fmt.pix_mp.num_planes == userset_planeno) { for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++) psize[i] = fmt->fmt.pix_mp.plane_fmt[i].sizeimage; - verifyPlanesize(psize, braw, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, userset_planeno, 8); + verifyPlanesize(psize, braw, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, userset_planeno, 0); } else calcPlanesize(ctx, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, psize, fmt->type, fmt->fmt.pix_mp.num_planes); for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++) @@ -1302,13 +1305,13 @@ static int vsiv4l2_decidepixeldepth(int pixelformat, int origdepth) case VSI_V4L2_DEC_PIX_FMT_411SP: case VSI_V4L2_DEC_PIX_FMT_422SP: case VSI_V4L2_DEC_PIX_FMT_444SP: - case VSI_V4L2_DECOUT_DTRC: - case VSI_V4L2_DECOUT_RFC: return 8; case VSI_V4L2_DECOUT_NV12_10BIT: + return 10; case VSI_V4L2_DECOUT_DTRC_10BIT: case VSI_V4L2_DECOUT_RFC_10BIT: - return 10; + case VSI_V4L2_DECOUT_DTRC: + case VSI_V4L2_DECOUT_RFC: default: return origdepth; } @@ -1320,19 +1323,17 @@ static int vsiv4l2_setfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt) struct vsi_video_fmt *targetfmt; unsigned int *psize; int braw = brawfmt(ctx->flag, fmt->type); - int oldsize = 0; targetfmt = vsi_find_format(ctx, fmt); if (targetfmt == NULL) return -EINVAL; if (binputqueue(fmt->type)) psize = pcfg->sizeimagesrc; - else { + else psize = pcfg->sizeimagedst; - oldsize = psize[0]; - } + v4l2_klog(LOGLVL_BRIEF, "%s:%d:%x:%d:%d:%d:%d", __func__, - fmt->type, fmt->fmt.pix.pixelformat, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.bytesperline, oldsize); + fmt->type, fmt->fmt.pix.pixelformat, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.bytesperline, psize[0]); if (binputqueue(fmt->type)) { pcfg->decparams.dec_info.io_buffer.srcwidth = fmt->fmt.pix.width; pcfg->decparams.dec_info.io_buffer.srcheight = fmt->fmt.pix.height; @@ -1347,19 +1348,22 @@ static int vsiv4l2_setfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt) fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.output_height; pcfg->decparams.dec_info.io_buffer.outBufFormat = targetfmt->dec_fmt; pcfg->decparams.dec_info.io_buffer.outputPixelDepth = - vsiv4l2_decidepixeldepth(targetfmt->dec_fmt, pcfg->decparams.dec_info.io_buffer.outputPixelDepth); + vsiv4l2_decidepixeldepth(targetfmt->dec_fmt, pcfg->src_pixeldepth); } - pcfg->bytesperline = fmt->fmt.pix.bytesperline; /* for padding, zero if unused */ - pcfg->bytesperline = ALIGN(pcfg->bytesperline, 16); - if (pcfg->bytesperline == 0) - pcfg->bytesperline = ALIGN(fmt->fmt.pix.width, 16); - fmt->fmt.pix.bytesperline = pcfg->bytesperline; psize[0] = fmt->fmt.pix.sizeimage; - verifyPlanesize(psize, braw, fmt->fmt.pix.pixelformat, pcfg->bytesperline, fmt->fmt.pix.height, 1, - !binputqueue(fmt->type) ? pcfg->decparams.dec_info.io_buffer.outputPixelDepth:8); - if (!binputqueue(fmt->type) && oldsize > psize[0]) - psize[0] = oldsize; - fmt->fmt.pix.sizeimage = psize[0]; + if (!binputqueue(fmt->type)) { + if (pcfg->decparams.dec_info.io_buffer.outputPixelDepth < pcfg->src_pixeldepth) { + pcfg->bytesperline = fmt->fmt.pix.width * pcfg->decparams.dec_info.io_buffer.outputPixelDepth / 8; + pcfg->bytesperline = ALIGN(pcfg->bytesperline, 16); + if (fmt->fmt.pix.sizeimage * pcfg->src_pixeldepth < + pcfg->decparams.dec_info.io_buffer.outputPixelDepth * pcfg->orig_dpbsize) { + verifyPlanesize(psize, braw, fmt->fmt.pix.pixelformat, pcfg->bytesperline, fmt->fmt.pix.height, 1, 1); + fmt->fmt.pix.sizeimage = psize[0]; + } + } else if (fmt->fmt.pix.sizeimage < pcfg->orig_dpbsize) + fmt->fmt.pix.sizeimage = psize[0] = pcfg->orig_dpbsize; + fmt->fmt.pix.bytesperline = pcfg->bytesperline; + } if (binputqueue(fmt->type)) pcfg->srcplanes = 1; else @@ -1544,11 +1548,10 @@ static int vsiv4l2_getfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt) fmt->fmt.pix.width = pcfg->decparams.dec_info.io_buffer.srcwidth; fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.srcheight; fmt->fmt.pix.pixelformat = find_local_dec_format(pcfg->decparams.dec_info.io_buffer.inputFormat, braw); - fmt->fmt.pix.bytesperline = pcfg->bytesperline; } else { fmt->fmt.pix.width = pcfg->decparams.dec_info.io_buffer.output_width; fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.output_height; - fmt->fmt.pix.bytesperline = pcfg->decparams.dec_info.io_buffer.output_wstride; + fmt->fmt.pix.bytesperline = pcfg->bytesperline; //return latest value fmt->fmt.pix.pixelformat = find_local_dec_format(pcfg->decparams.dec_info.io_buffer.outBufFormat, braw); } fmt->fmt.pix.field = pcfg->field; diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c b/drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c index 180dcc50373f..c06d27b86c5b 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c @@ -279,6 +279,7 @@ static int vsi_dec_streamon(struct file *filp, void *priv, enum v4l2_buf_type ty vsi_dec_dec2drain(ctx); if (test_bit(CTX_FLAG_ENDOFSTRM_BIT, &ctx->flag)) { struct vb2_buffer *vb = ctx->output_que.bufs[0]; + vb->planes[0].bytesused = 0; ctx->lastcapbuffer_idx = 0; vb2_buffer_done(vb, VB2_BUF_STATE_DONE); @@ -310,7 +311,8 @@ static int vsi_dec_checkctx_srcbuf(struct vsi_v4l2_ctx *ctx) static int vsi_checkctx_capoffdone(struct vsi_v4l2_ctx *ctx) { - if (test_and_clear_bit(CTX_FLAG_STREAMOFFDONE, &ctx->flag)) + if (test_and_clear_bit(CTX_FLAG_STREAMOFFDONE, &ctx->flag) + || ctx->error < 0) return 1; return 0; } @@ -325,6 +327,8 @@ static void vsi_dec_update_reso(struct vsi_v4l2_ctx *ctx) pcfg->decparams.dec_info.io_buffer.output_width = pcfg->decparams_bkup.io_buffer.output_width; pcfg->decparams.dec_info.io_buffer.output_height = pcfg->decparams_bkup.io_buffer.output_height; pcfg->decparams.dec_info.io_buffer.output_wstride = pcfg->decparams_bkup.io_buffer.output_wstride; + pcfg->bytesperline = pcfg->decparams_bkup.io_buffer.output_wstride; + pcfg->orig_dpbsize = pcfg->sizeimagedst_bkup; pcfg->src_pixeldepth = pcfg->decparams_bkup.dec_info.dec_info.bit_depth; pcfg->minbuf_4output = pcfg->minbuf_4capture = pcfg->minbuf_4output_bkup; pcfg->sizeimagedst[0] = pcfg->sizeimagedst_bkup; @@ -617,13 +621,13 @@ static int vsi_dec_subscribe_event( static int vsi_dec_handlestop_unspec(struct vsi_v4l2_ctx *ctx) { //some unexpected condition fro CTS, not quite conformant to spec - if ((ctx->status == VSI_STATUS_INIT && !test_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag)) || + if ((ctx->status == VSI_STATUS_INIT && !test_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag)) || ctx->status == DEC_STATUS_STOPPED) { clear_bit(CTX_FLAG_PRE_DRAINING_BIT, &ctx->flag); vsi_v4l2_sendeos(ctx); return 0; } - if (ctx->status == DEC_STATUS_SEEK && !test_bit(CTX_FLAG_SRCBUF_BIT, &ctx->flag)) { + if (ctx->status == DEC_STATUS_SEEK && !test_bit(CTX_FLAG_SRCBUF_BIT, &ctx->flag)) { vsi_v4l2_sendeos(ctx); return 0; } @@ -1146,8 +1150,7 @@ static __poll_t vsi_dec_poll(struct file *file, poll_table *wait) } if (vb2_is_streaming(&ctx->output_que)) ret |= vb2_poll(&ctx->output_que, file, wait); - if (vb2_is_streaming(&ctx->input_que)) - ret |= vb2_poll(&ctx->input_que, file, wait); + ret |= vb2_poll(&ctx->input_que, file, wait); /*recheck for poll hang*/ if (ret == 0) { diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c b/drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c index 8c39351d4744..69b15d47ea58 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c @@ -695,10 +695,8 @@ static void vsi_enc_buf_queue(struct vb2_buffer *vb) vsibuf = vb_to_vsibuf(vb); if (!binputqueue(vq->type)) list_add_tail(&vsibuf->list, &ctx->output_list); - else { + else list_add_tail(&vsibuf->list, &ctx->input_list); - ctx->queued_srcnum++; - } ret = vsiv4l2_execcmd(ctx, V4L2_DAEMON_VIDIOC_BUF_RDY, vb); } @@ -1390,10 +1388,8 @@ static __poll_t vsi_enc_poll(struct file *file, poll_table *wait) v4l2_klog(LOGLVL_BRIEF, "%s event", __func__); ret |= POLLPRI; } - if (vb2_is_streaming(&ctx->output_que)) - ret |= vb2_poll(&ctx->output_que, file, wait); - if (vb2_is_streaming(&ctx->input_que)) - ret |= vb2_poll(&ctx->input_que, file, wait); + ret |= vb2_poll(&ctx->output_que, file, wait); + ret |= vb2_poll(&ctx->input_que, file, wait); /*recheck for poll hang*/ if (ret == 0) { diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h b/drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h index d88fa6eb0241..bfd1fd354b44 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h @@ -212,6 +212,7 @@ struct vsi_v4l2_mediacfg { u32 infmt_fourcc; u32 outfmt_fourcc; u32 src_pixeldepth; //dec only + u32 orig_dpbsize; //dec only /*profiles for each format is put here instead of encparams to save some transfer data*/ s32 profile_h264; s32 profile_hevc; @@ -314,8 +315,8 @@ struct vsi_v4l2_ctx { u32 rfc_luma_offset[VIDEO_MAX_FRAME]; u32 rfc_chroma_offset[VIDEO_MAX_FRAME]; s32 queued_srcnum; - u32 buffed_capnum; - u32 buffed_cropcapnum; + s32 buffed_capnum; + s32 buffed_cropcapnum; u32 lastcapbuffer_idx; //latest received capture buffer index struct vsi_v4l2_mediacfg mediacfg; @@ -481,6 +482,7 @@ static inline int update_and_removecropinfo(struct vsi_v4l2_ctx *ctx) pcfg->decparams.dec_info.io_buffer.output_width = crop->frame_width; pcfg->decparams.dec_info.io_buffer.output_height = crop->frame_height; pcfg->decparams.dec_info.io_buffer.output_wstride = crop->pic_wstride; + pcfg->bytesperline = crop->pic_wstride; pcfg->decparams.dec_info.dec_info.frame_width = crop->frame_width; pcfg->decparams.dec_info.dec_info.frame_height = crop->frame_height; pcfg->decparams.dec_info.dec_info.visible_rect.left = crop->left; diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2.c b/drivers/mxc/hantro_v4l2/vsi-v4l2.c index ac111bb291d5..2bce2b5ce410 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2.c +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2.c @@ -306,9 +306,9 @@ int vsi_v4l2_notify_reschange(struct vsi_v4l2_msg *pmsg) return -EBUSY; v4l2_klog(LOGLVL_BRIEF, "%lx sending event res change:%d, delay=%d", ctx->ctxid, ctx->status, (ctx->status == DEC_STATUS_DECODING || ctx->status == DEC_STATUS_DRAINING) && !list_empty(&ctx->output_que.done_list)); - v4l2_klog(LOGLVL_BRIEF, "reso=%d:%d,bitdepth=%d,dpb=%d:%d,orig yuvfmt=%d", - decinfo->frame_width, decinfo->frame_height, decinfo->bit_depth, decinfo->needed_dpb_nums, - decinfo->dpb_buffer_size, decinfo->src_pix_fmt); + v4l2_klog(LOGLVL_BRIEF, "reso=%d:%d,bitdepth=%d,stride=%d,dpb=%d:%d,orig yuvfmt=%d", + decinfo->frame_width, decinfo->frame_height, decinfo->bit_depth, pmsg->params.dec_params.io_buffer.output_wstride, + decinfo->needed_dpb_nums, decinfo->dpb_buffer_size, decinfo->src_pix_fmt); if ((ctx->status == DEC_STATUS_DECODING || ctx->status == DEC_STATUS_DRAINING) && !list_empty(&ctx->output_que.done_list)) { pcfg->decparams_bkup.dec_info = pmsg->params.dec_params.dec_info; @@ -327,6 +327,8 @@ int vsi_v4l2_notify_reschange(struct vsi_v4l2_msg *pmsg) pcfg->decparams.dec_info.io_buffer.output_width = pmsg->params.dec_params.dec_info.io_buffer.output_width; pcfg->decparams.dec_info.io_buffer.output_height = pmsg->params.dec_params.dec_info.io_buffer.output_height; pcfg->decparams.dec_info.io_buffer.output_wstride = pmsg->params.dec_params.dec_info.io_buffer.output_wstride; + pcfg->bytesperline = pmsg->params.dec_params.dec_info.io_buffer.output_wstride; + pcfg->orig_dpbsize = decinfo->dpb_buffer_size; pcfg->src_pixeldepth = decinfo->bit_depth; pcfg->minbuf_4output = pcfg->minbuf_4capture = pmsg->params.dec_params.dec_info.dec_info.needed_dpb_nums; @@ -423,6 +425,7 @@ int vsi_v4l2_handle_cropchange(struct vsi_v4l2_msg *pmsg) pcfg->decparams.dec_info.io_buffer.output_height = pmsg->params.dec_params.pic_info.pic_info.height; pcfg->decparams.dec_info.io_buffer.output_wstride = pmsg->params.dec_params.pic_info.pic_info.pic_wstride; pcfg->decparams.dec_info.dec_info.frame_width = pmsg->params.dec_params.pic_info.pic_info.width; + pcfg->bytesperline = pmsg->params.dec_params.pic_info.pic_info.pic_wstride; pcfg->decparams.dec_info.dec_info.frame_height = pmsg->params.dec_params.pic_info.pic_info.height; pcfg->decparams.dec_info.dec_info.visible_rect.left = pmsg->params.dec_params.pic_info.pic_info.crop_left; pcfg->decparams.dec_info.dec_info.visible_rect.top = pmsg->params.dec_params.pic_info.pic_info.crop_top; @@ -483,11 +486,6 @@ int vsi_v4l2_bufferdone(struct vsi_v4l2_msg *pmsg) if (outbufidx >= 0 && outbufidx < ctx->output_que.num_buffers) { if (mutex_lock_interruptible(&ctx->ctxlock)) return -EBUSY; - if (isencoder(ctx)) { - ctx->queued_srcnum--; - if (ctx->queued_srcnum < 0) - ctx->queued_srcnum = 0; - } if (!inst_isactive(ctx)) { if (!vb2_is_streaming(&ctx->output_que)) v4l2_klog(LOGLVL_ERROR, "%lx ignore dst buffer %d in state %d", ctx->ctxid, outbufidx, ctx->status); diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2.h b/drivers/mxc/hantro_v4l2/vsi-v4l2.h index 20b0f66041eb..b4b1d9055801 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2.h +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2.h @@ -102,7 +102,9 @@ enum v4l2_daemon_cmd_id { V4L2_DAEMON_VIDIOC_STREAMON = 0,//for streamon and start V4L2_DAEMON_VIDIOC_BUF_RDY, V4L2_DAEMON_VIDIOC_CMD_STOP, //this is for flush. - V4L2_DAEMON_VIDIOC_STREAMOFF,//for encoder, 4 cmd is enough. + V4L2_DAEMON_VIDIOC_STREAMOFF, //enc destroy + V4L2_DAEMON_VIDIOC_ENC_RESET, //enc reset, as in spec + //above are enc cmds V4L2_DAEMON_VIDIOC_FAKE,//fake command. diff --git a/drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c b/drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c index 62d43d10f8ff..b450208cc435 100755 --- a/drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c +++ b/drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c @@ -398,7 +398,8 @@ static void format_bufinfo_dec(struct vsi_v4l2_ctx *ctx, struct vsi_v4l2_msg *pm decbufinfo->busOutBuf = busaddr[0] + buf->planes[0].data_offset; decbufinfo->OutBufSize = ctx->outbuflen[buf->index];//ctx->mediacfg.sizeimagedst[0]; decbufinfo->bytesused = buf->planes[0].bytesused; - if ((ctx->mediacfg.src_pixeldepth == ctx->mediacfg.decparams.dec_info.io_buffer.outputPixelDepth) + if (((ctx->mediacfg.src_pixeldepth == ctx->mediacfg.decparams.dec_info.io_buffer.outputPixelDepth) + && ctx->mediacfg.src_pixeldepth != 16) //p010 can only set by user, not from ctrl sw || !test_bit(CTX_FLAG_SRCCHANGED_BIT, &ctx->flag)) pmsg->params.dec_params.io_buffer.outputPixelDepth = DEFAULT_PIXELDEPTH; } else { @@ -492,7 +493,7 @@ tail: if (ctx) { if (ret < 0) { vsi_set_ctx_error(ctx, ret); - v4l2_klog(LOGLVL_ERROR, "%lx fail to communicate with daemon, error=%d", ctx->ctxid, ret); + v4l2_klog(LOGLVL_ERROR, "%lx fail to communicate with daemon, error=%d, cmd=%d", ctx->ctxid, ret, id); } else set_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag); } @@ -665,16 +666,16 @@ static ssize_t v4l2_msg_write(struct file *fh, const char __user *buf, size_t si vsi_handle_daemonmsg(pmsg); kfree(pmsg); return size; - } else { - if (mutex_lock_interruptible(&ret_lock)) { - kfree(pmsg); - return size; - } - ret = idr_alloc(retarray, (void *)pmsg, 1, 0, GFP_KERNEL); - mutex_unlock(&ret_lock); - if (ret < 0) - kfree(pmsg); } + if (mutex_lock_interruptible(&ret_lock)) { + kfree(pmsg); + return size; + } + ret = idr_alloc(retarray, (void *)pmsg, 1, 0, GFP_KERNEL); + mutex_unlock(&ret_lock); + if (ret < 0) + kfree(pmsg); + error: if (ret >= 0) wake_up_interruptible_all(&ret_queue); -- 2.17.1