From patchwork Tue Feb 14 07:52:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 93927 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1447337qgi; Mon, 13 Feb 2017 23:52:41 -0800 (PST) X-Received: by 10.99.234.83 with SMTP id l19mr31595987pgk.114.1487058761182; Mon, 13 Feb 2017 23:52:41 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 128si12354946pgg.245.2017.02.13.23.52.40; Mon, 13 Feb 2017 23:52:41 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-samsung-soc-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-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-samsung-soc-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752612AbdBNHwj (ORCPT + 4 others); Tue, 14 Feb 2017 02:52:39 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:39062 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752585AbdBNHwZ (ORCPT ); Tue, 14 Feb 2017 02:52:25 -0500 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OLC003ILTV9O120@mailout2.w1.samsung.com>; Tue, 14 Feb 2017 07:52:21 +0000 (GMT) Received: from eusmges1.samsung.com (unknown [203.254.199.239]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170214075220eucas1p1aaee34493f4221eea6eadb04db450553~jGAvH_ZGa2142821428eucas1p1I; Tue, 14 Feb 2017 07:52:20 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges1.samsung.com (EUCPMTA) with SMTP id C5.51.16908.737B2A85; Tue, 14 Feb 2017 07:52:23 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170214075220eucas1p21d7f82fa19a9f058bb6fbe0a994478cc~jGAugTXZL1704117041eucas1p2T; Tue, 14 Feb 2017 07:52:20 +0000 (GMT) X-AuditID: cbfec7ef-f79d26d00000420c-07-58a2b737808a Received: from eusync2.samsung.com ( [203.254.199.212]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id D4.00.10233.737B2A85; Tue, 14 Feb 2017 07:52:23 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OLC00FWGTUYP980@eusync2.samsung.com>; Tue, 14 Feb 2017 07:52:19 +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 12/15] media: s5p-mfc: Add support for probe-time preallocated block based allocator Date: Tue, 14 Feb 2017 08:52:05 +0100 Message-id: <1487058728-16501-13-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1487058728-16501-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrCIsWRmVeSWpSXmKPExsWy7djP87rm2xdFGOxaJ2Rxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDmKyyYl NSezLLVI3y6BK2PpqnPsBbdsK87eqW5gXGncxcjJISFgIvH61QlGCFtM4sK99WxdjFwcQgLL GCVetf9hgnA+M0pMfNDFCtPRv2EHC1zVzGfT2CGcBiaJxwuvsoBUsQkYSnS97WIDsUUEnCQW zvoLVsQs8J1R4tvu02CjhAXSJPZ92MAOYrMIqEpcaTzCBGLzCnhKLD5zCWqdnMTJY5PBbE6g +KbPUxhBBkkIPGeTWHFgH9AGDiBHVmLTAWaIeheJN1d+MUHYwhKvjm9hh7BlJC5P7maBsPsZ JZpatSHsGYwS597yQtjWEoePXwTbxSzAJzFp23RmiPG8Eh1tQhAlHhInNn6FhpejxOyJt6BB NIdR4uz3j+wTGGUWMDKsYhRJLS3OTU8tNtQrTswtLs1L10vOz93ECIzb0/+Ov9/B+LQ55BCj AAejEg/vhAMLI4RYE8uKK3MPMUpwMCuJ8DL0LooQ4k1JrKxKLcqPLyrNSS0+xCjNwaIkzrt3 wZVwIYH0xJLU7NTUgtQimCwTB6dUA6NA5T6lSaGH1io1fT15562u4R2FlI1dz5/xL/9dUORv XX4yRu/1V4lrr/aGmc4Sq41NTHTbf6qF9e3ba32r2ir2flcrW71NPo9fbuF3p1dcj5YzP/nl 1Lvmi8YSx+bQyRJFL5ae3VVhEMl6MDLAVPLYy7Bv/2+EhGYnrbyy/T1X2Bvuf5OW22YqsRRn JBpqMRcVJwIA7yXfu9cCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrMLMWRmVeSWpSXmKPExsVy+t/xK7rm2xdFGKzaomJxa905VotJ9yew WJw/v4HdomfDVlaLGef3MVmsPXKX3eLwm3Ygd/JLNgcOj02rOtk8+rasYvT4vEkugDnKzSYj NTEltUghNS85PyUzL91WKTTETddCSSEvMTfVVilC1zckSEmhLDGnFMgzMkADDs4B7sFK+nYJ bhlLV51jL7hlW3H2TnUD40rjLkZODgkBE4n+DTtYIGwxiQv31rN1MXJxCAksYZTY3TCLEcJp YpLYd283M0gVm4ChRNfbLjYQW0TASWLhrL/sIDazwHdGiWU300BsYYE0ifP9r8DiLAKqElca jzCB2LwCnhKLz1xihdgmJ3Hy2GQwmxMovunzFEYQW0jAQ+Lsmh3sExh5FzAyrGIUSS0tzk3P LTbSK07MLS7NS9dLzs/dxAgM4G3Hfm7Zwdj1LvgQowAHoxIPr8W+hRFCrIllxZW5hxglOJiV RHgZehdFCPGmJFZWpRblxxeV5qQWH2I0BTpqIrOUaHI+MLrySuINTQzNLQ2NjC0szI2MlMR5 p364Ei4kkJ5YkpqdmlqQWgTTx8TBKdXAGF+nXx2meHVjR9+SmnsT5b/sOW3fknb14bOZuj3F ZVdm+xnPlbD2fGUyuXRW7ZcFHsl3dBdu8k+Zff66rVjqbYuiixO/TTeTXWpygDNoDrv+s6/l HX4LvnvaMmkrrVgs0BFqoqDGbzGZlffeB62NJR+ye5n75q39w6R5eg/H3xl28RYnut/YK7EU ZyQaajEXFScCAJwLSCd2AgAA X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170214075220eucas1p21d7f82fa19a9f058bb6fbe0a994478cc X-Msg-Generator: CA X-Sender-IP: 182.198.249.180 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: 20170214075220eucas1p21d7f82fa19a9f058bb6fbe0a994478cc X-RootMTR: 20170214075220eucas1p21d7f82fa19a9f058bb6fbe0a994478cc References: <1487058728-16501-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 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 --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index a18740c81c55..7492e81fde6d 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 */ @@ -1174,6 +1178,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 @@ -1187,17 +1193,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; } @@ -1206,6 +1234,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; }