From patchwork Mon Feb 20 13:39:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 94213 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1327150qgi; Mon, 20 Feb 2017 05:39:55 -0800 (PST) X-Received: by 10.99.121.78 with SMTP id u75mr27601984pgc.202.1487597995814; Mon, 20 Feb 2017 05:39:55 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d2si18592166pge.343.2017.02.20.05.39.55; Mon, 20 Feb 2017 05:39:55 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753333AbdBTNjZ (ORCPT + 4 others); Mon, 20 Feb 2017 08:39:25 -0500 Received: from mailout4.w1.samsung.com ([210.118.77.14]:23438 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753142AbdBTNjU (ORCPT ); Mon, 20 Feb 2017 08:39:20 -0500 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OLO0084LDXHB150@mailout4.w1.samsung.com>; Mon, 20 Feb 2017 13:39:17 +0000 (GMT) Received: from eusmges5.samsung.com (unknown [203.254.199.245]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170220133916eucas1p2d5b649e36afcc413ee9eff61b497f4aa~lAnXLaJA30833608336eucas1p2y; Mon, 20 Feb 2017 13:39:16 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges5.samsung.com (EUCPMTA) with SMTP id FF.43.17477.481FAA85; Mon, 20 Feb 2017 13:39:16 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170220133916eucas1p148acb6b6c3d0fbcaefa90f85bb723c9a~lAnWionu03266132661eucas1p16; Mon, 20 Feb 2017 13:39:16 +0000 (GMT) X-AuditID: cbfec7f5-f79d06d000004445-e6-58aaf184393e Received: from eusync1.samsung.com ( [203.254.199.211]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 2F.E7.06687.8D1FAA85; Mon, 20 Feb 2017 13:40:40 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OLO00HBFDX6PK30@eusync1.samsung.com>; Mon, 20 Feb 2017 13:39:16 +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 v2 12/15] media: s5p-mfc: Add support for probe-time preallocated block based allocator Date: Mon, 20 Feb 2017 14:39:01 +0100 Message-id: <1487597944-2000-13-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1487597944-2000-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrAIsWRmVeSWpSXmKPExsWy7djPc7otH1dFGHxfoGJxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDmKyyYl NSezLLVI3y6BK+PUr4iCG3YV70//YmtgnG3SxcjJISFgInFs5Q42CFtM4sK99WC2kMBSRokv f0S6GLmA7M+MEh+2fGXvYuQAa+jZoQYRX8Yoce3jAXYIp4FJYvPp0+wg3WwChhJdb7vAJokI OEksnPUXrIhZ4DujxLfdp1lBEsICmRI3bvYwgtgsAqoSJ6/fA2vmFfCQ6Hh+ihHiJDmJk8cm s4Js5gSK72hPBpkjIfCaTeLHmZtQF8lKbDrADFHuIvF802MoW1ji1fEt7BC2jERnx0EmCLuf UaKpVRvCnsEoce4tL4RtLXH4+EWw05gF+CQmbZvODDGeV6KjTQiixENi5oJPUGMcJQ68u8sM CazZjBKnn7NOYJRZwMiwilEktbQ4Nz212FSvODG3uDQvXS85P3cTIzBeT/87/nUH49JjVocY BTgYlXh4G2avjBBiTSwrrsw9xCjBwawkwnv55aoIId6UxMqq1KL8+KLSnNTiQ4zSHCxK4rx7 FlwJFxJITyxJzU5NLUgtgskycXBKNTBqnO/4m7CwTjPUmiF0xzxRr/BFSzgal1u46n/KVV24 fMdua+UrmzKvTtT3/i8g5rSVk9l8mfGzvX5uZyaJ9eb+WV77fkej6YVTQrvdYn7IZs3c8suQ 65Xrh3XB62dtbQ6UOudVwpCsdGT6VefI+O/xLY7ROdPLJQsutvrltC7xXfI/+fCBhXOUWIoz Eg21mIuKEwE22yVt0wIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrILMWRmVeSWpSXmKPExsVy+t/xy7o3Pq6KMGi/zmJxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDnKzSYj NTEltUghNS85PyUzL91WKTTETddCSSEvMTfVVilC1zckSEmhLDGnFMgzMkADDs4B7sFK+nYJ bhmnfkUU3LCreH/6F1sD42yTLkYODgkBE4meHWpdjJxAppjEhXvr2boYuTiEBJYwSvQf/sMM 4TQxSbxfeJUFpIpNwFCi620XG4gtIuAksXDWX3YQm1ngO6PEsptpILawQKbEjZs9jCA2i4Cq xMnr98BqeAU8JDqen2KE2CYncfLYZFaQIziB4jvak0HCQgLuEl+e9TJNYORdwMiwilEktbQ4 Nz232FCvODG3uDQvXS85P3cTIzB4tx37uXkH46WNwYcYBTgYlXh4NWaujBBiTSwrrsw9xCjB wawkwnv55aoIId6UxMqq1KL8+KLSnNTiQ4ymQDdNZJYSTc4HRlZeSbyhiaG5paGRsYWFuZGR kjhvyYcr4UIC6YklqdmpqQWpRTB9TBycUg2MhQ8SH4Yels70sGef72HGt+7k2pf7zLYnfD27 8zTrmWbvwD18f3Z//9Pw571Qq/H6TbOmdOT4vPis+eN58E6hpNJt364trPicUhsaYyuc9Cev tyR7+0Q+hZpWHoVuvo1PfwfNXRV4cJnraeH2n4/3zb/XLd9kk8AqJPxr/VVvtlW828W+SFqw KrEUZyQaajEXFScCAB3yQ5B0AgAA X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170220133916eucas1p148acb6b6c3d0fbcaefa90f85bb723c9a X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?utf-8?q?Marek_Szyprowski=1BSRPOL-Kernel_=28TP=29=1B?= =?utf-8?b?7IK87ISx7KCE7J6QG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Global-Sender: =?utf-8?q?Marek_Szyprowski=1BSRPOL-Kernel_=28TP=29=1BSam?= =?utf-8?q?sung_Electronics=1BSenior_Software_Engineer?= X-Sender-Code: =?utf-8?q?C10=1BEHQ=1BC10CD02CD027392?= CMS-TYPE: 201P X-HopCount: 7 X-CMS-RootMailID: 20170220133916eucas1p148acb6b6c3d0fbcaefa90f85bb723c9a X-RootMTR: 20170220133916eucas1p148acb6b6c3d0fbcaefa90f85bb723c9a References: <1487597944-2000-1-git-send-email-m.szyprowski@samsung.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 --- 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(-) -- 1.9.1 diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 04067bcc3feb..1c5ec8257f4f 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 */ @@ -1178,6 +1182,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 @@ -1191,17 +1197,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; } @@ -1210,6 +1238,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; }