From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CB13C433DF for ; Fri, 22 May 2020 14:21:24 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EED012245F for ; Fri, 22 May 2020 14:21:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="KCVXzv8P"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="euRrR6yk" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EED012245F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=pspplheWxdx8TfgDHxqUkRI+1USuHKkAr425H+eGvCk=; b=KCVXzv8PGsiM7z 05PsTW6ZtH3lj9dsTmWl96EBKHosm82guNUGRykbDxvwjpjmWRSbddGvJRQaBbWMVVsrwb5Fxa0eR vCTZlhXbHX/SrX+TktT4lKcyn8j4aoHx9/nkruNunIojT9zqEJobZuhWE+QrcKmBOQ9Duf9m7Kuai ZvXZkuHABAA9mjs+knO/ySqlB94DthJJDg/s55EGQw6wmpeGAP3CTbD+/jB3Gwq1A2pAiERK6x6Hx DgdNC68HFPfHuV64onzB8TVO3eyBiEUnC+OGD5yazB5hSY1ZcWbJhMnSsGcfswfIq1/idqRrqC1JZ u3QXwU+1s+63v+ki1F3Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jc8Xy-0004jA-R0; Fri, 22 May 2020 14:21:14 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jc8Xt-0004iJ-RS; Fri, 22 May 2020 14:21:12 +0000 X-UUID: e30fc0b0d0fb4d3995e101d7598b6c9e-20200522 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=O6kJJyACUJalT+c1EmXfnkhAwzGhDrPE+kC/YlUnpFQ=; b=euRrR6ykCaGMem3OCznfB4XIJ5FX+rNOJBxp0UFgjM/RV9YQdTtKwq+ozeyrnqzYlkiyoy/zjpi6KrQyEQtjBb9+crg4FjdXWOxe+EZQkCfgHbpPYIJx3SsS24NNID/PvLkB8joGMElI64JCUG9uvurcL+XILSX+93hgHM5QxCQ=; X-UUID: e30fc0b0d0fb4d3995e101d7598b6c9e-20200522 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1563402749; Fri, 22 May 2020 06:20:46 -0800 Received: from mtkmbs08n1.mediatek.inc (172.21.101.55) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 22 May 2020 07:10:57 -0700 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 22 May 2020 22:10:56 +0800 Received: from [172.21.84.99] (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 22 May 2020 22:10:55 +0800 Message-ID: <1590156658.27807.84.camel@mtksdccf07> Subject: Re: [RFC PATCH V4 4/4] platform: mtk-isp: Add Mediatek FD driver From: Jerry-ch Chen To: Tomasz Figa Date: Fri, 22 May 2020 22:10:58 +0800 In-Reply-To: <20200521182825.GA249683@chromium.org> References: <20191204124732.10932-1-Jerry-Ch.chen@mediatek.com> <20191204124732.10932-5-Jerry-Ch.chen@mediatek.com> <20200521182825.GA249683@chromium.org> X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200522_072110_070357_211AC7E5 X-CRM114-Status: GOOD ( 33.05 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Sean.Cheng@mediatek.com, laurent.pinchart+renesas@ideasonboard.com, Rynn.Wu@mediatek.com, zwisler@chromium.org, srv_heupstream@mediatek.com, christie.yu@mediatek.com, jerry-ch.chen@mediatek.com, hverkuil@xs4all.nl, jungo.lin@mediatek.com, sj.huang@mediatek.com, yuzhao@chromium.org, hans.verkuil@cisco.com, pihsun@chromium.org, frederic.chen@mediatek.com, matthias.bgg@gmail.com, linux-mediatek@lists.infradead.org, mchehab@kernel.org, linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Hi Tomasz, On Thu, 2020-05-21 at 18:28 +0000, Tomasz Figa wrote: > Hi Jerry, > > On Wed, Dec 04, 2019 at 08:47:32PM +0800, Jerry-ch Chen wrote: > > From: Jerry-ch Chen > > > > This patch adds the driver of Face Detection (FD) unit in > > Mediatek camera system, providing face detection function. > > > > The mtk-isp directory will contain drivers for multiple IP > > blocks found in Mediatek ISP system. It will include ISP Pass 1 > > driver (CAM), sensor interface driver, DIP driver and face > > detection driver. > > > > Signed-off-by: Jerry-ch Chen > > --- > > drivers/media/platform/Kconfig | 2 + > > drivers/media/platform/Makefile | 2 + > > drivers/media/platform/mtk-isp/fd/Kconfig | 19 + > > drivers/media/platform/mtk-isp/fd/Makefile | 5 + > > drivers/media/platform/mtk-isp/fd/mtk_fd.h | 149 ++ > > drivers/media/platform/mtk-isp/fd/mtk_fd_40.c | 1279 +++++++++++++++++ > > include/uapi/linux/v4l2-controls.h | 4 + > > include/uapi/linux/videodev2.h | 3 + > > 8 files changed, 1463 insertions(+) > > create mode 100644 drivers/media/platform/mtk-isp/fd/Kconfig > > create mode 100644 drivers/media/platform/mtk-isp/fd/Makefile > > create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd.h > > create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd_40.c > > > > Thank you for the patch. Please see my comments inline. Really sorry for > the much delayed review. > I appreciate your comments, here's the reply > [snip] > > +config VIDEO_MEDIATEK_FD > > + tristate "Mediatek face detection processing function" > > + depends on VIDEO_V4L2 > > + depends on ARCH_MEDIATEK > > + select VIDEOBUF2_DMA_CONTIG > > + select VIDEOBUF2_CORE > > + select VIDEOBUF2_V4L2 > > + select VIDEOBUF2_MEMOPS > > + select MEDIA_CONTROLLER > > + select MTK_SCP > > + > > + default n > > + help > > + Support the Face Detection (FD) feature in the Mediatek > > + mt8183 Soc. > > MT8183? Fixed. > > > + > > + FD driver is a V4L2 memory-to-memory device driver which > > + provides hardware accelerated face detection function, > > + it can detect different sizes of faces in a raw image. > > A YUV image I guess? Fixed > > [snip] > > diff --git a/drivers/media/platform/mtk-isp/fd/mtk_fd.h b/drivers/media/platform/mtk-isp/fd/mtk_fd.h > > new file mode 100644 > > index 000000000000..d85bdcb70d6d > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/fd/mtk_fd.h > > @@ -0,0 +1,149 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +// > > +// Copyright (c) 2018 MediaTek Inc. > > + > > +#ifndef __MTK_FD_HW_H__ > > +#define __MTK_FD_HW_H__ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define MTK_FD_OUTPUT_MIN_WIDTH 26U > > +#define MTK_FD_OUTPUT_MIN_HEIGHT 26U > > +#define MTK_FD_OUTPUT_MAX_WIDTH 640U > > +#define MTK_FD_OUTPUT_MAX_HEIGHT 480U > > + > > +#define MTK_FD_HW_FMT_VYUY 2 > > +#define MTK_FD_HW_FMT_UYVY 3 > > +#define MTK_FD_HW_FMT_YVYU 4 > > +#define MTK_FD_HW_FMT_YUYV 5 > > +#define MTK_FD_HW_FMT_YVU_2P 6 > > +#define MTK_FD_HW_FMT_YUV_2P 7 > > +#define MTK_FD_HW_FMT_UNKNOWN 8 > > What is an unknown format? It's used in translate v4l2 pixel format to the value that FD HW recognized. But I think the case of UNKNWOWN shouldn't happened. I will remove it > > > + > > +#define MTK_FD_IPI_CMD_INIT 0 > > +#define MTK_FD_IPI_CMD_INIT_ACK 1 > > +#define MTK_FD_IPI_CMD_ENQUEUE 2 > > +#define MTK_FD_IPI_CMD_ENQ_ACK 3 > > +#define MTK_FD_IPI_CMD_EXIT 4 > > +#define MTK_FD_IPI_CMD_EXIT_ACK 5 > > +#define MTK_FD_IPI_CMD_RESET 6 > > +#define MTK_FD_IPI_CMD_RESET_ACK 7 > > + > > +#define MTK_FD_REG_OFFSET_HW_ENABLE 0x4 > > +#define MTK_FD_REG_OFFSET_INT_EN 0x15c > > +#define MTK_FD_REG_OFFSET_INT_VAL 0x168 > > +#define MTK_FD_REG_OFFSET_RESULT 0x178 > > + > > +#define MTK_FD_SET_HW_ENABLE 0x111 > > +#define MTK_FD_RS_BUF_SIZE 2289664 > > +#define MTK_FD_HW_WORK_BUF_SIZE 0x100000 > > How about using the SZ_1M? > yes, fixed. > > +#define MTK_FD_MAX_SPEEDUP 7 > > +#define MTK_FD_MAX_RESULT_NUM 1026 > > Perhaps NUM_RESULTS? > fixed as MTK_FD_MAX_NUM_RESULT. > > + > > +/* Max scale size counts */ > > +#define MTK_FD_SCALE_ARR_NUM 15 > > Perhaps NUM_SCALE_SIZES? > fixed as MTK_FD_NUM_SCALE_SIZE > > + > > +#define MTK_FD_HW_TIMEOUT 1000 > > What's the unit? it's in milliseconds, I would like to rename it to MTK_FD_HW_TIMEOUT_MSEC > > > + > > +enum face_angle { > > + MTK_FD_FACE_FRONT, > > + MTK_FD_FACE_RIGHT_50, > > + MTK_FD_FACE_LEFT_50, > > + MTK_FD_FACE_RIGHT_90, > > + MTK_FD_FACE_LEFT_90, > > + MTK_FD_FACE_ANGLE_NUM, > > +}; > > This enum seems to define values for the V4L2_CID_MTK_FD_DETECT_POSE > control. Considering that this is an enumeration and the values are > actually integers (-90, -50, 0, 50, 90), perhaps this should be an > INTEGER_MENU control instead? > this ioctl let user select multiple face positions(combination of angles and directions) to be detected. so I thought I am not able to use the INTEGER_MENU for this purpose. A bit-field as following should be used by user. I consider adding it to uapi. struct face_direction_def { __u16 MTK_FD_FACE_DIR_0 : 1, MTK_FD_FACE_DIR_30 : 1, MTK_FD_FACE_DIR_60 : 1, MTK_FD_FACE_DIR_90 : 1, MTK_FD_FACE_DIR_120 : 1, MTK_FD_FACE_DIR_150 : 1, MTK_FD_FACE_DIR_180 : 1, MTK_FD_FACE_DIR_210 : 1, MTK_FD_FACE_DIR_240 : 1, MTK_FD_FACE_DIR_270 : 1, MTK_FD_FACE_DIR_300 : 1, MTK_FD_FACE_DIR_330 : 1, : 4; }; User can also select some face directions of each face angle in one ioctl, for example: /* * u16 face_directions[MTK_FD_FACE_ANGLE_NUM] = {0}; * * face_directions[MTK_FD_FACE_FRONT] = 0x7; //angle:0, dir:0,30,60 * face_directions[MTK_FACE_RIGHT_50] = 0x2; //angle:50, dir:30 * */ > > + > > +struct fd_buffer { > > + __u32 scp_addr; /* used by SCP */ > > + __u32 dma_addr; /* used by DMA HW */ > > +} __packed; fd buffer is used for scp ipi > > + > > +struct fd_face_result { > > + char data[16]; > > +}; fd_face_result is used for user, so it should be moved to include/uapi/linux. In fact, it has bit-field definition for user, so I would like to define it in include/uapi/linux as following: struct fd_face_result { __u64 face_idx : 12, type : 1, x0 : 10, y0 : 10, x1 : 10, y1 : 10, fcv1 : 11; __u64 fcv2 : 7, rip_dir : 4, rop_dir : 3, det_size : 5; }; > > + > > +struct fd_user_output { > > + struct fd_face_result results[MTK_FD_MAX_RESULT_NUM]; > > + __u16 number; > > Is this perhaps the number of results? If so, would num_results be a better > name? > yes, fixed. > > +}; > > Since this struct is the meta buffer format, it is a part of the userspace > interface and should be defined in a header under include/uapi/linux/. > Ok, I will create include/uapi/linux/mtk_fd_40.h which suppose to include structures that userspace will use. should the private IOCTLs be placed in it together? > > + > > +struct user_param { > > + u8 fd_speedup; > > + u8 fd_extra_model; > > + u8 scale_img_num; > > + u8 src_img_fmt; > > + __u16 scale_img_width[MTK_FD_SCALE_ARR_NUM]; > > + __u16 scale_img_height[MTK_FD_SCALE_ARR_NUM]; > > + __u16 face_directions[MTK_FD_FACE_ANGLE_NUM]; > > Is this a user-facing definition or an interface between the kernel driver > and firmware? If the latter, the __ types shouldn't be used. > It's the later, I'll fix it. > > +} __packed; > > + > > +struct fd_init_param { > > + struct fd_buffer fd_manager; > > + __u32 rs_dma_addr; > > Ditto. > done. > > +} __packed; > > + > > +struct fd_enq_param { > > + __u64 output_vaddr; > > Ditto. done. > > > + struct fd_buffer src_img[2]; > > + struct fd_buffer user_result; > > + struct user_param user_param; > > +} __packed; > > + > > +struct fd_ack_param { > > + __u32 ret_code; > > + __u32 ret_msg; > > Ditto. done. > > > +} __packed; > [snip] > > +/* */ > > Was there supposed to be a comment here? :) Ooops, no, it should be removed. > > > +static int mtk_fd_hw_alloc_rs_dma_addr(struct mtk_fd_dev *fd) > > +{ > > + struct device *dev = fd->dev; > > + void *va; > > + dma_addr_t dma_handle; > > + > > + va = dma_alloc_coherent(dev, MTK_FD_RS_BUF_SIZE, &dma_handle, > > + GFP_KERNEL); > > + if (!va) { > > + dev_err(dev, "dma_alloc null va\n"); > > No need to print errors for memory allocation failures, because one will be > printed automatically. Ok, log removed. > > [snip] > > +static int mtk_fd_hw_connect(struct mtk_fd_dev *fd) > > +{ > > + int ret; > > + > > + ret = rproc_boot(fd->rproc_handle); > > + > > nit: Unnecessary blank line. > fixed. > [snip] > > +static int mtk_fd_vb2_queue_setup(struct vb2_queue *vq, > > + unsigned int *num_buffers, > > + unsigned int *num_planes, > > + unsigned int sizes[], > > + struct device *alloc_devs[]) > > +{ > > + struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq); > > + unsigned int size[2]; > > + unsigned int plane; > > + > > + switch (vq->type) { > > + case V4L2_BUF_TYPE_META_CAPTURE: > > + size[0] = ctx->dst_fmt.buffersize; > > + break; > > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > > + size[0] = ctx->src_fmt.plane_fmt[0].sizeimage; > > + if (*num_planes == 2) > > + size[1] = ctx->src_fmt.plane_fmt[1].sizeimage; > > + break; > > + } > > Is this code above needed? The code below sets sizes[] and it uses a for loop, > without opencoded assignment for the second plane. > Looks like not really useful here, it should check sizes and num_planes if num_plane not zero, and for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, it will at most have 2 planes, maybe no need for loop as well. I will refine this function as following: mtk_fd_vb2_queue_setup(...) { struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq); if (*num_planes == 0) { if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { sizes[0] = ctx->dst_fmt.buffersize; *num_planes = 1; return 0; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { *num_planes = ctx->src_fmt.num_planes; sizes[0] = ctx->src_fmt.plane_fmt[0].sizeimage; if (*num_planes == 2) sizes[1] = ctx->src_fmt.plane_fmt[1].sizeimage; return 0; } return -EINVAL; } /* If num_plane not zero, check the num_plane and sizes*/ if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { if ((*num_planes == 1) && (sizes[0] <= ctx->dst_fmt.buffersize)) return 0; else return -EINVAL; } if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if ((*num_planes == 1) && (sizes[0] <= ctx->src_fmt.plane_fmt[0].sizeimage)) return 0; else if ((*num_planes == 2) && (sizes[0] <= ctx->src_fmt.plane_fmt[0].sizeimage) && (sizes[1] <= ctx->src_fmt.plane_fmt[1].sizeimage)) return 0; else return -EINVAL; } return 0; } > > + > > + if (*num_planes > 2) > > + return -EINVAL; > > + if (*num_planes == 0) { > > + if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { > > + sizes[0] = ctx->dst_fmt.buffersize; > > + *num_planes = 1; > > + return 0; > > + } > > + > > + *num_planes = ctx->src_fmt.num_planes; > > + for (plane = 0; plane < *num_planes; plane++) > > + sizes[plane] = ctx->src_fmt.plane_fmt[plane].sizeimage; > > + return 0; > > + } > > + > > + for (plane = 0; plane < *num_planes; plane++) { > > + if (sizes[plane] < size[plane]) > > + return -EINVAL; > > + } > > + return 0; > > +} > [snip] > > +static int mtk_fd_enum_fmt_out_mp(struct file *file, void *fh, > > + struct v4l2_fmtdesc *f) > > +{ > > + if (f->index >= NUM_FORMATS) > > Please use ARRAY_SIZE(). fixed. > > > + return -EINVAL; > > + > > + f->pixelformat = mtk_fd_img_fmts[f->index].pixelformat; > > + return 0; > > +} > > + > > +static void mtk_fd_fill_pixfmt_mp(struct v4l2_pix_format_mplane *dfmt, > > + const struct v4l2_pix_format_mplane *sfmt) > > +{ > > + dfmt->field = V4L2_FIELD_NONE; > > + dfmt->colorspace = V4L2_COLORSPACE_BT2020; > > + dfmt->num_planes = sfmt->num_planes; > > + dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; > > + dfmt->quantization = V4L2_QUANTIZATION_DEFAULT; > > + dfmt->xfer_func = > > + V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace); > > + > > + /* Keep user setting as possible */ > > + dfmt->width = clamp(dfmt->width, > > + MTK_FD_OUTPUT_MIN_WIDTH, > > + MTK_FD_OUTPUT_MAX_WIDTH); > > + dfmt->height = clamp(dfmt->height, > > + MTK_FD_OUTPUT_MIN_HEIGHT, > > + MTK_FD_OUTPUT_MAX_HEIGHT); > > + > > + if (sfmt->num_planes == 2) { > > + /* NV16M and NV61M has 1 byte per pixel */ > > + dfmt->plane_fmt[0].bytesperline = dfmt->width; > > + dfmt->plane_fmt[1].bytesperline = dfmt->width; > > + } else { > > + /* 2 bytes per pixel */ > > + dfmt->plane_fmt[0].bytesperline = dfmt->width * 2; > > + } > > + > > + dfmt->plane_fmt[0].sizeimage = > > + dfmt->height * dfmt->plane_fmt[0].bytesperline; > > Could some of the code above be replaced with v4l2_fill_pixfmt_mp()? > I would like to refine as following mtk_fd_fill_pixfmt_mp(...){ v4l2_fill_pixfmt_mp(dfmt, sfmt->pixelformat, dfmt->width, dfmt->height); dfmt->field = V4L2_FIELD_NONE; dfmt->colorspace = V4L2_COLORSPACE_BT2020; dfmt->num_planes = sfmt->num_planes; dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; dfmt->quantization = V4L2_QUANTIZATION_DEFAULT; dfmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace); } > > +} > > + > > +static const struct v4l2_pix_format_mplane *mtk_fd_find_fmt(u32 format) > > +{ > > + unsigned int i; > > + const struct v4l2_pix_format_mplane *dev_fmt; > > + > > + for (i = 0; i < NUM_FORMATS; i++) { > > Please use ARRAY_SIZE rather than a custom macro. fixed. > > > + dev_fmt = &mtk_fd_img_fmts[i]; > > + if (dev_fmt->pixelformat == format) > > + return dev_fmt; > > + } > > + > > + return NULL; > > +} > > + > > +static int mtk_fd_try_fmt_out_mp(struct file *file, > > + void *fh, > > + struct v4l2_format *f) > > +{ > > + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; > > + const struct v4l2_pix_format_mplane *fmt; > > + > > + fmt = mtk_fd_find_fmt(pix_mp->pixelformat); > > + if (!fmt) > > + fmt = &mtk_fd_img_fmts[0]; /* Get default img fmt */ > > nit: Please move the comment to a separate line and add braces. > fixed. > > + > > + mtk_fd_fill_pixfmt_mp(pix_mp, fmt); > > + return 0; > > +} > [snip] > > +static unsigned int get_fd_img_fmt(unsigned int fourcc) > > +{ > > + switch (fourcc) { > > + case V4L2_PIX_FMT_VYUY: > > + return MTK_FD_HW_FMT_VYUY; > > + case V4L2_PIX_FMT_YUYV: > > + return MTK_FD_HW_FMT_YUYV; > > + case V4L2_PIX_FMT_YVYU: > > + return MTK_FD_HW_FMT_YVYU; > > + case V4L2_PIX_FMT_UYVY: > > + return MTK_FD_HW_FMT_UYVY; > > + case V4L2_PIX_FMT_NV16M: > > + return MTK_FD_HW_FMT_YUV_2P; > > + case V4L2_PIX_FMT_NV61M: > > + return MTK_FD_HW_FMT_YVU_2P; > > + default: > > + return MTK_FD_HW_FMT_UNKNOWN; > > If we want to be paranoid, we can just add a WARN here and return 0. > Shouldn't be a need to define an unknown format. Ok, I will refine as following: default: dev_warn(dev, "%s: Unsupported V4L2_PIX_FMT\n", __func__); return 0; > > [snip] > > +static void mtk_fd_fill_user_param(struct user_param *user_param, > > + struct v4l2_ctrl_handler *hdl) > > +{ > > + struct v4l2_ctrl *ctrl; > > + int i; > > + > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_WIDTH); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->scale_img_width[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_HEIGHT); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->scale_img_height[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_IMG_NUM); > > + if (ctrl) > > + user_param->scale_img_num = ctrl->val; > > + > > nit: Either separate the code dealing with all controls from each other, or > none. > Fixed. > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_POSE); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->face_directions[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_SPEED); > > + if (ctrl) > > + user_param->fd_speedup = ctrl->val; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECTION_MODEL); > > + if (ctrl) > > + user_param->fd_extra_model = ctrl->val; > > +} > > + > > +static void mtk_fd_device_run(void *priv) > > +{ > > + struct mtk_fd_ctx *ctx = priv; > > + struct mtk_fd_dev *fd = ctx->fd_dev; > > + struct vb2_v4l2_buffer *src_buf, *dst_buf; > > + struct fd_enq_param fd_param; > > + void *plane_vaddr; > > + > > + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > > + > > + fd_param.src_img[0].dma_addr = > > + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); > > + fd_param.user_result.dma_addr = > > + vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); > > + plane_vaddr = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); > > + fd_param.output_vaddr = (u64)(unsigned long)plane_vaddr; > > Why is the vaddr needed here? Specfically, it could pose a security problem > if CPU virtual addresses are exchanged with firmware. > This should be removed... SCP side as well. > > + fd_param.user_param.src_img_fmt = > > + get_fd_img_fmt(ctx->src_fmt.pixelformat); > > + if (ctx->src_fmt.num_planes == 2) > > + fd_param.src_img[1].dma_addr = > > + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); > > nit: Could this be moved above, to be just below src_img[0] initialization, > for readability reasons? > Ok, this function will be refined as static void mtk_fd_device_run(void *priv) { struct mtk_fd_ctx *ctx = priv; struct mtk_fd_dev *fd = ctx->fd_dev; struct vb2_v4l2_buffer *src_buf, *dst_buf; struct fd_enq_param fd_param; src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); fd_param.src_img[0].dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); if (ctx->src_fmt.num_planes == 2) fd_param.src_img[1].dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); fd_param.user_result.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); fd_param.user_param.src_img_fmt = get_fd_img_fmt(fd->dev, ctx->src_fmt.pixelformat); mtk_fd_fill_user_param(&fd_param.user_param, &ctx->hdl); /* Complete request controls if any */ v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl); fd->output = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); mtk_fd_hw_job_exec(fd, &fd_param); } > > + mtk_fd_fill_user_param(&fd_param.user_param, &ctx->hdl); > > + > > + /* Complete request controls if any */ > > + v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl); > > + > > + fd->output = plane_vaddr; > > + mtk_fd_hw_job_exec(fd, &fd_param); > > +} > > + > > +static struct v4l2_m2m_ops fd_m2m_ops = { > > + .device_run = mtk_fd_device_run, > > +}; > > + > > +static const struct media_device_ops fd_m2m_media_ops = { > > + .req_validate = vb2_request_validate, > > + .req_queue = v4l2_m2m_request_queue, > > +}; > > + > > +static int mtk_fd_video_device_register(struct mtk_fd_dev *fd) > > +{ > > + struct video_device *vfd = &fd->vfd; > > + struct v4l2_m2m_dev *m2m_dev = fd->m2m_dev; > > + struct device *dev = fd->dev; > > + int ret; > > + > > + vfd->fops = &fd_video_fops; > > + vfd->release = video_device_release; > > + vfd->lock = &fd->vfd_lock; > > + vfd->v4l2_dev = &fd->v4l2_dev; > > + vfd->vfl_dir = VFL_DIR_M2M; > > + vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE | > > + V4L2_CAP_META_CAPTURE; > > + vfd->ioctl_ops = &mtk_fd_v4l2_video_out_ioctl_ops; > > + > > + strscpy(vfd->name, dev_driver_string(dev), sizeof(vfd->name)); > > + > > + video_set_drvdata(vfd, fd); > > + > > + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); > > + if (ret) { > > + dev_err(dev, "Failed to register video device\n"); > > + goto err_free_dev; > > + } > > + > > + ret = v4l2_m2m_register_media_controller(m2m_dev, vfd, > > + MEDIA_ENT_F_PROC_VIDEO_STATISTICS); > > + if (ret) { > > + dev_err(dev, "Failed to init mem2mem media controller\n"); > > + goto err_unreg_video; > > + } > > + return 0; > > + > > +err_unreg_video: > > + video_unregister_device(vfd); > > +err_free_dev: > > + video_device_release(vfd); > > + return ret; > > +} > > + > > +static int mtk_fd_dev_v4l2_init(struct mtk_fd_dev *fd) > > +{ > > + struct media_device *mdev = &fd->mdev; > > + struct device *dev = fd->dev; > > + int ret; > > + > > + ret = v4l2_device_register(dev, &fd->v4l2_dev); > > + if (ret) { > > + dev_err(dev, "Failed to register v4l2 device\n"); > > + return ret; > > + } > > + > > + fd->m2m_dev = v4l2_m2m_init(&fd_m2m_ops); > > + if (IS_ERR(fd->m2m_dev)) { > > + dev_err(dev, "Failed to init mem2mem device\n"); > > + ret = PTR_ERR(fd->m2m_dev); > > + goto err_unreg_v4l2_dev; > > + } > > + > > + mdev->dev = dev; > > + strscpy(mdev->model, dev_driver_string(dev), sizeof(mdev->model)); > > + snprintf(mdev->bus_info, sizeof(mdev->bus_info), > > + "platform:%s", dev_name(dev)); > > + media_device_init(mdev); > > + mdev->ops = &fd_m2m_media_ops; > > + fd->v4l2_dev.mdev = mdev; > > + > > + ret = mtk_fd_video_device_register(fd); > > + if (ret) { > > + dev_err(dev, "Failed to register video device\n"); > > + goto err_cleanup_mdev; > > + } > > + > > + ret = media_device_register(mdev); > > + if (ret) { > > + dev_err(dev, "Failed to register mem2mem media device\n"); > > + goto err_unreg_vdev; > > + } > > + > > + return 0; > > + > > +err_unreg_vdev: > > + v4l2_m2m_unregister_media_controller(fd->m2m_dev); > > + video_unregister_device(&fd->vfd); > > + video_device_release(&fd->vfd); > > This is inconsistent with the registration, which registers all of these in > a function. Perhaps it would be worth to move this cleanup to a > mtk_fd_video_device_unregister() function? > Fixed. > > +err_cleanup_mdev: > > + media_device_cleanup(mdev); > > + v4l2_m2m_release(fd->m2m_dev); > > +err_unreg_v4l2_dev: > > + v4l2_device_unregister(&fd->v4l2_dev); > > + return ret; > > +} > > + > > +static void mtk_fd_dev_v4l2_release(struct mtk_fd_dev *fd) > > +{ > > + v4l2_m2m_unregister_media_controller(fd->m2m_dev); > > + video_unregister_device(&fd->vfd); > > + video_device_release(&fd->vfd); > > + media_device_cleanup(&fd->mdev); > > + v4l2_m2m_release(fd->m2m_dev); > > + v4l2_device_unregister(&fd->v4l2_dev); > > +} > > + > > +static irqreturn_t mtk_fd_irq(int irq, void *data) > > +{ > > + struct mtk_fd_dev *fd = (struct mtk_fd_dev *)data; > > + > > + /* must read this register otherwise HW will keep sending irq */ > > + readl(fd->fd_base + MTK_FD_REG_OFFSET_INT_VAL); > > + fd->output->number = readl(fd->fd_base + MTK_FD_REG_OFFSET_RESULT); > > + dev_dbg(fd->dev, "mtk_fd_face_num:%d\n", fd->output->number); > > + > > + mtk_fd_hw_done(fd, VB2_BUF_STATE_DONE); > > + return IRQ_HANDLED; > > +} > > + > > +static int mtk_fd_hw_get_scp_mem(struct mtk_fd_dev *fd) > > +{ > > + struct device *dev = fd->dev; > > + dma_addr_t addr; > > + void *ptr; > > + u32 ret; > > + > > + /* > > + * Allocate coherent reserved memory for SCP firmware usage. > > + * The size of SCP composer's memory is fixed to 0x100000 > > + * for the requirement of firmware. > > + */ > > + ptr = dma_alloc_coherent(&fd->scp_pdev->dev, > > + MTK_FD_HW_WORK_BUF_SIZE, &addr, GFP_KERNEL); > > + if (!ptr) > > + return -ENOMEM; > > + > > + fd->scp_mem.scp_addr = addr; > > + fd->scp_mem_virt_addr = ptr; > > + dev_info(dev, "scp addr:%pad va:%pK\n", &addr, ptr); > > These addresses are nothing a user should be concerned about, so please > don't use the _info level here. If you think this is an important debugging > information, please make it dev_dbg(). Otherwise, please just remove. > Removed. > > + > > + /* > > + * This reserved memory is also be used by FD HW. > > + * Need to get iova address for FD DMA. > > + */ > > + addr = dma_map_resource(dev, addr, MTK_FD_HW_WORK_BUF_SIZE, > > + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); > > Note that the second argument to dma_map_resource() is phys_addr_t, but the > code above passes a DMA address. This works only by luck, because both > physical and SCP DMA address space have the same addresses. To be fully > correct, dma_map_single() needs to be used, with the kernel virtual address > passed to it, but currently it doesn't handle the memory from a reserved > pool. Thus, we can only keep the hack as is, but please add a comment > explaining it, e.g. > > /* > * FIXME: Assume SCP DMA and physical addresses are the same until > * dma_map_single() is fixed to handle reserved memory allocations. > */ > Ok, I've insert it above the comments there. as following: /* * FIXME: Assume SCP DMA and physical addresses are the same until * dma_map_single() is fixed to handle reserved memory allocations. * * This reserved memory will also be used by FD HW. * Need to get iova address for FD DMA. */ > > + if (dma_mapping_error(dev, addr)) { > > + dev_err(dev, "Failed to map scp iova\n"); > > + ret = -ENOMEM; > > + goto fail_free_mem; > > + } > > + fd->scp_mem.dma_addr = addr; > > + dev_info(dev, "scp iova addr:%pad\n", &addr); > > Ditto. fixed. > > Best regards, > Tomasz Thanks and best regards, Jerry _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFBB3C433E0 for ; Fri, 22 May 2020 14:21:24 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 92ED122460 for ; Fri, 22 May 2020 14:21:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iQTfsREr"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="euRrR6yk" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 92ED122460 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=e4fOMmi8waMUa4GxlKJsrmlH5d/asMbdhMJutS4p/uw=; b=iQTfsRErjMEiCN Ih5qCdOPwnEHehxnb9GLchJ+JqieAq8WGdbbinGN8mDJWrpISwbqFI42nHncl6GRTM1hoOLMkK4ex xtAHPF9dpUnaloQfW+dxPCCyI29f3dVH7r0XXkD61BN0eqKaWyccdwZ/xaNL5cEManBocqdOvUeHV zE//calhAKUVLzL4YkXDe4qJ1NEtI3TqJNjWMJOIPrhwhG2dIwlHf/Nb2Vk9ogYVCXDTv6UVQSIL2 jBzarHESqVfdwBg4VnFp+kW3W3DbCv5NEjhOSnVVwCgyi9skNgcjXrudlanb4iUkFqt7WpQNpOkBP 8Pw7Tjh/lmuVGkUE5aWA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jc8Xz-0004jt-TR; Fri, 22 May 2020 14:21:15 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jc8Xt-0004iJ-RS; Fri, 22 May 2020 14:21:12 +0000 X-UUID: e30fc0b0d0fb4d3995e101d7598b6c9e-20200522 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=O6kJJyACUJalT+c1EmXfnkhAwzGhDrPE+kC/YlUnpFQ=; b=euRrR6ykCaGMem3OCznfB4XIJ5FX+rNOJBxp0UFgjM/RV9YQdTtKwq+ozeyrnqzYlkiyoy/zjpi6KrQyEQtjBb9+crg4FjdXWOxe+EZQkCfgHbpPYIJx3SsS24NNID/PvLkB8joGMElI64JCUG9uvurcL+XILSX+93hgHM5QxCQ=; X-UUID: e30fc0b0d0fb4d3995e101d7598b6c9e-20200522 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1563402749; Fri, 22 May 2020 06:20:46 -0800 Received: from mtkmbs08n1.mediatek.inc (172.21.101.55) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 22 May 2020 07:10:57 -0700 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 22 May 2020 22:10:56 +0800 Received: from [172.21.84.99] (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 22 May 2020 22:10:55 +0800 Message-ID: <1590156658.27807.84.camel@mtksdccf07> Subject: Re: [RFC PATCH V4 4/4] platform: mtk-isp: Add Mediatek FD driver From: Jerry-ch Chen To: Tomasz Figa Date: Fri, 22 May 2020 22:10:58 +0800 In-Reply-To: <20200521182825.GA249683@chromium.org> References: <20191204124732.10932-1-Jerry-Ch.chen@mediatek.com> <20191204124732.10932-5-Jerry-Ch.chen@mediatek.com> <20200521182825.GA249683@chromium.org> X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200522_072110_070357_211AC7E5 X-CRM114-Status: GOOD ( 33.05 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Sean.Cheng@mediatek.com, laurent.pinchart+renesas@ideasonboard.com, Rynn.Wu@mediatek.com, zwisler@chromium.org, srv_heupstream@mediatek.com, christie.yu@mediatek.com, jerry-ch.chen@mediatek.com, hverkuil@xs4all.nl, jungo.lin@mediatek.com, sj.huang@mediatek.com, yuzhao@chromium.org, hans.verkuil@cisco.com, pihsun@chromium.org, frederic.chen@mediatek.com, matthias.bgg@gmail.com, linux-mediatek@lists.infradead.org, mchehab@kernel.org, linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi Tomasz, On Thu, 2020-05-21 at 18:28 +0000, Tomasz Figa wrote: > Hi Jerry, > > On Wed, Dec 04, 2019 at 08:47:32PM +0800, Jerry-ch Chen wrote: > > From: Jerry-ch Chen > > > > This patch adds the driver of Face Detection (FD) unit in > > Mediatek camera system, providing face detection function. > > > > The mtk-isp directory will contain drivers for multiple IP > > blocks found in Mediatek ISP system. It will include ISP Pass 1 > > driver (CAM), sensor interface driver, DIP driver and face > > detection driver. > > > > Signed-off-by: Jerry-ch Chen > > --- > > drivers/media/platform/Kconfig | 2 + > > drivers/media/platform/Makefile | 2 + > > drivers/media/platform/mtk-isp/fd/Kconfig | 19 + > > drivers/media/platform/mtk-isp/fd/Makefile | 5 + > > drivers/media/platform/mtk-isp/fd/mtk_fd.h | 149 ++ > > drivers/media/platform/mtk-isp/fd/mtk_fd_40.c | 1279 +++++++++++++++++ > > include/uapi/linux/v4l2-controls.h | 4 + > > include/uapi/linux/videodev2.h | 3 + > > 8 files changed, 1463 insertions(+) > > create mode 100644 drivers/media/platform/mtk-isp/fd/Kconfig > > create mode 100644 drivers/media/platform/mtk-isp/fd/Makefile > > create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd.h > > create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd_40.c > > > > Thank you for the patch. Please see my comments inline. Really sorry for > the much delayed review. > I appreciate your comments, here's the reply > [snip] > > +config VIDEO_MEDIATEK_FD > > + tristate "Mediatek face detection processing function" > > + depends on VIDEO_V4L2 > > + depends on ARCH_MEDIATEK > > + select VIDEOBUF2_DMA_CONTIG > > + select VIDEOBUF2_CORE > > + select VIDEOBUF2_V4L2 > > + select VIDEOBUF2_MEMOPS > > + select MEDIA_CONTROLLER > > + select MTK_SCP > > + > > + default n > > + help > > + Support the Face Detection (FD) feature in the Mediatek > > + mt8183 Soc. > > MT8183? Fixed. > > > + > > + FD driver is a V4L2 memory-to-memory device driver which > > + provides hardware accelerated face detection function, > > + it can detect different sizes of faces in a raw image. > > A YUV image I guess? Fixed > > [snip] > > diff --git a/drivers/media/platform/mtk-isp/fd/mtk_fd.h b/drivers/media/platform/mtk-isp/fd/mtk_fd.h > > new file mode 100644 > > index 000000000000..d85bdcb70d6d > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/fd/mtk_fd.h > > @@ -0,0 +1,149 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +// > > +// Copyright (c) 2018 MediaTek Inc. > > + > > +#ifndef __MTK_FD_HW_H__ > > +#define __MTK_FD_HW_H__ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define MTK_FD_OUTPUT_MIN_WIDTH 26U > > +#define MTK_FD_OUTPUT_MIN_HEIGHT 26U > > +#define MTK_FD_OUTPUT_MAX_WIDTH 640U > > +#define MTK_FD_OUTPUT_MAX_HEIGHT 480U > > + > > +#define MTK_FD_HW_FMT_VYUY 2 > > +#define MTK_FD_HW_FMT_UYVY 3 > > +#define MTK_FD_HW_FMT_YVYU 4 > > +#define MTK_FD_HW_FMT_YUYV 5 > > +#define MTK_FD_HW_FMT_YVU_2P 6 > > +#define MTK_FD_HW_FMT_YUV_2P 7 > > +#define MTK_FD_HW_FMT_UNKNOWN 8 > > What is an unknown format? It's used in translate v4l2 pixel format to the value that FD HW recognized. But I think the case of UNKNWOWN shouldn't happened. I will remove it > > > + > > +#define MTK_FD_IPI_CMD_INIT 0 > > +#define MTK_FD_IPI_CMD_INIT_ACK 1 > > +#define MTK_FD_IPI_CMD_ENQUEUE 2 > > +#define MTK_FD_IPI_CMD_ENQ_ACK 3 > > +#define MTK_FD_IPI_CMD_EXIT 4 > > +#define MTK_FD_IPI_CMD_EXIT_ACK 5 > > +#define MTK_FD_IPI_CMD_RESET 6 > > +#define MTK_FD_IPI_CMD_RESET_ACK 7 > > + > > +#define MTK_FD_REG_OFFSET_HW_ENABLE 0x4 > > +#define MTK_FD_REG_OFFSET_INT_EN 0x15c > > +#define MTK_FD_REG_OFFSET_INT_VAL 0x168 > > +#define MTK_FD_REG_OFFSET_RESULT 0x178 > > + > > +#define MTK_FD_SET_HW_ENABLE 0x111 > > +#define MTK_FD_RS_BUF_SIZE 2289664 > > +#define MTK_FD_HW_WORK_BUF_SIZE 0x100000 > > How about using the SZ_1M? > yes, fixed. > > +#define MTK_FD_MAX_SPEEDUP 7 > > +#define MTK_FD_MAX_RESULT_NUM 1026 > > Perhaps NUM_RESULTS? > fixed as MTK_FD_MAX_NUM_RESULT. > > + > > +/* Max scale size counts */ > > +#define MTK_FD_SCALE_ARR_NUM 15 > > Perhaps NUM_SCALE_SIZES? > fixed as MTK_FD_NUM_SCALE_SIZE > > + > > +#define MTK_FD_HW_TIMEOUT 1000 > > What's the unit? it's in milliseconds, I would like to rename it to MTK_FD_HW_TIMEOUT_MSEC > > > + > > +enum face_angle { > > + MTK_FD_FACE_FRONT, > > + MTK_FD_FACE_RIGHT_50, > > + MTK_FD_FACE_LEFT_50, > > + MTK_FD_FACE_RIGHT_90, > > + MTK_FD_FACE_LEFT_90, > > + MTK_FD_FACE_ANGLE_NUM, > > +}; > > This enum seems to define values for the V4L2_CID_MTK_FD_DETECT_POSE > control. Considering that this is an enumeration and the values are > actually integers (-90, -50, 0, 50, 90), perhaps this should be an > INTEGER_MENU control instead? > this ioctl let user select multiple face positions(combination of angles and directions) to be detected. so I thought I am not able to use the INTEGER_MENU for this purpose. A bit-field as following should be used by user. I consider adding it to uapi. struct face_direction_def { __u16 MTK_FD_FACE_DIR_0 : 1, MTK_FD_FACE_DIR_30 : 1, MTK_FD_FACE_DIR_60 : 1, MTK_FD_FACE_DIR_90 : 1, MTK_FD_FACE_DIR_120 : 1, MTK_FD_FACE_DIR_150 : 1, MTK_FD_FACE_DIR_180 : 1, MTK_FD_FACE_DIR_210 : 1, MTK_FD_FACE_DIR_240 : 1, MTK_FD_FACE_DIR_270 : 1, MTK_FD_FACE_DIR_300 : 1, MTK_FD_FACE_DIR_330 : 1, : 4; }; User can also select some face directions of each face angle in one ioctl, for example: /* * u16 face_directions[MTK_FD_FACE_ANGLE_NUM] = {0}; * * face_directions[MTK_FD_FACE_FRONT] = 0x7; //angle:0, dir:0,30,60 * face_directions[MTK_FACE_RIGHT_50] = 0x2; //angle:50, dir:30 * */ > > + > > +struct fd_buffer { > > + __u32 scp_addr; /* used by SCP */ > > + __u32 dma_addr; /* used by DMA HW */ > > +} __packed; fd buffer is used for scp ipi > > + > > +struct fd_face_result { > > + char data[16]; > > +}; fd_face_result is used for user, so it should be moved to include/uapi/linux. In fact, it has bit-field definition for user, so I would like to define it in include/uapi/linux as following: struct fd_face_result { __u64 face_idx : 12, type : 1, x0 : 10, y0 : 10, x1 : 10, y1 : 10, fcv1 : 11; __u64 fcv2 : 7, rip_dir : 4, rop_dir : 3, det_size : 5; }; > > + > > +struct fd_user_output { > > + struct fd_face_result results[MTK_FD_MAX_RESULT_NUM]; > > + __u16 number; > > Is this perhaps the number of results? If so, would num_results be a better > name? > yes, fixed. > > +}; > > Since this struct is the meta buffer format, it is a part of the userspace > interface and should be defined in a header under include/uapi/linux/. > Ok, I will create include/uapi/linux/mtk_fd_40.h which suppose to include structures that userspace will use. should the private IOCTLs be placed in it together? > > + > > +struct user_param { > > + u8 fd_speedup; > > + u8 fd_extra_model; > > + u8 scale_img_num; > > + u8 src_img_fmt; > > + __u16 scale_img_width[MTK_FD_SCALE_ARR_NUM]; > > + __u16 scale_img_height[MTK_FD_SCALE_ARR_NUM]; > > + __u16 face_directions[MTK_FD_FACE_ANGLE_NUM]; > > Is this a user-facing definition or an interface between the kernel driver > and firmware? If the latter, the __ types shouldn't be used. > It's the later, I'll fix it. > > +} __packed; > > + > > +struct fd_init_param { > > + struct fd_buffer fd_manager; > > + __u32 rs_dma_addr; > > Ditto. > done. > > +} __packed; > > + > > +struct fd_enq_param { > > + __u64 output_vaddr; > > Ditto. done. > > > + struct fd_buffer src_img[2]; > > + struct fd_buffer user_result; > > + struct user_param user_param; > > +} __packed; > > + > > +struct fd_ack_param { > > + __u32 ret_code; > > + __u32 ret_msg; > > Ditto. done. > > > +} __packed; > [snip] > > +/* */ > > Was there supposed to be a comment here? :) Ooops, no, it should be removed. > > > +static int mtk_fd_hw_alloc_rs_dma_addr(struct mtk_fd_dev *fd) > > +{ > > + struct device *dev = fd->dev; > > + void *va; > > + dma_addr_t dma_handle; > > + > > + va = dma_alloc_coherent(dev, MTK_FD_RS_BUF_SIZE, &dma_handle, > > + GFP_KERNEL); > > + if (!va) { > > + dev_err(dev, "dma_alloc null va\n"); > > No need to print errors for memory allocation failures, because one will be > printed automatically. Ok, log removed. > > [snip] > > +static int mtk_fd_hw_connect(struct mtk_fd_dev *fd) > > +{ > > + int ret; > > + > > + ret = rproc_boot(fd->rproc_handle); > > + > > nit: Unnecessary blank line. > fixed. > [snip] > > +static int mtk_fd_vb2_queue_setup(struct vb2_queue *vq, > > + unsigned int *num_buffers, > > + unsigned int *num_planes, > > + unsigned int sizes[], > > + struct device *alloc_devs[]) > > +{ > > + struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq); > > + unsigned int size[2]; > > + unsigned int plane; > > + > > + switch (vq->type) { > > + case V4L2_BUF_TYPE_META_CAPTURE: > > + size[0] = ctx->dst_fmt.buffersize; > > + break; > > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > > + size[0] = ctx->src_fmt.plane_fmt[0].sizeimage; > > + if (*num_planes == 2) > > + size[1] = ctx->src_fmt.plane_fmt[1].sizeimage; > > + break; > > + } > > Is this code above needed? The code below sets sizes[] and it uses a for loop, > without opencoded assignment for the second plane. > Looks like not really useful here, it should check sizes and num_planes if num_plane not zero, and for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, it will at most have 2 planes, maybe no need for loop as well. I will refine this function as following: mtk_fd_vb2_queue_setup(...) { struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq); if (*num_planes == 0) { if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { sizes[0] = ctx->dst_fmt.buffersize; *num_planes = 1; return 0; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { *num_planes = ctx->src_fmt.num_planes; sizes[0] = ctx->src_fmt.plane_fmt[0].sizeimage; if (*num_planes == 2) sizes[1] = ctx->src_fmt.plane_fmt[1].sizeimage; return 0; } return -EINVAL; } /* If num_plane not zero, check the num_plane and sizes*/ if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { if ((*num_planes == 1) && (sizes[0] <= ctx->dst_fmt.buffersize)) return 0; else return -EINVAL; } if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if ((*num_planes == 1) && (sizes[0] <= ctx->src_fmt.plane_fmt[0].sizeimage)) return 0; else if ((*num_planes == 2) && (sizes[0] <= ctx->src_fmt.plane_fmt[0].sizeimage) && (sizes[1] <= ctx->src_fmt.plane_fmt[1].sizeimage)) return 0; else return -EINVAL; } return 0; } > > + > > + if (*num_planes > 2) > > + return -EINVAL; > > + if (*num_planes == 0) { > > + if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) { > > + sizes[0] = ctx->dst_fmt.buffersize; > > + *num_planes = 1; > > + return 0; > > + } > > + > > + *num_planes = ctx->src_fmt.num_planes; > > + for (plane = 0; plane < *num_planes; plane++) > > + sizes[plane] = ctx->src_fmt.plane_fmt[plane].sizeimage; > > + return 0; > > + } > > + > > + for (plane = 0; plane < *num_planes; plane++) { > > + if (sizes[plane] < size[plane]) > > + return -EINVAL; > > + } > > + return 0; > > +} > [snip] > > +static int mtk_fd_enum_fmt_out_mp(struct file *file, void *fh, > > + struct v4l2_fmtdesc *f) > > +{ > > + if (f->index >= NUM_FORMATS) > > Please use ARRAY_SIZE(). fixed. > > > + return -EINVAL; > > + > > + f->pixelformat = mtk_fd_img_fmts[f->index].pixelformat; > > + return 0; > > +} > > + > > +static void mtk_fd_fill_pixfmt_mp(struct v4l2_pix_format_mplane *dfmt, > > + const struct v4l2_pix_format_mplane *sfmt) > > +{ > > + dfmt->field = V4L2_FIELD_NONE; > > + dfmt->colorspace = V4L2_COLORSPACE_BT2020; > > + dfmt->num_planes = sfmt->num_planes; > > + dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; > > + dfmt->quantization = V4L2_QUANTIZATION_DEFAULT; > > + dfmt->xfer_func = > > + V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace); > > + > > + /* Keep user setting as possible */ > > + dfmt->width = clamp(dfmt->width, > > + MTK_FD_OUTPUT_MIN_WIDTH, > > + MTK_FD_OUTPUT_MAX_WIDTH); > > + dfmt->height = clamp(dfmt->height, > > + MTK_FD_OUTPUT_MIN_HEIGHT, > > + MTK_FD_OUTPUT_MAX_HEIGHT); > > + > > + if (sfmt->num_planes == 2) { > > + /* NV16M and NV61M has 1 byte per pixel */ > > + dfmt->plane_fmt[0].bytesperline = dfmt->width; > > + dfmt->plane_fmt[1].bytesperline = dfmt->width; > > + } else { > > + /* 2 bytes per pixel */ > > + dfmt->plane_fmt[0].bytesperline = dfmt->width * 2; > > + } > > + > > + dfmt->plane_fmt[0].sizeimage = > > + dfmt->height * dfmt->plane_fmt[0].bytesperline; > > Could some of the code above be replaced with v4l2_fill_pixfmt_mp()? > I would like to refine as following mtk_fd_fill_pixfmt_mp(...){ v4l2_fill_pixfmt_mp(dfmt, sfmt->pixelformat, dfmt->width, dfmt->height); dfmt->field = V4L2_FIELD_NONE; dfmt->colorspace = V4L2_COLORSPACE_BT2020; dfmt->num_planes = sfmt->num_planes; dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; dfmt->quantization = V4L2_QUANTIZATION_DEFAULT; dfmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace); } > > +} > > + > > +static const struct v4l2_pix_format_mplane *mtk_fd_find_fmt(u32 format) > > +{ > > + unsigned int i; > > + const struct v4l2_pix_format_mplane *dev_fmt; > > + > > + for (i = 0; i < NUM_FORMATS; i++) { > > Please use ARRAY_SIZE rather than a custom macro. fixed. > > > + dev_fmt = &mtk_fd_img_fmts[i]; > > + if (dev_fmt->pixelformat == format) > > + return dev_fmt; > > + } > > + > > + return NULL; > > +} > > + > > +static int mtk_fd_try_fmt_out_mp(struct file *file, > > + void *fh, > > + struct v4l2_format *f) > > +{ > > + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; > > + const struct v4l2_pix_format_mplane *fmt; > > + > > + fmt = mtk_fd_find_fmt(pix_mp->pixelformat); > > + if (!fmt) > > + fmt = &mtk_fd_img_fmts[0]; /* Get default img fmt */ > > nit: Please move the comment to a separate line and add braces. > fixed. > > + > > + mtk_fd_fill_pixfmt_mp(pix_mp, fmt); > > + return 0; > > +} > [snip] > > +static unsigned int get_fd_img_fmt(unsigned int fourcc) > > +{ > > + switch (fourcc) { > > + case V4L2_PIX_FMT_VYUY: > > + return MTK_FD_HW_FMT_VYUY; > > + case V4L2_PIX_FMT_YUYV: > > + return MTK_FD_HW_FMT_YUYV; > > + case V4L2_PIX_FMT_YVYU: > > + return MTK_FD_HW_FMT_YVYU; > > + case V4L2_PIX_FMT_UYVY: > > + return MTK_FD_HW_FMT_UYVY; > > + case V4L2_PIX_FMT_NV16M: > > + return MTK_FD_HW_FMT_YUV_2P; > > + case V4L2_PIX_FMT_NV61M: > > + return MTK_FD_HW_FMT_YVU_2P; > > + default: > > + return MTK_FD_HW_FMT_UNKNOWN; > > If we want to be paranoid, we can just add a WARN here and return 0. > Shouldn't be a need to define an unknown format. Ok, I will refine as following: default: dev_warn(dev, "%s: Unsupported V4L2_PIX_FMT\n", __func__); return 0; > > [snip] > > +static void mtk_fd_fill_user_param(struct user_param *user_param, > > + struct v4l2_ctrl_handler *hdl) > > +{ > > + struct v4l2_ctrl *ctrl; > > + int i; > > + > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_WIDTH); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->scale_img_width[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_HEIGHT); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->scale_img_height[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_IMG_NUM); > > + if (ctrl) > > + user_param->scale_img_num = ctrl->val; > > + > > nit: Either separate the code dealing with all controls from each other, or > none. > Fixed. > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_POSE); > > + if (ctrl) > > + for (i = 0; i < ctrl->elems; i++) > > + user_param->face_directions[i] = ctrl->p_new.p_u16[i]; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_SPEED); > > + if (ctrl) > > + user_param->fd_speedup = ctrl->val; > > + ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECTION_MODEL); > > + if (ctrl) > > + user_param->fd_extra_model = ctrl->val; > > +} > > + > > +static void mtk_fd_device_run(void *priv) > > +{ > > + struct mtk_fd_ctx *ctx = priv; > > + struct mtk_fd_dev *fd = ctx->fd_dev; > > + struct vb2_v4l2_buffer *src_buf, *dst_buf; > > + struct fd_enq_param fd_param; > > + void *plane_vaddr; > > + > > + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > > + > > + fd_param.src_img[0].dma_addr = > > + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); > > + fd_param.user_result.dma_addr = > > + vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); > > + plane_vaddr = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); > > + fd_param.output_vaddr = (u64)(unsigned long)plane_vaddr; > > Why is the vaddr needed here? Specfically, it could pose a security problem > if CPU virtual addresses are exchanged with firmware. > This should be removed... SCP side as well. > > + fd_param.user_param.src_img_fmt = > > + get_fd_img_fmt(ctx->src_fmt.pixelformat); > > + if (ctx->src_fmt.num_planes == 2) > > + fd_param.src_img[1].dma_addr = > > + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); > > nit: Could this be moved above, to be just below src_img[0] initialization, > for readability reasons? > Ok, this function will be refined as static void mtk_fd_device_run(void *priv) { struct mtk_fd_ctx *ctx = priv; struct mtk_fd_dev *fd = ctx->fd_dev; struct vb2_v4l2_buffer *src_buf, *dst_buf; struct fd_enq_param fd_param; src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); fd_param.src_img[0].dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); if (ctx->src_fmt.num_planes == 2) fd_param.src_img[1].dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); fd_param.user_result.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); fd_param.user_param.src_img_fmt = get_fd_img_fmt(fd->dev, ctx->src_fmt.pixelformat); mtk_fd_fill_user_param(&fd_param.user_param, &ctx->hdl); /* Complete request controls if any */ v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl); fd->output = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); mtk_fd_hw_job_exec(fd, &fd_param); } > > + mtk_fd_fill_user_param(&fd_param.user_param, &ctx->hdl); > > + > > + /* Complete request controls if any */ > > + v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl); > > + > > + fd->output = plane_vaddr; > > + mtk_fd_hw_job_exec(fd, &fd_param); > > +} > > + > > +static struct v4l2_m2m_ops fd_m2m_ops = { > > + .device_run = mtk_fd_device_run, > > +}; > > + > > +static const struct media_device_ops fd_m2m_media_ops = { > > + .req_validate = vb2_request_validate, > > + .req_queue = v4l2_m2m_request_queue, > > +}; > > + > > +static int mtk_fd_video_device_register(struct mtk_fd_dev *fd) > > +{ > > + struct video_device *vfd = &fd->vfd; > > + struct v4l2_m2m_dev *m2m_dev = fd->m2m_dev; > > + struct device *dev = fd->dev; > > + int ret; > > + > > + vfd->fops = &fd_video_fops; > > + vfd->release = video_device_release; > > + vfd->lock = &fd->vfd_lock; > > + vfd->v4l2_dev = &fd->v4l2_dev; > > + vfd->vfl_dir = VFL_DIR_M2M; > > + vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE | > > + V4L2_CAP_META_CAPTURE; > > + vfd->ioctl_ops = &mtk_fd_v4l2_video_out_ioctl_ops; > > + > > + strscpy(vfd->name, dev_driver_string(dev), sizeof(vfd->name)); > > + > > + video_set_drvdata(vfd, fd); > > + > > + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); > > + if (ret) { > > + dev_err(dev, "Failed to register video device\n"); > > + goto err_free_dev; > > + } > > + > > + ret = v4l2_m2m_register_media_controller(m2m_dev, vfd, > > + MEDIA_ENT_F_PROC_VIDEO_STATISTICS); > > + if (ret) { > > + dev_err(dev, "Failed to init mem2mem media controller\n"); > > + goto err_unreg_video; > > + } > > + return 0; > > + > > +err_unreg_video: > > + video_unregister_device(vfd); > > +err_free_dev: > > + video_device_release(vfd); > > + return ret; > > +} > > + > > +static int mtk_fd_dev_v4l2_init(struct mtk_fd_dev *fd) > > +{ > > + struct media_device *mdev = &fd->mdev; > > + struct device *dev = fd->dev; > > + int ret; > > + > > + ret = v4l2_device_register(dev, &fd->v4l2_dev); > > + if (ret) { > > + dev_err(dev, "Failed to register v4l2 device\n"); > > + return ret; > > + } > > + > > + fd->m2m_dev = v4l2_m2m_init(&fd_m2m_ops); > > + if (IS_ERR(fd->m2m_dev)) { > > + dev_err(dev, "Failed to init mem2mem device\n"); > > + ret = PTR_ERR(fd->m2m_dev); > > + goto err_unreg_v4l2_dev; > > + } > > + > > + mdev->dev = dev; > > + strscpy(mdev->model, dev_driver_string(dev), sizeof(mdev->model)); > > + snprintf(mdev->bus_info, sizeof(mdev->bus_info), > > + "platform:%s", dev_name(dev)); > > + media_device_init(mdev); > > + mdev->ops = &fd_m2m_media_ops; > > + fd->v4l2_dev.mdev = mdev; > > + > > + ret = mtk_fd_video_device_register(fd); > > + if (ret) { > > + dev_err(dev, "Failed to register video device\n"); > > + goto err_cleanup_mdev; > > + } > > + > > + ret = media_device_register(mdev); > > + if (ret) { > > + dev_err(dev, "Failed to register mem2mem media device\n"); > > + goto err_unreg_vdev; > > + } > > + > > + return 0; > > + > > +err_unreg_vdev: > > + v4l2_m2m_unregister_media_controller(fd->m2m_dev); > > + video_unregister_device(&fd->vfd); > > + video_device_release(&fd->vfd); > > This is inconsistent with the registration, which registers all of these in > a function. Perhaps it would be worth to move this cleanup to a > mtk_fd_video_device_unregister() function? > Fixed. > > +err_cleanup_mdev: > > + media_device_cleanup(mdev); > > + v4l2_m2m_release(fd->m2m_dev); > > +err_unreg_v4l2_dev: > > + v4l2_device_unregister(&fd->v4l2_dev); > > + return ret; > > +} > > + > > +static void mtk_fd_dev_v4l2_release(struct mtk_fd_dev *fd) > > +{ > > + v4l2_m2m_unregister_media_controller(fd->m2m_dev); > > + video_unregister_device(&fd->vfd); > > + video_device_release(&fd->vfd); > > + media_device_cleanup(&fd->mdev); > > + v4l2_m2m_release(fd->m2m_dev); > > + v4l2_device_unregister(&fd->v4l2_dev); > > +} > > + > > +static irqreturn_t mtk_fd_irq(int irq, void *data) > > +{ > > + struct mtk_fd_dev *fd = (struct mtk_fd_dev *)data; > > + > > + /* must read this register otherwise HW will keep sending irq */ > > + readl(fd->fd_base + MTK_FD_REG_OFFSET_INT_VAL); > > + fd->output->number = readl(fd->fd_base + MTK_FD_REG_OFFSET_RESULT); > > + dev_dbg(fd->dev, "mtk_fd_face_num:%d\n", fd->output->number); > > + > > + mtk_fd_hw_done(fd, VB2_BUF_STATE_DONE); > > + return IRQ_HANDLED; > > +} > > + > > +static int mtk_fd_hw_get_scp_mem(struct mtk_fd_dev *fd) > > +{ > > + struct device *dev = fd->dev; > > + dma_addr_t addr; > > + void *ptr; > > + u32 ret; > > + > > + /* > > + * Allocate coherent reserved memory for SCP firmware usage. > > + * The size of SCP composer's memory is fixed to 0x100000 > > + * for the requirement of firmware. > > + */ > > + ptr = dma_alloc_coherent(&fd->scp_pdev->dev, > > + MTK_FD_HW_WORK_BUF_SIZE, &addr, GFP_KERNEL); > > + if (!ptr) > > + return -ENOMEM; > > + > > + fd->scp_mem.scp_addr = addr; > > + fd->scp_mem_virt_addr = ptr; > > + dev_info(dev, "scp addr:%pad va:%pK\n", &addr, ptr); > > These addresses are nothing a user should be concerned about, so please > don't use the _info level here. If you think this is an important debugging > information, please make it dev_dbg(). Otherwise, please just remove. > Removed. > > + > > + /* > > + * This reserved memory is also be used by FD HW. > > + * Need to get iova address for FD DMA. > > + */ > > + addr = dma_map_resource(dev, addr, MTK_FD_HW_WORK_BUF_SIZE, > > + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); > > Note that the second argument to dma_map_resource() is phys_addr_t, but the > code above passes a DMA address. This works only by luck, because both > physical and SCP DMA address space have the same addresses. To be fully > correct, dma_map_single() needs to be used, with the kernel virtual address > passed to it, but currently it doesn't handle the memory from a reserved > pool. Thus, we can only keep the hack as is, but please add a comment > explaining it, e.g. > > /* > * FIXME: Assume SCP DMA and physical addresses are the same until > * dma_map_single() is fixed to handle reserved memory allocations. > */ > Ok, I've insert it above the comments there. as following: /* * FIXME: Assume SCP DMA and physical addresses are the same until * dma_map_single() is fixed to handle reserved memory allocations. * * This reserved memory will also be used by FD HW. * Need to get iova address for FD DMA. */ > > + if (dma_mapping_error(dev, addr)) { > > + dev_err(dev, "Failed to map scp iova\n"); > > + ret = -ENOMEM; > > + goto fail_free_mem; > > + } > > + fd->scp_mem.dma_addr = addr; > > + dev_info(dev, "scp iova addr:%pad\n", &addr); > > Ditto. fixed. > > Best regards, > Tomasz Thanks and best regards, Jerry _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.3 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7741AC433E0 for ; Fri, 22 May 2020 14:11:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4502022226 for ; Fri, 22 May 2020 14:11:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="euRrR6yk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729796AbgEVOLW (ORCPT ); Fri, 22 May 2020 10:11:22 -0400 Received: from mailgw01.mediatek.com ([210.61.82.183]:2258 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729399AbgEVOLW (ORCPT ); Fri, 22 May 2020 10:11:22 -0400 X-UUID: e2eaaf3e1e24495a94af64af80bbba4b-20200522 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=O6kJJyACUJalT+c1EmXfnkhAwzGhDrPE+kC/YlUnpFQ=; b=euRrR6ykCaGMem3OCznfB4XIJ5FX+rNOJBxp0UFgjM/RV9YQdTtKwq+ozeyrnqzYlkiyoy/zjpi6KrQyEQtjBb9+crg4FjdXWOxe+EZQkCfgHbpPYIJx3SsS24NNID/PvLkB8joGMElI64JCUG9uvurcL+XILSX+93hgHM5QxCQ=; X-UUID: e2eaaf3e1e24495a94af64af80bbba4b-20200522 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw01.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 798828432; Fri, 22 May 2020 22:11:06 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 22 May 2020 22:10:56 +0800 Received: from [172.21.84.99] (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 22 May 2020 22:10:55 +0800 Message-ID: <1590156658.27807.84.camel@mtksdccf07> Subject: Re: [RFC PATCH V4 4/4] platform: mtk-isp: Add Mediatek FD driver From: Jerry-ch Chen To: Tomasz Figa CC: , , , , , , , , , , , , , , , , , , , Date: Fri, 22 May 2020 22:10:58 +0800 In-Reply-To: <20200521182825.GA249683@chromium.org> References: <20191204124732.10932-1-Jerry-Ch.chen@mediatek.com> <20191204124732.10932-5-Jerry-Ch.chen@mediatek.com> <20200521182825.GA249683@chromium.org> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N Content-Transfer-Encoding: base64 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org SGkgVG9tYXN6LA0KDQpPbiBUaHUsIDIwMjAtMDUtMjEgYXQgMTg6MjggKzAwMDAsIFRvbWFzeiBG aWdhIHdyb3RlOg0KPiBIaSBKZXJyeSwNCj4gDQo+IE9uIFdlZCwgRGVjIDA0LCAyMDE5IGF0IDA4 OjQ3OjMyUE0gKzA4MDAsIEplcnJ5LWNoIENoZW4gd3JvdGU6DQo+ID4gRnJvbTogSmVycnktY2gg Q2hlbiA8amVycnktY2guY2hlbkBtZWRpYXRlay5jb20+DQo+ID4gDQo+ID4gVGhpcyBwYXRjaCBh ZGRzIHRoZSBkcml2ZXIgb2YgRmFjZSBEZXRlY3Rpb24gKEZEKSB1bml0IGluDQo+ID4gTWVkaWF0 ZWsgY2FtZXJhIHN5c3RlbSwgcHJvdmlkaW5nIGZhY2UgZGV0ZWN0aW9uIGZ1bmN0aW9uLg0KPiA+ IA0KPiA+IFRoZSBtdGstaXNwIGRpcmVjdG9yeSB3aWxsIGNvbnRhaW4gZHJpdmVycyBmb3IgbXVs dGlwbGUgSVANCj4gPiBibG9ja3MgZm91bmQgaW4gTWVkaWF0ZWsgSVNQIHN5c3RlbS4gSXQgd2ls bCBpbmNsdWRlIElTUCBQYXNzIDENCj4gPiBkcml2ZXIgKENBTSksIHNlbnNvciBpbnRlcmZhY2Ug ZHJpdmVyLCBESVAgZHJpdmVyIGFuZCBmYWNlDQo+ID4gZGV0ZWN0aW9uIGRyaXZlci4NCj4gPiAN Cj4gPiBTaWduZWQtb2ZmLWJ5OiBKZXJyeS1jaCBDaGVuIDxqZXJyeS1jaC5jaGVuQG1lZGlhdGVr LmNvbT4NCj4gPiAtLS0NCj4gPiAgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9LY29uZmlnICAgICAg ICAgICAgICAgIHwgICAgMiArDQo+ID4gIGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vTWFrZWZpbGUg ICAgICAgICAgICAgICB8ICAgIDIgKw0KPiA+ICBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1p c3AvZmQvS2NvbmZpZyAgICAgfCAgIDE5ICsNCj4gPiAgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9t dGstaXNwL2ZkL01ha2VmaWxlICAgIHwgICAgNSArDQo+ID4gIGRyaXZlcnMvbWVkaWEvcGxhdGZv cm0vbXRrLWlzcC9mZC9tdGtfZmQuaCAgICB8ICAxNDkgKysNCj4gPiAgZHJpdmVycy9tZWRpYS9w bGF0Zm9ybS9tdGstaXNwL2ZkL210a19mZF80MC5jIHwgMTI3OSArKysrKysrKysrKysrKysrKw0K PiA+ICBpbmNsdWRlL3VhcGkvbGludXgvdjRsMi1jb250cm9scy5oICAgICAgICAgICAgfCAgICA0 ICsNCj4gPiAgaW5jbHVkZS91YXBpL2xpbnV4L3ZpZGVvZGV2Mi5oICAgICAgICAgICAgICAgIHwg ICAgMyArDQo+ID4gIDggZmlsZXMgY2hhbmdlZCwgMTQ2MyBpbnNlcnRpb25zKCspDQo+ID4gIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvZmQvS2NvbmZp Zw0KPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNw L2ZkL01ha2VmaWxlDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRm b3JtL210ay1pc3AvZmQvbXRrX2ZkLmgNCj4gPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv bWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9mZC9tdGtfZmRfNDAuYw0KPiA+IA0KPiANCj4gVGhhbmsg eW91IGZvciB0aGUgcGF0Y2guIFBsZWFzZSBzZWUgbXkgY29tbWVudHMgaW5saW5lLiBSZWFsbHkg c29ycnkgZm9yDQo+IHRoZSBtdWNoIGRlbGF5ZWQgcmV2aWV3Lg0KPiANCg0KSSBhcHByZWNpYXRl IHlvdXIgY29tbWVudHMsIGhlcmUncyB0aGUgcmVwbHkNCg0KPiBbc25pcF0NCj4gPiArY29uZmln IFZJREVPX01FRElBVEVLX0ZEDQo+ID4gKwl0cmlzdGF0ZSAiTWVkaWF0ZWsgZmFjZSBkZXRlY3Rp b24gcHJvY2Vzc2luZyBmdW5jdGlvbiINCj4gPiArCWRlcGVuZHMgb24gVklERU9fVjRMMg0KPiA+ ICsJZGVwZW5kcyBvbiBBUkNIX01FRElBVEVLDQo+ID4gKwlzZWxlY3QgVklERU9CVUYyX0RNQV9D T05USUcNCj4gPiArCXNlbGVjdCBWSURFT0JVRjJfQ09SRQ0KPiA+ICsJc2VsZWN0IFZJREVPQlVG Ml9WNEwyDQo+ID4gKwlzZWxlY3QgVklERU9CVUYyX01FTU9QUw0KPiA+ICsJc2VsZWN0IE1FRElB X0NPTlRST0xMRVINCj4gPiArCXNlbGVjdCBNVEtfU0NQDQo+ID4gKw0KPiA+ICsJZGVmYXVsdCBu DQo+ID4gKwloZWxwDQo+ID4gKwkJU3VwcG9ydCB0aGUgRmFjZSBEZXRlY3Rpb24gKEZEKSBmZWF0 dXJlIGluIHRoZSBNZWRpYXRlaw0KPiA+ICsJCW10ODE4MyBTb2MuDQo+IA0KPiBNVDgxODM/DQpG aXhlZC4NCg0KPiANCj4gPiArDQo+ID4gKwkJRkQgZHJpdmVyIGlzIGEgVjRMMiBtZW1vcnktdG8t bWVtb3J5IGRldmljZSBkcml2ZXIgd2hpY2gNCj4gPiArCQlwcm92aWRlcyBoYXJkd2FyZSBhY2Nl bGVyYXRlZCBmYWNlIGRldGVjdGlvbiBmdW5jdGlvbiwNCj4gPiArCQlpdCBjYW4gZGV0ZWN0IGRp ZmZlcmVudCBzaXplcyBvZiBmYWNlcyBpbiBhIHJhdyBpbWFnZS4NCj4gDQo+IEEgWVVWIGltYWdl IEkgZ3Vlc3M/DQpGaXhlZA0KDQo+IA0KPiBbc25pcF0NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVy cy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2ZkL210a19mZC5oIGIvZHJpdmVycy9tZWRpYS9wbGF0 Zm9ybS9tdGstaXNwL2ZkL210a19mZC5oDQo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBp bmRleCAwMDAwMDAwMDAwMDAuLmQ4NWJkY2I3MGQ2ZA0KPiA+IC0tLSAvZGV2L251bGwNCj4gPiAr KysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvZmQvbXRrX2ZkLmgNCj4gPiBAQCAt MCwwICsxLDE0OSBAQA0KPiA+ICsvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCAq Lw0KPiA+ICsvLw0KPiA+ICsvLyBDb3B5cmlnaHQgKGMpIDIwMTggTWVkaWFUZWsgSW5jLg0KPiA+ ICsNCj4gPiArI2lmbmRlZiBfX01US19GRF9IV19IX18NCj4gPiArI2RlZmluZSBfX01US19GRF9I V19IX18NCj4gPiArDQo+ID4gKyNpbmNsdWRlIDxsaW51eC9jb21wbGV0aW9uLmg+DQo+ID4gKyNp bmNsdWRlIDxsaW51eC9pby5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4NCj4gPiAr I2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPg0KPiA+ICsjaW5jbHVkZSA8bWVkaWEv djRsMi1jdHJscy5oPg0KPiA+ICsjaW5jbHVkZSA8bWVkaWEvdjRsMi1kZXZpY2UuaD4NCj4gPiAr I2luY2x1ZGUgPG1lZGlhL3ZpZGVvYnVmMi12NGwyLmg+DQo+ID4gKw0KPiA+ICsjZGVmaW5lIE1U S19GRF9PVVRQVVRfTUlOX1dJRFRICQkJMjZVDQo+ID4gKyNkZWZpbmUgTVRLX0ZEX09VVFBVVF9N SU5fSEVJR0hUCQkyNlUNCj4gPiArI2RlZmluZSBNVEtfRkRfT1VUUFVUX01BWF9XSURUSAkJCTY0 MFUNCj4gPiArI2RlZmluZSBNVEtfRkRfT1VUUFVUX01BWF9IRUlHSFQJCTQ4MFUNCj4gPiArDQo+ ID4gKyNkZWZpbmUgTVRLX0ZEX0hXX0ZNVF9WWVVZCQkJMg0KPiA+ICsjZGVmaW5lIE1US19GRF9I V19GTVRfVVlWWQkJCTMNCj4gPiArI2RlZmluZSBNVEtfRkRfSFdfRk1UX1lWWVUJCQk0DQo+ID4g KyNkZWZpbmUgTVRLX0ZEX0hXX0ZNVF9ZVVlWCQkJNQ0KPiA+ICsjZGVmaW5lIE1US19GRF9IV19G TVRfWVZVXzJQCQkJNg0KPiA+ICsjZGVmaW5lIE1US19GRF9IV19GTVRfWVVWXzJQCQkJNw0KPiA+ ICsjZGVmaW5lIE1US19GRF9IV19GTVRfVU5LTk9XTgkJCTgNCj4gDQo+IFdoYXQgaXMgYW4gdW5r bm93biBmb3JtYXQ/DQpJdCdzIHVzZWQgaW4gdHJhbnNsYXRlIHY0bDIgcGl4ZWwgZm9ybWF0IHRv IHRoZSB2YWx1ZSB0aGF0IEZEIEhXDQpyZWNvZ25pemVkLiBCdXQgSSB0aGluayB0aGUgY2FzZSBv ZiBVTktOV09XTiBzaG91bGRuJ3QgaGFwcGVuZWQuDQpJIHdpbGwgcmVtb3ZlIGl0DQoNCj4gDQo+ ID4gKw0KPiA+ICsjZGVmaW5lIE1US19GRF9JUElfQ01EX0lOSVQJCQkwDQo+ID4gKyNkZWZpbmUg TVRLX0ZEX0lQSV9DTURfSU5JVF9BQ0sJCQkxDQo+ID4gKyNkZWZpbmUgTVRLX0ZEX0lQSV9DTURf RU5RVUVVRQkJCTINCj4gPiArI2RlZmluZSBNVEtfRkRfSVBJX0NNRF9FTlFfQUNLCQkJMw0KPiA+ ICsjZGVmaW5lIE1US19GRF9JUElfQ01EX0VYSVQJCQk0DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX0lQ SV9DTURfRVhJVF9BQ0sJCQk1DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX0lQSV9DTURfUkVTRVQJCQk2 DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX0lQSV9DTURfUkVTRVRfQUNLCQk3DQo+ID4gKw0KPiA+ICsj ZGVmaW5lIE1US19GRF9SRUdfT0ZGU0VUX0hXX0VOQUJMRQkJMHg0DQo+ID4gKyNkZWZpbmUgTVRL X0ZEX1JFR19PRkZTRVRfSU5UX0VOCQkweDE1Yw0KPiA+ICsjZGVmaW5lIE1US19GRF9SRUdfT0ZG U0VUX0lOVF9WQUwJCTB4MTY4DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX1JFR19PRkZTRVRfUkVTVUxU CQkweDE3OA0KPiA+ICsNCj4gPiArI2RlZmluZSBNVEtfRkRfU0VUX0hXX0VOQUJMRQkJCTB4MTEx DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX1JTX0JVRl9TSVpFCQkJMjI4OTY2NA0KPiA+ICsjZGVmaW5l IE1US19GRF9IV19XT1JLX0JVRl9TSVpFCQkJMHgxMDAwMDANCj4gDQo+IEhvdyBhYm91dCB1c2lu ZyB0aGUgU1pfMU0/DQo+IA0KeWVzLCBmaXhlZC4NCj4gPiArI2RlZmluZSBNVEtfRkRfTUFYX1NQ RUVEVVAJCQk3DQo+ID4gKyNkZWZpbmUgTVRLX0ZEX01BWF9SRVNVTFRfTlVNCQkJMTAyNg0KPiAN Cj4gUGVyaGFwcyBOVU1fUkVTVUxUUz8NCj4gDQpmaXhlZCBhcyBNVEtfRkRfTUFYX05VTV9SRVNV TFQuDQoNCj4gPiArDQo+ID4gKy8qIE1heCBzY2FsZSBzaXplIGNvdW50cyAqLw0KPiA+ICsjZGVm aW5lIE1US19GRF9TQ0FMRV9BUlJfTlVNCQkJMTUNCj4gDQo+IFBlcmhhcHMgTlVNX1NDQUxFX1NJ WkVTPw0KPiANCmZpeGVkIGFzIE1US19GRF9OVU1fU0NBTEVfU0laRQ0KDQo+ID4gKw0KPiA+ICsj ZGVmaW5lIE1US19GRF9IV19USU1FT1VUCQkJMTAwMA0KPiANCj4gV2hhdCdzIHRoZSB1bml0Pw0K aXQncyBpbiBtaWxsaXNlY29uZHMsIEkgd291bGQgbGlrZSB0byByZW5hbWUgaXQgdG8NCk1US19G RF9IV19USU1FT1VUX01TRUMNCg0KPiANCj4gPiArDQo+ID4gK2VudW0gZmFjZV9hbmdsZSB7DQo+ ID4gKwlNVEtfRkRfRkFDRV9GUk9OVCwNCj4gPiArCU1US19GRF9GQUNFX1JJR0hUXzUwLA0KPiA+ ICsJTVRLX0ZEX0ZBQ0VfTEVGVF81MCwNCj4gPiArCU1US19GRF9GQUNFX1JJR0hUXzkwLA0KPiA+ ICsJTVRLX0ZEX0ZBQ0VfTEVGVF85MCwNCj4gPiArCU1US19GRF9GQUNFX0FOR0xFX05VTSwNCj4g PiArfTsNCj4gDQo+IFRoaXMgZW51bSBzZWVtcyB0byBkZWZpbmUgdmFsdWVzIGZvciB0aGUgVjRM Ml9DSURfTVRLX0ZEX0RFVEVDVF9QT1NFDQo+IGNvbnRyb2wuIENvbnNpZGVyaW5nIHRoYXQgdGhp cyBpcyBhbiBlbnVtZXJhdGlvbiBhbmQgdGhlIHZhbHVlcyBhcmUNCj4gYWN0dWFsbHkgaW50ZWdl cnMgKC05MCwgLTUwLCAwLCA1MCwgOTApLCBwZXJoYXBzIHRoaXMgc2hvdWxkIGJlIGFuDQo+IElO VEVHRVJfTUVOVSBjb250cm9sIGluc3RlYWQ/DQo+IA0KDQp0aGlzIGlvY3RsIGxldCB1c2VyIHNl bGVjdCBtdWx0aXBsZSBmYWNlIHBvc2l0aW9ucyhjb21iaW5hdGlvbiBvZiBhbmdsZXMNCmFuZCBk aXJlY3Rpb25zKSB0byBiZSBkZXRlY3RlZC4gc28gSSB0aG91Z2h0IEkgYW0gbm90IGFibGUgdG8g dXNlIHRoZQ0KSU5URUdFUl9NRU5VIGZvciB0aGlzIHB1cnBvc2UuDQoNCkEgYml0LWZpZWxkIGFz IGZvbGxvd2luZyBzaG91bGQgYmUgdXNlZCBieSB1c2VyLg0KSSBjb25zaWRlciBhZGRpbmcgaXQg dG8gdWFwaS4NCg0Kc3RydWN0IGZhY2VfZGlyZWN0aW9uX2RlZiB7DQpfX3UxNiBNVEtfRkRfRkFD RV9ESVJfMCA6IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzMwIDogMSwNCglNVEtfRkRfRkFDRV9ESVJf NjAgOiAxLA0KCU1US19GRF9GQUNFX0RJUl85MCA6IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzEyMCA6 IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzE1MCA6IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzE4MCA6IDEs DQoJTVRLX0ZEX0ZBQ0VfRElSXzIxMCA6IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzI0MCA6IDEsDQoJ TVRLX0ZEX0ZBQ0VfRElSXzI3MCA6IDEsDQoJTVRLX0ZEX0ZBQ0VfRElSXzMwMCA6IDEsDQoJTVRL X0ZEX0ZBQ0VfRElSXzMzMCA6IDEsDQoJOiA0Ow0KfTsNCg0KVXNlciBjYW4gYWxzbyBzZWxlY3Qg c29tZSBmYWNlIGRpcmVjdGlvbnMgb2YgZWFjaCBmYWNlIGFuZ2xlIGluIG9uZQ0KaW9jdGwsIGZv ciBleGFtcGxlOg0KDQovKiANCiAqIHUxNiBmYWNlX2RpcmVjdGlvbnNbTVRLX0ZEX0ZBQ0VfQU5H TEVfTlVNXSA9IHswfTsNCiAqDQogKglmYWNlX2RpcmVjdGlvbnNbTVRLX0ZEX0ZBQ0VfRlJPTlRd ID0gMHg3OyAvL2FuZ2xlOjAsIGRpcjowLDMwLDYwDQogKglmYWNlX2RpcmVjdGlvbnNbTVRLX0ZB Q0VfUklHSFRfNTBdID0gMHgyOyAvL2FuZ2xlOjUwLCBkaXI6MzAgDQogKiANCiAqLw0KDQo+ID4g Kw0KPiA+ICtzdHJ1Y3QgZmRfYnVmZmVyIHsNCj4gPiArCV9fdTMyIHNjcF9hZGRyOwkvKiB1c2Vk IGJ5IFNDUCAqLw0KPiA+ICsJX191MzIgZG1hX2FkZHI7CS8qIHVzZWQgYnkgRE1BIEhXICovDQo+ ID4gK30gX19wYWNrZWQ7DQpmZCBidWZmZXIgaXMgdXNlZCBmb3Igc2NwIGlwaQ0KDQo+ID4gKw0K PiA+ICtzdHJ1Y3QgZmRfZmFjZV9yZXN1bHQgew0KPiA+ICsJY2hhciBkYXRhWzE2XTsNCj4gPiAr fTsNCmZkX2ZhY2VfcmVzdWx0IGlzIHVzZWQgZm9yIHVzZXIsIHNvIGl0IHNob3VsZCBiZSBtb3Zl ZCB0bw0KaW5jbHVkZS91YXBpL2xpbnV4Lg0KSW4gZmFjdCwgaXQgaGFzIGJpdC1maWVsZCBkZWZp bml0aW9uIGZvciB1c2VyLCBzbyBJIHdvdWxkIGxpa2UgdG8gZGVmaW5lDQppdCBpbiBpbmNsdWRl L3VhcGkvbGludXggYXMgZm9sbG93aW5nOg0KDQpzdHJ1Y3QgZmRfZmFjZV9yZXN1bHQgew0KICBf X3U2NCBmYWNlX2lkeCA6IDEyLA0KCXR5cGUgOiAxLA0KCXgwIDogMTAsDQoJeTAgOiAxMCwNCgl4 MSA6IDEwLA0KCXkxIDogMTAsDQoJZmN2MSA6IDExOw0KICBfX3U2NCBmY3YyIDogNywNCglyaXBf ZGlyIDogNCwNCglyb3BfZGlyIDogMywNCglkZXRfc2l6ZSA6IDU7DQp9Ow0KDQoNCj4gPiArDQo+ ID4gK3N0cnVjdCBmZF91c2VyX291dHB1dCB7DQo+ID4gKwlzdHJ1Y3QgZmRfZmFjZV9yZXN1bHQg cmVzdWx0c1tNVEtfRkRfTUFYX1JFU1VMVF9OVU1dOw0KPiA+ICsJX191MTYgbnVtYmVyOw0KPiAN Cj4gSXMgdGhpcyBwZXJoYXBzIHRoZSBudW1iZXIgb2YgcmVzdWx0cz8gSWYgc28sIHdvdWxkIG51 bV9yZXN1bHRzIGJlIGEgYmV0dGVyDQo+IG5hbWU/DQo+IA0KeWVzLCBmaXhlZC4NCj4gPiArfTsN Cj4gDQo+IFNpbmNlIHRoaXMgc3RydWN0IGlzIHRoZSBtZXRhIGJ1ZmZlciBmb3JtYXQsIGl0IGlz IGEgcGFydCBvZiB0aGUgdXNlcnNwYWNlDQo+IGludGVyZmFjZSBhbmQgc2hvdWxkIGJlIGRlZmlu ZWQgaW4gYSBoZWFkZXIgdW5kZXIgaW5jbHVkZS91YXBpL2xpbnV4Ly4NCj4gDQpPaywgSSB3aWxs IGNyZWF0ZSBpbmNsdWRlL3VhcGkvbGludXgvbXRrX2ZkXzQwLmgNCndoaWNoIHN1cHBvc2UgdG8g aW5jbHVkZSBzdHJ1Y3R1cmVzIHRoYXQgdXNlcnNwYWNlIHdpbGwgdXNlLg0Kc2hvdWxkIHRoZSBw cml2YXRlIElPQ1RMcyBiZSBwbGFjZWQgaW4gaXQgdG9nZXRoZXI/DQoNCg0KPiA+ICsNCj4gPiAr c3RydWN0IHVzZXJfcGFyYW0gew0KPiA+ICsJdTggZmRfc3BlZWR1cDsNCj4gPiArCXU4IGZkX2V4 dHJhX21vZGVsOw0KPiA+ICsJdTggc2NhbGVfaW1nX251bTsNCj4gPiArCXU4IHNyY19pbWdfZm10 Ow0KPiA+ICsJX191MTYgc2NhbGVfaW1nX3dpZHRoW01US19GRF9TQ0FMRV9BUlJfTlVNXTsNCj4g PiArCV9fdTE2IHNjYWxlX2ltZ19oZWlnaHRbTVRLX0ZEX1NDQUxFX0FSUl9OVU1dOw0KPiA+ICsJ X191MTYgZmFjZV9kaXJlY3Rpb25zW01US19GRF9GQUNFX0FOR0xFX05VTV07DQo+IA0KPiBJcyB0 aGlzIGEgdXNlci1mYWNpbmcgZGVmaW5pdGlvbiBvciBhbiBpbnRlcmZhY2UgYmV0d2VlbiB0aGUg a2VybmVsIGRyaXZlcg0KPiBhbmQgZmlybXdhcmU/IElmIHRoZSBsYXR0ZXIsIHRoZSBfXyB0eXBl cyBzaG91bGRuJ3QgYmUgdXNlZC4NCj4gDQpJdCdzIHRoZSBsYXRlciwgSSdsbCBmaXggaXQuDQoN Cg0KPiA+ICt9IF9fcGFja2VkOw0KPiA+ICsNCj4gPiArc3RydWN0IGZkX2luaXRfcGFyYW0gew0K PiA+ICsJc3RydWN0IGZkX2J1ZmZlciBmZF9tYW5hZ2VyOw0KPiA+ICsJX191MzIgcnNfZG1hX2Fk ZHI7DQo+IA0KPiBEaXR0by4NCj4gDQpkb25lLg0KDQo+ID4gK30gX19wYWNrZWQ7DQo+ID4gKw0K PiA+ICtzdHJ1Y3QgZmRfZW5xX3BhcmFtIHsNCj4gPiArCV9fdTY0IG91dHB1dF92YWRkcjsNCj4g DQo+IERpdHRvLg0KZG9uZS4NCg0KPiANCj4gPiArCXN0cnVjdCBmZF9idWZmZXIgc3JjX2ltZ1sy XTsNCj4gPiArCXN0cnVjdCBmZF9idWZmZXIgdXNlcl9yZXN1bHQ7DQo+ID4gKwlzdHJ1Y3QgdXNl cl9wYXJhbSB1c2VyX3BhcmFtOw0KPiA+ICt9IF9fcGFja2VkOw0KPiA+ICsNCj4gPiArc3RydWN0 IGZkX2Fja19wYXJhbSB7DQo+ID4gKwlfX3UzMiByZXRfY29kZTsNCj4gPiArCV9fdTMyIHJldF9t c2c7DQo+IA0KPiBEaXR0by4NCmRvbmUuDQoNCj4gDQo+ID4gK30gX19wYWNrZWQ7DQo+IFtzbmlw XQ0KPiA+ICsvKiAgKi8NCj4gDQo+IFdhcyB0aGVyZSBzdXBwb3NlZCB0byBiZSBhIGNvbW1lbnQg aGVyZT8gOikNCk9vb3BzLCBubywgaXQgc2hvdWxkIGJlIHJlbW92ZWQuDQo+IA0KPiA+ICtzdGF0 aWMgaW50IG10a19mZF9od19hbGxvY19yc19kbWFfYWRkcihzdHJ1Y3QgbXRrX2ZkX2RldiAqZmQp DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IGZkLT5kZXY7DQo+ID4gKwl2b2lk ICp2YTsNCj4gPiArCWRtYV9hZGRyX3QgZG1hX2hhbmRsZTsNCj4gPiArDQo+ID4gKwl2YSA9IGRt YV9hbGxvY19jb2hlcmVudChkZXYsIE1US19GRF9SU19CVUZfU0laRSwgJmRtYV9oYW5kbGUsDQo+ ID4gKwkJCQlHRlBfS0VSTkVMKTsNCj4gPiArCWlmICghdmEpIHsNCj4gPiArCQlkZXZfZXJyKGRl diwgImRtYV9hbGxvYyBudWxsIHZhXG4iKTsNCj4gDQo+IE5vIG5lZWQgdG8gcHJpbnQgZXJyb3Jz IGZvciBtZW1vcnkgYWxsb2NhdGlvbiBmYWlsdXJlcywgYmVjYXVzZSBvbmUgd2lsbCBiZQ0KPiBw cmludGVkIGF1dG9tYXRpY2FsbHkuDQpPaywgbG9nIHJlbW92ZWQuDQo+IA0KPiBbc25pcF0NCj4g PiArc3RhdGljIGludCBtdGtfZmRfaHdfY29ubmVjdChzdHJ1Y3QgbXRrX2ZkX2RldiAqZmQpDQo+ ID4gK3sNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0gcnByb2NfYm9vdChmZC0+ cnByb2NfaGFuZGxlKTsNCj4gPiArDQo+IA0KPiBuaXQ6IFVubmVjZXNzYXJ5IGJsYW5rIGxpbmUu DQo+IA0KZml4ZWQuDQoNCj4gW3NuaXBdDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2ZkX3ZiMl9xdWV1 ZV9zZXR1cChzdHJ1Y3QgdmIyX3F1ZXVlICp2cSwNCj4gPiArCQkJCSAgdW5zaWduZWQgaW50ICpu dW1fYnVmZmVycywNCj4gPiArCQkJCSAgdW5zaWduZWQgaW50ICpudW1fcGxhbmVzLA0KPiA+ICsJ CQkJICB1bnNpZ25lZCBpbnQgc2l6ZXNbXSwNCj4gPiArCQkJCSAgc3RydWN0IGRldmljZSAqYWxs b2NfZGV2c1tdKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2ZkX2N0eCAqY3R4ID0gdmIyX2dl dF9kcnZfcHJpdih2cSk7DQo+ID4gKwl1bnNpZ25lZCBpbnQgc2l6ZVsyXTsNCj4gPiArCXVuc2ln bmVkIGludCBwbGFuZTsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKHZxLT50eXBlKSB7DQo+ID4gKwlj YXNlIFY0TDJfQlVGX1RZUEVfTUVUQV9DQVBUVVJFOg0KPiA+ICsJCXNpemVbMF0gPSBjdHgtPmRz dF9mbXQuYnVmZmVyc2l6ZTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgVjRMMl9CVUZfVFlQ RV9WSURFT19PVVRQVVRfTVBMQU5FOg0KPiA+ICsJCXNpemVbMF0gPSBjdHgtPnNyY19mbXQucGxh bmVfZm10WzBdLnNpemVpbWFnZTsNCj4gPiArCQlpZiAoKm51bV9wbGFuZXMgPT0gMikNCj4gPiAr CQkJc2l6ZVsxXSA9IGN0eC0+c3JjX2ZtdC5wbGFuZV9mbXRbMV0uc2l6ZWltYWdlOw0KPiA+ICsJ CWJyZWFrOw0KPiA+ICsJfQ0KPiANCj4gSXMgdGhpcyBjb2RlIGFib3ZlIG5lZWRlZD8gVGhlIGNv ZGUgYmVsb3cgc2V0cyBzaXplc1tdIGFuZCBpdCB1c2VzIGEgZm9yIGxvb3AsDQo+IHdpdGhvdXQg b3BlbmNvZGVkIGFzc2lnbm1lbnQgZm9yIHRoZSBzZWNvbmQgcGxhbmUuDQo+IA0KDQpMb29rcyBs aWtlIG5vdCByZWFsbHkgdXNlZnVsIGhlcmUsDQppdCBzaG91bGQgY2hlY2sgc2l6ZXMgYW5kIG51 bV9wbGFuZXMgaWYgbnVtX3BsYW5lIG5vdCB6ZXJvLA0KYW5kIGZvciBWNEwyX0JVRl9UWVBFX1ZJ REVPX09VVFBVVF9NUExBTkUsIGl0IHdpbGwgYXQgbW9zdCBoYXZlIDINCnBsYW5lcywgbWF5YmUg bm8gbmVlZCBmb3IgbG9vcCBhcyB3ZWxsLg0KSSB3aWxsIHJlZmluZSB0aGlzIGZ1bmN0aW9uIGFz IGZvbGxvd2luZzoNCm10a19mZF92YjJfcXVldWVfc2V0dXAoLi4uKQ0Kew0KCXN0cnVjdCBtdGtf ZmRfY3R4ICpjdHggPSB2YjJfZ2V0X2Rydl9wcml2KHZxKTsNCg0KCWlmICgqbnVtX3BsYW5lcyA9 PSAwKSB7DQoJCWlmICh2cS0+dHlwZSA9PSBWNEwyX0JVRl9UWVBFX01FVEFfQ0FQVFVSRSkgew0K CQkJc2l6ZXNbMF0gPSBjdHgtPmRzdF9mbXQuYnVmZmVyc2l6ZTsNCgkJCSpudW1fcGxhbmVzID0g MTsNCgkJCXJldHVybiAwOw0KCQl9IGVsc2UgaWYgKHZxLT50eXBlID09IFY0TDJfQlVGX1RZUEVf VklERU9fT1VUUFVUX01QTEFORSkgew0KCQkJKm51bV9wbGFuZXMgPSBjdHgtPnNyY19mbXQubnVt X3BsYW5lczsNCgkJCXNpemVzWzBdID0gY3R4LT5zcmNfZm10LnBsYW5lX2ZtdFswXS5zaXplaW1h Z2U7DQoJCQlpZiAoKm51bV9wbGFuZXMgPT0gMikNCgkJCQlzaXplc1sxXSA9IGN0eC0+c3JjX2Zt dC5wbGFuZV9mbXRbMV0uc2l6ZWltYWdlOw0KCQkJcmV0dXJuIDA7DQoJCX0NCgkJcmV0dXJuIC1F SU5WQUw7DQoJfQ0KDQoJLyogSWYgbnVtX3BsYW5lIG5vdCB6ZXJvLCBjaGVjayB0aGUgbnVtX3Bs YW5lIGFuZCBzaXplcyovDQoJaWYgKHZxLT50eXBlID09IFY0TDJfQlVGX1RZUEVfTUVUQV9DQVBU VVJFKSB7DQoJCWlmICgoKm51bV9wbGFuZXMgPT0gMSkgJiYNCgkJICAgIChzaXplc1swXSA8PSBj dHgtPmRzdF9mbXQuYnVmZmVyc2l6ZSkpDQoJCQlyZXR1cm4gMDsNCgkJZWxzZQ0KCQkJcmV0dXJu IC1FSU5WQUw7DQoJfQ0KCWlmICh2cS0+dHlwZSA9PSBWNEwyX0JVRl9UWVBFX1ZJREVPX09VVFBV VF9NUExBTkUpIHsNCgkJaWYgKCgqbnVtX3BsYW5lcyA9PSAxKSAmJg0KCQkgICAgKHNpemVzWzBd IDw9IGN0eC0+c3JjX2ZtdC5wbGFuZV9mbXRbMF0uc2l6ZWltYWdlKSkNCgkJCXJldHVybiAwOw0K CQllbHNlIGlmICgoKm51bV9wbGFuZXMgPT0gMikgJiYNCgkJCSAoc2l6ZXNbMF0gPD0gY3R4LT5z cmNfZm10LnBsYW5lX2ZtdFswXS5zaXplaW1hZ2UpICYmDQoJCQkgKHNpemVzWzFdIDw9IGN0eC0+ c3JjX2ZtdC5wbGFuZV9mbXRbMV0uc2l6ZWltYWdlKSkNCgkJCXJldHVybiAwOw0KCQllbHNlDQoJ CQlyZXR1cm4gLUVJTlZBTDsNCg0KCX0NCglyZXR1cm4gMDsNCn0NCg0KPiA+ICsNCj4gPiArCWlm ICgqbnVtX3BsYW5lcyA+IDIpDQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwlpZiAoKm51 bV9wbGFuZXMgPT0gMCkgew0KPiA+ICsJCWlmICh2cS0+dHlwZSA9PSBWNEwyX0JVRl9UWVBFX01F VEFfQ0FQVFVSRSkgew0KPiA+ICsJCQlzaXplc1swXSA9IGN0eC0+ZHN0X2ZtdC5idWZmZXJzaXpl Ow0KPiA+ICsJCQkqbnVtX3BsYW5lcyA9IDE7DQo+ID4gKwkJCXJldHVybiAwOw0KPiA+ICsJCSB9 DQo+ID4gKw0KPiA+ICsJCSpudW1fcGxhbmVzID0gY3R4LT5zcmNfZm10Lm51bV9wbGFuZXM7DQo+ ID4gKwkJZm9yIChwbGFuZSA9IDA7IHBsYW5lIDwgKm51bV9wbGFuZXM7IHBsYW5lKyspDQo+ID4g KwkJCXNpemVzW3BsYW5lXSA9IGN0eC0+c3JjX2ZtdC5wbGFuZV9mbXRbcGxhbmVdLnNpemVpbWFn ZTsNCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlmb3IgKHBsYW5lID0g MDsgcGxhbmUgPCAqbnVtX3BsYW5lczsgcGxhbmUrKykgew0KPiA+ICsJCWlmIChzaXplc1twbGFu ZV0gPCBzaXplW3BsYW5lXSkNCj4gPiArCQkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4g KwlyZXR1cm4gMDsNCj4gPiArfQ0KPiBbc25pcF0NCj4gPiArc3RhdGljIGludCBtdGtfZmRfZW51 bV9mbXRfb3V0X21wKHN0cnVjdCBmaWxlICpmaWxlLCB2b2lkICpmaCwNCj4gPiArCQkJCSAgc3Ry dWN0IHY0bDJfZm10ZGVzYyAqZikNCj4gPiArew0KPiA+ICsJaWYgKGYtPmluZGV4ID49IE5VTV9G T1JNQVRTKQ0KPiANCj4gUGxlYXNlIHVzZSBBUlJBWV9TSVpFKCkuDQpmaXhlZC4NCg0KPiANCj4g PiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArDQo+ID4gKwlmLT5waXhlbGZvcm1hdCA9IG10a19m ZF9pbWdfZm10c1tmLT5pbmRleF0ucGl4ZWxmb3JtYXQ7DQo+ID4gKwlyZXR1cm4gMDsNCj4gPiAr fQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgbXRrX2ZkX2ZpbGxfcGl4Zm10X21wKHN0cnVjdCB2 NGwyX3BpeF9mb3JtYXRfbXBsYW5lICpkZm10LA0KPiA+ICsJCQkJICBjb25zdCBzdHJ1Y3QgdjRs Ml9waXhfZm9ybWF0X21wbGFuZSAqc2ZtdCkNCj4gPiArew0KPiA+ICsJZGZtdC0+ZmllbGQgPSBW NEwyX0ZJRUxEX05PTkU7DQo+ID4gKwlkZm10LT5jb2xvcnNwYWNlID0gVjRMMl9DT0xPUlNQQUNF X0JUMjAyMDsNCj4gPiArCWRmbXQtPm51bV9wbGFuZXMgPSBzZm10LT5udW1fcGxhbmVzOw0KPiA+ ICsJZGZtdC0+eWNiY3JfZW5jID0gVjRMMl9ZQ0JDUl9FTkNfREVGQVVMVDsNCj4gPiArCWRmbXQt PnF1YW50aXphdGlvbiA9IFY0TDJfUVVBTlRJWkFUSU9OX0RFRkFVTFQ7DQo+ID4gKwlkZm10LT54 ZmVyX2Z1bmMgPQ0KPiA+ICsJCVY0TDJfTUFQX1hGRVJfRlVOQ19ERUZBVUxUKGRmbXQtPmNvbG9y c3BhY2UpOw0KPiA+ICsNCj4gPiArCS8qIEtlZXAgdXNlciBzZXR0aW5nIGFzIHBvc3NpYmxlICov DQo+ID4gKwlkZm10LT53aWR0aCA9IGNsYW1wKGRmbXQtPndpZHRoLA0KPiA+ICsJCQkgICAgTVRL X0ZEX09VVFBVVF9NSU5fV0lEVEgsDQo+ID4gKwkJCSAgICBNVEtfRkRfT1VUUFVUX01BWF9XSURU SCk7DQo+ID4gKwlkZm10LT5oZWlnaHQgPSBjbGFtcChkZm10LT5oZWlnaHQsDQo+ID4gKwkJCSAg ICAgTVRLX0ZEX09VVFBVVF9NSU5fSEVJR0hULA0KPiA+ICsJCQkgICAgIE1US19GRF9PVVRQVVRf TUFYX0hFSUdIVCk7DQo+ID4gKw0KPiA+ICsJaWYgKHNmbXQtPm51bV9wbGFuZXMgPT0gMikgew0K PiA+ICsJCS8qIE5WMTZNIGFuZCBOVjYxTSBoYXMgMSBieXRlIHBlciBwaXhlbCAqLw0KPiA+ICsJ CWRmbXQtPnBsYW5lX2ZtdFswXS5ieXRlc3BlcmxpbmUgPSBkZm10LT53aWR0aDsNCj4gPiArCQlk Zm10LT5wbGFuZV9mbXRbMV0uYnl0ZXNwZXJsaW5lID0gZGZtdC0+d2lkdGg7DQo+ID4gKwl9IGVs c2Ugew0KPiA+ICsJCS8qIDIgYnl0ZXMgcGVyIHBpeGVsICovDQo+ID4gKwkJZGZtdC0+cGxhbmVf Zm10WzBdLmJ5dGVzcGVybGluZSA9IGRmbXQtPndpZHRoICogMjsNCj4gPiArCX0NCj4gPiArDQo+ ID4gKwlkZm10LT5wbGFuZV9mbXRbMF0uc2l6ZWltYWdlID0NCj4gPiArCQlkZm10LT5oZWlnaHQg KiBkZm10LT5wbGFuZV9mbXRbMF0uYnl0ZXNwZXJsaW5lOw0KPiANCj4gQ291bGQgc29tZSBvZiB0 aGUgY29kZSBhYm92ZSBiZSByZXBsYWNlZCB3aXRoIHY0bDJfZmlsbF9waXhmbXRfbXAoKT8NCj4g DQpJIHdvdWxkIGxpa2UgdG8gcmVmaW5lIGFzIGZvbGxvd2luZw0KDQptdGtfZmRfZmlsbF9waXhm bXRfbXAoLi4uKXsNCgl2NGwyX2ZpbGxfcGl4Zm10X21wKGRmbXQsIHNmbXQtPnBpeGVsZm9ybWF0 LCBkZm10LT53aWR0aCwNCmRmbXQtPmhlaWdodCk7DQoNCglkZm10LT5maWVsZCA9IFY0TDJfRklF TERfTk9ORTsNCglkZm10LT5jb2xvcnNwYWNlID0gVjRMMl9DT0xPUlNQQUNFX0JUMjAyMDsNCglk Zm10LT5udW1fcGxhbmVzID0gc2ZtdC0+bnVtX3BsYW5lczsNCglkZm10LT55Y2Jjcl9lbmMgPSBW NEwyX1lDQkNSX0VOQ19ERUZBVUxUOw0KCWRmbXQtPnF1YW50aXphdGlvbiA9IFY0TDJfUVVBTlRJ WkFUSU9OX0RFRkFVTFQ7DQoJZGZtdC0+eGZlcl9mdW5jID0NCgkJVjRMMl9NQVBfWEZFUl9GVU5D X0RFRkFVTFQoZGZtdC0+Y29sb3JzcGFjZSk7DQp9DQoNCg0KPiA+ICt9DQo+ID4gKw0KPiA+ICtz dGF0aWMgY29uc3Qgc3RydWN0IHY0bDJfcGl4X2Zvcm1hdF9tcGxhbmUgKm10a19mZF9maW5kX2Zt dCh1MzIgZm9ybWF0KQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgaTsNCj4gPiArCWNvbnN0 IHN0cnVjdCB2NGwyX3BpeF9mb3JtYXRfbXBsYW5lICpkZXZfZm10Ow0KPiA+ICsNCj4gPiArCWZv ciAoaSA9IDA7IGkgPCBOVU1fRk9STUFUUzsgaSsrKSB7DQo+IA0KPiBQbGVhc2UgdXNlIEFSUkFZ X1NJWkUgcmF0aGVyIHRoYW4gYSBjdXN0b20gbWFjcm8uDQpmaXhlZC4NCg0KPiANCj4gPiArCQlk ZXZfZm10ID0gJm10a19mZF9pbWdfZm10c1tpXTsNCj4gPiArCQlpZiAoZGV2X2ZtdC0+cGl4ZWxm b3JtYXQgPT0gZm9ybWF0KQ0KPiA+ICsJCQlyZXR1cm4gZGV2X2ZtdDsNCj4gPiArCX0NCj4gPiAr DQo+ID4gKwlyZXR1cm4gTlVMTDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtf ZmRfdHJ5X2ZtdF9vdXRfbXAoc3RydWN0IGZpbGUgKmZpbGUsDQo+ID4gKwkJCQkgdm9pZCAqZmgs DQo+ID4gKwkJCQkgc3RydWN0IHY0bDJfZm9ybWF0ICpmKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3Qg djRsMl9waXhfZm9ybWF0X21wbGFuZSAqcGl4X21wID0gJmYtPmZtdC5waXhfbXA7DQo+ID4gKwlj b25zdCBzdHJ1Y3QgdjRsMl9waXhfZm9ybWF0X21wbGFuZSAqZm10Ow0KPiA+ICsNCj4gPiArCWZt dCA9IG10a19mZF9maW5kX2ZtdChwaXhfbXAtPnBpeGVsZm9ybWF0KTsNCj4gPiArCWlmICghZm10 KQ0KPiA+ICsJCWZtdCA9ICZtdGtfZmRfaW1nX2ZtdHNbMF07CS8qIEdldCBkZWZhdWx0IGltZyBm bXQgKi8NCj4gDQo+IG5pdDogUGxlYXNlIG1vdmUgdGhlIGNvbW1lbnQgdG8gYSBzZXBhcmF0ZSBs aW5lIGFuZCBhZGQgYnJhY2VzLg0KPiANCmZpeGVkLg0KDQo+ID4gKw0KPiA+ICsJbXRrX2ZkX2Zp bGxfcGl4Zm10X21wKHBpeF9tcCwgZm10KTsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+IFtz bmlwXQ0KPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IGdldF9mZF9pbWdfZm10KHVuc2lnbmVkIGlu dCBmb3VyY2MpDQo+ID4gK3sNCj4gPiArCXN3aXRjaCAoZm91cmNjKSB7DQo+ID4gKwljYXNlIFY0 TDJfUElYX0ZNVF9WWVVZOg0KPiA+ICsJCXJldHVybiBNVEtfRkRfSFdfRk1UX1ZZVVk7DQo+ID4g KwljYXNlIFY0TDJfUElYX0ZNVF9ZVVlWOg0KPiA+ICsJCXJldHVybiBNVEtfRkRfSFdfRk1UX1lV WVY7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9ZVllVOg0KPiA+ICsJCXJldHVybiBNVEtfRkRf SFdfRk1UX1lWWVU7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9VWVZZOg0KPiA+ICsJCXJldHVy biBNVEtfRkRfSFdfRk1UX1VZVlk7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9OVjE2TToNCj4g PiArCQlyZXR1cm4gTVRLX0ZEX0hXX0ZNVF9ZVVZfMlA7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZN VF9OVjYxTToNCj4gPiArCQlyZXR1cm4gTVRLX0ZEX0hXX0ZNVF9ZVlVfMlA7DQo+ID4gKwlkZWZh dWx0Og0KPiA+ICsJCXJldHVybiBNVEtfRkRfSFdfRk1UX1VOS05PV047DQo+IA0KPiBJZiB3ZSB3 YW50IHRvIGJlIHBhcmFub2lkLCB3ZSBjYW4ganVzdCBhZGQgYSBXQVJOIGhlcmUgYW5kIHJldHVy biAwLg0KPiBTaG91bGRuJ3QgYmUgYSBuZWVkIHRvIGRlZmluZSBhbiB1bmtub3duIGZvcm1hdC4N Ck9rLCBJIHdpbGwgcmVmaW5lIGFzIGZvbGxvd2luZzoNCgkNCmRlZmF1bHQ6DQoJZGV2X3dhcm4o ZGV2LCAiJXM6IFVuc3VwcG9ydGVkIFY0TDJfUElYX0ZNVFxuIiwgX19mdW5jX18pOw0KCXJldHVy biAwOw0KPiANCj4gW3NuaXBdDQo+ID4gK3N0YXRpYyB2b2lkIG10a19mZF9maWxsX3VzZXJfcGFy YW0oc3RydWN0IHVzZXJfcGFyYW0gKnVzZXJfcGFyYW0sDQo+ID4gKwkJCQkgICBzdHJ1Y3QgdjRs Ml9jdHJsX2hhbmRsZXIgKmhkbCkNCj4gPiArew0KPiA+ICsJc3RydWN0IHY0bDJfY3RybCAqY3Ry bDsNCj4gPiArCWludCBpOw0KPiA+ICsNCj4gPiArCWN0cmwgPSB2NGwyX2N0cmxfZmluZChoZGws IFY0TDJfQ0lEX01US19GRF9TQ0FMRV9ET1dOX0lNR19XSURUSCk7DQo+ID4gKwlpZiAoY3RybCkN Cj4gPiArCQlmb3IgKGkgPSAwOyBpIDwgY3RybC0+ZWxlbXM7IGkrKykNCj4gPiArCQkJdXNlcl9w YXJhbS0+c2NhbGVfaW1nX3dpZHRoW2ldID0gY3RybC0+cF9uZXcucF91MTZbaV07DQo+ID4gKwlj dHJsID0gdjRsMl9jdHJsX2ZpbmQoaGRsLCBWNEwyX0NJRF9NVEtfRkRfU0NBTEVfRE9XTl9JTUdf SEVJR0hUKTsNCj4gPiArCWlmIChjdHJsKQ0KPiA+ICsJCWZvciAoaSA9IDA7IGkgPCBjdHJsLT5l bGVtczsgaSsrKQ0KPiA+ICsJCQl1c2VyX3BhcmFtLT5zY2FsZV9pbWdfaGVpZ2h0W2ldID0gY3Ry bC0+cF9uZXcucF91MTZbaV07DQo+ID4gKwljdHJsID0gdjRsMl9jdHJsX2ZpbmQoaGRsLCBWNEwy X0NJRF9NVEtfRkRfU0NBTEVfSU1HX05VTSk7DQo+ID4gKwlpZiAoY3RybCkNCj4gPiArCQl1c2Vy X3BhcmFtLT5zY2FsZV9pbWdfbnVtID0gY3RybC0+dmFsOw0KPiA+ICsNCj4gDQo+IG5pdDogRWl0 aGVyIHNlcGFyYXRlIHRoZSBjb2RlIGRlYWxpbmcgd2l0aCBhbGwgY29udHJvbHMgZnJvbSBlYWNo IG90aGVyLCBvcg0KPiBub25lLg0KPiANCkZpeGVkLiANCg0KPiA+ICsJY3RybCA9IHY0bDJfY3Ry bF9maW5kKGhkbCwgVjRMMl9DSURfTVRLX0ZEX0RFVEVDVF9QT1NFKTsNCj4gPiArCWlmIChjdHJs KQ0KPiA+ICsJCWZvciAoaSA9IDA7IGkgPCBjdHJsLT5lbGVtczsgaSsrKQ0KPiA+ICsJCQl1c2Vy X3BhcmFtLT5mYWNlX2RpcmVjdGlvbnNbaV0gPSBjdHJsLT5wX25ldy5wX3UxNltpXTsNCj4gPiAr CWN0cmwgPSB2NGwyX2N0cmxfZmluZChoZGwsIFY0TDJfQ0lEX01US19GRF9ERVRFQ1RfU1BFRUQp Ow0KPiA+ICsJaWYgKGN0cmwpDQo+ID4gKwkJdXNlcl9wYXJhbS0+ZmRfc3BlZWR1cCA9IGN0cmwt PnZhbDsNCj4gPiArCWN0cmwgPSB2NGwyX2N0cmxfZmluZChoZGwsIFY0TDJfQ0lEX01US19GRF9E RVRFQ1RJT05fTU9ERUwpOw0KPiA+ICsJaWYgKGN0cmwpDQo+ID4gKwkJdXNlcl9wYXJhbS0+ZmRf ZXh0cmFfbW9kZWwgPSBjdHJsLT52YWw7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lk IG10a19mZF9kZXZpY2VfcnVuKHZvaWQgKnByaXYpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtf ZmRfY3R4ICpjdHggPSBwcml2Ow0KPiA+ICsJc3RydWN0IG10a19mZF9kZXYgKmZkID0gY3R4LT5m ZF9kZXY7DQo+ID4gKwlzdHJ1Y3QgdmIyX3Y0bDJfYnVmZmVyICpzcmNfYnVmLCAqZHN0X2J1ZjsN Cj4gPiArCXN0cnVjdCBmZF9lbnFfcGFyYW0gZmRfcGFyYW07DQo+ID4gKwl2b2lkICpwbGFuZV92 YWRkcjsNCj4gPiArDQo+ID4gKwlzcmNfYnVmID0gdjRsMl9tMm1fbmV4dF9zcmNfYnVmKGN0eC0+ ZmgubTJtX2N0eCk7DQo+ID4gKwlkc3RfYnVmID0gdjRsMl9tMm1fbmV4dF9kc3RfYnVmKGN0eC0+ ZmgubTJtX2N0eCk7DQo+ID4gKw0KPiA+ICsJZmRfcGFyYW0uc3JjX2ltZ1swXS5kbWFfYWRkciA9 DQo+ID4gKwkJdmIyX2RtYV9jb250aWdfcGxhbmVfZG1hX2FkZHIoJnNyY19idWYtPnZiMl9idWYs IDApOw0KPiA+ICsJZmRfcGFyYW0udXNlcl9yZXN1bHQuZG1hX2FkZHIgPQ0KPiA+ICsJCXZiMl9k bWFfY29udGlnX3BsYW5lX2RtYV9hZGRyKCZkc3RfYnVmLT52YjJfYnVmLCAwKTsNCj4gPiArCXBs YW5lX3ZhZGRyID0gdmIyX3BsYW5lX3ZhZGRyKCZkc3RfYnVmLT52YjJfYnVmLCAwKTsNCj4gPiAr CWZkX3BhcmFtLm91dHB1dF92YWRkciA9ICh1NjQpKHVuc2lnbmVkIGxvbmcpcGxhbmVfdmFkZHI7 DQo+IA0KPiBXaHkgaXMgdGhlIHZhZGRyIG5lZWRlZCBoZXJlPyBTcGVjZmljYWxseSwgaXQgY291 bGQgcG9zZSBhIHNlY3VyaXR5IHByb2JsZW0NCj4gaWYgQ1BVIHZpcnR1YWwgYWRkcmVzc2VzIGFy ZSBleGNoYW5nZWQgd2l0aCBmaXJtd2FyZS4NCj4gDQpUaGlzIHNob3VsZCBiZSByZW1vdmVkLi4u IFNDUCBzaWRlIGFzIHdlbGwuIA0KDQo+ID4gKwlmZF9wYXJhbS51c2VyX3BhcmFtLnNyY19pbWdf Zm10ID0NCj4gPiArCQlnZXRfZmRfaW1nX2ZtdChjdHgtPnNyY19mbXQucGl4ZWxmb3JtYXQpOw0K PiA+ICsJaWYgKGN0eC0+c3JjX2ZtdC5udW1fcGxhbmVzID09IDIpDQo+ID4gKwkJZmRfcGFyYW0u c3JjX2ltZ1sxXS5kbWFfYWRkciA9DQo+ID4gKwkJCXZiMl9kbWFfY29udGlnX3BsYW5lX2RtYV9h ZGRyKCZzcmNfYnVmLT52YjJfYnVmLCAxKTsNCj4gDQo+IG5pdDogQ291bGQgdGhpcyBiZSBtb3Zl ZCBhYm92ZSwgdG8gYmUganVzdCBiZWxvdyBzcmNfaW1nWzBdIGluaXRpYWxpemF0aW9uLA0KPiBm b3IgcmVhZGFiaWxpdHkgcmVhc29ucz8NCj4gDQpPaywgdGhpcyBmdW5jdGlvbiB3aWxsIGJlIHJl ZmluZWQgYXMgDQoNCnN0YXRpYyB2b2lkIG10a19mZF9kZXZpY2VfcnVuKHZvaWQgKnByaXYpDQp7 DQoJc3RydWN0IG10a19mZF9jdHggKmN0eCA9IHByaXY7DQoJc3RydWN0IG10a19mZF9kZXYgKmZk ID0gY3R4LT5mZF9kZXY7DQoJc3RydWN0IHZiMl92NGwyX2J1ZmZlciAqc3JjX2J1ZiwgKmRzdF9i dWY7DQoJc3RydWN0IGZkX2VucV9wYXJhbSBmZF9wYXJhbTsNCg0KCXNyY19idWYgPSB2NGwyX20y bV9uZXh0X3NyY19idWYoY3R4LT5maC5tMm1fY3R4KTsNCglkc3RfYnVmID0gdjRsMl9tMm1fbmV4 dF9kc3RfYnVmKGN0eC0+ZmgubTJtX2N0eCk7DQoNCglmZF9wYXJhbS5zcmNfaW1nWzBdLmRtYV9h ZGRyID0NCgkJdmIyX2RtYV9jb250aWdfcGxhbmVfZG1hX2FkZHIoJnNyY19idWYtPnZiMl9idWYs IDApOw0KCWlmIChjdHgtPnNyY19mbXQubnVtX3BsYW5lcyA9PSAyKQ0KCQlmZF9wYXJhbS5zcmNf aW1nWzFdLmRtYV9hZGRyID0NCgkJCXZiMl9kbWFfY29udGlnX3BsYW5lX2RtYV9hZGRyKCZzcmNf YnVmLT52YjJfYnVmLCAxKTsNCglmZF9wYXJhbS51c2VyX3Jlc3VsdC5kbWFfYWRkciA9DQoJCXZi Ml9kbWFfY29udGlnX3BsYW5lX2RtYV9hZGRyKCZkc3RfYnVmLT52YjJfYnVmLCAwKTsNCglmZF9w YXJhbS51c2VyX3BhcmFtLnNyY19pbWdfZm10ID0NCgkJZ2V0X2ZkX2ltZ19mbXQoZmQtPmRldiwg Y3R4LT5zcmNfZm10LnBpeGVsZm9ybWF0KTsNCg0KCW10a19mZF9maWxsX3VzZXJfcGFyYW0oJmZk X3BhcmFtLnVzZXJfcGFyYW0sICZjdHgtPmhkbCk7DQoNCgkvKiBDb21wbGV0ZSByZXF1ZXN0IGNv bnRyb2xzIGlmIGFueSAqLw0KCXY0bDJfY3RybF9yZXF1ZXN0X2NvbXBsZXRlKHNyY19idWYtPnZi Ml9idWYucmVxX29iai5yZXEsICZjdHgtPmhkbCk7DQoNCglmZC0+b3V0cHV0ID0gdmIyX3BsYW5l X3ZhZGRyKCZkc3RfYnVmLT52YjJfYnVmLCAwKTsNCgltdGtfZmRfaHdfam9iX2V4ZWMoZmQsICZm ZF9wYXJhbSk7DQp9DQo+ID4gKwltdGtfZmRfZmlsbF91c2VyX3BhcmFtKCZmZF9wYXJhbS51c2Vy X3BhcmFtLCAmY3R4LT5oZGwpOw0KPiA+ICsNCj4gPiArCS8qIENvbXBsZXRlIHJlcXVlc3QgY29u dHJvbHMgaWYgYW55ICovDQo+ID4gKwl2NGwyX2N0cmxfcmVxdWVzdF9jb21wbGV0ZShzcmNfYnVm LT52YjJfYnVmLnJlcV9vYmoucmVxLCAmY3R4LT5oZGwpOw0KPiA+ICsNCj4gPiArCWZkLT5vdXRw dXQgPSBwbGFuZV92YWRkcjsNCj4gPiArCW10a19mZF9od19qb2JfZXhlYyhmZCwgJmZkX3BhcmFt KTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCB2NGwyX20ybV9vcHMgZmRfbTJt X29wcyA9IHsNCj4gPiArCS5kZXZpY2VfcnVuID0gbXRrX2ZkX2RldmljZV9ydW4sDQo+ID4gK307 DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG1lZGlhX2RldmljZV9vcHMgZmRfbTJt X21lZGlhX29wcyA9IHsNCj4gPiArCS5yZXFfdmFsaWRhdGUJPSB2YjJfcmVxdWVzdF92YWxpZGF0 ZSwNCj4gPiArCS5yZXFfcXVldWUJPSB2NGwyX20ybV9yZXF1ZXN0X3F1ZXVlLA0KPiA+ICt9Ow0K PiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfZmRfdmlkZW9fZGV2aWNlX3JlZ2lzdGVyKHN0cnVj dCBtdGtfZmRfZGV2ICpmZCkNCj4gPiArew0KPiA+ICsJc3RydWN0IHZpZGVvX2RldmljZSAqdmZk ID0gJmZkLT52ZmQ7DQo+ID4gKwlzdHJ1Y3QgdjRsMl9tMm1fZGV2ICptMm1fZGV2ID0gZmQtPm0y bV9kZXY7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBmZC0+ZGV2Ow0KPiA+ICsJaW50IHJl dDsNCj4gPiArDQo+ID4gKwl2ZmQtPmZvcHMgPSAmZmRfdmlkZW9fZm9wczsNCj4gPiArCXZmZC0+ cmVsZWFzZSA9IHZpZGVvX2RldmljZV9yZWxlYXNlOw0KPiA+ICsJdmZkLT5sb2NrID0gJmZkLT52 ZmRfbG9jazsNCj4gPiArCXZmZC0+djRsMl9kZXYgPSAmZmQtPnY0bDJfZGV2Ow0KPiA+ICsJdmZk LT52ZmxfZGlyID0gVkZMX0RJUl9NMk07DQo+ID4gKwl2ZmQtPmRldmljZV9jYXBzID0gVjRMMl9D QVBfU1RSRUFNSU5HIHwgVjRMMl9DQVBfVklERU9fT1VUUFVUX01QTEFORSB8DQo+ID4gKwkJVjRM Ml9DQVBfTUVUQV9DQVBUVVJFOw0KPiA+ICsJdmZkLT5pb2N0bF9vcHMgPSAmbXRrX2ZkX3Y0bDJf dmlkZW9fb3V0X2lvY3RsX29wczsNCj4gPiArDQo+ID4gKwlzdHJzY3B5KHZmZC0+bmFtZSwgZGV2 X2RyaXZlcl9zdHJpbmcoZGV2KSwgc2l6ZW9mKHZmZC0+bmFtZSkpOw0KPiA+ICsNCj4gPiArCXZp ZGVvX3NldF9kcnZkYXRhKHZmZCwgZmQpOw0KPiA+ICsNCj4gPiArCXJldCA9IHZpZGVvX3JlZ2lz dGVyX2RldmljZSh2ZmQsIFZGTF9UWVBFX0dSQUJCRVIsIDApOw0KPiA+ICsJaWYgKHJldCkgew0K PiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIHJlZ2lzdGVyIHZpZGVvIGRldmljZVxuIik7 DQo+ID4gKwkJZ290byBlcnJfZnJlZV9kZXY7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0g djRsMl9tMm1fcmVnaXN0ZXJfbWVkaWFfY29udHJvbGxlcihtMm1fZGV2LCB2ZmQsDQo+ID4gKwkJ CQkJICAgICBNRURJQV9FTlRfRl9QUk9DX1ZJREVPX1NUQVRJU1RJQ1MpOw0KPiA+ICsJaWYgKHJl dCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIGluaXQgbWVtMm1lbSBtZWRpYSBj b250cm9sbGVyXG4iKTsNCj4gPiArCQlnb3RvIGVycl91bnJlZ192aWRlbzsNCj4gPiArCX0NCj4g PiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiArZXJyX3VucmVnX3ZpZGVvOg0KPiA+ICsJdmlkZW9f dW5yZWdpc3Rlcl9kZXZpY2UodmZkKTsNCj4gPiArZXJyX2ZyZWVfZGV2Og0KPiA+ICsJdmlkZW9f ZGV2aWNlX3JlbGVhc2UodmZkKTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ ID4gK3N0YXRpYyBpbnQgbXRrX2ZkX2Rldl92NGwyX2luaXQoc3RydWN0IG10a19mZF9kZXYgKmZk KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbWVkaWFfZGV2aWNlICptZGV2ID0gJmZkLT5tZGV2Ow0K PiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gZmQtPmRldjsNCj4gPiArCWludCByZXQ7DQo+ID4g Kw0KPiA+ICsJcmV0ID0gdjRsMl9kZXZpY2VfcmVnaXN0ZXIoZGV2LCAmZmQtPnY0bDJfZGV2KTsN Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byByZWdpc3Rl ciB2NGwyIGRldmljZVxuIik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ ID4gKwlmZC0+bTJtX2RldiA9IHY0bDJfbTJtX2luaXQoJmZkX20ybV9vcHMpOw0KPiA+ICsJaWYg KElTX0VSUihmZC0+bTJtX2RldikpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byBp bml0IG1lbTJtZW0gZGV2aWNlXG4iKTsNCj4gPiArCQlyZXQgPSBQVFJfRVJSKGZkLT5tMm1fZGV2 KTsNCj4gPiArCQlnb3RvIGVycl91bnJlZ192NGwyX2RldjsNCj4gPiArCX0NCj4gPiArDQo+ID4g KwltZGV2LT5kZXYgPSBkZXY7DQo+ID4gKwlzdHJzY3B5KG1kZXYtPm1vZGVsLCBkZXZfZHJpdmVy X3N0cmluZyhkZXYpLCBzaXplb2YobWRldi0+bW9kZWwpKTsNCj4gPiArCXNucHJpbnRmKG1kZXYt PmJ1c19pbmZvLCBzaXplb2YobWRldi0+YnVzX2luZm8pLA0KPiA+ICsJCSAicGxhdGZvcm06JXMi LCBkZXZfbmFtZShkZXYpKTsNCj4gPiArCW1lZGlhX2RldmljZV9pbml0KG1kZXYpOw0KPiA+ICsJ bWRldi0+b3BzID0gJmZkX20ybV9tZWRpYV9vcHM7DQo+ID4gKwlmZC0+djRsMl9kZXYubWRldiA9 IG1kZXY7DQo+ID4gKw0KPiA+ICsJcmV0ID0gbXRrX2ZkX3ZpZGVvX2RldmljZV9yZWdpc3Rlcihm ZCk7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJGYWlsZWQgdG8gcmVn aXN0ZXIgdmlkZW8gZGV2aWNlXG4iKTsNCj4gPiArCQlnb3RvIGVycl9jbGVhbnVwX21kZXY7DQo+ ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gbWVkaWFfZGV2aWNlX3JlZ2lzdGVyKG1kZXYpOw0K PiA+ICsJaWYgKHJldCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIHJlZ2lzdGVy IG1lbTJtZW0gbWVkaWEgZGV2aWNlXG4iKTsNCj4gPiArCQlnb3RvIGVycl91bnJlZ192ZGV2Ow0K PiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiArZXJyX3VucmVnX3Zk ZXY6DQo+ID4gKwl2NGwyX20ybV91bnJlZ2lzdGVyX21lZGlhX2NvbnRyb2xsZXIoZmQtPm0ybV9k ZXYpOw0KPiA+ICsJdmlkZW9fdW5yZWdpc3Rlcl9kZXZpY2UoJmZkLT52ZmQpOw0KPiA+ICsJdmlk ZW9fZGV2aWNlX3JlbGVhc2UoJmZkLT52ZmQpOw0KPiANCj4gVGhpcyBpcyBpbmNvbnNpc3RlbnQg d2l0aCB0aGUgcmVnaXN0cmF0aW9uLCB3aGljaCByZWdpc3RlcnMgYWxsIG9mIHRoZXNlIGluDQo+ IGEgZnVuY3Rpb24uIFBlcmhhcHMgaXQgd291bGQgYmUgd29ydGggdG8gbW92ZSB0aGlzIGNsZWFu dXAgdG8gYQ0KPiBtdGtfZmRfdmlkZW9fZGV2aWNlX3VucmVnaXN0ZXIoKSBmdW5jdGlvbj8NCj4g DQpGaXhlZC4NCg0KPiA+ICtlcnJfY2xlYW51cF9tZGV2Og0KPiA+ICsJbWVkaWFfZGV2aWNlX2Ns ZWFudXAobWRldik7DQo+ID4gKwl2NGwyX20ybV9yZWxlYXNlKGZkLT5tMm1fZGV2KTsNCj4gPiAr ZXJyX3VucmVnX3Y0bDJfZGV2Og0KPiA+ICsJdjRsMl9kZXZpY2VfdW5yZWdpc3RlcigmZmQtPnY0 bDJfZGV2KTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2 b2lkIG10a19mZF9kZXZfdjRsMl9yZWxlYXNlKHN0cnVjdCBtdGtfZmRfZGV2ICpmZCkNCj4gPiAr ew0KPiA+ICsJdjRsMl9tMm1fdW5yZWdpc3Rlcl9tZWRpYV9jb250cm9sbGVyKGZkLT5tMm1fZGV2 KTsNCj4gPiArCXZpZGVvX3VucmVnaXN0ZXJfZGV2aWNlKCZmZC0+dmZkKTsNCj4gPiArCXZpZGVv X2RldmljZV9yZWxlYXNlKCZmZC0+dmZkKTsNCj4gPiArCW1lZGlhX2RldmljZV9jbGVhbnVwKCZm ZC0+bWRldik7DQo+ID4gKwl2NGwyX20ybV9yZWxlYXNlKGZkLT5tMm1fZGV2KTsNCj4gPiArCXY0 bDJfZGV2aWNlX3VucmVnaXN0ZXIoJmZkLT52NGwyX2Rldik7DQo+ID4gK30NCj4gPiArDQo+ID4g K3N0YXRpYyBpcnFyZXR1cm5fdCBtdGtfZmRfaXJxKGludCBpcnEsIHZvaWQgKmRhdGEpDQo+ID4g K3sNCj4gPiArCXN0cnVjdCBtdGtfZmRfZGV2ICpmZCA9IChzdHJ1Y3QgbXRrX2ZkX2RldiAqKWRh dGE7DQo+ID4gKw0KPiA+ICsJLyogbXVzdCByZWFkIHRoaXMgcmVnaXN0ZXIgb3RoZXJ3aXNlIEhX IHdpbGwga2VlcCBzZW5kaW5nIGlycSAqLw0KPiA+ICsJcmVhZGwoZmQtPmZkX2Jhc2UgKyBNVEtf RkRfUkVHX09GRlNFVF9JTlRfVkFMKTsNCj4gPiArCWZkLT5vdXRwdXQtPm51bWJlciA9IHJlYWRs KGZkLT5mZF9iYXNlICsgTVRLX0ZEX1JFR19PRkZTRVRfUkVTVUxUKTsNCj4gPiArCWRldl9kYmco ZmQtPmRldiwgIm10a19mZF9mYWNlX251bTolZFxuIiwgZmQtPm91dHB1dC0+bnVtYmVyKTsNCj4g PiArDQo+ID4gKwltdGtfZmRfaHdfZG9uZShmZCwgVkIyX0JVRl9TVEFURV9ET05FKTsNCj4gPiAr CXJldHVybiBJUlFfSEFORExFRDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtf ZmRfaHdfZ2V0X3NjcF9tZW0oc3RydWN0IG10a19mZF9kZXYgKmZkKQ0KPiA+ICt7DQo+ID4gKwlz dHJ1Y3QgZGV2aWNlICpkZXYgPSBmZC0+ZGV2Ow0KPiA+ICsJZG1hX2FkZHJfdCBhZGRyOw0KPiA+ ICsJdm9pZCAqcHRyOw0KPiA+ICsJdTMyIHJldDsNCj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJICog QWxsb2NhdGUgY29oZXJlbnQgcmVzZXJ2ZWQgbWVtb3J5IGZvciBTQ1AgZmlybXdhcmUgdXNhZ2Uu DQo+ID4gKwkgKiBUaGUgc2l6ZSBvZiBTQ1AgY29tcG9zZXIncyBtZW1vcnkgaXMgZml4ZWQgdG8g MHgxMDAwMDANCj4gPiArCSAqIGZvciB0aGUgcmVxdWlyZW1lbnQgb2YgZmlybXdhcmUuDQo+ID4g KwkgKi8NCj4gPiArCXB0ciA9IGRtYV9hbGxvY19jb2hlcmVudCgmZmQtPnNjcF9wZGV2LT5kZXYs DQo+ID4gKwkJCQkgTVRLX0ZEX0hXX1dPUktfQlVGX1NJWkUsICZhZGRyLCBHRlBfS0VSTkVMKTsN Cj4gPiArCWlmICghcHRyKQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiArCWZk LT5zY3BfbWVtLnNjcF9hZGRyID0gYWRkcjsNCj4gPiArCWZkLT5zY3BfbWVtX3ZpcnRfYWRkciA9 IHB0cjsNCj4gPiArCWRldl9pbmZvKGRldiwgInNjcCBhZGRyOiVwYWQgdmE6JXBLXG4iLCAmYWRk ciwgcHRyKTsNCj4gDQo+IFRoZXNlIGFkZHJlc3NlcyBhcmUgbm90aGluZyBhIHVzZXIgc2hvdWxk IGJlIGNvbmNlcm5lZCBhYm91dCwgc28gcGxlYXNlDQo+IGRvbid0IHVzZSB0aGUgX2luZm8gbGV2 ZWwgaGVyZS4gSWYgeW91IHRoaW5rIHRoaXMgaXMgYW4gaW1wb3J0YW50IGRlYnVnZ2luZw0KPiBp bmZvcm1hdGlvbiwgcGxlYXNlIG1ha2UgaXQgZGV2X2RiZygpLiBPdGhlcndpc2UsIHBsZWFzZSBq dXN0IHJlbW92ZS4NCj4gDQpSZW1vdmVkLg0KDQo+ID4gKw0KPiA+ICsJLyoNCj4gPiArCSAqIFRo aXMgcmVzZXJ2ZWQgbWVtb3J5IGlzIGFsc28gYmUgdXNlZCBieSBGRCBIVy4NCj4gPiArCSAqIE5l ZWQgdG8gZ2V0IGlvdmEgYWRkcmVzcyBmb3IgRkQgRE1BLg0KPiA+ICsJICovDQo+ID4gKwlhZGRy ID0gZG1hX21hcF9yZXNvdXJjZShkZXYsIGFkZHIsIE1US19GRF9IV19XT1JLX0JVRl9TSVpFLA0K PiA+ICsJCQkJRE1BX1RPX0RFVklDRSwgRE1BX0FUVFJfU0tJUF9DUFVfU1lOQyk7DQo+IA0KPiBO b3RlIHRoYXQgdGhlIHNlY29uZCBhcmd1bWVudCB0byBkbWFfbWFwX3Jlc291cmNlKCkgaXMgcGh5 c19hZGRyX3QsIGJ1dCB0aGUNCj4gY29kZSBhYm92ZSBwYXNzZXMgYSBETUEgYWRkcmVzcy4gVGhp cyB3b3JrcyBvbmx5IGJ5IGx1Y2ssIGJlY2F1c2UgYm90aA0KPiBwaHlzaWNhbCBhbmQgU0NQIERN QSBhZGRyZXNzIHNwYWNlIGhhdmUgdGhlIHNhbWUgYWRkcmVzc2VzLiBUbyBiZSBmdWxseQ0KPiBj b3JyZWN0LCBkbWFfbWFwX3NpbmdsZSgpIG5lZWRzIHRvIGJlIHVzZWQsIHdpdGggdGhlIGtlcm5l bCB2aXJ0dWFsIGFkZHJlc3MNCj4gcGFzc2VkIHRvIGl0LCBidXQgY3VycmVudGx5IGl0IGRvZXNu J3QgaGFuZGxlIHRoZSBtZW1vcnkgZnJvbSBhIHJlc2VydmVkDQo+IHBvb2wuIFRodXMsIHdlIGNh biBvbmx5IGtlZXAgdGhlIGhhY2sgYXMgaXMsIGJ1dCBwbGVhc2UgYWRkIGEgY29tbWVudA0KPiBl eHBsYWluaW5nIGl0LCBlLmcuDQo+IA0KPiAvKg0KPiAgKiBGSVhNRTogQXNzdW1lIFNDUCBETUEg YW5kIHBoeXNpY2FsIGFkZHJlc3NlcyBhcmUgdGhlIHNhbWUgdW50aWwNCj4gICogZG1hX21hcF9z aW5nbGUoKSBpcyBmaXhlZCB0byBoYW5kbGUgcmVzZXJ2ZWQgbWVtb3J5IGFsbG9jYXRpb25zLg0K PiAgKi8NCj4gDQpPaywgSSd2ZSBpbnNlcnQgaXQgYWJvdmUgdGhlIGNvbW1lbnRzIHRoZXJlLg0K YXMgZm9sbG93aW5nOg0KDQovKg0KICogRklYTUU6IEFzc3VtZSBTQ1AgRE1BIGFuZCBwaHlzaWNh bCBhZGRyZXNzZXMgYXJlIHRoZSBzYW1lIHVudGlsDQogKiBkbWFfbWFwX3NpbmdsZSgpIGlzIGZp eGVkIHRvIGhhbmRsZSByZXNlcnZlZCBtZW1vcnkgYWxsb2NhdGlvbnMuDQogKg0KICogVGhpcyBy ZXNlcnZlZCBtZW1vcnkgd2lsbCBhbHNvIGJlIHVzZWQgYnkgRkQgSFcuDQogKiBOZWVkIHRvIGdl dCBpb3ZhIGFkZHJlc3MgZm9yIEZEIERNQS4NCiAqLw0KDQo+ID4gKwlpZiAoZG1hX21hcHBpbmdf ZXJyb3IoZGV2LCBhZGRyKSkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIG1hcCBz Y3AgaW92YVxuIik7DQo+ID4gKwkJcmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3RvIGZhaWxfZnJl ZV9tZW07DQo+ID4gKwl9DQo+ID4gKwlmZC0+c2NwX21lbS5kbWFfYWRkciA9IGFkZHI7DQo+ID4g KwlkZXZfaW5mbyhkZXYsICJzY3AgaW92YSBhZGRyOiVwYWRcbiIsICZhZGRyKTsNCj4gDQo+IERp dHRvLg0KZml4ZWQuDQoNCj4gDQo+IEJlc3QgcmVnYXJkcywNCj4gVG9tYXN6DQoNClRoYW5rcyBh bmQgYmVzdCByZWdhcmRzLA0KSmVycnkNCg0K