From patchwork Mon Mar 20 10:56:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 9633737 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C30B460327 for ; Mon, 20 Mar 2017 10:59:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B2A6E27F17 for ; Mon, 20 Mar 2017 10:59:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A78E227F94; Mon, 20 Mar 2017 10:59:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F33DB27F85 for ; Mon, 20 Mar 2017 10:59:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753422AbdCTK7C (ORCPT ); Mon, 20 Mar 2017 06:59:02 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:30564 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753676AbdCTK5S (ORCPT ); Mon, 20 Mar 2017 06:57:18 -0400 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0ON400EHG12VLE20@mailout3.w1.samsung.com>; Mon, 20 Mar 2017 10:56:55 +0000 (GMT) Received: from eusmges5.samsung.com (unknown [203.254.199.245]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170320105654eucas1p2c7cca84d61a1554ed4850f0453405ed0~tkdldL-BD2733327333eucas1p29; Mon, 20 Mar 2017 10:56:54 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges5.samsung.com (EUCPMTA) with SMTP id 8D.7B.17477.675BFC85; Mon, 20 Mar 2017 10:56:54 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170320105653eucas1p20276c75ba618fbed0e70a78fc14394f8~tkdkmuEzE2242222422eucas1p2M; Mon, 20 Mar 2017 10:56:53 +0000 (GMT) X-AuditID: cbfec7f5-f79d06d000004445-7d-58cfb576c0ee Received: from eusync4.samsung.com ( [203.254.199.214]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 24.E7.06687.FD5BFC85; Mon, 20 Mar 2017 10:58:39 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0ON4005OP12KYT20@eusync4.samsung.com>; Mon, 20 Mar 2017 10:56:53 +0000 (GMT) From: Marek Szyprowski To: linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Sylwester Nawrocki , Andrzej Hajda , Krzysztof Kozlowski , Inki Dae , Seung-Woo Kim Subject: [PATCH v3 12/16] media: s5p-mfc: Add support for probe-time preallocated block based allocator Date: Mon, 20 Mar 2017 11:56:38 +0100 Message-id: <1490007402-30265-13-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1490007402-30265-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrCIsWRmVeSWpSXmKPExsWy7djPc7plW89HGPxbzGtxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDmKyyYl NSezLLVI3y6BK+PrxaWMBbvsK3p2X2BrYPxk0sXIySEhYCJx+sQhdghbTOLCvfVsXYxcHEIC SxklLl46wQzhfGaUeLh/NVAVB1jHmY3mEPFljBJn5myCKmpgkrgz6wczyCg2AUOJrrddbCC2 iICTxMJZf9lBipgFvjNKfNt9mhUkISyQKXGhZwdYEYuAqsSyV2fAbF4BT4lZPy+xQtwkJ3Hy 2GQwmxMo/uL6X7D7JARes0lc7bsMdZKsxKYDzBD1LhJ3r12HsoUlXh3fAvWbjERnx0EmCLuf UaKpVRvCnsEoce4tL4RtLXH4+EWwXcwCfBKTtk1nhhjPK9HRJgRR4iHx+OEqNgjbUWLFyves EM/PYZTYO2kZ6wRGmQWMDKsYRVJLi3PTU4tN9YoTc4tL89L1kvNzNzEC4/b0v+NfdzAuPWZ1 iFGAg1GJh9fg6rkIIdbEsuLK3EOMEhzMSiK8H+eejxDiTUmsrEotyo8vKs1JLT7EKM3BoiTO u2fBlXAhgfTEktTs1NSC1CKYLBMHp1QD49LzmkphQmXnyy5Pqv0neNlYY6Y434sKli0KpuE3 7gkpfFb+11by8dh6rxmTb6ie9Jx+vs3keXL367V+ZXL5W/dfncaU/XGdgvakRpGVM25lKJVv 6GVYxn5n3pPCBVOOLdPIPhpSMXfO9nsVZXNfLw09vapgmWa32m59Rsk/h75X1JucdC+cP0WJ pTgj0VCLuag4EQCpX8NH1wIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrMLMWRmVeSWpSXmKPExsVy+t/xa7r3t56PMFjZIWVxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDnKzSYj NTEltUghNS85PyUzL91WKTTETddCSSEvMTfVVilC1zckSEmhLDGnFMgzMkADDs4B7sFK+nYJ bhlfLy5lLNhlX9Gz+wJbA+Mnky5GDg4JAROJMxvNuxg5gUwxiQv31rN1MXJxCAksYZT4fu0n E4TTxCRxdGUvG0gVm4ChRNfbLjBbRMBJYuGsv+wgNrPAd0aJZTfTQGxhgUyJCz07wGpYBFQl lr06A2bzCnhKzPp5iRVim5zEyWOTwWxOoPiL63/BaoQEPCTWfZ7INIGRdwEjwypGkdTS4tz0 3GJDveLE3OLSvHS95PzcTYzAAN527OfmHYyXNgYfYhTgYFTi4TW4ei5CiDWxrLgy9xCjBAez kgjvx7nnI4R4UxIrq1KL8uOLSnNSiw8xmgIdNZFZSjQ5HxhdeSXxhiaG5paGRsYWFuZGRkri vCUfroQLCaQnlqRmp6YWpBbB9DFxcEo1MJafvhN4/uwBVgmt+dfVqiXyzs8ttUo9nvVr8+zq lBXLbjNmLbe+Va3X87hdk3Hh9ieTpO78jxf/P9OyONRpzr4akSP3mUWj3yj9VFt5hv3gRrbX d+ZxzJqgl7WYdyZTm2pyvrWlqouWv//lekWfFaVf9HjvP13B8kr/1MKeKeVn/mevnjSvIFOJ pTgj0VCLuag4EQBYKzLrdgIAAA== X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170320105653eucas1p20276c75ba618fbed0e70a78fc14394f8 X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRs=?= =?UTF-8?B?7IK87ISx7KCE7J6QG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Global-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRtT?= =?UTF-8?B?YW1zdW5nIEVsZWN0cm9uaWNzG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTI=?= CMS-TYPE: 201P X-HopCount: 7 X-CMS-RootMailID: 20170320105653eucas1p20276c75ba618fbed0e70a78fc14394f8 X-RootMTR: 20170320105653eucas1p20276c75ba618fbed0e70a78fc14394f8 References: <1490007402-30265-1-git-send-email-m.szyprowski@samsung.com> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current MFC driver depends on the fact that when IOMMU is available, the DMA-mapping framework and its IOMMU glue will use first-fit allocator. This was true for ARM architecture, but its not for ARM64 arch. However, in case of MFC v6+ hardware and latest firmware, it turned out that there is no strict requirement for ALL buffers to be allocated on higher addresses than the firmware base. This requirement is true only for the device and per-context buffers. All video data buffers can be allocated anywhere for all MFC v6+ versions. Such relaxed requirements for the memory buffers can be easily fulfilled by allocating firmware, device and per-context buffers from the probe-time preallocated larger buffer. This patch adds support for it. This way the driver finally works fine on ARM64 architecture. The size of the preallocated buffer is 8 MiB, what is enough for three instances H264 decoders or encoders (other codecs have smaller memory requirements). If one needs more for particular use case, one can use "mem" module parameter to force larger (or smaller) buffer (for example by adding "s5p_mfc.mem=16M" to kernel command line). Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 43 ++++++++++++++++--- drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 4 ++ drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 57 ++++++++++++++++--------- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index ff3bb8af2423..ea01d0aa8303 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -43,6 +43,10 @@ module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages"); +static char *mfc_mem_size = NULL; +module_param_named(mem, mfc_mem_size, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers"); + /* Helper functions for interrupt processing */ /* Remove from hw execution round robin */ @@ -1173,6 +1177,8 @@ static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; + unsigned long mem_size = SZ_8M; + unsigned int bitmap_size; /* * When IOMMU is available, we cannot use the default configuration, * because of MFC firmware requirements: address space limited to @@ -1186,17 +1192,39 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) if (ret) return ret; - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { + if (mfc_mem_size) + mem_size = memparse(mfc_mem_size, NULL); + + bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); + + mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!mfc_dev->mem_bitmap) { exynos_unconfigure_iommu(dev); - return ret; + return -ENOMEM; } - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; - mfc_dev->dma_base[BANK2_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, + &mfc_dev->mem_base, GFP_KERNEL); + if (!mfc_dev->mem_virt) { + kfree(mfc_dev->mem_bitmap); + dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", + (mem_size / SZ_1M)); + exynos_unconfigure_iommu(dev); + return -ENOMEM; + } + mfc_dev->mem_size = mem_size; + mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; + mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; + + /* Firmware allocation cannot fail in this case */ + s5p_mfc_alloc_firmware(mfc_dev); + + mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n", + (mem_size / SZ_1M)); + return 0; } @@ -1205,6 +1233,9 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; exynos_unconfigure_iommu(dev); + dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, + mfc_dev->mem_base); + kfree(mfc_dev->mem_bitmap); vb2_dma_contig_clear_max_seg_size(dev); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index cea17a737ef7..e64dc6e3c75e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -315,6 +315,10 @@ struct s5p_mfc_dev { unsigned int int_err; wait_queue_head_t queue; struct s5p_mfc_priv_buf fw_buf; + size_t mem_size; + dma_addr_t mem_base; + unsigned long *mem_bitmap; + void *mem_virt; dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 9294ee124661..34a66189d980 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -40,41 +40,60 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[mem_ctx]; - dma_addr_t base = dev->dma_base[mem_ctx]; + unsigned int bits = dev->mem_size >> PAGE_SHIFT; + unsigned int count = b->size >> PAGE_SHIFT; + unsigned int align = (SZ_64K >> PAGE_SHIFT) - 1; + unsigned int start, offset; mfc_debug(3, "Allocating priv: %zu\n", b->size); - b->ctx = mem_ctx; - b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + if (dev->mem_virt) { + start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align); + if (start > bits) + goto no_mem; - if (!b->virt) { - mfc_err("Allocating private buffer of size %zu failed\n", - b->size); - return -ENOMEM; - } + bitmap_set(dev->mem_bitmap, start, count); + offset = start << PAGE_SHIFT; + b->virt = dev->mem_virt + offset; + b->dma = dev->mem_base + offset; + } else { + struct device *mem_dev = dev->mem_dev[mem_ctx]; + dma_addr_t base = dev->dma_base[mem_ctx]; - if (b->dma < base) { - mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", - &b->dma, &base); - dma_free_coherent(mem_dev, b->size, b->virt, b->dma); - return -ENOMEM; + b->ctx = mem_ctx; + b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + if (!b->virt) + goto no_mem; + if (b->dma < base) { + mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", + &b->dma, &base); + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + return -ENOMEM; + } } mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma); return 0; +no_mem: + mfc_err("Allocating private buffer of size %zu failed\n", b->size); + return -ENOMEM; } void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[b->ctx]; + if (dev->mem_virt) { + unsigned int start = (b->dma - dev->mem_base) >> PAGE_SHIFT; + unsigned int count = b->size >> PAGE_SHIFT; + + bitmap_clear(dev->mem_bitmap, start, count); + } else { + struct device *mem_dev = dev->mem_dev[b->ctx]; - if (b->virt) { dma_free_coherent(mem_dev, b->size, b->virt, b->dma); - b->virt = NULL; - b->dma = 0; - b->size = 0; } + b->virt = NULL; + b->dma = 0; + b->size = 0; }