Re: [PATCHv2 04/12] media: s5p_mfc_dec: set flags for OUTPUT coded formats

2019-08-16 Thread Marek Szyprowski
gt; @@ -111,6 +123,7 @@ static struct s5p_mfc_fmt formats[] = {
>>  .type   = MFC_FMT_DEC,
>>  .num_planes = 1,
>>  .versions   = MFC_V5PLUS_BITS,
>> +   .flags  = V4L2_FMT_FLAG_DYN_RESOLUTION,
>>  },
>>  {
>>  .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
>> @@ -118,6 +131,7 @@ static struct s5p_mfc_fmt formats[] = {
>>  .type   = MFC_FMT_DEC,
>>  .num_planes = 1,
>>  .versions   = MFC_V5PLUS_BITS,
>> +   .flags  = V4L2_FMT_FLAG_DYN_RESOLUTION,
>>  },
>>  {
>>  .fourcc = V4L2_PIX_FMT_VP8,
>> @@ -125,6 +139,7 @@ static struct s5p_mfc_fmt formats[] = {
>>  .type   = MFC_FMT_DEC,
>>  .num_planes = 1,
>>  .versions   = MFC_V6PLUS_BITS,
>> +   .flags  = V4L2_FMT_FLAG_DYN_RESOLUTION,
>>  },
>>  {
>>  .fourcc = V4L2_PIX_FMT_HEVC,
>> @@ -132,6 +147,8 @@ static struct s5p_mfc_fmt formats[] = {
>>  .type   = MFC_FMT_DEC,
>>  .num_planes = 1,
>>  .versions   = MFC_V10_BIT,
>> +   .flags  = V4L2_FMT_FLAG_DYN_RESOLUTION |
>> + V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
>>  },
>>  {
>>  .fourcc = V4L2_PIX_FMT_VP9,
>> @@ -139,6 +156,7 @@ static struct s5p_mfc_fmt formats[] = {
>>  .type   = MFC_FMT_DEC,
>>  .num_planes = 1,
>>  .versions   = MFC_V10_BIT,
>> +   .flags  = V4L2_FMT_FLAG_DYN_RESOLUTION,
>>  },
>>   };
>>
>> --
>> 2.20.1
>>
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v2] media: vb2-dc: skip CPU sync in map/unmap dma_buf

2019-07-16 Thread Marek Szyprowski
Hi Lucas,

On 2019-07-08 15:07, Lucas Stach wrote:
> This is rougly equivalent to ca0e68e21aae (drm/prime: skip CPU sync
> in map/unmap dma_buf). The contig memory allocated is already device
> coherent memory, so there is no point in doing a CPU sync when
> mapping it to another deevice. Also most importers currently cache
> the mapping so the CPU sync would only happen on the first import,
> so we are better off with not pretending to do a cache synchronization
> at all.
>
> This gets rid of a lot of CPU overhead in uses where those dma-bufs
> are regularily imported and detached again, like Weston is currently
> doing in the DRM compositor.
>
> Signed-off-by: Lucas Stach 
Acked-by: Marek Szyprowski 
> ---
> v2: Add comments why it is safe to skip the CPU sync.
> ---
>   .../common/videobuf2/videobuf2-dma-contig.c   | 23 +--
>   1 file changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> index ecbef266130b..1b8f86366290 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> @@ -267,8 +267,14 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf 
> *dbuf,
>   
>   /* release the scatterlist cache */
>   if (attach->dma_dir != DMA_NONE)
> - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> - attach->dma_dir);
> + /*
> +  * Cache sync can be skipped here, as the vb2_dc memory is
> +  * allocated from device coherent memory, which means the
> +  * memory locations do not require any explicit cache
> +  * maintenance prior or after being used by the device.
> +  */
> + dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
> + attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
>   sg_free_table(sgt);
>   kfree(attach);
>   db_attach->priv = NULL;
> @@ -293,14 +299,17 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
>   
>   /* release any previous cache */
>   if (attach->dma_dir != DMA_NONE) {
> - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> - attach->dma_dir);
> + dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
> + attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
>   attach->dma_dir = DMA_NONE;
>   }
>   
> - /* mapping to the client with new direction */
> - sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> - dma_dir);
> + /*
> +  * mapping to the client with new direction, no cache sync
> +  * required see comment in vb2_dc_dmabuf_ops_detach()
> +  */
> + sgt->nents = dma_map_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
> + dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
>   if (!sgt->nents) {
>   pr_err("failed to map scatterlist\n");
>   mutex_unlock(lock);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 4/6] s5p-cec: use cec_notifier_cec_adap_(un)register

2019-07-15 Thread Marek Szyprowski
Hi Hans,

On 2019-07-15 12:30, Hans Verkuil wrote:
> Use cec_notifier_cec_adap_(un)register instead of
> cec_notifier_get, cec_notifier_put and cec_register_cec_notifier.
>
> Also enable the CEC_CAP_CONNECTOR_INFO capability.
>
> Signed-off-by: Hans Verkuil 
> Cc: Marek Szyprowski 
> Cc: Sylwester Nawrocki 

Acked-by: Marek Szyprowski 

> ---
>   drivers/media/platform/s5p-cec/s5p_cec.c | 23 ++-
>   1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c 
> b/drivers/media/platform/s5p-cec/s5p_cec.c
> index ea6231b387ed..6ddcc35b0bbd 100644
> --- a/drivers/media/platform/s5p-cec/s5p_cec.c
> +++ b/drivers/media/platform/s5p-cec/s5p_cec.c
> @@ -214,21 +214,23 @@ static int s5p_cec_probe(struct platform_device *pdev)
>   if (IS_ERR(cec->reg))
>   return PTR_ERR(cec->reg);
>   
> - cec->notifier = cec_notifier_get(hdmi_dev);
> - if (cec->notifier == NULL)
> - return -ENOMEM;
> -
>   cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME,
> - CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0), 1);
> + CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0) |
> + CEC_CAP_CONNECTOR_INFO, 1);
>   ret = PTR_ERR_OR_ZERO(cec->adap);
>   if (ret)
>   return ret;
>   
> - ret = cec_register_adapter(cec->adap, &pdev->dev);
> - if (ret)
> + cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
> +cec->adap);
> + if (!cec->notifier) {
> + ret = -ENOMEM;
>   goto err_delete_adapter;
> + }
>   
> - cec_register_cec_notifier(cec->adap, cec->notifier);
> + ret = cec_register_adapter(cec->adap, &pdev->dev);
> + if (ret)
> + goto err_notifier;
>   
>   platform_set_drvdata(pdev, cec);
>   pm_runtime_enable(dev);
> @@ -236,6 +238,9 @@ static int s5p_cec_probe(struct platform_device *pdev)
>   dev_dbg(dev, "successfully probed\n");
>   return 0;
>   
> +err_notifier:
> + cec_notifier_cec_adap_unregister(cec->notifier);
> +
>   err_delete_adapter:
>   cec_delete_adapter(cec->adap);
>   return ret;
> @@ -245,8 +250,8 @@ static int s5p_cec_remove(struct platform_device *pdev)
>   {
>   struct s5p_cec_dev *cec = platform_get_drvdata(pdev);
>   
> + cec_notifier_cec_adap_unregister(cec->notifier);
>   cec_unregister_adapter(cec->adap);
> - cec_notifier_put(cec->notifier);
>   pm_runtime_disable(&pdev->dev);
>   return 0;
>   }

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] media: s5p-mfc: Make additional clocks optional

2019-06-13 Thread Marek Szyprowski
Since the beginning the second clock ('special', 'sclk') was optional and
it is not available on some variants of Exynos SoCs (i.e. Exynos5420 with
v7 of MFC hardware). However commit 1bce6fb3edf1 made handling of all
specified clocks mandatory. This patch restores original behavior of the
driver and fixes its operation on Exynos5420 SoCs.

Fixes: 1bce6fb3edf1 ("[media] s5p-mfc: Rework clock handling")
Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 2e62f8721fa5..d2872e19dd9d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -34,6 +34,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
for (i = 0; i < pm->num_clocks; i++) {
pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
if (IS_ERR(pm->clocks[i])) {
+   /* additional clocks are optional */
+   if (i && PTR_ERR(pm->clocks[i] == -ENOENT)) {
+   pm->clocks[i] = NULL;
+   continue;
+   }
mfc_err("Failed to get clock: %s\n",
pm->clk_names[i]);
return PTR_ERR(pm->clocks[i]);
-- 
2.17.1



[PATCH v2] media: s5p-mfc: Make additional clocks optional

2019-06-13 Thread Marek Szyprowski
Since the beginning the second clock ('special', 'sclk') was optional and
it is not available on some variants of Exynos SoCs (i.e. Exynos5420 with
v7 of MFC hardware). However commit 1bce6fb3edf1 made handling of all
specified clocks mandatory. This patch restores original behavior of the
driver and fixes its operation on Exynos5420 SoCs.

Fixes: 1bce6fb3edf1 ("[media] s5p-mfc: Rework clock handling")
Signed-off-by: Marek Szyprowski 
---
v2: this is the correct version, v1 had parenthesis in wrong place
---
 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 2e62f8721fa5..7d52431c2c83 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -34,6 +34,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
for (i = 0; i < pm->num_clocks; i++) {
pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
if (IS_ERR(pm->clocks[i])) {
+   /* additional clocks are optional */
+   if (i && PTR_ERR(pm->clocks[i]) == -ENOENT) {
+   pm->clocks[i] = NULL;
+   continue;
+   }
mfc_err("Failed to get clock: %s\n",
pm->clk_names[i]);
return PTR_ERR(pm->clocks[i]);
-- 
2.17.1



[PATCH] media: s5p-mfc: fix reading min scratch buffer size on MFC v6/v7

2019-06-12 Thread Marek Szyprowski
MFC v6 and v7 has no register to read min scratch buffer size, so it has
to be read conditionally only if hardware supports it. This fixes following
NULL pointer exception on SoCs with MFC v6/v7:

8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 
pgd = f25837f9
[] *pgd=bd93d835
Internal error: Oops: 17 [#1] PREEMPT SMP ARM
Modules linked in: btmrvl_sdio btmrvl bluetooth mwifiex_sdio mwifiex 
ecdh_generic ecc
CPU: 0 PID: 1430 Comm: v4l2_decode Not tainted 
5.2.0-rc4-next-20190612-6-gf077fba72e95-dirty #6167
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
PC is at s5p_mfc_get_min_scratch_buf_size+0x30/0x3c
LR is at s5p_mfc_get_min_scratch_buf_size+0x28/0x3c
...
[] (s5p_mfc_get_min_scratch_buf_size) from [] 
(s5p_mfc_irq+0x814/0xa5c)
[] (s5p_mfc_irq) from [] 
(__handle_irq_event_percpu+0x64/0x3f8)
[] (__handle_irq_event_percpu) from [] 
(handle_irq_event_percpu+0x2c/0x7c)
[] (handle_irq_event_percpu) from [] 
(handle_irq_event+0x38/0x5c)
[] (handle_irq_event) from [] 
(handle_fasteoi_irq+0xc4/0x180)
[] (handle_fasteoi_irq) from [] 
(generic_handle_irq+0x24/0x34)
[] (generic_handle_irq) from [] 
(__handle_domain_irq+0x7c/0xec)
[] (__handle_domain_irq) from [] (gic_handle_irq+0x58/0x9c)
[] (gic_handle_irq) from [] (__irq_svc+0x70/0xb0)
Exception stack(0xe73ddc60 to 0xe73ddca8)
...
[] (__irq_svc) from [] (console_unlock+0x5a8/0x6a8)
[] (console_unlock) from [] (vprintk_emit+0x118/0x2d8)
[] (vprintk_emit) from [] (vprintk_default+0x20/0x28)
[] (vprintk_default) from [] (printk+0x30/0x54)
[] (printk) from [] (s5p_mfc_init_decode_v6+0x1d4/0x284)
[] (s5p_mfc_init_decode_v6) from [] 
(vb2_start_streaming+0x24/0x150)
[] (vb2_start_streaming) from [] 
(vb2_core_streamon+0x11c/0x15c)
[] (vb2_core_streamon) from [] (vidioc_streamon+0x64/0xa0)
[] (vidioc_streamon) from [] (__video_do_ioctl+0x28c/0x45c)
[] (__video_do_ioctl) from [] (video_usercopy+0x260/0x8a4)
[] (video_usercopy) from [] (do_vfs_ioctl+0xb0/0x9fc)
[] (do_vfs_ioctl) from [] (ksys_ioctl+0x34/0x58)
[] (ksys_ioctl) from [] (ret_fast_syscall+0x0/0x28)
Exception stack(0xe73ddfa8 to 0xe73ddff0)
...
---[ end trace 376cf5ba6e0bee93 ]---

Fixes: c8ffbd433a77 ("media: s5p-mfc: Use min scratch buffer size as provided 
by F/W")
Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index c5dc1880a4c6..b776f83e395e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -523,7 +523,8 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
dev);
ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
dev);
-   ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
+   if (FW_HAS_E_MIN_SCRATCH_BUF(dev))
+   ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
get_min_scratch_buf_size, dev);
if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
-- 
2.17.1



Re: [PATCH v2 1/5] media: vb2: Introduce a vb2_get_buffer accessor

2019-06-11 Thread Marek Szyprowski


On 2019-06-10 22:55, Ezequiel Garcia wrote:
> Some drivers need to access a vb2 buffer from its
> queue index. Introduce an accessor to abstract this,
> and avoid drivers from accessing private members.
>
> Reviewed-by: Boris Brezillon 
> Signed-off-by: Ezequiel Garcia 

Acked-by: Marek Szyprowski 

> ---
> Changes from v1:
> * Drop redundant num_buffers > 0 check.
> ---
>   include/media/videobuf2-core.h | 18 ++
>   1 file changed, 18 insertions(+)
>
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index c03ef7cc5071..640aabe69450 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -1163,6 +1163,24 @@ static inline void 
> vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
>   q->last_buffer_dequeued = false;
>   }
>   
> +/**
> + * vb2_get_buffer() - get a buffer from a queue
> + * @q:   pointer to &struct vb2_queue with videobuf2 queue.
> + * @index:   buffer index
> + *
> + * This function obtains a buffer from a queue, by its index.
> + * Keep in mind that there is no refcounting involved in this
> + * operation, so the buffer lifetime should be taken into
> + * consideration.
> + */
> +static inline struct vb2_buffer *vb2_get_buffer(struct vb2_queue *q,
> + unsigned int index)
> +{
> + if (index < q->num_buffers)
> + return q->bufs[index];
> + return NULL;
> +}
> +
>   /*
>    * The following functions are not part of the vb2 core API, but are useful
>* functions for videobuf2-*.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory

2019-06-11 Thread Marek Szyprowski
Hi Hans,

On 2019-06-11 09:52, Hans Verkuil wrote:
> On 6/7/19 9:43 PM, Nicolas Dufresne wrote:
>> Le vendredi 07 juin 2019 à 16:39 +0200, Marek Szyprowski a écrit :
>>> Hi Hans,
>>>
>>> On 2019-06-07 16:11, Hans Verkuil wrote:
>>>> On 6/7/19 3:55 PM, Marek Szyprowski wrote:
>>>>> On 2019-06-07 15:40, Hans Verkuil wrote:
>>>>>> On 6/7/19 2:47 PM, Hans Verkuil wrote:
>>>>>>> On 6/7/19 2:23 PM, Hans Verkuil wrote:
>>>>>>>> On 6/7/19 2:14 PM, Marek Szyprowski wrote:
>>>>>>>>> On 2019-06-07 14:01, Hans Verkuil wrote:
>>>>>>>>>> On 6/7/19 1:16 PM, Laurent Pinchart wrote:
>>>>>>>>>>> Thank you for the patch.
>>>>>>>>>>>
>>>>>>>>>>> On Fri, Jun 07, 2019 at 10:45:31AM +0200, Hans Verkuil wrote:
>>>>>>>>>>>> The __prepare_userptr() function made the incorrect assumption 
>>>>>>>>>>>> that if the
>>>>>>>>>>>> same user pointer was used as the last one for which memory was 
>>>>>>>>>>>> acquired, then
>>>>>>>>>>>> there was no need to re-acquire the memory. This assumption was 
>>>>>>>>>>>> never properly
>>>>>>>>>>>> tested, and after doing that it became clear that this was in fact 
>>>>>>>>>>>> wrong.
>>>>>>>>>>> Could you explain in the commit message why the assumption is not
>>>>>>>>>>> correct ?
>>>>>>>>>> You can free the memory, then allocate it again and you can get the 
>>>>>>>>>> same pointer,
>>>>>>>>>> even though it is not necessarily using the same physical pages for 
>>>>>>>>>> the memory
>>>>>>>>>> that the kernel is still using for it.
>>>>>>>>>>
>>>>>>>>>> Worse, you can free the memory, then allocate only half the memory 
>>>>>>>>>> you need and
>>>>>>>>>> get back the same pointer. vb2 wouldn't notice this. And it seems to 
>>>>>>>>>> work (since
>>>>>>>>>> the original mapping still remains), but this can corrupt userspace 
>>>>>>>>>> memory
>>>>>>>>>> causing the application to crash. It's not quite clear to me how the 
>>>>>>>>>> memory can
>>>>>>>>>> get corrupted. I don't know enough of those low-level mm internals 
>>>>>>>>>> to understand
>>>>>>>>>> the sequence of events.
>>>>>>>>>>
>>>>>>>>>> I have test code for v4l2-compliance available if someone wants to 
>>>>>>>>>> test this.
>>>>>>>>> I'm interested, I would really like to know what happens in the mm
>>>>>>>>> subsystem in such case.
>>>>>>>> Here it is:
>>>>>>>>
>>>>>>>> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp 
>>>>>>>> b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>>>>> index be606e48..9abf41da 100644
>>>>>>>> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>>>>> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>>>>> @@ -797,7 +797,7 @@ int testReadWrite(struct node *node)
>>>>>>>>return 0;
>>>>>>>> }
>>>>>>>>
>>>>>>>> -static int captureBufs(struct node *node, const cv4l_queue &q,
>>>>>>>> +static int captureBufs(struct node *node, cv4l_queue &q,
>>>>>>>>const cv4l_queue &m2m_q, unsigned frame_count, int 
>>>>>>>> pollmode,
>>>>>>>>unsigned &capture_count)
>>>>>>>> {
>>>>>>>> @@ -962,6 +962,21 @@ static int captureBufs(struct node *node, const 
>>>>>>>> cv4l_queue &q,
>>>>>>>>buf.s_flags(V4L2_BUF_FLAG_REQUEST_FD);
>>>>

Re: [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory

2019-06-07 Thread Marek Szyprowski
Hi Hans,

On 2019-06-07 16:11, Hans Verkuil wrote:
> On 6/7/19 3:55 PM, Marek Szyprowski wrote:
>> On 2019-06-07 15:40, Hans Verkuil wrote:
>>> On 6/7/19 2:47 PM, Hans Verkuil wrote:
>>>> On 6/7/19 2:23 PM, Hans Verkuil wrote:
>>>>> On 6/7/19 2:14 PM, Marek Szyprowski wrote:
>>>>>> On 2019-06-07 14:01, Hans Verkuil wrote:
>>>>>>> On 6/7/19 1:16 PM, Laurent Pinchart wrote:
>>>>>>>> Thank you for the patch.
>>>>>>>>
>>>>>>>> On Fri, Jun 07, 2019 at 10:45:31AM +0200, Hans Verkuil wrote:
>>>>>>>>> The __prepare_userptr() function made the incorrect assumption that 
>>>>>>>>> if the
>>>>>>>>> same user pointer was used as the last one for which memory was 
>>>>>>>>> acquired, then
>>>>>>>>> there was no need to re-acquire the memory. This assumption was never 
>>>>>>>>> properly
>>>>>>>>> tested, and after doing that it became clear that this was in fact 
>>>>>>>>> wrong.
>>>>>>>> Could you explain in the commit message why the assumption is not
>>>>>>>> correct ?
>>>>>>> You can free the memory, then allocate it again and you can get the 
>>>>>>> same pointer,
>>>>>>> even though it is not necessarily using the same physical pages for the 
>>>>>>> memory
>>>>>>> that the kernel is still using for it.
>>>>>>>
>>>>>>> Worse, you can free the memory, then allocate only half the memory you 
>>>>>>> need and
>>>>>>> get back the same pointer. vb2 wouldn't notice this. And it seems to 
>>>>>>> work (since
>>>>>>> the original mapping still remains), but this can corrupt userspace 
>>>>>>> memory
>>>>>>> causing the application to crash. It's not quite clear to me how the 
>>>>>>> memory can
>>>>>>> get corrupted. I don't know enough of those low-level mm internals to 
>>>>>>> understand
>>>>>>> the sequence of events.
>>>>>>>
>>>>>>> I have test code for v4l2-compliance available if someone wants to test 
>>>>>>> this.
>>>>>> I'm interested, I would really like to know what happens in the mm
>>>>>> subsystem in such case.
>>>>> Here it is:
>>>>>
>>>>> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp 
>>>>> b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>> index be606e48..9abf41da 100644
>>>>> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>>>> @@ -797,7 +797,7 @@ int testReadWrite(struct node *node)
>>>>>   return 0;
>>>>>}
>>>>>
>>>>> -static int captureBufs(struct node *node, const cv4l_queue &q,
>>>>> +static int captureBufs(struct node *node, cv4l_queue &q,
>>>>>   const cv4l_queue &m2m_q, unsigned frame_count, int 
>>>>> pollmode,
>>>>>   unsigned &capture_count)
>>>>>{
>>>>> @@ -962,6 +962,21 @@ static int captureBufs(struct node *node, const 
>>>>> cv4l_queue &q,
>>>>>   buf.s_flags(V4L2_BUF_FLAG_REQUEST_FD);
>>>>>   buf.s_request_fd(buf_req_fds[req_idx]);
>>>>>   }
>>>>> + if (v4l_type_is_capture(buf.g_type()) && q.g_memory() 
>>>>> == V4L2_MEMORY_USERPTR) {
>>>>> + printf("\nidx: %d", buf.g_index());
>>>>> + for (unsigned p = 0; p < q.g_num_planes(); p++) 
>>>>> {
>>>>> + printf(" old buf[%d]: %p ", p, 
>>>>> buf.g_userptr(p));
>>>>> + fflush(stdout);
>>>>> + free(buf.g_userptr(p));
>>>>> + void *m = calloc(1, q.g_length(p)/2);
>>>>> +
>>>>> + fail_on_tes

Re: [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory

2019-06-07 Thread Marek Szyprowski
Hi Hans,

On 2019-06-07 15:40, Hans Verkuil wrote:
> On 6/7/19 2:47 PM, Hans Verkuil wrote:
>> On 6/7/19 2:23 PM, Hans Verkuil wrote:
>>> On 6/7/19 2:14 PM, Marek Szyprowski wrote:
>>>> On 2019-06-07 14:01, Hans Verkuil wrote:
>>>>> On 6/7/19 1:16 PM, Laurent Pinchart wrote:
>>>>>> Thank you for the patch.
>>>>>>
>>>>>> On Fri, Jun 07, 2019 at 10:45:31AM +0200, Hans Verkuil wrote:
>>>>>>> The __prepare_userptr() function made the incorrect assumption that if 
>>>>>>> the
>>>>>>> same user pointer was used as the last one for which memory was 
>>>>>>> acquired, then
>>>>>>> there was no need to re-acquire the memory. This assumption was never 
>>>>>>> properly
>>>>>>> tested, and after doing that it became clear that this was in fact 
>>>>>>> wrong.
>>>>>> Could you explain in the commit message why the assumption is not
>>>>>> correct ?
>>>>> You can free the memory, then allocate it again and you can get the same 
>>>>> pointer,
>>>>> even though it is not necessarily using the same physical pages for the 
>>>>> memory
>>>>> that the kernel is still using for it.
>>>>>
>>>>> Worse, you can free the memory, then allocate only half the memory you 
>>>>> need and
>>>>> get back the same pointer. vb2 wouldn't notice this. And it seems to work 
>>>>> (since
>>>>> the original mapping still remains), but this can corrupt userspace memory
>>>>> causing the application to crash. It's not quite clear to me how the 
>>>>> memory can
>>>>> get corrupted. I don't know enough of those low-level mm internals to 
>>>>> understand
>>>>> the sequence of events.
>>>>>
>>>>> I have test code for v4l2-compliance available if someone wants to test 
>>>>> this.
>>>> I'm interested, I would really like to know what happens in the mm
>>>> subsystem in such case.
>>> Here it is:
>>>
>>> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp 
>>> b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>> index be606e48..9abf41da 100644
>>> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>>> @@ -797,7 +797,7 @@ int testReadWrite(struct node *node)
>>> return 0;
>>>   }
>>>
>>> -static int captureBufs(struct node *node, const cv4l_queue &q,
>>> +static int captureBufs(struct node *node, cv4l_queue &q,
>>> const cv4l_queue &m2m_q, unsigned frame_count, int pollmode,
>>> unsigned &capture_count)
>>>   {
>>> @@ -962,6 +962,21 @@ static int captureBufs(struct node *node, const 
>>> cv4l_queue &q,
>>> buf.s_flags(V4L2_BUF_FLAG_REQUEST_FD);
>>> buf.s_request_fd(buf_req_fds[req_idx]);
>>> }
>>> +   if (v4l_type_is_capture(buf.g_type()) && q.g_memory() 
>>> == V4L2_MEMORY_USERPTR) {
>>> +   printf("\nidx: %d", buf.g_index());
>>> +   for (unsigned p = 0; p < q.g_num_planes(); p++) 
>>> {
>>> +   printf(" old buf[%d]: %p ", p, 
>>> buf.g_userptr(p));
>>> +   fflush(stdout);
>>> +   free(buf.g_userptr(p));
>>> +   void *m = calloc(1, q.g_length(p)/2);
>>> +
>>> +   fail_on_test(m == NULL);
>>> +   q.s_userptr(buf.g_index(), p, m);
>>> +   printf("new buf[%d]: %p", p, m);
>>> +   buf.s_userptr(m, p);
>>> +   }
>>> +   printf("\n");
>>> +   }
>>> fail_on_test(buf.qbuf(node, q));
>>> fail_on_test(buf.g_flags() & V4L2_BUF_FLAG_DONE);
>>> if (buf.g_flags() & V4L2_BUF_FLAG_REQUEST_FD) {
>>>
>>>
>>>
>>> Load the vivid driver and just run 'v4l2

Re: [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory

2019-06-07 Thread Marek Szyprowski
Hi Hans,

On 2019-06-07 14:01, Hans Verkuil wrote:
> On 6/7/19 1:16 PM, Laurent Pinchart wrote:
>> Hi Hans,
>>
>> Thank you for the patch.
>>
>> On Fri, Jun 07, 2019 at 10:45:31AM +0200, Hans Verkuil wrote:
>>> The __prepare_userptr() function made the incorrect assumption that if the
>>> same user pointer was used as the last one for which memory was acquired, 
>>> then
>>> there was no need to re-acquire the memory. This assumption was never 
>>> properly
>>> tested, and after doing that it became clear that this was in fact wrong.
>> Could you explain in the commit message why the assumption is not
>> correct ?
> You can free the memory, then allocate it again and you can get the same 
> pointer,
> even though it is not necessarily using the same physical pages for the memory
> that the kernel is still using for it.
>
> Worse, you can free the memory, then allocate only half the memory you need 
> and
> get back the same pointer. vb2 wouldn't notice this. And it seems to work 
> (since
> the original mapping still remains), but this can corrupt userspace memory
> causing the application to crash. It's not quite clear to me how the memory 
> can
> get corrupted. I don't know enough of those low-level mm internals to 
> understand
> the sequence of events.
>
> I have test code for v4l2-compliance available if someone wants to test this.

I'm interested, I would really like to know what happens in the mm 
subsystem in such case.


Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: fix a layering violation in videobuf2 and improve dma_map_resource v2

2019-01-31 Thread Marek Szyprowski
Hi All,

On 2019-01-18 12:37, Christoph Hellwig wrote:
> Hi all,
>
> this series fixes a rather gross layering violation in videobuf2, which
> pokes into arm DMA mapping internals to get a DMA address for memory that
> does not have a page structure, and to do so fixes up the dma_map_resource
> implementation to not provide a somewhat dangerous default and improve
> the error handling.
>
> Changes since v1:
>  - don't apply bus offsets in dma_direct_map_resource

Works fine on older Exynos based boards with IOMMU and CMA disabled.

Tested-by: Marek Szyprowski 

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCHv2 7/9] videobuf2/videobuf2-dma-sg.c: Convert to use vm_insert_range

2019-01-31 Thread Marek Szyprowski
Hi Souptick,

On 2019-01-31 04:13, Souptick Joarder wrote:
> Convert to use vm_insert_range to map range of kernel memory
> to user vma.
>
> vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
> not as a in-buffer offset by design and it always want to mmap a
> whole buffer from its beginning.
>
> Signed-off-by: Souptick Joarder 

Suggested-by: Marek Szyprowski 

Reviewed-by: Marek Szyprowski 

> ---
>  drivers/media/common/videobuf2/videobuf2-core.c|  7 +++
>  .../media/common/videobuf2/videobuf2-dma-contig.c  |  6 --
>  drivers/media/common/videobuf2/videobuf2-dma-sg.c  | 22 
> ++
>  3 files changed, 13 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
> b/drivers/media/common/videobuf2/videobuf2-core.c
> index 70e8c33..ca4577a 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -2175,6 +2175,13 @@ int vb2_mmap(struct vb2_queue *q, struct 
> vm_area_struct *vma)
>   goto unlock;
>   }
>  
> + /*
> +  * vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
> +  * not as a in-buffer offset. We always want to mmap a whole buffer
> +  * from its beginning.
> +  */
> + vma->vm_pgoff = 0;
> +
>   ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
>  
>  unlock:
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> index aff0ab7..46245c5 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> @@ -186,12 +186,6 @@ static int vb2_dc_mmap(void *buf_priv, struct 
> vm_area_struct *vma)
>   return -EINVAL;
>   }
>  
> - /*
> -  * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
> -  * map whole buffer
> -  */
> - vma->vm_pgoff = 0;
> -
>   ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
>   buf->dma_addr, buf->size, buf->attrs);
>  
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> index 015e737..a800200 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> @@ -328,28 +328,18 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
>  static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
>  {
>   struct vb2_dma_sg_buf *buf = buf_priv;
> - unsigned long uaddr = vma->vm_start;
> - unsigned long usize = vma->vm_end - vma->vm_start;
> - int i = 0;
> + int err;
>  
>   if (!buf) {
>   printk(KERN_ERR "No memory to map\n");
>   return -EINVAL;
>   }
>  
> - do {
> - int ret;
> -
> - ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
> - if (ret) {
> - printk(KERN_ERR "Remapping memory, error: %d\n", ret);
> - return ret;
> - }
> -
> - uaddr += PAGE_SIZE;
> - usize -= PAGE_SIZE;
> - } while (usize > 0);
> -
> + err = vm_insert_range(vma, buf->pages, buf->num_pages);
> + if (err) {
> + printk(KERN_ERR "Remapping memory, error: %d\n", err);
> + return err;
> + }
>  
>   /*
>* Use common vm_area operations to track buffer refcount.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 7/9] videobuf2/videobuf2-dma-sg.c: Convert to use vm_insert_range_buggy

2019-01-25 Thread Marek Szyprowski
Hi Souptick,

On 2019-01-25 05:55, Souptick Joarder wrote:
> On Tue, Jan 22, 2019 at 8:37 PM Marek Szyprowski
>  wrote:
>> On 2019-01-11 16:11, Souptick Joarder wrote:
>>> Convert to use vm_insert_range_buggy to map range of kernel memory
>>> to user vma.
>>>
>>> This driver has ignored vm_pgoff. We could later "fix" these drivers
>>> to behave according to the normal vm_pgoff offsetting simply by
>>> removing the _buggy suffix on the function name and if that causes
>>> regressions, it gives us an easy way to revert.
>> Just a generic note about videobuf2: videobuf2-dma-sg is ignoring vm_pgoff 
>> by design. vm_pgoff is used as a 'cookie' to select a buffer to mmap and 
>> videobuf2-core already checks that. If userspace provides an offset, which 
>> doesn't match any of the registered 'cookies' (reported to userspace via 
>> separate v4l2 ioctl), an error is returned.
> Ok, it means once the buf is selected, videobuf2-dma-sg should always
> mapped buf->pages[i]
> from index 0 ( irrespective of vm_pgoff value). So although we are
> replacing the code with
> vm_insert_range_buggy(), *_buggy* suffix will mislead others and
> should not be used.
> And if we replace this code with  vm_insert_range(), this will
> introduce bug for *non zero*
> value of vm_pgoff.
>
> Please correct me if my understanding is wrong.

You are correct. IMHO the best solution in this case would be to add
following fix:


diff --git a/drivers/media/common/videobuf2/videobuf2-core.c
b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e8c3366f9c..ca4577a7d28a 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -2175,6 +2175,13 @@ int vb2_mmap(struct vb2_queue *q, struct
vm_area_struct *vma)
     goto unlock;
 }
 
+    /*
+     * vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
+     * not as a in-buffer offset. We always want to mmap a whole buffer
+     * from its beginning.
+     */
+    vma->vm_pgoff = 0;
+
 ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
 
 unlock:
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index aff0ab7bf83d..46245c598a18 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -186,12 +186,6 @@ static int vb2_dc_mmap(void *buf_priv, struct
vm_area_struct *vma)
     return -EINVAL;
 }
 
-    /*
-     * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
-     * map whole buffer
-     */
-    vma->vm_pgoff = 0;
-
 ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
     buf->dma_addr, buf->size, buf->attrs);
 
-- 

Then you can simply use non-buggy version of your function in
drivers/media/common/videobuf2/videobuf2-dma-sg.c.

I can send above as a formal patch if you want.

> So what your opinion about this patch ? Shall I drop this patch from
> current series ?
> or,
> There is any better way to handle this scenario ?
>
>
>>> There is an existing bug inside gem_mmap_obj(), where user passed
>>> length is not checked against buf->num_pages. For any value of
>>> length > buf->num_pages it will end up overrun buf->pages[i],
>>> which could lead to a potential bug.
> It is not gem_mmap_obj(), it should be vb2_dma_sg_mmap().
> Sorry about it.
>
> What about this issue ? Does it looks like a valid issue ?

It is already handled in vb2_mmap(). Such call will be rejected.


> ...

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 7/9] videobuf2/videobuf2-dma-sg.c: Convert to use vm_insert_range_buggy

2019-01-22 Thread Marek Szyprowski
Hi Souptick,

On 2019-01-11 16:11, Souptick Joarder wrote:
> Convert to use vm_insert_range_buggy to map range of kernel memory
> to user vma.
>
> This driver has ignored vm_pgoff. We could later "fix" these drivers
> to behave according to the normal vm_pgoff offsetting simply by
> removing the _buggy suffix on the function name and if that causes
> regressions, it gives us an easy way to revert.

Just a generic note about videobuf2: videobuf2-dma-sg is ignoring vm_pgoff by 
design. vm_pgoff is used as a 'cookie' to select a buffer to mmap and 
videobuf2-core already checks that. If userspace provides an offset, which 
doesn't match any of the registered 'cookies' (reported to userspace via 
separate v4l2 ioctl), an error is returned.

I'm sorry for the late reply.

> There is an existing bug inside gem_mmap_obj(), where user passed
> length is not checked against buf->num_pages. For any value of
> length > buf->num_pages it will end up overrun buf->pages[i],
> which could lead to a potential bug.
>
> This has been addressed by passing buf->num_pages as input to
> vm_insert_range_buggy() and inside this API error condition is
> checked which will avoid overrun the page boundary.
>
> Signed-off-by: Souptick Joarder 
> ---
>  drivers/media/common/videobuf2/videobuf2-dma-sg.c | 22 ++
>  1 file changed, 6 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> index 015e737..ef046b4 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> @@ -328,28 +328,18 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
>  static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
>  {
>   struct vb2_dma_sg_buf *buf = buf_priv;
> - unsigned long uaddr = vma->vm_start;
> - unsigned long usize = vma->vm_end - vma->vm_start;
> - int i = 0;
> + int err;
>  
>   if (!buf) {
>   printk(KERN_ERR "No memory to map\n");
>   return -EINVAL;
>   }
>  
> - do {
> - int ret;
> -
> - ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
> - if (ret) {
> - printk(KERN_ERR "Remapping memory, error: %d\n", ret);
> - return ret;
> - }
> -
> - uaddr += PAGE_SIZE;
> - usize -= PAGE_SIZE;
> - } while (usize > 0);
> -
> + err = vm_insert_range_buggy(vma, buf->pages, buf->num_pages);
> + if (err) {
> + printk(KERN_ERR "Remapping memory, error: %d\n", err);
> + return err;
> + }
>  
>   /*
>* Use common vm_area operations to track buffer refcount.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 3/3] videobuf2: replace a layering violation with dma_map_resource

2019-01-18 Thread Marek Szyprowski
Hi Christoph,

On 2019-01-17 18:21, Christoph Hellwig wrote:
> On Mon, Jan 14, 2019 at 01:42:26PM +0100, Marek Szyprowski wrote:
>> On 2019-01-11 19:17, Christoph Hellwig wrote:
>>> vb2_dc_get_userptr pokes into arm direct mapping details to get the
>>> resemblance of a dma address for a a physical address that does is
>>> not backed by a page struct.  Not only is this not portable to other
>>> architectures with dma direct mapping offsets, but also not to uses
>>> of IOMMUs of any kind.  Switch to the proper dma_map_resource /
>>> dma_unmap_resource interface instead.
>>>
>>> Signed-off-by: Christoph Hellwig 
>> There are checks for IOMMU presence in other places in vb2-dma-contig,
>> so it was used only when no IOMMU is available, but I agree that the
>> hacky code should be replaced by a generic code if possible.
>>
>> Tested-by: Marek Szyprowski 
>>
>> V4L2 pipeline works fine on older Exynos-based boards with CMA and IOMMU
>> disabled.
> Do you know if these rely on the offsets?  E.g. would they still work
> with the patch below applied on top.  That would keep the map_resource
> semantics as-is as solve the issue pointed out by Robin for now.

AFAIK that code was only used for sharing buffers between hardware
modules that are a part of the same SoC, usually implemented as platform
devices. AFAIR this never worked for devices on different buses. So far
I wasn't aware on ANY which would require an offset for the DMA access.

The first version of videobuf2-dc code even incorrectly used paddr
instead of dma_addr as a buffer 'address' returned to the client
drivers, because in case of those SoC this was exactly the same (see
commits 472af2b05bdefcaee7e754e22cbf131110017ad6 and
ba7fcb0c954921534707f08ebc4d8beeb2eb17e7).

> If not I can only think of a flag to bypass the offseting for now, but
> that would be pretty ugly.  Or go for the long-term solution of
> discovering the relationship between the two devices, as done by the
> PCIe P2P code..
>
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index 8e0359b04957..25bd19974223 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -359,7 +359,7 @@ EXPORT_SYMBOL(dma_direct_map_sg);
>  dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
>   size_t size, enum dma_data_direction dir, unsigned long attrs)
>  {
> - dma_addr_t dma_addr = phys_to_dma(dev, paddr);
> + dma_addr_t dma_addr = paddr;
>  
>   if (unlikely(!dma_direct_possible(dev, dma_addr, size))) {
>   report_addr(dev, dma_addr, size);
>
>
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 3/3] videobuf2: replace a layering violation with dma_map_resource

2019-01-14 Thread Marek Szyprowski
Hi Christoph,

On 2019-01-11 19:17, Christoph Hellwig wrote:
> vb2_dc_get_userptr pokes into arm direct mapping details to get the
> resemblance of a dma address for a a physical address that does is
> not backed by a page struct.  Not only is this not portable to other
> architectures with dma direct mapping offsets, but also not to uses
> of IOMMUs of any kind.  Switch to the proper dma_map_resource /
> dma_unmap_resource interface instead.
>
> Signed-off-by: Christoph Hellwig 

There are checks for IOMMU presence in other places in vb2-dma-contig,
so it was used only when no IOMMU is available, but I agree that the
hacky code should be replaced by a generic code if possible.

Tested-by: Marek Szyprowski 

V4L2 pipeline works fine on older Exynos-based boards with CMA and IOMMU
disabled.

> ---
>  .../common/videobuf2/videobuf2-dma-contig.c   | 41 ---
>  1 file changed, 9 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> index aff0ab7bf83d..82389aead6ed 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
> @@ -439,42 +439,14 @@ static void vb2_dc_put_userptr(void *buf_priv)
>   set_page_dirty_lock(pages[i]);
>   sg_free_table(sgt);
>   kfree(sgt);
> + } else {
> + dma_unmap_resource(buf->dev, buf->dma_addr, buf->size,
> +buf->dma_dir, 0);
>   }
>   vb2_destroy_framevec(buf->vec);
>   kfree(buf);
>  }
>  
> -/*
> - * For some kind of reserved memory there might be no struct page available,
> - * so all that can be done to support such 'pages' is to try to convert
> - * pfn to dma address or at the last resort just assume that
> - * dma address == physical address (like it has been assumed in earlier 
> version
> - * of videobuf2-dma-contig
> - */
> -
> -#ifdef __arch_pfn_to_dma
> -static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long 
> pfn)
> -{
> - return (dma_addr_t)__arch_pfn_to_dma(dev, pfn);
> -}
> -#elif defined(__pfn_to_bus)
> -static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long 
> pfn)
> -{
> - return (dma_addr_t)__pfn_to_bus(pfn);
> -}
> -#elif defined(__pfn_to_phys)
> -static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long 
> pfn)
> -{
> - return (dma_addr_t)__pfn_to_phys(pfn);
> -}
> -#else
> -static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long 
> pfn)
> -{
> - /* really, we cannot do anything better at this point */
> - return (dma_addr_t)(pfn) << PAGE_SHIFT;
> -}
> -#endif
> -
>  static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
>   unsigned long size, enum dma_data_direction dma_dir)
>  {
> @@ -528,7 +500,12 @@ static void *vb2_dc_get_userptr(struct device *dev, 
> unsigned long vaddr,
>   for (i = 1; i < n_pages; i++)
>   if (nums[i-1] + 1 != nums[i])
>   goto fail_pfnvec;
> - buf->dma_addr = vb2_dc_pfn_to_dma(buf->dev, nums[0]);
> + buf->dma_addr = dma_map_resource(buf->dev,
> +     __pfn_to_phys(nums[0]), size, buf->dma_dir, 0);
> + if (dma_mapping_error(buf->dev, buf->dma_addr)) {
> + ret = -ENOMEM;
> + goto fail_pfnvec;
> + }
>   goto out;
>   }
>  

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: fix a layering violation in videobuf2 and improve dma_map_resource

2019-01-14 Thread Marek Szyprowski
Hi Christoph,

On 2019-01-11 19:17, Christoph Hellwig wrote:
> Hi all,
>
> this series fixes a rather gross layering violation in videobuf2, which
> pokes into arm DMA mapping internals to get a DMA address for memory that
> does not have a page structure, and to do so fixes up the dma_map_resource
> implementation to be practically useful.

Thanks for rewriting this 'temporary code'! It predates
dma_map_resource() and that time this was the only way to get it working
somehow. Good that now it is possible to implement in it a clean way
without any unwritten assumptions about the DMA mapping internals. Feel
free to add my:

Reviewed-by: Marek Szyprowski 

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] media: s5p-mfc: fix incorrect bus assignment in virtual child device

2019-01-07 Thread Marek Szyprowski
Virtual MFC codec's child devices must not be assigned to platform bus,
because they are allocated as raw 'struct device' and don't have the
corresponding 'platform' part. This fixes NULL pointer access revealed
recently by commit a66d972465d1 ("devres: Align data[] to
ARCH_KMALLOC_MINALIGN").

Reported-by: Paweł Chmiel 
Fixes: c79667dd93b0 ("media: s5p-mfc: replace custom reserved memory handling 
code with generic one")
Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 927a1235408d..ca11f8a7569d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1089,7 +1089,6 @@ static struct device *s5p_mfc_alloc_memdev(struct device 
*dev,
device_initialize(child);
dev_set_name(child, "%s:%s", dev_name(dev), name);
child->parent = dev;
-   child->bus = dev->bus;
child->coherent_dma_mask = dev->coherent_dma_mask;
child->dma_mask = dev->dma_mask;
child->release = s5p_mfc_memdev_release;
-- 
2.17.1



Re: [PATCH 7/9] videobuf2/videobuf2-dma-sg.c: Convert to use vm_insert_range

2018-11-20 Thread Marek Szyprowski
Hi Souptick,

On 2018-11-15 16:50, Souptick Joarder wrote:
> Convert to use vm_insert_range to map range of kernel memory
> to user vma.
>
> Signed-off-by: Souptick Joarder 
> Reviewed-by: Matthew Wilcox 

Acked-by: Marek Szyprowski 

> ---
>  drivers/media/common/videobuf2/videobuf2-dma-sg.c | 23 
> +++
>  1 file changed, 7 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
> b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> index 015e737..898adef 100644
> --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
> @@ -328,28 +328,19 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
>  static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
>  {
>   struct vb2_dma_sg_buf *buf = buf_priv;
> - unsigned long uaddr = vma->vm_start;
> - unsigned long usize = vma->vm_end - vma->vm_start;
> - int i = 0;
> + unsigned long page_count = vma_pages(vma);
> + int err;
>  
>   if (!buf) {
>   printk(KERN_ERR "No memory to map\n");
>   return -EINVAL;
>   }
>  
> - do {
> - int ret;
> -
> - ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
> - if (ret) {
> - printk(KERN_ERR "Remapping memory, error: %d\n", ret);
> - return ret;
> - }
> -
> - uaddr += PAGE_SIZE;
> - usize -= PAGE_SIZE;
> - } while (usize > 0);
> -
> + err = vm_insert_range(vma, vma->vm_start, buf->pages, page_count);
> + if (err) {
> + printk(KERN_ERR "Remapping memory, error: %d\n", err);
> + return err;
> + }
>  
>   /*
>* Use common vm_area operations to track buffer refcount.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] media: videobuf2-core: Fix error handling when fileio is deallocated

2018-11-13 Thread Marek Szyprowski
Hi Myungho,

On 2018-11-12 01:49, Myungho Jung wrote:
> The mutex that is held from vb2_fop_read() can be unlocked while waiting
> for a buffer if the queue is streaming and blocking. Meanwhile, fileio
> can be released. So, it should return an error if the fileio address is
> changed.
>
> Signed-off-by: Myungho Jung 
> Reported-by: syzbot+4180ff9ca6810b06c...@syzkaller.appspotmail.com

Acked-by: Marek Szyprowski 

Thanks for analyzing the code and fixing this issue!

> ---
>  drivers/media/common/videobuf2/videobuf2-core.c | 4 
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
> b/drivers/media/common/videobuf2/videobuf2-core.c
> index 975ff5669f72..bff94752eb27 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -2564,6 +2564,10 @@ static size_t __vb2_perform_fileio(struct vb2_queue 
> *q, char __user *data, size_
>   dprintk(5, "vb2_dqbuf result: %d\n", ret);
>   if (ret)
>   return ret;
> + if (fileio != q->fileio) {
> + dprintk(3, "fileio deallocated\n");
> + return -EFAULT;
> + }
>       fileio->dq_count += 1;
>  
>   fileio->cur_index = index;

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] MAINTAINERS: update videobuf2 entry

2018-10-05 Thread Marek Szyprowski
Commits 03fbdb2fc2b8 ("media: move videobuf2 to drivers/media/common")
and 7952be9b6ece ("media: drivers/media/common/videobuf2: rename from
videobuf") moved videobuf2 framework source code finally to
drivers/media/common/videobuf2 directory, so update relevant paths in
MAINTAINERS file.

Reported-by: Joe Perches 
Signed-off-by: Marek Szyprowski 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 29c08106bd22..4455fe05d3a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15720,7 +15720,7 @@ M:  Marek Szyprowski 
 M: Kyungmin Park 
 L: linux-media@vger.kernel.org
 S: Maintained
-F: drivers/media/v4l2-core/videobuf2-*
+F: drivers/media/common/videobuf2/*
 F: include/media/videobuf2-*
 
 VIMC VIRTUAL MEDIA CONTROLLER DRIVER
-- 
2.17.1



[PATCH] media: s5p-mfc: Use real device for request_firmware() call

2018-03-13 Thread Marek Szyprowski
Provide proper (real) struct device to request_firmware() call. This fixes
following error messages:

(NULL device *): Direct firmware load for s5p-mfc-v6-v2.fw failed with error -2
(NULL device *): Direct firmware load for s5p-mfc-v6.fw failed with error -2

into a bit more meaningful ones:

s5p-mfc 1100.codec: Direct firmware load for s5p-mfc-v6-v2.fw failed with 
error -2
s5p-mfc 1100.codec: Direct firmware load for s5p-mfc-v6.fw failed with 
error -2

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index f95cd76af537..ef9ae969d307 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -62,7 +62,7 @@ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
if (!dev->variant->fw_name[i])
continue;
err = request_firmware((const struct firmware **)&fw_blob,
-   dev->variant->fw_name[i], dev->v4l2_dev.dev);
+   dev->variant->fw_name[i], &dev->plat_dev->dev);
if (!err) {
dev->fw_ver = (enum s5p_mfc_fw_ver) i;
break;
-- 
2.15.0



Re: [PATCH 1/8] clk: Add clk_bulk_alloc functions

2018-02-20 Thread Marek Szyprowski

Hi Robin,

On 2018-02-19 17:29, Robin Murphy wrote:

Hi Maciej,

On 19/02/18 15:43, Maciej Purski wrote:

When a driver is going to use clk_bulk_get() function, it has to
initialize an array of clk_bulk_data, by filling its id fields.

Add a new function to the core, which dynamically allocates
clk_bulk_data array and fills its id fields. Add clk_bulk_free()
function, which frees the array allocated by clk_bulk_alloc() function.
Add a managed version of clk_bulk_alloc().


Seeing how every subsequent patch ends up with the roughly this same 
stanza:


x = devm_clk_bulk_alloc(dev, num, names);
if (IS_ERR(x)
    return PTR_ERR(x);
ret = devm_clk_bulk_get(dev, x, num);

I wonder if it might be better to simply implement:

int devm_clk_bulk_alloc_get(dev, &x, num, names)

that does the whole lot in one go, and let drivers that want to do 
more fiddly things continue to open-code the allocation.


But perhaps that's an abstraction too far... I'm not all that familiar 
with the lie of the land here.


Hmmm. This patchset clearly shows, that it would be much simpler if we
get rid of clk_bulk_data structure at all and let clk_bulk_* functions
to operate on struct clk *array[]. Typically the list of clock names
is already in some kind of array (taken from driver data or statically
embedded into driver), so there is little benefit from duplicating it
in clk_bulk_data. Sadly, I missed clk_bulk_* api discussion and maybe
there are other benefits from this approach.

If not, I suggest simplifying clk_bulk_* api by dropping clk_bulk_data
structure and switching to clock ptr array:

int clk_bulk_get(struct device *dev, int num_clock, struct clk *clocks[],
             const char *clk_names[]);
int clk_bulk_prepare(int num_clks, struct clk *clks[]);
int clk_bulk_enable(int num_clks, struct clk *clks[]);
...






Signed-off-by: Maciej Purski 
---
  drivers/clk/clk-bulk.c   | 16 
  drivers/clk/clk-devres.c | 37 +---
  include/linux/clk.h  | 64 


  3 files changed, 113 insertions(+), 4 deletions(-)



[...]
@@ -598,6 +645,23 @@ struct clk *clk_get_sys(const char *dev_id, 
const char *con_id);

    #else /* !CONFIG_HAVE_CLK */
  +static inline struct clk_bulk_data *clk_bulk_alloc(int num_clks,
+   const char **clk_ids)
+{
+    return NULL;


Either way, is it intentional not returning an ERR_PTR() value in this 
case? Since NULL will pass an IS_ERR() check, it seems a bit fragile 
for an allocation call to apparently succeed when the whole API is 
configured out (and I believe introducing new uses of IS_ERR_OR_NULL() 
is in general strongly discouraged.)


Robin.


+}
+
+static inline struct clk_bulk_data *devm_clk_bulk_alloc(struct 
device *dev,

+    int num_clks,
+    const char **clk_ids)
+{
+    return NULL;
+}
+
+static inline void clk_bulk_free(struct clk_bulk_data *clks)
+{
+}
+
  static inline struct clk *clk_get(struct device *dev, const char *id)
  {
  return NULL;



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v2] media: vb2: Fix videobuf2 to map correct area

2018-02-06 Thread Marek Szyprowski

Hi Masami,

On 2018-02-06 09:02, Masami Hiramatsu wrote:

Fixes vb2_vmalloc_get_userptr() to ioremap correct area.
Since the current code does ioremap the page address, if the offset > 0,
it does not do ioremap the last page and results in kernel panic.

This fixes to pass the size + offset to ioremap so that ioremap
can map correct area. Also, this uses __pfn_to_phys() to get the physical
address of given PFN.

Signed-off-by: Masami Hiramatsu 
Reported-by: Takao Orito 
Reported-by: Fumihiro ATSUMI 


Reviewed-by: Marek Szyprowski 


---
   Chanegs in v2:
- Fix to pass size + offset instead of changing address.
---
  drivers/media/v4l2-core/videobuf2-vmalloc.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c 
b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 3a7c80cd1a17..359fb9804d16 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -106,7 +106,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, 
unsigned long vaddr,
if (nums[i-1] + 1 != nums[i])
goto fail_map;
buf->vaddr = (__force void *)
-   ioremap_nocache(nums[0] << PAGE_SHIFT, size);
+   ioremap_nocache(__pfn_to_phys(nums[0]), size + offset);
} else {
buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1,
PAGE_KERNEL);






Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] [BUGFIX] media: vb2: Fix videobuf2 to map correct area

2018-02-05 Thread Marek Szyprowski

Hi Masami,

On 2018-02-05 03:30, Masami Hiramatsu wrote:

Fixes vb2_vmalloc_get_userptr() to ioremap correct area.
Since the current code does ioremap the page address, if the offset > 0,
it does not do ioremap the last page and results in kernel panic.

This fixes to pass the page address + offset to ioremap so that ioremap
can map correct area. Also, this uses __pfn_to_phys() to get the physical
address of given PFN.

Signed-off-by: Masami Hiramatsu 
Reported-by: Takao Orito 
---
  drivers/media/v4l2-core/videobuf2-vmalloc.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c 
b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 3a7c80cd1a17..896f2f378b40 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -106,7 +106,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, 
unsigned long vaddr,
if (nums[i-1] + 1 != nums[i])
goto fail_map;
buf->vaddr = (__force void *)
-   ioremap_nocache(nums[0] << PAGE_SHIFT, size);
+   ioremap_nocache(__pfn_to_phys(nums[0]) + offset, size);


Thanks for reporting this issue. However the above line doesn't look like
a proper fix. Please note that at the end of that function there is already
"buf->vaddr += offset;".

IMHO the proper fix is to create a larger mapping, which would include the
in-page start offset:

ioremap_nocache(__pfn_to_phys(nums[0]), offset + size);

BTW, thanks for updating "<< PAGE_SHIFT" to better __pfn_to_phys() macro!


} else {
buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1,
        PAGE_KERNEL);






Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-12-18 Thread Marek Szyprowski

Hi Hans,

On 2017-12-15 16:57, Hans Verkuil wrote:

On 14/12/17 15:11, Marek Szyprowski wrote:

I would like to get your opinion on this patch. Do you think it makes sense to:

1. add limited support for USERPTR and DMA-buf import? (limited means driver 
will accept setting buffer pointer/fd only once after reqbufs for each buffer 
index)

I don't like this. It's unexpected almost-but-not-quite behavior that will make
life very difficult for userspace.


2. add a V4L2 device flag to let userspace to discover if device support queue 
buffer reconfiguration on-fly or not?

This seems to me a better approach. It should be possible to implement most/all 
of this
in vb2, but we need to find a way to signal this to the user.


Okay, I will prepare a patch with such flag soon.


Is this an MFC limitation for the decoder, encoder or both? And is it a 
limitation
of the capture or output side or both?


Both and both. DMA addresses of all buffers must be known while 
initializing decoder

and encoder.

> ...

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-12-14 Thread Marek Szyprowski

Hi Hans,

I would like to get your opinion on this patch. Do you think it makes 
sense to:


1. add limited support for USERPTR and DMA-buf import? (limited means 
driver will accept setting buffer pointer/fd only once after reqbufs for 
each buffer index)


2. add a V4L2 device flag to let userspace to discover if device support 
queue buffer reconfiguration on-fly or not?


Here is the discussion: https://patchwork.linuxtv.org/patch/45305/

Best regards
Marek Szyprowski, PhD
Samsung R&D Institute Poland


On 2017-11-06 20:21, Nicolas Dufresne wrote:

Le lundi 06 novembre 2017 à 10:28 +0100, Marek Szyprowski a écrit :

On 2017-11-03 14:45, Nicolas Dufresne wrote:

Le vendredi 03 novembre 2017 à 09:11 +0100, Marek Szyprowski a écrit :

MFC driver supports only MMAP operation mode mainly due to the hardware
restrictions of the addresses of the DMA buffers (MFC v5 hardware can
access buffers only in 128MiB memory region starting from the base address
of its firmware). When IOMMU is available, this requirement is easily
fulfilled even for the buffers located anywhere in the memory - typically
by mapping them in the DMA address space as close as possible to the
firmware. Later hardware revisions don't have this limitations at all.

The second limitation of the MFC hardware related to the memory buffers
is constant buffer address. Once the hardware has been initialized for
operation on given buffer set, the addresses of the buffers cannot be
changed.

With the above assumptions, a limited support for USERPTR and DMABUF
operation modes can be added. The main requirement is to have all buffers
known when starting hardware. This has been achieved by postponing
hardware initialization once all the DMABUF or USERPTR buffers have been
queued for the first time. Once then, buffers cannot be modified to point
to other memory area.

I am concerned about enabling this support with existing userspace.
Userspace application will be left with some driver with this
limitation and other drivers without. I think it is harmful to enable
that feature without providing userspace the ability to know.

This is specially conflicting with let's say UVC driver providing
buffers, since UVC driver implementing CREATE_BUFS ioctl. So even if
userspace start making an effort to maintain the same DMABuf for the
same buffer index, if a new buffer is created, we won't be able to use
it.

Sorry, but I don't get this as an 'issue'. The typical use scenario is to
configure buffer queue and start streaming. Basically ReqBufs, stream on and
a sequence of bufq/bufdq. This is handled without any problem by MFC driver
with this patch. After releasing a queue with reqbufs(0), one can use
different set of buffers.

In real life, you often have capture code decorelated from the encoder
code. At least, it's the case in GStreamer. The encoder have no
information about how many buffers were pre-allocated by let's say the
capture driver. As a side effect, we cannot make sure the importation
queue is of the same size (amount of buffer). Specially if you have UVC
driver that allow allocating more buffers at run-time. This is used in
real-life to compensate additional latency that get's added when a
pipeline topology is changed (at run-time). Only workaround I had in
mind, would be to always prepare the queue with the maximum (32), and
use this as a cache size, but for now, this is not how the deployed
userspace works unfortunately.

Your reqbuf(0) technique cause a break in the stream (probably a new
keyframe), as you are forced to STREAMOFF. This is often unwanted, and
it may create a time discontinuity in case the allocation took time.


What is the point of changing the buffers during the streaming? IMHO it was
one of the biggest pathology of the V4L2 USERPTR API that the buffers
were in
fact 'created' on the first queue operation. By creating I mean creating all
the kernel all needed structures and mappings between the real memory (user
ptr value) and the buffer index. The result of this was userspace, which
don't
use buffer indices and always queues buffers with index = 0, what means that
kernel has to reacquire direct access to each buffer every single frame.
That
is highly inefficient approach. DMABUF operation mode inherited this
drawback.

This in fact is an implementation detail of the caching in the kernel
framework. There is nothing that prevent the framework to maintain a
validation cache that isn't bound to the queue size. DMABuf simply
makes the buffer identification easier and safer. I bet it is difficult
and it will stay like this, so it should at least be documented.

I am completely aware of the inefficiency of the GStreamer behaviour,
though it remains much faster in many case then copying raw frames
using the CPU. You can complain as much as you can about what this
userspace doing, but it as has been working better then nothing for
many users. It might not be lik

Re: [PATCH 12/12] media: videobuf2: don't use kernel-doc "/**" markups

2017-11-29 Thread Marek Szyprowski

Hi Mauro,

On 2017-11-29 11:46, Mauro Carvalho Chehab wrote:

While it would be very cool to have those functions using
kernel-doc markups, the reality right now is that they
don't follow kernel-doc rules, as parameters aren't documented.

So, stop abusing on "/**" markups.

Signed-off-by: Mauro Carvalho Chehab 


Acked-by: Marek Szyprowski 


---
  drivers/media/v4l2-core/videobuf2-core.c | 56 
  drivers/media/v4l2-core/videobuf2-v4l2.c | 10 +++---
  2 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index cb115ba6a1d2..a8589d96ef72 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -188,7 +188,7 @@ module_param(debug, int, 0644);
  static void __vb2_queue_cancel(struct vb2_queue *q);
  static void __enqueue_in_driver(struct vb2_buffer *vb);
  
-/**

+/*
   * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
   */
  static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
@@ -229,7 +229,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
return ret;
  }
  
-/**

+/*
   * __vb2_buf_mem_free() - free memory of the given buffer
   */
  static void __vb2_buf_mem_free(struct vb2_buffer *vb)
@@ -243,7 +243,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
}
  }
  
-/**

+/*
   * __vb2_buf_userptr_put() - release userspace memory associated with
   * a USERPTR buffer
   */
@@ -258,7 +258,7 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
}
  }
  
-/**

+/*
   * __vb2_plane_dmabuf_put() - release memory associated with
   * a DMABUF shared plane
   */
@@ -277,7 +277,7 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, 
struct vb2_plane *p)
p->dbuf_mapped = 0;
  }
  
-/**

+/*
   * __vb2_buf_dmabuf_put() - release memory associated with
   * a DMABUF shared buffer
   */
@@ -289,7 +289,7 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
  }
  
-/**

+/*
   * __setup_offsets() - setup unique offsets ("cookies") for every plane in
   * the buffer.
   */
@@ -317,7 +317,7 @@ static void __setup_offsets(struct vb2_buffer *vb)
}
  }
  
-/**

+/*
   * __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP 
type)
   * video buffer memory for all buffers/planes on the queue and initializes the
   * queue
@@ -386,7 +386,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
return buffer;
  }
  
-/**

+/*
   * __vb2_free_mem() - release all video buffer memory for a given queue
   */
  static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
@@ -410,7 +410,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned 
int buffers)
}
  }
  
-/**

+/*
   * __vb2_queue_free() - free buffers at the end of the queue - video memory 
and
   * related information, if no buffers are left return the queue to an
   * uninitialized state. Might be called even if the queue has already been 
freed.
@@ -544,7 +544,7 @@ bool vb2_buffer_in_use(struct vb2_queue *q, struct 
vb2_buffer *vb)
  }
  EXPORT_SYMBOL(vb2_buffer_in_use);
  
-/**

+/*
   * __buffers_in_use() - return true if any buffers on the queue are in use and
   * the queue cannot be freed (by the means of REQBUFS(0)) call
   */
@@ -564,7 +564,7 @@ void vb2_core_querybuf(struct vb2_queue *q, unsigned int 
index, void *pb)
  }
  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
  
-/**

+/*
   * __verify_userptr_ops() - verify that all memory operations required for
   * USERPTR queue type have been provided
   */
@@ -577,7 +577,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
return 0;
  }
  
-/**

+/*
   * __verify_mmap_ops() - verify that all memory operations required for
   * MMAP queue type have been provided
   */
@@ -590,7 +590,7 @@ static int __verify_mmap_ops(struct vb2_queue *q)
return 0;
  }
  
-/**

+/*
   * __verify_dmabuf_ops() - verify that all memory operations required for
   * DMABUF queue type have been provided
   */
@@ -953,7 +953,7 @@ void vb2_discard_done(struct vb2_queue *q)
  }
  EXPORT_SYMBOL_GPL(vb2_discard_done);
  
-/**

+/*
   * __prepare_mmap() - prepare an MMAP buffer
   */
  static int __prepare_mmap(struct vb2_buffer *vb, const void *pb)
@@ -966,7 +966,7 @@ static int __prepare_mmap(struct vb2_buffer *vb, const void 
*pb)
return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
  }
  
-/**

+/*
   * __prepare_userptr() - prepare a USERPTR buffer
   */
  static int __prepare_userptr(struct vb2_buffer *vb, const void *pb)
@@ -1082,7 +1082,7 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
return ret;
  }
  
-/**

+/*
   * __prepare_dmabuf() - prepare a DMABUF buffer
   */
  static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb)
@@ -1215,

Re: [PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-11-06 Thread Marek Szyprowski

Hi Nicolas,

On 2017-11-03 14:45, Nicolas Dufresne wrote:

Le vendredi 03 novembre 2017 à 09:11 +0100, Marek Szyprowski a écrit :

MFC driver supports only MMAP operation mode mainly due to the hardware
restrictions of the addresses of the DMA buffers (MFC v5 hardware can
access buffers only in 128MiB memory region starting from the base address
of its firmware). When IOMMU is available, this requirement is easily
fulfilled even for the buffers located anywhere in the memory - typically
by mapping them in the DMA address space as close as possible to the
firmware. Later hardware revisions don't have this limitations at all.

The second limitation of the MFC hardware related to the memory buffers
is constant buffer address. Once the hardware has been initialized for
operation on given buffer set, the addresses of the buffers cannot be
changed.

With the above assumptions, a limited support for USERPTR and DMABUF
operation modes can be added. The main requirement is to have all buffers
known when starting hardware. This has been achieved by postponing
hardware initialization once all the DMABUF or USERPTR buffers have been
queued for the first time. Once then, buffers cannot be modified to point
to other memory area.

I am concerned about enabling this support with existing userspace.
Userspace application will be left with some driver with this
limitation and other drivers without. I think it is harmful to enable
that feature without providing userspace the ability to know.

This is specially conflicting with let's say UVC driver providing
buffers, since UVC driver implementing CREATE_BUFS ioctl. So even if
userspace start making an effort to maintain the same DMABuf for the
same buffer index, if a new buffer is created, we won't be able to use
it.


Sorry, but I don't get this as an 'issue'. The typical use scenario is to
configure buffer queue and start streaming. Basically ReqBufs, stream on and
a sequence of bufq/bufdq. This is handled without any problem by MFC driver
with this patch. After releasing a queue with reqbufs(0), one can use
different set of buffers.

What is the point of changing the buffers during the streaming? IMHO it was
one of the biggest pathology of the V4L2 USERPTR API that the buffers 
were in

fact 'created' on the first queue operation. By creating I mean creating all
the kernel all needed structures and mappings between the real memory (user
ptr value) and the buffer index. The result of this was userspace, which 
don't

use buffer indices and always queues buffers with index = 0, what means that
kernel has to reacquire direct access to each buffer every single frame. 
That
is highly inefficient approach. DMABUF operation mode inherited this 
drawback.


When we have a pipeline for processing video data it should use N buffers on
both input and output of each element when DMAbuf is used. Once we 
allocate N
buffers, using N dmabuf-imported buffers which maps 1-1 is trivial. Only 
this

way you will have true zero-copy processing without any additional overhead.


This patch also removes unconditional USERPTR operation mode from encoder
video node, because it doesn't work with v5 MFC hardware without IOMMU
being enabled.

In case of MFC v5 a bidirectional queue flag has to be enabled as a
workaround of the strange hardware behavior - MFC performs a few writes
to source data during the operation.

Do you have more information about this ? It is quite terrible, since
if you enable buffer importation, the buffer might be multi-plex across
multiple encoder instance. That is another way this feature can be
harmful to existing userspace.


I also don't like this behavior of the hardware. I will probably investigate
it further once I have some time. The other workaround would be to 
always use

driver allocated buffers and simply copy input stream in case of USERPTR or
DMABUF to avoid modifying source data. It would mean copying the compressed
stream, what should not hurt us that much.


Signed-off-by: Seung-Woo Kim 
[mszyprow: adapted to v4.14 code base, rewrote and extended commit message,
  added checks for changing buffer addresses, added bidirectional queue
  flags and comments]
Signed-off-by: Marek Szyprowski 
---
v2:
- fixed copy/paste bug, which broke encoding support (thanks to Marian
   Mihailescu for reporting it)
- added checks for changing buffers DMA addresses
- added bidirectional queue flags

v1:
- inital version
---
  drivers/media/platform/s5p-mfc/s5p_mfc.c |  23 +-
  drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 111 +++
  drivers/media/platform/s5p-mfc/s5p_mfc_enc.c |  64 +++
  3 files changed, 147 insertions(+), 51 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 1839a86cc2a5..f1ab8d198158 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -75

[PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-11-03 Thread Marek Szyprowski
MFC driver supports only MMAP operation mode mainly due to the hardware
restrictions of the addresses of the DMA buffers (MFC v5 hardware can
access buffers only in 128MiB memory region starting from the base address
of its firmware). When IOMMU is available, this requirement is easily
fulfilled even for the buffers located anywhere in the memory - typically
by mapping them in the DMA address space as close as possible to the
firmware. Later hardware revisions don't have this limitations at all.

The second limitation of the MFC hardware related to the memory buffers
is constant buffer address. Once the hardware has been initialized for
operation on given buffer set, the addresses of the buffers cannot be
changed.

With the above assumptions, a limited support for USERPTR and DMABUF
operation modes can be added. The main requirement is to have all buffers
known when starting hardware. This has been achieved by postponing
hardware initialization once all the DMABUF or USERPTR buffers have been
queued for the first time. Once then, buffers cannot be modified to point
to other memory area.

This patch also removes unconditional USERPTR operation mode from encoder
video node, because it doesn't work with v5 MFC hardware without IOMMU
being enabled.

In case of MFC v5 a bidirectional queue flag has to be enabled as a
workaround of the strange hardware behavior - MFC performs a few writes
to source data during the operation.

Signed-off-by: Seung-Woo Kim 
[mszyprow: adapted to v4.14 code base, rewrote and extended commit message,
 added checks for changing buffer addresses, added bidirectional queue
 flags and comments]
Signed-off-by: Marek Szyprowski 
---
v2:
- fixed copy/paste bug, which broke encoding support (thanks to Marian
  Mihailescu for reporting it)
- added checks for changing buffers DMA addresses
- added bidirectional queue flags

v1:
- inital version
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c |  23 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 111 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c |  64 +++
 3 files changed, 147 insertions(+), 51 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 1839a86cc2a5..f1ab8d198158 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -754,6 +754,7 @@ static int s5p_mfc_open(struct file *file)
struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_ctx *ctx = NULL;
struct vb2_queue *q;
+   unsigned int io_modes;
int ret = 0;
 
mfc_debug_enter();
@@ -839,16 +840,25 @@ static int s5p_mfc_open(struct file *file)
if (ret)
goto err_init_hw;
}
+
+   io_modes = VB2_MMAP;
+   if (exynos_is_iommu_available(&dev->plat_dev->dev) || !IS_TWOPORT(dev))
+   io_modes |= VB2_USERPTR | VB2_DMABUF;
+
/* Init videobuf2 queue for CAPTURE */
q = &ctx->vq_dst;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+   q->io_modes = io_modes;
+   /*
+* Destination buffers are always bidirectional, they use used as
+* reference data, which require READ access
+*/
+   q->bidirectional = true;
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
if (vdev == dev->vfd_dec) {
-   q->io_modes = VB2_MMAP;
q->ops = get_dec_queue_ops();
} else if (vdev == dev->vfd_enc) {
-   q->io_modes = VB2_MMAP | VB2_USERPTR;
q->ops = get_enc_queue_ops();
} else {
ret = -ENOENT;
@@ -869,13 +879,18 @@ static int s5p_mfc_open(struct file *file)
/* Init videobuf2 queue for OUTPUT */
q = &ctx->vq_src;
q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+   q->io_modes = io_modes;
+   /*
+* MFV v5 performs write operations on source data, so make queue
+* bidirectional to avoid IOMMU protection fault.
+*/
+   if (!IS_MFCV6_PLUS(dev))
+   q->bidirectional = true;
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
if (vdev == dev->vfd_dec) {
-   q->io_modes = VB2_MMAP;
q->ops = get_dec_queue_ops();
} else if (vdev == dev->vfd_enc) {
-   q->io_modes = VB2_MMAP | VB2_USERPTR;
q->ops = get_enc_queue_ops();
} else {
ret = -ENOENT;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index e3e5c442902a..26ee8315e2cf 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -551,14 +551,27 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, 
struct s5p_mfc_c

Re: [PATCH] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-11-02 Thread Marek Szyprowski

Hi Tobias,

On 2017-10-20 15:59, Tobias Jakobi wrote:

Hey Marek and others,

just wanted to point out that I've also played around with Seung-Woo' patch for
a while. However this patch alone is very much incomplete.

In particular this is missing:
- At least v5 MFC hw needs source buffers to be also writable, so dma mapping
needs to be setup bidirectional.
- Like with mmap, all buffers need to be setup before decoding can begin. This
is due to how MFC hw gets initialized. dmabufs that are added later are not
going to be used before MFC hw isn't reinitialized.
- Removing dmabufs, or replacing them seems to be impossible with the current
code architecture.


Right. Those are limitations of the hardware and in next version of this 
patch I will

add checks for them.


I had extended samsung-utils with some C++ app to test stuff when I was looking
into this. You can find the code here:
https://github.com/tobiasjakobi/samsung-utils/tree/devel/v4l2-mfc-drm-direct

Now here is what happens. I allocate N buffer objects in DRM land to be used as
destination for the MFC decoder. The BOs are exported, so that I can then use
them in V4L2 space. I have to queue n (with n < N) buffers before I can start
the MFC engine.


According to my knowledge of the MFC HW, if you want to use N buffers 
with MFC,
you have to queue all N buffers to initialize the HW. Otherwise, HW will 
produce

video data only to the n buffer queued on stream on.


If I do start the engine at that point (n buffers queued), I soon get an IOMMU
pagefault. I need to queue all N buffers before anything works at all. Queueing
a buffer the first time also registers it, and this has to happen before the MFC
hw is initialized.

In particular I can't just allocate more buffers from DRM and use them here
_after_ decoding has started.

To me it looks like the MFC code was never written with dmabuf in mind. It's
centered around a static memory setup that is fixed before decoding begins.


That's true, but still, using it with DMA-bufs might be convenient in 
some cases,
even with the above limitations. The IOMMU fault can be mitigated by 
enabling
bidirectional flag on OUTPUT queue. This is a bit strange, but that's 
how the
hardware behaves. From my research it looks that it happens only in case 
of MFCv5,

higher versions don't modify source stream.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH 2/2] media: exynos4-is: drop obsolete capabilities

2017-10-31 Thread Marek Szyprowski
Setting both V4L2_CAP_VIDEO_CAPTURE_MPLANE and V4L2_CAP_VIDEO_OUTPUT_MPLANE
for mem2mem video nodes is obsolete since commit f0476a83d61a ("[media]
V4L: Add capability flags for memory-to-memory devices"). It was enough
time to adapt all users to the new flags, so drop the legacy caps for now
to match other mem2mem drivers.

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/exynos4-is/fimc-m2m.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c 
b/drivers/media/platform/exynos4-is/fimc-m2m.c
index 9027d0b0d2bd..a19f8b164a47 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -236,15 +236,7 @@ static int fimc_m2m_querycap(struct file *file, void *fh,
 struct v4l2_capability *cap)
 {
struct fimc_dev *fimc = video_drvdata(file);
-   unsigned int caps;
-
-   /*
-* This is only a mem-to-mem video device. The capture and output
-* device capability flags are left only for backward compatibility
-* and are scheduled for removal.
-*/
-   caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE |
-   V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+   unsigned int caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
 
__fimc_vidioc_querycap(&fimc->pdev->dev, cap, caps);
return 0;
-- 
2.14.2



[PATCH 1/2] media: exynos-gsc: drop obsolete capabilities

2017-10-31 Thread Marek Szyprowski
Setting both V4L2_CAP_VIDEO_CAPTURE_MPLANE and V4L2_CAP_VIDEO_OUTPUT_MPLANE
for mem2mem video nodes is obsolete since commit f0476a83d61a ("[media]
V4L: Add capability flags for memory-to-memory devices"). It was enough
time to adapt all users to the new flags, so drop the legacy caps for now
to match other mem2mem drivers.

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/exynos-gsc/gsc-m2m.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c 
b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index 722d7c45bf9e..785e67752194 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -298,9 +298,7 @@ static int gsc_m2m_querycap(struct file *file, void *fh,
strlcpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 dev_name(&gsc->pdev->dev));
-   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE |
-   V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
-
+   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
 }
-- 
2.14.2



[PATCH] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

2017-10-20 Thread Marek Szyprowski
From: Seung-Woo Kim 

There is memory constraint for the buffers in V5 of the MFC hardware, but
when IOMMU is used, then this constraint is meaningless. Other version of
the MFC hardware don't have such limitations. So in such cases the driver
is able to use buffers placed anywhere in the system memory, thus USERPTR
and DMABUF operation modes can be also enabled.

This patch also removes USERPTR operation mode from encoder node, as it
doesn't work with v5 MFC hardware without IOMMU being enabled.

Signed-off-by: Seung-Woo Kim 
[mszyprow: adapted to v4.14 code base and updated commit message]
Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 14 --
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 73 
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 24 ++---
 3 files changed, 89 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index cf68aed59e0d..f975523dc040 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -754,6 +754,7 @@ static int s5p_mfc_open(struct file *file)
struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_ctx *ctx = NULL;
struct vb2_queue *q;
+   unsigned int io_modes;
int ret = 0;
 
mfc_debug_enter();
@@ -839,16 +840,21 @@ static int s5p_mfc_open(struct file *file)
if (ret)
goto err_init_hw;
}
+
+   io_modes = VB2_MMAP;
+   if (exynos_is_iommu_available(&dev->plat_dev->dev) || !IS_TWOPORT(dev))
+   io_modes |= VB2_USERPTR | VB2_DMABUF;
+
/* Init videobuf2 queue for CAPTURE */
q = &ctx->vq_dst;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
if (vdev == dev->vfd_dec) {
-   q->io_modes = VB2_MMAP;
+   q->io_modes = io_modes;
q->ops = get_dec_queue_ops();
} else if (vdev == dev->vfd_enc) {
-   q->io_modes = VB2_MMAP | VB2_USERPTR;
+   q->io_modes = io_modes;
q->ops = get_enc_queue_ops();
} else {
ret = -ENOENT;
@@ -872,10 +878,10 @@ static int s5p_mfc_open(struct file *file)
q->drv_priv = &ctx->fh;
q->lock = &dev->mfc_mutex;
if (vdev == dev->vfd_dec) {
-   q->io_modes = VB2_MMAP;
+   q->io_modes = io_modes;
q->ops = get_dec_queue_ops();
} else if (vdev == dev->vfd_enc) {
-   q->io_modes = VB2_MMAP | VB2_USERPTR;
+   q->io_modes = io_modes;
q->ops = get_enc_queue_ops();
} else {
ret = -ENOENT;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 8937b0af7cb3..efe65fce4880 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -546,14 +546,27 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, 
struct s5p_mfc_ctx *ctx,
goto out;
}
 
-   WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);
-   ctx->capture_state = QUEUE_BUFS_MMAPED;
+   if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+   if (ctx->dst_bufs_cnt == ctx->total_dpb_count) {
+   ctx->capture_state = QUEUE_BUFS_MMAPED;
+   } else {
+   mfc_err("Not all buffers passed to buf_init\n");
+   reqbufs->count = 0;
+   ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+   s5p_mfc_hw_call(dev->mfc_ops,
+   release_codec_buffers, ctx);
+   ret = -ENOMEM;
+   goto out;
+   }
+   }
 
if (s5p_mfc_ctx_ready(ctx))
set_work_bit_irqsave(ctx);
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-   s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,
- 0);
+   if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+   s5p_mfc_wait_for_done_ctx(ctx,
+S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
+   }
} else {
mfc_err("Buffers have already been requested\n");
ret = -EINVAL;
@@ -571,15 +584,19 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 {
struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p

Re: Exynos MFC issues on 4.14-rc4

2017-10-16 Thread Marek Szyprowski

Hi Marian,

On 2017-10-12 02:49, Marian Mihailescu wrote:

I've been testing 4.14-rc4 on Odroid-XU4, and here's a kernel
complaint when running:

gst-launch-1.0 filesrc location=bunny_trailer_1080p.mov ! parsebin !
v4l2video4dec capture-io-mode=dmabuf ! v4l2video6convert
output-io-mode=dmabuf-import capture-io-mode=dmabuf ! kmssink

http://paste.debian.net/990353/


This is rather harmless and it happens on v4.14-rcX, because LOCKDEP has
been enabled by default in the exynos_defconfig. For more information
see https://lkml.org/lkml/2017/10/13/974


PS: on kernel 4.9 patched with MFC & GSC updates (almost up to date
with 4.14 I think) there was no "Wrong buffer/video queue type (1)"
message either


I will check it and let you know if this is something we should worry about.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH 0/2] fix lockdep warnings in s5p_mfc and exynos-gsc vb2 drivers

2017-10-16 Thread Marek Szyprowski

Hi Shuah,

On 2017-10-14 01:13, Shuah Khan wrote:

Driver mmap functions shouldn't hold lock when calling vb2_mmap(). The
vb2_mmap() function has its own lock that it uses to protect the critical
section.

Reference: commit log for f035eb4e976ef5a059e30bc91cfd310ff030a7d3


It would make sense to add the information about the reference commit to 
each
commit message and also point to commit 
e752577ed7bf55c81e10343fced8b378cda2b63b,

as it is exactly the same case here. Anyway:

Acked-by: Marek Szyprowski 

I wonder if makes sense to send those patches also to sta...@vget.kernel.org
(maybe v4.3+, like the mentioned above commit, if they really apply?).


Shuah Khan (2):
   media: exynos-gsc: fix lockdep warning
   media: s5p-mfc: fix lockdep warning

  drivers/media/platform/exynos-gsc/gsc-m2m.c | 5 -
  drivers/media/platform/s5p-mfc/s5p_mfc.c| 3 ---
  2 files changed, 8 deletions(-)



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] media: vb2: unify calling of set_page_dirty_lock

2017-10-10 Thread Marek Szyprowski

Hi Stanimir,

On 2017-10-10 09:42, Stanimir Varbanov wrote:

Marek,

Any comments?


Oh, I thought that this one has been already merged. If not (yet),
here is my ack.


On 08/29/2017 02:26 PM, Stanimir Varbanov wrote:

Currently videobuf2-dma-sg checks for dma direction for
every single page and videobuf2-dc lacks any dma direction
checks and calls set_page_dirty_lock unconditionally.

Thus unify and align the invocations of set_page_dirty_lock
for videobuf2-dc, videobuf2-sg  memory allocators with
videobuf2-vmalloc, i.e. the pattern used in vmalloc has been
copied to dc and dma-sg.

Suggested-by: Marek Szyprowski 
Signed-off-by: Stanimir Varbanov 


Acked-by: Marek Szyprowski 


---
  drivers/media/v4l2-core/videobuf2-dma-contig.c | 6 --
  drivers/media/v4l2-core/videobuf2-dma-sg.c | 7 +++
  2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 9f389f36566d..696e24f9128d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -434,8 +434,10 @@ static void vb2_dc_put_userptr(void *buf_priv)
pages = frame_vector_pages(buf->vec);
/* sgt should exist only if vector contains pages... */
BUG_ON(IS_ERR(pages));
-   for (i = 0; i < frame_vector_count(buf->vec); i++)
-   set_page_dirty_lock(pages[i]);
+   if (buf->dma_dir == DMA_FROM_DEVICE ||
+   buf->dma_dir == DMA_BIDIRECTIONAL)
+   for (i = 0; i < frame_vector_count(buf->vec); i++)
+   set_page_dirty_lock(pages[i]);
sg_free_table(sgt);
kfree(sgt);
}
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 6808231a6bdc..753ed3138dcc 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -292,11 +292,10 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
if (buf->vaddr)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
-   while (--i >= 0) {
-   if (buf->dma_dir == DMA_FROM_DEVICE ||
-   buf->dma_dir == DMA_BIDIRECTIONAL)
+   if (buf->dma_dir == DMA_FROM_DEVICE ||
+   buf->dma_dir == DMA_BIDIRECTIONAL)
+   while (--i >= 0)
set_page_dirty_lock(buf->pages[i]);
-   }
vb2_destroy_framevec(buf->vec);
    kfree(buf);
  }



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH 4/7] media: exynos4-is: Remove dependency on obsolete SoC support

2017-10-03 Thread Marek Szyprowski
Support for Exynos4212 SoCs has been removed by commit bca9085e0ae9 ("ARM:
dts: exynos: remove Exynos4212 support (dead code)"), so there is no need
to keep remaining dead code related to this SoC version.

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/exynos4-is/Kconfig | 2 +-
 drivers/media/platform/exynos4-is/fimc-core.c | 2 +-
 drivers/media/platform/exynos4-is/fimc-lite.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/exynos4-is/Kconfig 
b/drivers/media/platform/exynos4-is/Kconfig
index 46a7d242a1a5..7b2c49e5a592 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -41,7 +41,7 @@ config VIDEO_S5P_MIPI_CSIS
  To compile this driver as a module, choose M here: the
  module will be called s5p-csis.
 
-if SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250
+if SOC_EXYNOS4412 || SOC_EXYNOS5250
 
 config VIDEO_EXYNOS_FIMC_LITE
tristate "EXYNOS FIMC-LITE camera interface driver"
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c 
b/drivers/media/platform/exynos4-is/fimc-core.c
index 099c735a39b7..7ae239f2b0fd 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -1211,7 +1211,7 @@ static const struct fimc_drvdata fimc_drvdata_exynos4210 
= {
.out_buf_count  = 32,
 };
 
-/* EXYNOS4212, EXYNOS4412 */
+/* EXYNOS4412 */
 static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
.num_entities   = 4,
.lclk_frequency = 16600UL,
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c 
b/drivers/media/platform/exynos4-is/fimc-lite.c
index 4a3c9948ca54..3805a6daa3f4 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -1646,7 +1646,7 @@ static const struct dev_pm_ops fimc_lite_pm_ops = {
   NULL)
 };
 
-/* EXYNOS4212, EXYNOS4412 */
+/* EXYNOS4412 */
 static struct flite_drvdata fimc_lite_drvdata_exynos4 = {
.max_width  = 8192,
.max_height = 8192,
-- 
2.14.2



Re: [PATCH v2 16/17] media: videobuf2-core: improve kernel-doc markups

2017-09-29 Thread Marek Szyprowski

Hi,

On 2017-09-27 23:46, Mauro Carvalho Chehab wrote:

Now that nested structs are supported, change the
documentation to use it. While here, add cross-references
where pertinent and use monotonic fonts where pertinent,
using the right markup tags.

Signed-off-by: Mauro Carvalho Chehab 


Acked-by: Marek Szyprowski 


---
  include/media/videobuf2-core.h | 59 +-
  1 file changed, 29 insertions(+), 30 deletions(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ef9b64398c8c..5f4df060affb 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -69,7 +69,7 @@ struct vb2_threadio_data;
   * argument to other ops in this structure.
   * @put_userptr: inform the allocator that a USERPTR buffer will no longer
   * be used.
- * @attach_dmabuf: attach a shared struct dma_buf for a hardware operation;
+ * @attach_dmabuf: attach a shared &struct dma_buf for a hardware operation;
   *   used for DMABUF memory types; dev is the alloc device
   *   dbuf is the shared dma_buf; returns ERR_PTR() on failure;
   *   allocator private per-buffer structure on success;
@@ -153,20 +153,19 @@ struct vb2_mem_ops {
   * @length:   size of this plane (NOT the payload) in bytes
   * @min_length:   minimum required size of this plane (NOT the payload) 
in bytes.
   *@length is always greater or equal to @min_length.
- * @offset:when memory in the associated struct vb2_buffer is
- * VB2_MEMORY_MMAP, equals the offset from the start of
+ * @m: Union with memtype-specific data
+ * @m.offset:  when memory in the associated struct vb2_buffer is
+ * %VB2_MEMORY_MMAP, equals the offset from the start of
   *the device memory for this plane (or is a "cookie" that
   *should be passed to mmap() called on the video node)
- * @userptr:   when memory is VB2_MEMORY_USERPTR, a userspace pointer
+ * @m.userptr: when memory is %VB2_MEMORY_USERPTR, a userspace pointer
   *pointing to this plane
- * @fd:when memory is VB2_MEMORY_DMABUF, a userspace file
+ * @m.fd:  when memory is %VB2_MEMORY_DMABUF, a userspace file
   *descriptor associated with this plane
- * @m: Union with memtype-specific data (@offset, @userptr or
- * @fd).
   * @data_offset:  offset in the plane to the start of data; usually 0,
   *unless there is a header in front of the data
   * Should contain enough information to be able to cover all the fields
- * of struct v4l2_plane at videodev2.h
+ * of &struct v4l2_plane at videodev2.h
   */
  struct vb2_plane {
void*mem_priv;
@@ -356,7 +355,7 @@ struct vb2_buffer {
   *driver can return an error if hardware fails, in that
   *case all buffers that have been already given by
   *the @buf_queue callback are to be returned by the driver
- * by calling vb2_buffer_done() with %VB2_BUF_STATE_QUEUED.
+ * by calling vb2_buffer_done() with 
%%VB2_BUF_STATE_QUEUED.
   *If you need a minimum number of buffers before you can
   *start streaming, then set @min_buffers_needed in the
   *vb2_queue structure. If that is non-zero then
@@ -366,7 +365,7 @@ struct vb2_buffer {
   *should stop any DMA transactions or wait until they
   *finish and give back all buffers it got from &buf_queue
   *callback by calling vb2_buffer_done() with either
- * %VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use
+ * %VB2_BUF_STATE_DONE or %%VB2_BUF_STATE_ERROR; may use
   *vb2_wait_for_all_buffers() function
   * @buf_queue:passes buffer vb to the driver; driver may start
   *hardware operation on this buffer; driver should give
@@ -401,13 +400,13 @@ struct vb2_ops {
   * @verify_planes_array: Verify that a given user space structure contains
   *enough planes for the buffer. This is called
   *for each dequeued buffer.
- * @fill_user_buffer:  given a vb2_buffer fill in the userspace structure.
+ * @fill_user_buffer:  given a &vb2_buffer fill in the userspace structure.
   *For V4L2 this is a struct v4l2_buffer.
- * @fill_vb2_buffer:   given a userspace structure, fill in the vb2_buffer.
+ * @fill_vb2_buffer:   given a userspace structure, fill in the &vb2_buffer.
   *If the userspace structure is invalid, then this op
   *will return an error.
   * @copy_timestamp:   copy the timestamp from a userspace structure to
- * the vb2_buffer struct.
+ * 

Re: [PATCH 1/7 v3] media: vb2: add bidirectional flag in vb2_queue

2017-08-21 Thread Marek Szyprowski

Hi Stanimir,

On 2017-08-21 13:34, Stanimir Varbanov wrote:

This change is intended to give to the v4l2 drivers a choice to
change the default behavior of the v4l2-core DMA mapping direction
from DMA_TO/FROM_DEVICE (depending on the buffer type CAPTURE or
OUTPUT) to DMA_BIDIRECTIONAL during queue_init time.

Initially the issue with DMA mapping direction has been found in
Venus encoder driver where the hardware (firmware side) adds few
lines padding on bottom of the image buffer, and the consequence
is triggering of IOMMU protection faults.

This will help supporting venus encoder (and probably other drivers
in the future) which wants to map output type of buffers as
read/write.

Signed-off-by: Stanimir Varbanov 


Thanks for the patch.

Acked-by: Marek Szyprowski 

While touching this, I would love to unify set_page_dirty_lock()
related code in videobuf2-dc, videobuf2-sg and videobuf2-vmalloc.

IMHO the pattern used in videobuf2-vmalloc should be copied to
videobuf2-sg (currently checks for dma_dir for every single page)
and videobuf2-dc (currently it lacks any checks and calls
set_page_dirty_lock() unconditionally). If you have a little bit
of spare time, please prepare a separate patch for the above
mentioned fix.


---
v3: update V4L2 dma-sg/contig and vmalloc memory type ops with a
 check for DMA_BIDIRECTIONAL.
v2: move dma_dir into private section.

  drivers/media/v4l2-core/videobuf2-core.c   | 17 -
  drivers/media/v4l2-core/videobuf2-dma-contig.c |  3 ++-
  drivers/media/v4l2-core/videobuf2-dma-sg.c |  6 --
  drivers/media/v4l2-core/videobuf2-vmalloc.c|  6 --
  include/media/videobuf2-core.h | 13 +
  5 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 0924594989b4..cb115ba6a1d2 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
  static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
  {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
  
  		mem_priv = call_ptr_memop(vb, alloc,

q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR_OR_NULL(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
  
  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);

@@ -1030,7 +1026,7 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace memory for plane 
%d\n",
plane);
@@ -1096,8 +1092,6 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
  
  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);

@@ -1156,7 +1150,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
@@ -2003,6 +1997,11 @@ int vb2_core_queue_init(struct vb2_queue *q)
if (q->buf_struct_size == 0)
q->buf_struct_size = sizeof(struct vb2_buf

Re: [PATCH 1/7 v2] media: vb2: add bidirectional flag in vb2_queue

2017-08-21 Thread Marek Szyprowski
  doesn't fill in the @alloc_devs array.
   * @dma_attrs:DMA attributes to use for the DMA.
+ * @bidirectional: when this flag is set the DMA direction for the buffers of
+ * this queue will be overridden with DMA_BIDIRECTIONAL direction.
+ * This is useful in cases where the hardware (firmware) writes to
+ * a buffer which is mapped as read (DMA_TO_DEVICE), or reads from
+ * buffer which is mapped for write (DMA_FROM_DEVICE) in order
+ * to satisfy some internal hardware restrictions or adds a padding
+ * needed by the processing algorithm. In case the DMA mapping is
+ * not bidirectional but the hardware (firmware) trying to access
+ * the buffer (in the opposite direction) this could lead to an
+ * IOMMU protection faults.
   * @fileio_read_once: report EOF after reading the first buffer
   * @fileio_write_immediately: queue buffer after each write() call
   * @allow_zero_bytesused: allow bytesused == 0 to be passed to the driver
@@ -465,6 +475,7 @@ struct vb2_buf_ops {
   * Private elements (won't appear at the uAPI book):
   * @mmap_lock:private mutex used when buffers are 
allocated/freed/mmapped
   * @memory:   current memory type used
+ * @dma_dir:   DMA mapping direction.
   * @bufs: videobuf buffer structures
   * @num_buffers: number of allocated/used buffers
   * @queued_list: list of buffers currently queued from userspace
@@ -495,6 +506,7 @@ struct vb2_queue {
unsigned intio_modes;
struct device   *dev;
unsigned long   dma_attrs;
+   unsignedbidirectional:1;
unsignedfileio_read_once:1;
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
@@ -516,6 +528,7 @@ struct vb2_queue {
/* private: internal use only */
struct mutexmmap_lock;
unsigned intmemory;
+   enum dma_data_direction dma_dir;
struct vb2_buffer   *bufs[VB2_MAX_FRAME];
unsigned intnum_buffers;
  


Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2017-07-13 Thread Marek Szyprowski

Hi Christoph,

On 2017-07-05 19:33, Christoph Hellwig wrote:

On Mon, Jul 03, 2017 at 11:27:32AM +0200, Marek Szyprowski wrote:

The main question here if we want to merge incomplete solution or not. As
for now, there is no support in ARM/ARM64 for NON_CONSISTENT attribute.
Also none of the v4l2 drivers use it. Sadly support for NON_CONSISTENT
attribute is not fully implemented nor even defined in mainline.


DMA_ATTR_NON_CONSISTENT is the way to get the dma_alloc_noncoherent
semantics through the dma_alloc_attr API, and as such I think it is
pretty well defined, although the documentation in
Documentation/DMA-attributes.txt is really bad and we need to improve
it, by merging it with the dma_alloc_noncoherent description in
Documentation/DMA-API.txt. My series to remove dma_alloc_noncoherent
updates the latter to mention DMA_ATTR_NON_CONSISTENT, but
we should probably merge Documentation/DMA-API.txt,
Documentation/DMA-attributes.txt and Documentation/DMA-API-HOWTO.txt
into a single coherent document.


Right. I started conversion of dma_alloc_noncoherent to NON_CONSISTENT
DMA attribute, but later I got stuck at the details of cache 
synchronization.



I know that it works fine for some vendor kernel trees, but supporting it in
mainline was a bit controversial. There is no proper way to sync cache for
such
buffers. Calling dma_sync_sg worked so far, but it has to be first agreed as
a proper DMA API.

As documented in Documentation/DMA-API.txt the proper way to sync
noncoherent/nonconsistent regions is to call dma_cache_sync.  It seems
like it generally is the same as dma_sync_range/sg so if we could
eventually merge these APIs that should reduce the confusion further.


Original dma_alloc_noncoherent utilized dma_cache_sync() function, which had
some flaws, which prevented me to continue that task and introduce it to ARM
architecture. The dma_alloc_noncoherent() and dma_cache_sync() API lacks
buffer ownership and imprecisely defines how and when the caches has to be
synchronized. dma_cache_sync() also lacks DMA address argument, what also
complicates potential lightweight implementation.

IMHO it would make sense to change it to work similar to the other
dma_sync_*_for_{cpu,device} functions, but I didn't find enough time to
finally take a try.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] media: vb2 dma-sg: Constify dma_buf_ops structures.

2017-07-03 Thread Marek Szyprowski

Hi Arvind,

On 2017-07-01 14:18, Arvind Yadav wrote:

dma_buf_ops are not supposed to change at runtime. All functions
working with dma_buf_ops provided by  work with
const dma_buf_ops. So mark the non-const structs as const.

File size before:
text   data bss dec hex filename
5238112   4535414ea 
drivers/media/v4l2-core/videobuf2-dma-sg.o

File size After adding 'const':
text   data bss dec hex filename
5358  0   4536214f2 
drivers/media/v4l2-core/videobuf2-dma-sg.o

Signed-off-by: Arvind Yadav 


Acked-by: Marek Szyprowski 


---
  drivers/media/v4l2-core/videobuf2-dma-sg.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 8e8798a..f8b4643 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -500,7 +500,7 @@ static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
return vb2_dma_sg_mmap(dbuf->priv, vma);
  }
  
-static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {

+static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
.attach = vb2_dma_sg_dmabuf_ops_attach,
.detach = vb2_dma_sg_dmabuf_ops_detach,
.map_dma_buf = vb2_dma_sg_dmabuf_ops_map,


Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] media: vb2 dma-contig: Constify dma_buf_ops structures.

2017-07-03 Thread Marek Szyprowski

Hi Arvind,

On 2017-07-01 13:27, Arvind Yadav wrote:

dma_buf_ops are not supposed to change at runtime. All functions
working with dma_buf_ops provided by  work with
const dma_buf_ops. So mark the non-const structs as const.

File size before:
text   data bss dec hex filename
6035272   0630718a3 
drivers/media/v4l2-core/videobuf2-dma-contig.o

File size After adding 'const':
text   data bss dec hex filename
6155160   0631518ab 
drivers/media/v4l2-core/videobuf2-dma-contig.o

Signed-off-by: Arvind Yadav 


Thanks!
Acked-by: Marek Szyprowski 


---
  drivers/media/v4l2-core/videobuf2-dma-contig.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 4f246d1..5b90a66 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -352,7 +352,7 @@ static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
return vb2_dc_mmap(dbuf->priv, vma);
  }
  
-static struct dma_buf_ops vb2_dc_dmabuf_ops = {

+static const struct dma_buf_ops vb2_dc_dmabuf_ops = {
.attach = vb2_dc_dmabuf_ops_attach,
.detach = vb2_dc_dmabuf_ops_detach,
.map_dma_buf = vb2_dc_dmabuf_ops_map,


Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] media: vb2 vmalloc: Constify dma_buf_ops structures.

2017-07-03 Thread Marek Szyprowski

Hi Arvind,

On 2017-07-01 13:37, Arvind Yadav wrote:

dma_buf_ops are not supposed to change at runtime. All functions
working with dma_buf_ops provided by  work with
const dma_buf_ops. So mark the non-const structs as const.

File size before:
text   data bss dec hex filename
3171192   03363 d23 
drivers/media/v4l2-core/videobuf2-vmalloc.o

File size After adding 'const':
text   data bss dec hex filename
3291 80   03371 d2b 
drivers/media/v4l2-core/videobuf2-vmalloc.o

Signed-off-by: Arvind Yadav 


Acked-by: Marek Szyprowski 


---
  drivers/media/v4l2-core/videobuf2-vmalloc.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c 
b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index b337d78..6bc130f 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -338,7 +338,7 @@ static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
return vb2_vmalloc_mmap(dbuf->priv, vma);
  }
  
-static struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {

+static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
.attach = vb2_vmalloc_dmabuf_ops_attach,
.detach = vb2_vmalloc_dmabuf_ops_detach,
.map_dma_buf = vb2_vmalloc_dmabuf_ops_map,


Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2017-07-03 Thread Marek Szyprowski

Hi All,

On 2016-10-26 10:52, Thierry Escande wrote:

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.


I'm sorry for late review. Sylwester kicked me for pending v4l2/vb2 patches
and I've just found this thread in my TODO folder.

The main question here if we want to merge incomplete solution or not. As
for now, there is no support in ARM/ARM64 for NON_CONSISTENT attribute.
Also none of the v4l2 drivers use it. Sadly support for NON_CONSISTENT
attribute is not fully implemented nor even defined in mainline.

I know that it works fine for some vendor kernel trees, but supporting it in
mainline was a bit controversial. There is no proper way to sync cache 
for such

buffers. Calling dma_sync_sg worked so far, but it has to be first agreed as
a proper DMA API.


Changes in v2:
- Put function move in a separate patch
- Added comments

Changes in v3:
- Remove redundant test on NO_KERNEL_MAPPING DMA attribute in mmap()

Heng-Ruey Hsu (1):
   [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
   [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

  drivers/media/v4l2-core/videobuf2-dma-contig.c | 60 --
  1 file changed, 38 insertions(+), 22 deletions(-)



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH v2] s5p-cec: update MAINTAINERS entry

2017-06-19 Thread Marek Szyprowski
I would like to replace Kyungmin Park, who is no longer interested in
maintaining S5P-CEC driver. I have access to various Exynos boards. I also
already did some tests of this driver and helped enabling it on various
Exynos boards. The driver itself is no longer in staging, so lets fix the
path too and add DT bindings file pattern match. Also change the mailing
list from ARM generic to Samsung SoC specific to get more attention and
easier review in the future.

Signed-off-by: Marek Szyprowski 
Acked-by: Krzysztof Kozlowski 
---
v2:
- added DT bindings file as suggested by Krzysztof Kozlowski
---
 MAINTAINERS | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 053c3bdd1fe5..52e516376139 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1775,11 +1775,12 @@ F:  arch/arm/plat-samsung/s5p-dev-mfc.c
 F: drivers/media/platform/s5p-mfc/
 
 ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
-M: Kyungmin Park 
-L: linux-arm-ker...@lists.infradead.org
+M: Marek Szyprowski 
+L: linux-samsung-...@vger.kernel.org (moderated for non-subscribers)
 L: linux-media@vger.kernel.org
 S: Maintained
-F: drivers/staging/media/platform/s5p-cec/
+F: drivers/media/platform/s5p-cec/
+F: Documentation/devicetree/bindings/media/s5p-cec.txt
 
 ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
 M: Andrzej Pietrasiewicz 
-- 
1.9.1



[PATCH] s5p-cec: update MAINTAINERS entry

2017-06-19 Thread Marek Szyprowski
I would like to replace Kyungmin Park, who is no longer interested in
maintaining S5P-CEC driver. I have access to various Exynos boards. I also
already did some tests of this driver and helped enabling it on various
Exynos boards. The driver itself is no longer in staging, so lets fix the
path too. Also change the mailing list from ARM generic to Samsung SoC
specific to get more attention and easier review in the future.

Signed-off-by: Marek Szyprowski 
---
 MAINTAINERS | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 053c3bdd1fe5..fbfbc9866fa2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1775,11 +1775,11 @@ F:  arch/arm/plat-samsung/s5p-dev-mfc.c
 F: drivers/media/platform/s5p-mfc/
 
 ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
-M: Kyungmin Park 
-L: linux-arm-ker...@lists.infradead.org
+M: Marek Szyprowski 
+L: linux-samsung-...@vger.kernel.org (moderated for non-subscribers)
 L: linux-media@vger.kernel.org
 S: Maintained
-F: drivers/staging/media/platform/s5p-cec/
+F: drivers/media/platform/s5p-cec/
 
 ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
 M: Andrzej Pietrasiewicz 
-- 
1.9.1



Re: [PATCH 5/9] [media] s5p-jpeg: Add IOMMU support

2017-06-18 Thread Marek Szyprowski

Hi All,

I'm sorry for the late reply, I just got back from holidays.

On 2017-06-02 23:43, Jacek Anaszewski wrote:

Cc Marek Szyprowski.

Marek, could you share your opinion about this patch?

On 06/02/2017 06:02 PM, Thierry Escande wrote:

From: Tony K Nadackal 

This patch adds support for IOMMU s5p-jpeg driver if the Exynos IOMMU
and ARM DMA IOMMU configurations are supported. The address space is
created with size limited to 256M and base address set to 0x2000.


Could you clarify WHY this patch is needed? IOMMU core configures per-device
IO address space by default and AFAIR JPEG module doesn't have any specific
requirements for the IO address space layout (base or size), so it should
work fine (and works in my tests!) without this patch.

Please drop this patch for now.


Signed-off-by: Tony K Nadackal 
Signed-off-by: Thierry Escande 
---
  drivers/media/platform/s5p-jpeg/jpeg-core.c | 77 +
  1 file changed, 77 insertions(+)

diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c 
b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 770a709..5569b99 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -28,6 +28,14 @@
  #include 
  #include 
  #include 
+#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#endif
  
  #include "jpeg-core.h"

  #include "jpeg-hw-s5p.h"
@@ -35,6 +43,10 @@
  #include "jpeg-hw-exynos3250.h"
  #include "jpeg-regs.h"
  
+#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)

+static struct dma_iommu_mapping *mapping;
+#endif
+
  static struct s5p_jpeg_fmt sjpeg_formats[] = {
{
.name   = "JPEG JFIF",
@@ -956,6 +968,60 @@ static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx 
*ctx)
}
  }
  
+#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)

+static int jpeg_iommu_init(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   int err;
+
+   mapping = arm_iommu_create_mapping(&platform_bus_type, 0x2000,
+  SZ_512M);
+   if (IS_ERR(mapping)) {
+   dev_err(dev, "IOMMU mapping failed\n");
+   return PTR_ERR(mapping);
+   }
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
+   if (!dev->dma_parms) {
+   err = -ENOMEM;
+   goto error_alloc;
+   }
+
+   err = dma_set_max_seg_size(dev, 0xu);
+   if (err)
+   goto error;
+
+   err = arm_iommu_attach_device(dev, mapping);
+   if (err)
+   goto error;
+
+   return 0;
+
+error:
+   devm_kfree(dev, dev->dma_parms);
+   dev->dma_parms = NULL;
+
+error_alloc:
+   arm_iommu_release_mapping(mapping);
+   mapping = NULL;
+
+   return err;
+}
+
+static void jpeg_iommu_deinit(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+
+   if (mapping) {
+   arm_iommu_detach_device(dev);
+   devm_kfree(dev, dev->dma_parms);
+   dev->dma_parms = NULL;
+   arm_iommu_release_mapping(mapping);
+   mapping = NULL;
+   }
+}
+#endif
+
  /*
   * 

   * Device file operations
@@ -2816,6 +2882,13 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
spin_lock_init(&jpeg->slock);
jpeg->dev = &pdev->dev;
  
+#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)

+   ret = jpeg_iommu_init(pdev);
+   if (ret) {
+   dev_err(&pdev->dev, "IOMMU Initialization failed\n");
+   return ret;
+   }
+#endif
/* memory-mapped registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  
@@ -2962,6 +3035,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev)

clk_disable_unprepare(jpeg->clocks[i]);
}
  
+#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)

+   jpeg_iommu_deinit(pdev);
+#endif
+
return 0;
  }
  



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] ARM: dts: exynos: Add HDMI CEC device to Exynos5 SoC family

2017-05-31 Thread Marek Szyprowski

Hi Krzysztof,

On 2017-05-31 21:55, Krzysztof Kozlowski wrote:

On Wed, May 31, 2017 at 01:00:17PM +0200, Marek Szyprowski wrote:

Exynos5250 and Exynos542x SoCs have the same CEC hardware module as
Exynos4 SoC series, so enable support for it using the same compatible
string.

Tested on Odroid XU3 (Exynos5422) and Google Snow (Exynos5250) boards.

Signed-off-by: Marek Szyprowski 
---
  arch/arm/boot/dts/exynos5250-pinctrl.dtsi  |  7 +++
  arch/arm/boot/dts/exynos5250-snow-common.dtsi  |  4 
  arch/arm/boot/dts/exynos5250.dtsi  | 13 +
  arch/arm/boot/dts/exynos5420-pinctrl.dtsi  |  7 +++
  arch/arm/boot/dts/exynos5420.dtsi  | 13 +
  arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  4 
  6 files changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi 
b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
index 2f6ab32b5954..1fd122db18e6 100644
--- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
@@ -589,6 +589,13 @@
samsung,pin-pud = ;
samsung,pin-drv = ;
};
+
+   hdmi_cec: hdmi-cec {
+   samsung,pins = "gpx3-6";
+   samsung,pin-function = ;
+   samsung,pin-pud = ;
+   samsung,pin-drv = ;
+   };
  };
  
  &pinctrl_1 {

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi 
b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index 8f3a80430748..e1d293dbbe5d 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -272,6 +272,10 @@
vdd_pll-supply = <&ldo8_reg>;
  };
  
+&hdmicec {

+   status = "okay";
+};
+
  &i2c_0 {
status = "okay";
samsung,i2c-sda-delay = <100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi 
b/arch/arm/boot/dts/exynos5250.dtsi
index 79c9c885613a..fbdc1d53a2ce 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -689,6 +689,19 @@
samsung,syscon-phandle = <&pmu_system_controller>;
};
  
+		hdmicec: cec@101B {

+   compatible = "samsung,s5p-cec";
+   reg = <0x101B 0x200>;
+   interrupts = ;
+   clocks = <&clock CLK_HDMI_CEC>;
+   clock-names = "hdmicec";
+   samsung,syscon-phandle = <&pmu_system_controller>;
+   hdmi-phandle = <&hdmi>;
+   pinctrl-names = "default";
+   pinctrl-0 = <&hdmi_cec>;
+   status = "disabled";
+   };

What about Exynos5410? Is it applicable there as well? If yes, then this
could be added to exynos5.dtsi... although then clocks and pinctrl
should remain in SoC-specific DTSI. We're following such pattern in many
places but I am not sure if this more readable.


Exynos5410 has the same HW module, but as for now, it doesn't have 
support for

HDMI due to missing a few pieces (mainly clocks definitions). I'm not sure
if it makes sense to add only HDMICEC without HDMI itself. Maybe later, when
multimedia support is added to Exynos5410, this can be integrated to
exynos5.dtsi.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH RFC] v4l2-core: Use kvmalloc() for potentially big allocations

2017-05-31 Thread Marek Szyprowski

Hi Tomasz,

On 2017-05-31 08:58, Tomasz Figa wrote:

There are multiple places where arrays or otherwise variable sized
buffer are allocated through V4L2 core code, including things like
controls, memory pages, staging buffers for ioctls and so on. Such
allocations can potentially require an order > 0 allocation from the
page allocator, which is not guaranteed to be fulfilled and is likely to
fail on a system with severe memory fragmentation (e.g. a system with
very long uptime).

Since the memory being allocated is intended to be used by the CPU
exclusively, we can consider using vmalloc() as a fallback and this is
exactly what the recently merged kvmalloc() helpers do. A kmalloc() call
is still attempted, even for order > 0 allocations, but it is done
with __GFP_NORETRY and __GFP_NOWARN, with expectation of failing if
requested memory is not available instantly. Only then the vmalloc()
fallback is used. This should give us fast and more reliable allocations
even on systems with higher memory pressure and/or more fragmentation,
while still retaining the same performance level on systems not
suffering from such conditions.

While at it, replace explicit array size calculations on changed
allocations with kvmalloc_array().

Signed-off-by: Tomasz Figa 
---
  drivers/media/v4l2-core/v4l2-async.c   |  4 ++--
  drivers/media/v4l2-core/v4l2-ctrls.c   | 25 +
  drivers/media/v4l2-core/v4l2-event.c   |  8 +---
  drivers/media/v4l2-core/v4l2-ioctl.c   |  6 +++---
  drivers/media/v4l2-core/v4l2-subdev.c  |  7 ---
  drivers/media/v4l2-core/videobuf2-dma-sg.c |  8 


For vb2:
Acked-by: Marek Szyprowski 

There are also a few vmalloc calls in old videobuf (v1) framework, which
might be converted to kvmalloc if you have a few spare minutes to take
a look.


  6 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c 
b/drivers/media/v4l2-core/v4l2-async.c
index 96cc733f35ef..2d2d9f1f8831 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -204,7 +204,7 @@ void v4l2_async_notifier_unregister(struct 
v4l2_async_notifier *notifier)
if (!notifier->v4l2_dev)
return;
  
-	dev = kmalloc_array(n_subdev, sizeof(*dev), GFP_KERNEL);

+   dev = kvmalloc_array(n_subdev, sizeof(*dev), GFP_KERNEL);
if (!dev) {
dev_err(notifier->v4l2_dev->dev,
"Failed to allocate device cache!\n");
@@ -260,7 +260,7 @@ void v4l2_async_notifier_unregister(struct 
v4l2_async_notifier *notifier)
}
put_device(d);
}
-   kfree(dev);
+   kvfree(dev);
  
  	notifier->v4l2_dev = NULL;
  
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c

index ec42872d11cf..88025527c67e 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1745,8 +1745,9 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
INIT_LIST_HEAD(&hdl->ctrls);
INIT_LIST_HEAD(&hdl->ctrl_refs);
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
-   hdl->buckets = kcalloc(hdl->nr_of_buckets, sizeof(hdl->buckets[0]),
-  GFP_KERNEL);
+   hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
+ sizeof(hdl->buckets[0]),
+ GFP_KERNEL | __GFP_ZERO);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
return hdl->error;
  }
@@ -1773,9 +1774,9 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
list_del(&ctrl->node);
list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
list_del(&sev->node);
-   kfree(ctrl);
+   kvfree(ctrl);
}
-   kfree(hdl->buckets);
+   kvfree(hdl->buckets);
hdl->buckets = NULL;
hdl->cached = NULL;
hdl->error = 0;
@@ -2022,7 +2023,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
 is_array)
sz_extra += 2 * tot_ctrl_size;
  
-	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);

+   ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
if (ctrl == NULL) {
handler_set_err(hdl, -ENOMEM);
return NULL;
@@ -2071,7 +2072,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
}
  
  	if (handler_new_ref(hdl, ctrl)) {

-   kfree(ctrl);
+   kvfree(ctrl);
return NULL;
}
mutex_lock(hdl->lock);
@@ -2824,8 +2825,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
return class_check(hdl, cs->which

Re: [PATCH] ARM: dts: exynos: Add HDMI CEC device to Exynos5 SoC family

2017-05-31 Thread Marek Szyprowski

Hi Hans,

On 2017-05-31 13:17, Hans Verkuil wrote:

On 05/31/17 13:00, Marek Szyprowski wrote:

Exynos5250 and Exynos542x SoCs have the same CEC hardware module as
Exynos4 SoC series, so enable support for it using the same compatible
string.

Tested on Odroid XU3 (Exynos5422) and Google Snow (Exynos5250) boards.

Thanks!

Do you know if the CEC block is always on for these devices or only if there
is a hotplug signal? That was a problem with the exynos4 odroid.


Odroid XU3 has exactly same wiring between SoC & HDMI connector (via 
IP4791CZ12

chip) as Odroid U3, so I expect the same issues.

I don't have schematic for Google Snow board, so I have no idea how it works
there.


I have made a patch (not posted yet) to signal this in the device tree and
added a CEC capability to signal this to the user.

This capability will be added to 4.13 (see my patch 'cec: add CEC_CAP_NEEDS_HPD'
from May 25th) since the DisplayPort CEC tunneling feature needs it as well.

It's easy to test: don't connect an HDMI cable and run:

cec-ctl --playback
cec-ctl -t0 --image-view-on

If this returns with a NACK error, then it is OK. If you get a kernel message
that the transmit timed out, then you need this capability since CEC is disabled
without HPD.


I've checked those commands, but on all tested boards (Odroid U3+, 
Odroid XU3 and

Google Snow) I get the following message:

Transmit from Unregistered to TV (255 to 0):
CEC_MSG_IMAGE_VIEW_ON (0x04)
Sequence: 19 Tx Timestamp: 175.935s
Tx, Error (1), Max Retries

I have never got a timeout message from the kernel. Do I need to enable 
some kind

of CEC debugs?

> [...]

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [ANN] HDMI CEC Status Update

2017-05-31 Thread Marek Szyprowski

Hi Andrzej and Hans,

On 2017-05-31 10:12, Andrzej Hajda wrote:

On 30.05.2017 08:53, Hans Verkuil wrote:

For those who are interested in HDMI CEC support I made a little status
document that I intend to keep up to date:

https://hverkuil.home.xs4all.nl/cec-status.txt

My goal is to get CEC supported for any mainlined HDMI driver where the hardware
supports CEC.

If anyone is working on a CEC driver that I don't know already about, just drop
me an email so I can update the status.

Sii8620 HDMI->MHL bridge is on my TODO list.
Regarding Exynos5 it is apparently the same IP as in Exynos4.


I've just posted a patch enabling CEC module on Exynos5250 (Google Snow)
and Exynos5422 (Odroid XU3).

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] ARM: dts: exynos: Add HDMI CEC device to Exynos5 SoC family

2017-05-31 Thread Marek Szyprowski
Exynos5250 and Exynos542x SoCs have the same CEC hardware module as
Exynos4 SoC series, so enable support for it using the same compatible
string.

Tested on Odroid XU3 (Exynos5422) and Google Snow (Exynos5250) boards.

Signed-off-by: Marek Szyprowski 
---
 arch/arm/boot/dts/exynos5250-pinctrl.dtsi  |  7 +++
 arch/arm/boot/dts/exynos5250-snow-common.dtsi  |  4 
 arch/arm/boot/dts/exynos5250.dtsi  | 13 +
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi  |  7 +++
 arch/arm/boot/dts/exynos5420.dtsi  | 13 +
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  4 
 6 files changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi 
b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
index 2f6ab32b5954..1fd122db18e6 100644
--- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
@@ -589,6 +589,13 @@
samsung,pin-pud = ;
samsung,pin-drv = ;
};
+
+   hdmi_cec: hdmi-cec {
+   samsung,pins = "gpx3-6";
+   samsung,pin-function = ;
+   samsung,pin-pud = ;
+   samsung,pin-drv = ;
+   };
 };
 
 &pinctrl_1 {
diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi 
b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index 8f3a80430748..e1d293dbbe5d 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -272,6 +272,10 @@
vdd_pll-supply = <&ldo8_reg>;
 };
 
+&hdmicec {
+   status = "okay";
+};
+
 &i2c_0 {
status = "okay";
samsung,i2c-sda-delay = <100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi 
b/arch/arm/boot/dts/exynos5250.dtsi
index 79c9c885613a..fbdc1d53a2ce 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -689,6 +689,19 @@
samsung,syscon-phandle = <&pmu_system_controller>;
};
 
+   hdmicec: cec@101B {
+   compatible = "samsung,s5p-cec";
+   reg = <0x101B 0x200>;
+   interrupts = ;
+   clocks = <&clock CLK_HDMI_CEC>;
+   clock-names = "hdmicec";
+   samsung,syscon-phandle = <&pmu_system_controller>;
+   hdmi-phandle = <&hdmi>;
+   pinctrl-names = "default";
+   pinctrl-0 = <&hdmi_cec>;
+   status = "disabled";
+   };
+
mixer@1445 {
compatible = "samsung,exynos5250-mixer";
reg = <0x1445 0x1>;
diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi 
b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 3924b4fafe72..65aa0e300c23 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -67,6 +67,13 @@
samsung,pin-pud = ;
samsung,pin-drv = ;
};
+
+   hdmi_cec: hdmi-cec {
+   samsung,pins = "gpx3-6";
+   samsung,pin-function = ;
+   samsung,pin-pud = ;
+   samsung,pin-drv = ;
+   };
 };
 
 &pinctrl_1 {
diff --git a/arch/arm/boot/dts/exynos5420.dtsi 
b/arch/arm/boot/dts/exynos5420.dtsi
index 0db0bcf8da36..acd77b10b3df 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -624,6 +624,19 @@
reg = <0x145D 0x20>;
};
 
+   hdmicec: cec@101B {
+   compatible = "samsung,s5p-cec";
+   reg = <0x101B 0x200>;
+   interrupts = ;
+   clocks = <&clock CLK_HDMI_CEC>;
+   clock-names = "hdmicec";
+   samsung,syscon-phandle = <&pmu_system_controller>;
+   hdmi-phandle = <&hdmi>;
+   pinctrl-names = "default";
+   pinctrl-0 = <&hdmi_cec>;
+   status = "disabled";
+   };
+
mixer: mixer@1445 {
compatible = "samsung,exynos5420-mixer";
reg = <0x1445 0x1>;
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 
b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
index 05b9afdd6757..01d6ac99e974 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
@@ -265,6 +265,10 @@
vdd-supply = <&ldo6_reg>;
 };
 
+&hdmicec {
+   status = "okay";
+};
+
 &hsi2c_4 {
status = "okay";
 
-- 
1.9.1



Re: [RFC 0/4] Exynos DRM: add Picture Processor extension

2017-05-10 Thread Marek Szyprowski

Hi Daniel,

On 2017-05-10 09:55, Daniel Vetter wrote:

On Wed, May 10, 2017 at 03:27:02PM +0900, Inki Dae wrote:

Hi Tomasz,

2017년 05월 10일 14:38에 Tomasz Figa 이(가) 쓴 글:

Hi Everyone,

On Wed, May 10, 2017 at 9:24 AM, Inki Dae  wrote:


2017년 04월 26일 07:21에 Sakari Ailus 이(가) 쓴 글:

Hi Marek,

On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote:

Hi Laurent,

On 2017-04-20 12:25, Laurent Pinchart wrote:

Hi Marek,

(CC'ing Sakari Ailus)

Thank you for the patches.

On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote:

Dear all,

This is an updated proposal for extending EXYNOS DRM API with generic
support for hardware modules, which can be used for processing image data

>from the one memory buffer to another. Typical memory-to-memory operations

are: rotation, scaling, colour space conversion or mix of them. This is a
follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer
processors", which has been rejected as "not really needed in the DRM
core":
http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html

In this proposal I moved all the code to Exynos DRM driver, so now this
will be specific only to Exynos DRM. I've also changed the name from
framebuffer processor (fbproc) to picture processor (pp) to avoid confusion
with fbdev API.

Here is a bit more information what picture processors are:

Embedded SoCs are known to have a number of hardware blocks, which perform
such operations. They can be used in paralel to the main GPU module to
offload CPU from processing grapics or video data. One of example use of
such modules is implementing video overlay, which usually requires color
space conversion from NV12 (or similar) to RGB32 color space and scaling to
target window size.

The proposed API is heavily inspired by atomic KMS approach - it is also
based on DRM objects and their properties. A new DRM object is introduced:
picture processor (called pp for convenience). Such objects have a set of
standard DRM properties, which describes the operation to be performed by
respective hardware module. In typical case those properties are a source
fb id and rectangle (x, y, width, height) and destination fb id and
rectangle. Optionally a rotation property can be also specified if
supported by the given hardware. To perform an operation on image data,
userspace provides a set of properties and their values for given fbproc
object in a similar way as object and properties are provided for
performing atomic page flip / mode setting.

The proposed API consists of the 3 new ioctls:
- DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture
   processors,
- DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture
   processor,
- DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given
   property set.

The proposed API is extensible. Drivers can attach their own, custom
properties to add support for more advanced picture processing (for example
blending).

This proposal aims to replace Exynos DRM IPP (Image Post Processing)
subsystem. IPP API is over-engineered in general, but not really extensible
on the other side. It is also buggy, with significant design flaws - the
biggest issue is the fact that the API covers memory-2-memory picture
operations together with CRTC writeback and duplicating features, which
belongs to video plane. Comparing with IPP subsystem, the PP framework is
smaller (1807 vs 778 lines) and allows driver simplification (Exynos
rotator driver smaller by over 200 lines).

This seems to be the kind of hardware that is typically supported by V4L2.
Stupid question, why DRM ?

Let me elaborate a bit on the reasons for implementing it in Exynos DRM:

1. we want to replace existing Exynos IPP subsystem:
  - it is used only in some internal/vendor trees, not in open-source
  - we want it to have sane and potentially extensible userspace API
  - but we don't want to loose its functionality

2. we want to have simple API for performing single image processing
operation:
  - typically it will be used by compositing window manager, this means that
some parameters of the processing might change on each vblank (like
destination rectangle for example). This api allows such change on each
operation without any additional cost. V4L2 requires to reinitialize
queues with new configuration on such change, what means that a bunch of
ioctls has to be called.

What do you mean by re-initialising the queue? Format, buffers or something
else?

If you need a larger buffer than what you have already allocated, you'll
need to re-allocate, V4L2 or not.

We also do lack a way to destroy individual buffers in V4L2. It'd be up to
implementing that and some work in videobuf2.

Another thing is that V4L2 is very stream oriented. For most devices that's
fine as a lot of the parameters are not changeable during streaming,
especially if the pipeline is handled by multiple drivers. Th

Re: [RFC 0/4] Exynos DRM: add Picture Processor extension

2017-04-27 Thread Marek Szyprowski

Hi Tobias and Nicolas,

On 2017-04-26 17:16, Tobias Jakobi wrote:

Nicolas Dufresne wrote:

Le mercredi 26 avril 2017 à 01:21 +0300, Sakari Ailus a écrit :

Hi Marek,

On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote:

Hi Laurent,

On 2017-04-20 12:25, Laurent Pinchart wrote:

Hi Marek,

(CC'ing Sakari Ailus)

Thank you for the patches.

On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote:

Dear all,

This is an updated proposal for extending EXYNOS DRM API with generic
support for hardware modules, which can be used for processing image data
from the one memory buffer to another. Typical memory-to-memory operations
are: rotation, scaling, colour space conversion or mix of them. This is a
follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer
processors", which has been rejected as "not really needed in the DRM
core":
http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html

In this proposal I moved all the code to Exynos DRM driver, so now this
will be specific only to Exynos DRM. I've also changed the name from
framebuffer processor (fbproc) to picture processor (pp) to avoid confusion
with fbdev API.

Here is a bit more information what picture processors are:

Embedded SoCs are known to have a number of hardware blocks, which perform
such operations. They can be used in paralel to the main GPU module to
offload CPU from processing grapics or video data. One of example use of
such modules is implementing video overlay, which usually requires color
space conversion from NV12 (or similar) to RGB32 color space and scaling to
target window size.

The proposed API is heavily inspired by atomic KMS approach - it is also
based on DRM objects and their properties. A new DRM object is introduced:
picture processor (called pp for convenience). Such objects have a set of
standard DRM properties, which describes the operation to be performed by
respective hardware module. In typical case those properties are a source
fb id and rectangle (x, y, width, height) and destination fb id and
rectangle. Optionally a rotation property can be also specified if
supported by the given hardware. To perform an operation on image data,
userspace provides a set of properties and their values for given fbproc
object in a similar way as object and properties are provided for
performing atomic page flip / mode setting.

The proposed API consists of the 3 new ioctls:
- DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture
   processors,
- DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture
   processor,
- DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given
   property set.

The proposed API is extensible. Drivers can attach their own, custom
properties to add support for more advanced picture processing (for example
blending).

This proposal aims to replace Exynos DRM IPP (Image Post Processing)
subsystem. IPP API is over-engineered in general, but not really extensible
on the other side. It is also buggy, with significant design flaws - the
biggest issue is the fact that the API covers memory-2-memory picture
operations together with CRTC writeback and duplicating features, which
belongs to video plane. Comparing with IPP subsystem, the PP framework is
smaller (1807 vs 778 lines) and allows driver simplification (Exynos
rotator driver smaller by over 200 lines).

Just a side note, we have written code in GStreamer using the Exnynos 4
FIMC IPP driver. I don't know how many, if any, deployment still exist
(Exynos 4 is relatively old now), but there exist userspace for the
FIMC driver. We use this for color transformation (from tiled to
linear) and scaling. The FIMC driver is in fact quite stable in
upstream kernel today. The GScaler V4L2 M2M driver on Exynos 5 is
largely based on it and has received some maintenance to properly work
in GStreamer. unlike this DRM API, you can reuse the same userspace
code across multiple platforms (which we do already). We have also
integrated this driver in Chromium in the past (not upstream though).

I am well aware that the blitter driver has not got much attention
though. But again, V4L2 offers a generic interface to userspace
application. Fixing this driver could enable some work like this one:

https://bugzilla.gnome.org/show_bug.cgi?id=772766

This work in progress feature is a generic hardware accelerated video
mixer. It has been tested with IMX.6 v4l2 m2m blitter driver (which I
believe is in staging right now). Again, unlike the exynos/drm, this
code could be reused between platforms.

In general, the problem with the DRM approach is that it only targets
displays. We often need to use these IP block for stream pre/post
processing outside a "playback" use case.

just a short note that this is not true. You can use all this
functionality e.g. through render nodes, without needing to have a
display attached to your system.


Yes. As an alternative I al

Re: [RFC 0/4] Exynos DRM: add Picture Processor extension

2017-04-27 Thread Marek Szyprowski

Hi Sakari,

On 2017-04-26 00:21, Sakari Ailus wrote:

Hi Marek,

On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote:

Hi Laurent,

On 2017-04-20 12:25, Laurent Pinchart wrote:

Hi Marek,

(CC'ing Sakari Ailus)

Thank you for the patches.

On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote:

Dear all,

This is an updated proposal for extending EXYNOS DRM API with generic
support for hardware modules, which can be used for processing image data

>from the one memory buffer to another. Typical memory-to-memory operations

are: rotation, scaling, colour space conversion or mix of them. This is a
follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer
processors", which has been rejected as "not really needed in the DRM
core":
http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html

In this proposal I moved all the code to Exynos DRM driver, so now this
will be specific only to Exynos DRM. I've also changed the name from
framebuffer processor (fbproc) to picture processor (pp) to avoid confusion
with fbdev API.

Here is a bit more information what picture processors are:

Embedded SoCs are known to have a number of hardware blocks, which perform
such operations. They can be used in paralel to the main GPU module to
offload CPU from processing grapics or video data. One of example use of
such modules is implementing video overlay, which usually requires color
space conversion from NV12 (or similar) to RGB32 color space and scaling to
target window size.

The proposed API is heavily inspired by atomic KMS approach - it is also
based on DRM objects and their properties. A new DRM object is introduced:
picture processor (called pp for convenience). Such objects have a set of
standard DRM properties, which describes the operation to be performed by
respective hardware module. In typical case those properties are a source
fb id and rectangle (x, y, width, height) and destination fb id and
rectangle. Optionally a rotation property can be also specified if
supported by the given hardware. To perform an operation on image data,
userspace provides a set of properties and their values for given fbproc
object in a similar way as object and properties are provided for
performing atomic page flip / mode setting.

The proposed API consists of the 3 new ioctls:
- DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture
   processors,
- DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture
   processor,
- DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given
   property set.

The proposed API is extensible. Drivers can attach their own, custom
properties to add support for more advanced picture processing (for example
blending).

This proposal aims to replace Exynos DRM IPP (Image Post Processing)
subsystem. IPP API is over-engineered in general, but not really extensible
on the other side. It is also buggy, with significant design flaws - the
biggest issue is the fact that the API covers memory-2-memory picture
operations together with CRTC writeback and duplicating features, which
belongs to video plane. Comparing with IPP subsystem, the PP framework is
smaller (1807 vs 778 lines) and allows driver simplification (Exynos
rotator driver smaller by over 200 lines).

This seems to be the kind of hardware that is typically supported by V4L2.
Stupid question, why DRM ?

Let me elaborate a bit on the reasons for implementing it in Exynos DRM:

1. we want to replace existing Exynos IPP subsystem:
  - it is used only in some internal/vendor trees, not in open-source
  - we want it to have sane and potentially extensible userspace API
  - but we don't want to loose its functionality

2. we want to have simple API for performing single image processing
operation:
  - typically it will be used by compositing window manager, this means that
some parameters of the processing might change on each vblank (like
destination rectangle for example). This api allows such change on each
operation without any additional cost. V4L2 requires to reinitialize
queues with new configuration on such change, what means that a bunch of
ioctls has to be called.

What do you mean by re-initialising the queue? Format, buffers or something
else?


In case of compositor use case, the parameter that is being changed most
frequently is source and/or destination rectangle position and/or size.


If you need a larger buffer than what you have already allocated, you'll
need to re-allocate, V4L2 or not.

We also do lack a way to destroy individual buffers in V4L2. It'd be up to
implementing that and some work in videobuf2.


Well if we would use V4l2, buffers will always come as dmabuf objects. There
is a hard limit of the number of buffers that can be imported to v4l2/vb2
queue to get buffer ids. This also limits easy processing of the buffers
in the compositor, because you would need to reinitialize the v

Re: [Intel-gfx] [PATCH v2] dma-buf: Rename dma-ops to prevent conflict with kunmap_atomic macro

2017-04-20 Thread Marek Szyprowski

Hi All,

On 2017-04-20 09:51, Daniel Vetter wrote:

On Wed, Apr 19, 2017 at 01:36:10PM -0600, Logan Gunthorpe wrote:

Seeing the kunmap_atomic dma_buf_ops share the same name with a macro
in highmem.h, the former can be aliased if any dma-buf user includes
that header.

I'm personally trying to include highmem.h inside scatterlist.h and this
breaks the dma-buf code proper.

Christoph Hellwig suggested [1] renaming it and pushing this patch ASAP.

To maintain consistency I've renamed all four of kmap* and kunmap* to be
map* and unmap*. (Even though only kmap_atomic presently conflicts.)

[1] https://www.spinics.net/lists/target-devel/msg15070.html

Signed-off-by: Logan Gunthorpe 
Reviewed-by: Sinclair Yeh 

Acked-by: Daniel Vetter 

Probably simplest if we pull this in through the drm-misc tree for 4.12.
Can we have an ack for the v4l side for that pls?


For the V4L2/videobuf2:
Acked-by: Marek Szyprowski 



Thanks, Daniel

---

Changes since v1:

- Added the missing tegra driver (noticed by kbuild robot)
- Rebased off of drm-intel-next to get the i915 selftest that is new
- Fixed nits Sinclair pointed out.

  drivers/dma-buf/dma-buf.c  | 16 
  drivers/gpu/drm/armada/armada_gem.c|  8 
  drivers/gpu/drm/drm_prime.c|  8 
  drivers/gpu/drm/i915/i915_gem_dmabuf.c |  8 
  drivers/gpu/drm/i915/selftests/mock_dmabuf.c   |  8 
  drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c  |  8 
  drivers/gpu/drm/tegra/gem.c|  8 
  drivers/gpu/drm/udl/udl_dmabuf.c   |  8 
  drivers/gpu/drm/vmwgfx/vmwgfx_prime.c  |  8 
  drivers/media/v4l2-core/videobuf2-dma-contig.c |  4 ++--
  drivers/media/v4l2-core/videobuf2-dma-sg.c |  4 ++--
  drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
  drivers/staging/android/ion/ion.c  |  8 
  include/linux/dma-buf.h| 22 +++---
  14 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index f72aaac..512bdbc 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -405,8 +405,8 @@ struct dma_buf *dma_buf_export(const struct 
dma_buf_export_info *exp_info)
  || !exp_info->ops->map_dma_buf
  || !exp_info->ops->unmap_dma_buf
  || !exp_info->ops->release
- || !exp_info->ops->kmap_atomic
- || !exp_info->ops->kmap
+ || !exp_info->ops->map_atomic
+ || !exp_info->ops->map
  || !exp_info->ops->mmap)) {
return ERR_PTR(-EINVAL);
}
@@ -872,7 +872,7 @@ void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned 
long page_num)
  {
WARN_ON(!dmabuf);

-   return dmabuf->ops->kmap_atomic(dmabuf, page_num);
+   return dmabuf->ops->map_atomic(dmabuf, page_num);
  }
  EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);

@@ -889,8 +889,8 @@ void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned 
long page_num,
  {
WARN_ON(!dmabuf);

-   if (dmabuf->ops->kunmap_atomic)
-   dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
+   if (dmabuf->ops->unmap_atomic)
+   dmabuf->ops->unmap_atomic(dmabuf, page_num, vaddr);
  }
  EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);

@@ -907,7 +907,7 @@ void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long 
page_num)
  {
WARN_ON(!dmabuf);

-   return dmabuf->ops->kmap(dmabuf, page_num);
+   return dmabuf->ops->map(dmabuf, page_num);
  }
  EXPORT_SYMBOL_GPL(dma_buf_kmap);

@@ -924,8 +924,8 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long 
page_num,
  {
WARN_ON(!dmabuf);

-   if (dmabuf->ops->kunmap)
-   dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
+   if (dmabuf->ops->unmap)
+   dmabuf->ops->unmap(dmabuf, page_num, vaddr);
  }
  EXPORT_SYMBOL_GPL(dma_buf_kunmap);

diff --git a/drivers/gpu/drm/armada/armada_gem.c 
b/drivers/gpu/drm/armada/armada_gem.c
index 1597458..d6c2a5d 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -529,10 +529,10 @@ static const struct dma_buf_ops 
armada_gem_prime_dmabuf_ops = {
.map_dma_buf= armada_gem_prime_map_dma_buf,
.unmap_dma_buf  = armada_gem_prime_unmap_dma_buf,
.release= drm_gem_dmabuf_release,
-   .kmap_atomic= armada_gem_dmabuf_no_kmap,
-   .kunmap_atomic  = armada_gem_dmabuf_no_kunmap,
-   .kmap   = armada_gem_dmabuf_no_kmap,
-   .kunmap = armada_gem_dmabuf_no_kunmap,
+   .map_atomic = armada_gem_dmabuf_no_kmap,
+   .unmap_atomic   = armad

Re: [PATCH] arm: dma: fix sharing of coherent DMA memory without struct page

2017-04-14 Thread Marek Szyprowski

Hi Shuah,

On 2017-04-11 00:50, Shuah Khan wrote:

On 04/06/2017 06:01 AM, Marek Szyprowski wrote:

On 2017-04-05 18:02, Shuah Khan wrote:

When coherent DMA memory without struct page is shared, importer
fails to find the page and runs into kernel page fault when it
tries to dmabuf_ops_attach/map_sg/map_page the invalid page found
in the sg_table. Please see www.spinics.net/lists/stable/msg164204.html
for more information on this problem.

This solution allows coherent DMA memory without struct page to be
shared by providing a way for the exporter to tag the DMA buffer as
a special buffer without struct page association and passing the
information in sg_table to the importer. This information is used
in attach/map_sg to avoid cleaning D-cache and mapping.

The details of the change are:

Framework:
- Add a new dma_attrs field to struct scatterlist.
- Add a new DMA_ATTR_DEV_COHERENT_NOPAGE attribute to clearly identify
Coherent memory without struct page.
- Add a new dma_check_dev_coherent() interface to check if memory is
the device coherent area. There is no way to tell where the memory
returned by dma_alloc_attrs() came from.

Exporter logic:
- Add logic to vb2_dc_alloc() to call dma_check_dev_coherent() and set
DMA_ATTR_DEV_COHERENT_NOPAGE based the results of the check. This is
done in the exporter context.
- Add logic to arm_dma_get_sgtable() to identify memory without struct
page using DMA_ATTR_DEV_COHERENT_NOPAGE attribute. If this attr is
set, arm_dma_get_sgtable() will set page as the cpu_addr and update
dma_address and dma_attrs fields in struct scatterlist for this sgl.
This is done in exporter context when buffer is exported. With this
Note: This change is made on top of Russell King's patch that added
!pfn_valid(pfn) check to arm_dma_get_sgtable() to error out on invalid
pages. Coherent memory without struct page will trigger this error.

Importer logic:
- Add logic to vb2_dc_dmabuf_ops_attach() to identify memory without
struct page using DMA_ATTR_DEV_COHERENT_NOPAGE attribute when it copies
the sg_table from the exporter. It will copy dma_attrs and dma_address
fields. With this logic, dmabuf_ops_attach will no longer trip on an
invalid page.
- Add logic to arm_dma_map_sg() to avoid mapping the page when sg_table
has DMA_ATTR_DEV_COHERENT_NOPAGE buffer.
- Add logic to arm_dma_unmap_sg() to do nothing for sg entries with
DMA_ATTR_DEV_COHERENT_NOPAGE attribute.

Without this change the following use-case that runs into kernel
pagefault when importer tries to attach the exported buffer.

With this change it works: (what a relief after watching pagefaults for
weeks!!)

gst-launch-1.0 filesrc location=~/GH3_MOV_HD.mp4 ! qtdemux ! h264parse ! 
v4l2video4dec capture-io-mode=dmabuf ! v4l2video7convert 
output-io-mode=dmabuf-import ! kmssink force-modesetting=true

I am sending RFC patch to get feedback on the approach and see if I missed
anything.

Frankly, once You decided to hack around dma-buf and issues with coherent,
carved out memory, it might be a bit better to find the ultimate solution
instead of the another hack. Please note that it will still not allow to
share a buffer allocated from carved-out memory and a device, which is
behind IOMMU.

With your patch s5p-mfc patch series does address the problem for this
use-case for 4.12 onwards. However I am still concerned about prior
release and this pagefault is bad.


Right. It should simply fail with error code instead of pagefault.


Invalid page test partially solves the problem. Would it helpful to
at least prevent the pagfault with a definitive test. Please see my
response to Russell. Let me know your thoughts on that.


I thought a bit about this and the current shape of dma-buf code.

IMHO the proper way of solving all those issues would be to replace
dma-buf internal representation of the memory from struct scatter_list
to pfn array. This would really solve the problem of buffers which
cannot be properly represented by scatter lists/struct pages and would
even allow sharing buffers between all kinds of devices. Scatter-lists
are also quite over-engineered structures to represent a single buffer
(pfn array is a bit more compact representation). Also there is a lots
of buggy code which use scatter-list in a bit creative way (like
assuming that each page maps to a single scatter list entry for
example). The only missing piece, required for such change would be
extending DMA-mapping with dma_map_pfn() interface.

I agree with you on scatterlists being clumsy. Changing over to pfn array
could simplify things. I am exploring a slightly different option that
might not require too many changes. I will respond with concrete ideas
later on this week.


It looks that a similar issue is being worked on, see the following thread:
https://lkml.org/lkml/2017/4/13/710


This would be however quite large task, especially taking into account
all current users of DMA-buf fram

Re: [PATCH] arm: dma: fix sharing of coherent DMA memory without struct page

2017-04-06 Thread Marek Szyprowski

Hi Shuah,

On 2017-04-05 18:02, Shuah Khan wrote:

When coherent DMA memory without struct page is shared, importer
fails to find the page and runs into kernel page fault when it
tries to dmabuf_ops_attach/map_sg/map_page the invalid page found
in the sg_table. Please see www.spinics.net/lists/stable/msg164204.html
for more information on this problem.

This solution allows coherent DMA memory without struct page to be
shared by providing a way for the exporter to tag the DMA buffer as
a special buffer without struct page association and passing the
information in sg_table to the importer. This information is used
in attach/map_sg to avoid cleaning D-cache and mapping.

The details of the change are:

Framework:
- Add a new dma_attrs field to struct scatterlist.
- Add a new DMA_ATTR_DEV_COHERENT_NOPAGE attribute to clearly identify
   Coherent memory without struct page.
- Add a new dma_check_dev_coherent() interface to check if memory is
   the device coherent area. There is no way to tell where the memory
   returned by dma_alloc_attrs() came from.

Exporter logic:
- Add logic to vb2_dc_alloc() to call dma_check_dev_coherent() and set
   DMA_ATTR_DEV_COHERENT_NOPAGE based the results of the check. This is
   done in the exporter context.
- Add logic to arm_dma_get_sgtable() to identify memory without struct
   page using DMA_ATTR_DEV_COHERENT_NOPAGE attribute. If this attr is
   set, arm_dma_get_sgtable() will set page as the cpu_addr and update
   dma_address and dma_attrs fields in struct scatterlist for this sgl.
   This is done in exporter context when buffer is exported. With this
   Note: This change is made on top of Russell King's patch that added
   !pfn_valid(pfn) check to arm_dma_get_sgtable() to error out on invalid
   pages. Coherent memory without struct page will trigger this error.

Importer logic:
- Add logic to vb2_dc_dmabuf_ops_attach() to identify memory without
   struct page using DMA_ATTR_DEV_COHERENT_NOPAGE attribute when it copies
   the sg_table from the exporter. It will copy dma_attrs and dma_address
   fields. With this logic, dmabuf_ops_attach will no longer trip on an
   invalid page.
- Add logic to arm_dma_map_sg() to avoid mapping the page when sg_table
   has DMA_ATTR_DEV_COHERENT_NOPAGE buffer.
- Add logic to arm_dma_unmap_sg() to do nothing for sg entries with
   DMA_ATTR_DEV_COHERENT_NOPAGE attribute.

Without this change the following use-case that runs into kernel
pagefault when importer tries to attach the exported buffer.

With this change it works: (what a relief after watching pagefaults for
weeks!!)

gst-launch-1.0 filesrc location=~/GH3_MOV_HD.mp4 ! qtdemux ! h264parse ! 
v4l2video4dec capture-io-mode=dmabuf ! v4l2video7convert 
output-io-mode=dmabuf-import ! kmssink force-modesetting=true

I am sending RFC patch to get feedback on the approach and see if I missed
anything.


Frankly, once You decided to hack around dma-buf and issues with coherent,
carved out memory, it might be a bit better to find the ultimate solution
instead of the another hack. Please note that it will still not allow to
share a buffer allocated from carved-out memory and a device, which is
behind IOMMU.

I thought a bit about this and the current shape of dma-buf code.

IMHO the proper way of solving all those issues would be to replace
dma-buf internal representation of the memory from struct scatter_list
to pfn array. This would really solve the problem of buffers which
cannot be properly represented by scatter lists/struct pages and would
even allow sharing buffers between all kinds of devices. Scatter-lists
are also quite over-engineered structures to represent a single buffer
(pfn array is a bit more compact representation). Also there is a lots
of buggy code which use scatter-list in a bit creative way (like
assuming that each page maps to a single scatter list entry for
example). The only missing piece, required for such change would be
extending DMA-mapping with dma_map_pfn() interface.

This would be however quite large task, especially taking into account
all current users of DMA-buf framework...


Signed-off-by: Shuah Khan 
---
  arch/arm/mm/dma-mapping.c  | 34 ++
  drivers/base/dma-coherent.c| 25 +++
  drivers/media/v4l2-core/videobuf2-dma-contig.c |  6 +
  include/linux/dma-mapping.h|  8 ++
  include/linux/scatterlist.h|  1 +
  5 files changed, 69 insertions(+), 5 deletions(-)

> [...]

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] media: s5p-mfc: Don't allocate codec buffers from pre-allocated region

2017-03-22 Thread Marek Szyprowski
Further investigation revealed that codec buffers also don't need to
be allocated at higher addresses than firmware base for MFC v6+ hardware.
Those buffers can be quite large and its size depends on the selected
format and framesize. This patch changes the way the codec buffers are
allocated - driver will use generic allocator for them instead of the
pre-allocated buffer for firmware and contexts.

Signed-off-by: Marek Szyprowski 
---
This patch should solve failure of h264 encoding due to insufficient memory
for codec temporary buffers. Please consider it as part of "[PATCH v3 00/16]
Exynos MFC v6+ - remove the need for the reserved memory" patchset.
---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.c| 28 +
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.h|  4 
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c |  4 ++--
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index 34a66189d980..7f33cf23947f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -79,6 +79,25 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned 
int mem_ctx,
return -ENOMEM;
 }
 
+int s5p_mfc_alloc_generic_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];
+
+   mfc_debug(3, "Allocating generic buf: %zu\n", b->size);
+
+   b->ctx = mem_ctx;
+   b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
+   if (!b->virt)
+   goto no_mem;
+
+   mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
+   return 0;
+no_mem:
+   mfc_err("Allocating generic 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)
 {
@@ -97,3 +116,12 @@ void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
b->size = 0;
 }
 
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+ struct s5p_mfc_priv_buf *b)
+{
+   struct device *mem_dev = dev->mem_dev[b->ctx];
+   dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
+   b->virt = NULL;
+   b->dma = 0;
+   b->size = 0;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 108e59382e0c..16d553fcff08 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -319,6 +319,10 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, 
unsigned int mem_ctx,
   struct s5p_mfc_priv_buf *b);
 void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
  struct s5p_mfc_priv_buf *b);
+int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+  struct s5p_mfc_priv_buf *b);
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+ struct s5p_mfc_priv_buf *b);
 
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 70071a12db16..85880e9106be 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -239,7 +239,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct 
s5p_mfc_ctx *ctx)
 
/* Allocate only if memory from bank 1 is necessary */
if (ctx->bank1.size > 0) {
-   ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1);
+   ret = s5p_mfc_alloc_generic_buf(dev, BANK_L_CTX, &ctx->bank1);
if (ret) {
mfc_err("Failed to allocate Bank1 memory\n");
return ret;
@@ -252,7 +252,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct 
s5p_mfc_ctx *ctx)
 /* Release buffers allocated for codec */
 static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
 {
-   s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
+   s5p_mfc_release_generic_buf(ctx->dev, &ctx->bank1);
 }
 
 /* Allocate memory for instance data buffer */
-- 
1.9.1



Re: [PATCH v2 00/15] Exynos MFC v6+ - remove the need for the reserved memory

2017-03-22 Thread Marek Szyprowski

Hi Marian,


On 2017-03-22 10:33, Marian Mihailescu wrote:

Hi,

I was testing with the linux-next kernel + the v2 patches
HW: odroid xu4
decoding (working): tested with gstreamer
encoding: tested with gstreamer && mfc-patched ffmpeg
before patches: encoding worked
after patches: encoding didn’t work.

I moved on from linux-next in the meantime and I cannot give you logs, BUT I’ve 
seen Hardkernel applied these patches (and all the linux-next MFC patches) on 
top of their 4.9 tree, and the result is very similar to mine on linux-next: 
https://github.com/hardkernel/linux/issues/284

Mar 21 13:04:54 odroid kernel: [   37.165153] s5p_mfc_alloc_priv_buf:78: 
Allocating private buffer of size 23243744 failed
Mar 21 13:04:54 odroid kernel: [   37.171865] 
s5p_mfc_alloc_codec_buffers_v6:244: Failed to allocate Bank1 memory
Mar 21 13:04:54 odroid kernel: [   37.179143] vidioc_reqbufs:1174: Failed to 
allocate encoding buffers


A user reported even adding s5p_mfc.mem=64M did not make the encoder work.
Any thoughts?


s5p_mfc.mem=64M should fix the issue. If not then there is some kind of 
different issue.

We did a bit more tests and in fact encoding h264 requires quite a lot of 
memory, so the default preallocated size might be not enough. However the codec 
temporary buffers don't need to be allocated from the preallocated region. In 
our tests it also worked when codec buffers were allocated in a generic way. 
Please check if the attached patch (applied on top of v3 patchset) fixes the 
issue.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

From: Marek Szyprowski 
Date: Wed, 22 Mar 2017 10:59:26 +0100
Subject: [PATCH] media: s5p-mfc: Don't allocate codec buffers from
 pre-allocated region

Further investigation revealed that codec buffers also don't need to
be allocated at higher addresses than firmware base for MFC v6+ hardware.
Those buffers can be quite large and its size depends on the selected
format and framesize. This patch changes the way the codec buffers are
allocated - driver will use generic allocator for them instead of the
pre-allocated buffer for firmware and contexts.

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.c| 28 +
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.h|  4 
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c |  4 ++--
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index 34a66189d980..7f33cf23947f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -79,6 +79,25 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
 	return -ENOMEM;
 }
 
+int s5p_mfc_alloc_generic_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];
+
+	mfc_debug(3, "Allocating generic buf: %zu\n", b->size);
+
+	b->ctx = mem_ctx;
+	b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
+	if (!b->virt)
+		goto no_mem;
+
+	mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
+	return 0;
+no_mem:
+	mfc_err("Allocating generic 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)
 {
@@ -97,3 +116,12 @@ void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
 	b->size = 0;
 }
 
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+			  struct s5p_mfc_priv_buf *b)
+{
+	struct device *mem_dev = dev->mem_dev[b->ctx];
+	dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
+	b->virt = NULL;
+	b->dma = 0;
+	b->size = 0;
+}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 108e59382e0c..16d553fcff08 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -319,6 +319,10 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
 			   struct s5p_mfc_priv_buf *b);
 void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
 			  struct s5p_mfc_priv_buf *b);
+int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+			   struct s5p_mfc_priv_buf *b);
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+			  struct s5p_mfc_priv_buf *b);
 
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 70071a12db16..85880e9106be 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -239,7 +239,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
 
 	/* Allocate only if memory from

Re: [PATCH v2 00/15] Exynos MFC v6+ - remove the need for the reserved memory

2017-03-22 Thread Marek Szyprowski

Hi Marian,

On 2017-03-22 10:33, Marian Mihailescu wrote:

Hi,

I was testing with the linux-next kernel + the v2 patches
HW: odroid xu4
decoding (working): tested with gstreamer
encoding: tested with gstreamer && mfc-patched ffmpeg
before patches: encoding worked
after patches: encoding didn’t work.

I moved on from linux-next in the meantime and I cannot give you logs, BUT I’ve 
seen Hardkernel applied these patches (and all the linux-next MFC patches) on 
top of their 4.9 tree, and the result is very similar to mine on linux-next: 
https://github.com/hardkernel/linux/issues/284

Mar 21 13:04:54 odroid kernel: [   37.165153] s5p_mfc_alloc_priv_buf:78: 
Allocating private buffer of size 23243744 failed
Mar 21 13:04:54 odroid kernel: [   37.171865] 
s5p_mfc_alloc_codec_buffers_v6:244: Failed to allocate Bank1 memory
Mar 21 13:04:54 odroid kernel: [   37.179143] vidioc_reqbufs:1174: Failed to 
allocate encoding buffers


A user reported even adding s5p_mfc.mem=64M did not make the encoder work.
Any thoughts?


Thanks for the report. Could you provide a bit more information about 
the encoder configuration (selected format, frame size, etc). 23MiB for 
the temporary buffer seems to be a bit large value, but I would like to 
reproduce it here and check what can be done to avoid allocating it from 
the preallocated buffer.






Thanks,
M.

(resent in plain text format)


On 17 Mar. 2017, at 10:36 pm, Andrzej Hajda  wrote:

Hi Marian,

On 15.03.2017 12:36, Marian Mihailescu wrote:

Hi,

After testing these patches, encoding using MFC fails when requesting
buffers for capture (it works for output) with ENOMEM (it complains it
cannot allocate memory on bank1).
Did anyone else test encoding?

I have tested encoding and it works on my test target. Could you provide
more details of your setup:
- which kernel and patches,
- which hw,
- which test app.

Regards
Andrzej



Thanks,
Marian

Either I've been missing something or nothing has been going on. (K. E. Gordon)






Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] media: s5p-mfc: Fix unbalanced call to clock management

2017-03-22 Thread Marek Szyprowski
Clock should be turned off after calling s5p_mfc_init_hw() from the
watchdog worker, like it is already done in the s5p_mfc_open() which also
calls this function.

Signed-off-by: Marek Szyprowski 
Fixes: af93574678108 ("[media] MFC: Add MFC 5.1 V4L2 driver")
CC: sta...@vger.kernel.org # v3.7+
---
This issue was there from the beggining of the driver, but this patch applies
cleanly only to v3.7+ kernels.
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 0c7ef6251252..76d4681a1c79 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -211,6 +211,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct 
*work)
}
s5p_mfc_clock_on();
ret = s5p_mfc_init_hw(dev);
+   s5p_mfc_clock_off();
if (ret)
mfc_err("Failed to reinit FW\n");
}
-- 
1.9.1



[PATCH v3 03/16] media: s5p-mfc: Replace mem_dev_* entries with an array

2017-03-20 Thread Marek Szyprowski
Internal MFC driver device structure contains two pointers to devices used
for DMA memory allocation: mem_dev_l and mem_dev_r. Replace them with the
mem_dev[] array and use defines for accessing particular banks. This will
help to simplify code in the next patches.

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| 31 +---
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 11 -
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 23 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c|  8 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c| 10 
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 32 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 ++--
 7 files changed, 69 insertions(+), 61 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index af223b0a41a3..c03ed1a737b7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1118,7 +1118,8 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
if (ret == 0)
-   mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev;
+   mfc_dev->mem_dev[BANK1_CTX] =
+   mfc_dev->mem_dev[BANK2_CTX] = dev;
return ret;
}
 
@@ -1126,14 +1127,14 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 * Create and initialize virtual devices for accessing
 * reserved memory regions.
 */
-   mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left",
- MFC_BANK1_ALLOC_CTX);
-   if (!mfc_dev->mem_dev_l)
+   mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left",
+  BANK1_CTX);
+   if (!mfc_dev->mem_dev[BANK1_CTX])
return -ENODEV;
-   mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right",
- MFC_BANK2_ALLOC_CTX);
-   if (!mfc_dev->mem_dev_r) {
-   device_unregister(mfc_dev->mem_dev_l);
+   mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right",
+  BANK2_CTX);
+   if (!mfc_dev->mem_dev[BANK2_CTX]) {
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
return -ENODEV;
}
 
@@ -1149,8 +1150,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return;
}
 
-   device_unregister(mfc_dev->mem_dev_l);
-   device_unregister(mfc_dev->mem_dev_r);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
 }
 
 /* MFC probe function */
@@ -1208,8 +1209,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_dma;
}
 
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32));
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX],
+   DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX],
+   DMA_BIT_MASK(32));
 
mutex_init(&dev->mfc_mutex);
init_waitqueue_head(&dev->queue);
@@ -1343,8 +1346,8 @@ static int s5p_mfc_remove(struct platform_device *pdev)
v4l2_device_unregister(&dev->v4l2_dev);
s5p_mfc_release_firmware(dev);
s5p_mfc_unconfigure_dma_memory(dev);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r);
+   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]);
 
s5p_mfc_final_pm(dev);
return 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 2f1387a4c386..27d4c864e06e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -33,8 +33,9 @@
 *  while mmaping */
 #define DST_QUEUE_OFF_BASE (1 << 30)
 
-#define MFC_BANK1_ALLOC_CTX0
-#define MFC_BANK2_ALLOC_CTX1
+#define BANK1_CTX  0
+#define BANK2_CTX  1
+#define BANK_CTX_NUM   2
 
 #define MFC_BANK1_ALIGN_ORDER  13
 #define MFC_BA

[PATCH v3 01/16] media: s5p-mfc: Remove unused structures and dead code

2017-03-20 Thread Marek Szyprowski
Remove unused structures, definitions and functions that are no longer
called from the driver code.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
Reviewed-by: Smitha T Murthy 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 21 -
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 13 -
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h   |  1 -
 3 files changed, 35 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index b99a7d0466a8..4e9f349c1be3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1417,16 +1417,11 @@ static int s5p_mfc_resume(struct device *dev)
.priv   = &mfc_buf_size_v5,
 };
 
-static struct s5p_mfc_buf_align mfc_buf_align_v5 = {
-   .base = MFC_BASE_ALIGN_ORDER,
-};
-
 static struct s5p_mfc_variant mfc_drvdata_v5 = {
.version= MFC_VERSION,
.version_bit= MFC_V5_BIT,
.port_num   = MFC_NUM_PORTS,
.buf_size   = &buf_size_v5,
-   .buf_align  = &mfc_buf_align_v5,
.fw_name[0] = "s5p-mfc.fw",
.clk_names  = {"mfc", "sclk_mfc"},
.num_clocks = 2,
@@ -1447,16 +1442,11 @@ static int s5p_mfc_resume(struct device *dev)
.priv   = &mfc_buf_size_v6,
 };
 
-static struct s5p_mfc_buf_align mfc_buf_align_v6 = {
-   .base = 0,
-};
-
 static struct s5p_mfc_variant mfc_drvdata_v6 = {
.version= MFC_VERSION_V6,
.version_bit= MFC_V6_BIT,
.port_num   = MFC_NUM_PORTS_V6,
.buf_size   = &buf_size_v6,
-   .buf_align  = &mfc_buf_align_v6,
.fw_name[0] = "s5p-mfc-v6.fw",
/*
 * v6-v2 firmware contains bug fixes and interface change
@@ -1481,16 +1471,11 @@ static int s5p_mfc_resume(struct device *dev)
.priv   = &mfc_buf_size_v7,
 };
 
-static struct s5p_mfc_buf_align mfc_buf_align_v7 = {
-   .base = 0,
-};
-
 static struct s5p_mfc_variant mfc_drvdata_v7 = {
.version= MFC_VERSION_V7,
.version_bit= MFC_V7_BIT,
.port_num   = MFC_NUM_PORTS_V7,
.buf_size   = &buf_size_v7,
-   .buf_align  = &mfc_buf_align_v7,
.fw_name[0] = "s5p-mfc-v7.fw",
.clk_names  = {"mfc", "sclk_mfc"},
.num_clocks = 2,
@@ -1510,16 +1495,11 @@ static int s5p_mfc_resume(struct device *dev)
.priv   = &mfc_buf_size_v8,
 };
 
-static struct s5p_mfc_buf_align mfc_buf_align_v8 = {
-   .base = 0,
-};
-
 static struct s5p_mfc_variant mfc_drvdata_v8 = {
.version= MFC_VERSION_V8,
.version_bit= MFC_V8_BIT,
.port_num   = MFC_NUM_PORTS_V8,
.buf_size   = &buf_size_v8,
-   .buf_align  = &mfc_buf_align_v8,
.fw_name[0] = "s5p-mfc-v8.fw",
.clk_names  = {"mfc"},
.num_clocks = 1,
@@ -1530,7 +1510,6 @@ static int s5p_mfc_resume(struct device *dev)
.version_bit= MFC_V8_BIT,
.port_num   = MFC_NUM_PORTS_V8,
.buf_size   = &buf_size_v8,
-   .buf_align  = &mfc_buf_align_v8,
.fw_name[0] = "s5p-mfc-v8.fw",
.clk_names  = {"pclk", "aclk", "aclk_xiu"},
.num_clocks = 3,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index ab23236aa942..3e0e8eaf8bfe 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -44,14 +44,6 @@
 
 #include 
 
-static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
-{
-   /* Same functionality as the vb2_dma_contig_plane_paddr */
-   dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b);
-
-   return *paddr;
-}
-
 /* MFC definitions */
 #define MFC_MAX_EXTRA_DPB   5
 #define MFC_MAX_BUFFERS32
@@ -229,16 +221,11 @@ struct s5p_mfc_buf_size {
void *priv;
 };
 
-struct s5p_mfc_buf_align {
-   unsigned int base;
-};
-
 struct s5p_mfc_variant {
unsigned int version;
unsigned int port_num;
u32 version_bit;
struct s5p_mfc_buf_size *buf_size;
-   struct s5p_mfc_buf_align *buf_align;
char*fw_name[MFC_FW_MAX_VERSIONS];
const char  *clk_names[MFC_MAX_CLOCKS];
int num_clocks;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
index 8e5df041edf7..45c807bf19cc 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
@@ -18,7 +18,6 @@
 int s5p_mfc_release_firmware(struct s

[PATCH v3 13/16] media: s5p-mfc: Remove special configuration of IOMMU domain

2017-03-20 Thread Marek Szyprowski
The main reason for using special configuration of IOMMU domain was the
problem with MFC firmware, which failed to operate properly when placed
at 0 DMA address. Instead of adding custom code for configuring each
variant of IOMMU domain and architecture specific glue code, simply use
what arch code provides and if the DMA base address equals zero, skip
first 128 KiB to keep required alignment. This patch also make the driver
operational on ARM64 architecture, because it no longer depends on ARM
specific DMA-mapping and IOMMU glue code functions.

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   | 30 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h | 51 +-
 2 files changed, 14 insertions(+), 67 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index ea01d0aa8303..f1528054a713 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1179,18 +1179,6 @@ 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
-* 256M and non-zero default start address.
-* This is still simplified, not optimal configuration, but for now
-* IOMMU core doesn't allow to configure device's IOMMUs channel
-* separately.
-*/
-   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
-S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret)
-   return ret;
 
if (mfc_mem_size)
mem_size = memparse(mfc_mem_size, NULL);
@@ -1198,10 +1186,8 @@ static int s5p_mfc_configure_common_memory(struct 
s5p_mfc_dev *mfc_dev)
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);
+   if (!mfc_dev->mem_bitmap)
return -ENOMEM;
-   }
 
mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size,
   &mfc_dev->mem_base, GFP_KERNEL);
@@ -1209,13 +1195,24 @@ static int s5p_mfc_configure_common_memory(struct 
s5p_mfc_dev *mfc_dev)
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;
 
+   /*
+* MFC hardware cannot handle 0 as a base address, so mark first 128K
+* as used (to keep required base alignment) and adjust base address
+*/
+   if (mfc_dev->mem_base == (dma_addr_t)0) {
+   unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER;
+
+   bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT);
+   mfc_dev->dma_base[BANK1_CTX] += offset;
+   mfc_dev->dma_base[BANK2_CTX] += offset;
+   }
+
/* Firmware allocation cannot fail in this case */
s5p_mfc_alloc_firmware(mfc_dev);
 
@@ -1232,7 +1229,6 @@ 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);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
index 6962132ae8fa..76667924ee2a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
@@ -11,54 +11,13 @@
 #ifndef S5P_MFC_IOMMU_H_
 #define S5P_MFC_IOMMU_H_
 
-#define S5P_MFC_IOMMU_DMA_BASE 0x2000lu
-#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M
-
-#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)
-
-#include 
+#if defined(CONFIG_EXYNOS_IOMMU)
 
 static inline bool exynos_is_iommu_available(struct device *dev)
 {
return dev->archdata.iommu != NULL;
 }
 
-static inline void exynos_unconfigure_iommu(struct device *dev)
-{
-   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
-
-   arm_

[PATCH v3 00/16] Exynos MFC v6+ - remove the need for the reserved memory

2017-03-20 Thread Marek Szyprowski
Dear All,

This patchset is a result of my work on enabling full support for MFC device
(multimedia codec) on Exynos 5433 on ARM64 architecture. Initially I thought
that to let it working on ARM64 architecture with IOMMU, I would need to
solve the issue related to the fact that s5p-mfc driver was depending on the
first-fit allocation method in the DMA-mapping / IOMMU glue code (ARM64 use
different algorithm). It turned out, that there is a much simpler way.

During my research I found that some of the requirements for the memory
buffers for MFC v6+ devices were blindly copied from the previous
hardware (v5) version and simply turned out to be excessive. It turned out
that there is no strict requirement for ALL buffers to be allocated on
the 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. This heavily simplifies
memory management in the driver.

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. There is no need to create special reserved
memory regions. The only case, when those memory regions are needed is an
oldest Exynos series - Exynos4210 or Exyno4412, which both have MFC v5
hardware, and only when IOMMU is disabled.

This patchset has been tested on Odroid U3 (Exynos4412 with MFC v5), Google
Snow (Exynos5250 with MFC v6), Odroid XU3 (Exynos5422 with MFC v8) and
TM2 (Exynos5433 with MFC v8, ARM64) boards.

To get it working on TM2/Exynos5433 with IOMMU enabled, the following fixes
to Exynos SYSMMU driver are needed:
https://www.spinics.net/lists/linux-samsung-soc/msg58832.html
https://www.spinics.net/lists/linux-samsung-soc/msg58833.html

Patches are based on v4.11-rc3 with "media: s5p-mfc: Fix initialization of
internal structures" patch applied:
https://patchwork.linuxtv.org/patch/39198/

I've tried to split changes into small pieces to make it easier to review
the code. I've also did a bit of cleanup while touching the driver.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland


Changelog:

v3:
- collected tags
- added a patch, which renames BANK1/2 to BANK_L/R to match documentation
- rebased onto v4.11-rc3

v2:
- fixed issues pointed by Javier Martinez Canillas: code compiles now
  after applying each patch, added missing cleanup
- added tags

v1: https://www.spinics.net/lists/linux-media/msg56.html
- initial version


Patch summary:

Marek Szyprowski (16):
  media: s5p-mfc: Remove unused structures and dead code
  media: s5p-mfc: Use generic of_device_get_match_data helper
  media: s5p-mfc: Replace mem_dev_* entries with an array
  media: s5p-mfc: Replace bank1/bank2 entries with an array
  media: s5p-mfc: Simplify alloc/release private buffer functions
  media: s5p-mfc: Move setting DMA max segment size to DMA configure
function
  media: s5p-mfc: Put firmware to private buffer structure
  media: s5p-mfc: Move firmware allocation to DMA configure function
  media: s5p-mfc: Allocate firmware with internal private buffer alloc
function
  media: s5p-mfc: Reduce firmware buffer size for MFC v6+ variants
  media: s5p-mfc: Split variant DMA memory configuration into separate
functions
  media: s5p-mfc: Add support for probe-time preallocated block based
allocator
  media: s5p-mfc: Remove special configuration of IOMMU domain
  media: s5p-mfc: Use preallocated block allocator always for MFC v6+
  media: s5p-mfc: Rename BANK1/2 to BANK_L/R to better match
documentation
  ARM: dts: exynos: Remove MFC reserved buffers

 .../devicetree/bindings/media/s5p-mfc.txt  |   2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts   |   1 -
 arch/arm/boot/dts/exynos5250-smdk5250.dts  |   1 -
 arch/arm/boot/dts/exynos5250-spring.dts|   1 -
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  |   1 -
 arch/arm/boot/dts/exynos5420-peach-pit.dts |   1 -
 arch/arm/boot/dts/exynos5420-smdk5420.dts  |   1 -
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |   1 -
 arch/arm/boot/dts/exynos5800-peach-pi.dts  |   1 -
 drivers/media/platform/s5p-mfc/regs-mfc-v6.h   |   2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v7.h   |   2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v8.h   |   2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc.c   | 214 +
 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c|   2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h|  43 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c  |  72 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h  |   1 -
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   |   8 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   |  10 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h |  51 +
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.c 

[PATCH v3 05/16] media: s5p-mfc: Simplify alloc/release private buffer functions

2017-03-20 Thread Marek Szyprowski
Change parameters for s5p_mfc_alloc_priv_buf() and s5p_mfc_release_priv_buf()
functions. Instead of DMA device pointer and a base, provide common MFC
device structure and memory bank context identifier.

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_common.h |  2 ++
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.c| 20 +++--
 drivers/media/platform/s5p-mfc/s5p_mfc_opr.h|  8 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 30 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 +
 5 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index da601a2dba2f..9cf860f34c71 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -240,12 +240,14 @@ struct s5p_mfc_variant {
  * buffer accessed by driver
  * @dma:   DMA address, only valid when kernel DMA API used
  * @size:  size of the buffer
+ * @ctx:   memory context (bank) used for this allocation
  */
 struct s5p_mfc_priv_buf {
unsigned long   ofs;
void*virt;
dma_addr_t  dma;
size_t  size;
+   unsigned intctx;
 };
 
 /**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index 99f65a92a6be..9294ee124661 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -37,12 +37,16 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev)
dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev);
 }
 
-int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
-   struct s5p_mfc_priv_buf *b)
+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];
+
mfc_debug(3, "Allocating priv: %zu\n", b->size);
 
-   b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL);
+   b->ctx = mem_ctx;
+   b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
 
if (!b->virt) {
mfc_err("Allocating private buffer of size %zu failed\n",
@@ -53,7 +57,7 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t 
base,
if (b->dma < base) {
mfc_err("Invalid memory configuration - buffer (%pad) is below 
base memory address(%pad)\n",
&b->dma, &base);
-   dma_free_coherent(dev, b->size, b->virt, b->dma);
+   dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
return -ENOMEM;
}
 
@@ -61,11 +65,13 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t 
base,
return 0;
 }
 
-void s5p_mfc_release_priv_buf(struct device *dev,
-   struct s5p_mfc_priv_buf *b)
+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 (b->virt) {
-   dma_free_coherent(dev, b->size, b->virt, b->dma);
+   dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
b->virt = NULL;
b->dma = 0;
b->size = 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index b6ac417ab63e..108e59382e0c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -315,10 +315,10 @@ struct s5p_mfc_hw_ops {
 
 void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
 void s5p_mfc_init_regs(struct s5p_mfc_dev *dev);
-int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
-   struct s5p_mfc_priv_buf *b);
-void s5p_mfc_release_priv_buf(struct device *dev,
-   struct s5p_mfc_priv_buf *b);
+int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+  struct s5p_mfc_priv_buf *b);
+void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
+ struct s5p_mfc_priv_buf *b);
 
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 32ce9ade2edb..20e8a1bdc984 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers

[PATCH v3 07/16] media: s5p-mfc: Put firmware to private buffer structure

2017-03-20 Thread Marek Szyprowski
Use s5p_mfc_priv_buf structure for keeping the firmware image. This will
help handling of firmware buffer allocation in the next patches.

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_cmd_v5.c |  2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  3 +--
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 36 -
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
index 8c4739ca16d6..4c80bb4243be 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
@@ -47,7 +47,7 @@ static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
struct s5p_mfc_cmd_args h2r_args;
 
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-   h2r_args.arg[0] = dev->fw_size;
+   h2r_args.arg[0] = dev->fw_buf.size;
return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
&h2r_args);
 }
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 9cf860f34c71..cea17a737ef7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -314,8 +314,7 @@ struct s5p_mfc_dev {
int int_type;
unsigned int int_err;
wait_queue_head_t queue;
-   size_t fw_size;
-   void *fw_virt_addr;
+   struct s5p_mfc_priv_buf fw_buf;
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_ctrl.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index c9bff3d0655f..50d698968049 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -29,21 +29,22 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
void *bank2_virt;
dma_addr_t bank2_dma_addr;
unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER;
+   struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
 
-   dev->fw_size = dev->variant->buf_size->fw;
+   fw_buf->size = dev->variant->buf_size->fw;
 
-   if (dev->fw_virt_addr) {
+   if (fw_buf->virt) {
mfc_err("Attempting to allocate firmware when it seems that it 
is already loaded\n");
return -ENOMEM;
}
 
-   dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX],
-   dev->fw_size, &dev->dma_base[BANK1_CTX],
-   GFP_KERNEL);
-   if (!dev->fw_virt_addr) {
+   fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size,
+&fw_buf->dma, GFP_KERNEL);
+   if (!fw_buf->virt) {
mfc_err("Allocating bitprocessor buffer failed\n");
return -ENOMEM;
}
+   dev->dma_base[BANK1_CTX] = fw_buf->dma;
 
if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX],
@@ -51,10 +52,9 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 
if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
-   dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size,
- dev->fw_virt_addr,
- dev->dma_base[BANK1_CTX]);
-   dev->fw_virt_addr = NULL;
+   dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size,
+ fw_buf->virt, fw_buf->dma);
+   fw_buf->virt = NULL;
return -ENOMEM;
}
 
@@ -101,17 +101,17 @@ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
mfc_err("Firmware is not present in the /lib/firmware directory 
nor compiled in kernel\n");
return -EINVAL;
}
-   if (fw_blob->size > dev->fw_size) {
+   if (fw_blob->size > dev->fw_buf.size) {
mfc_err("MFC firmware is too big to be loaded\n");
release_firmware(fw_blob);
return -ENOMEM;
}
-   if (!dev->fw_virt_addr) {
+   if (!dev->fw_buf.virt) {
mfc_err("MFC firmware is not allocated\n");
release_firmware(fw_blob);
return -EINVAL;
}
-   memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
+   me

[PATCH v3 09/16] media: s5p-mfc: Allocate firmware with internal private buffer alloc function

2017-03-20 Thread Marek Szyprowski
Once firmware buffer has been converted to use s5p_mfc_priv_buf structure,
it is possible to allocate it with existing s5p_mfc_alloc_priv_buf()
function. This change will help to reduce code variants in the next
patches.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
---
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index b0cf3970117a..a1811ee538bd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -27,6 +27,7 @@
 int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 {
struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
+   int err;
 
fw_buf->size = dev->variant->buf_size->fw;
 
@@ -35,11 +36,10 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
return -ENOMEM;
}
 
-   fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size,
-&fw_buf->dma, GFP_KERNEL);
-   if (!fw_buf->virt) {
+   err = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->fw_buf);
+   if (err) {
mfc_err("Allocating bitprocessor buffer failed\n");
-   return -ENOMEM;
+   return err;
}
 
return 0;
@@ -92,11 +92,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
 {
/* Before calling this function one has to make sure
 * that MFC is no longer processing */
-   if (!dev->fw_buf.virt)
-   return -EINVAL;
-   dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_buf.size,
- dev->fw_buf.virt, dev->fw_buf.dma);
-   dev->fw_buf.virt = NULL;
+   s5p_mfc_release_priv_buf(dev, &dev->fw_buf);
return 0;
 }
 
-- 
1.9.1



[PATCH v3 08/16] media: s5p-mfc: Move firmware allocation to DMA configure function

2017-03-20 Thread Marek Szyprowski
To complete DMA memory configuration for MFC device, allocation of the
firmware buffer is needed, because some parameters are dependant on its base
address. Till now, this has been handled in the s5p_mfc_alloc_firmware()
function. This patch moves that logic to s5p_mfc_configure_dma_memory() to
keep DMA memory related operations in a single place. This way
s5p_mfc_alloc_firmware() is simplified and does what it name says. The
other consequence of this change is moving s5p_mfc_alloc_firmware() call
from the s5p_mfc_probe() function to the s5p_mfc_configure_dma_memory().

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c  | 62 +--
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 31 --
 2 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 1fe790d88e70..16f4ba4f25ee 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1105,6 +1105,11 @@ static struct device *s5p_mfc_alloc_memdev(struct device 
*dev,
 static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
+   void *bank2_virt;
+   dma_addr_t bank2_dma_addr;
+   unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
+   struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf;
+   int ret;
 
/*
 * When IOMMU is available, we cannot use the default configuration,
@@ -1117,14 +1122,21 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
if (exynos_is_iommu_available(dev)) {
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret == 0) {
-   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));
+   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) {
+   exynos_unconfigure_iommu(dev);
+   return ret;
}
 
-   return ret;
+   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+   mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma;
+   vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+   return 0;
}
 
/*
@@ -1142,6 +1154,35 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return -ENODEV;
}
 
+   /* Allocate memory for firmware and initialize both banks addresses */
+   ret = s5p_mfc_alloc_firmware(mfc_dev);
+   if (ret) {
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   return ret;
+   }
+
+   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+
+   bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size,
+   &bank2_dma_addr, GFP_KERNEL);
+   if (!bank2_virt) {
+   mfc_err("Allocating bank2 base failed\n");
+   s5p_mfc_release_firmware(mfc_dev);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   return -ENOMEM;
+   }
+
+   /* Valid buffers passed to MFC encoder with LAST_FRAME command
+* should not have address of bank2 - MFC will treat it as a null frame.
+* To avoid such situation we set bank2 address below the pool address.
+*/
+   mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size;
+
+   dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt,
+ bank2_dma_addr);
+
vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX],
DMA_BIT_MASK(32));
vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX],
@@ -1154,6 +1195,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
 
+   s5p_mfc_release_firmware(mfc_dev);
+
if (exynos_is_iommu_available(dev)) {
exynos_unconfigure_iommu(dev);
vb2_dma_contig_clear_max_seg_size(dev);
@@ -1230,10 +1273,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
dev->watch

[PATCH v3 10/16] media: s5p-mfc: Reduce firmware buffer size for MFC v6+ variants

2017-03-20 Thread Marek Szyprowski
Firmware for MFC v6+ variants is not larger than 400 KiB, so there is no
need to allocate a full 1 MiB buffer for it. Reduce it to 512 KiB to keep
proper alignment of allocated buffer.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
---
 drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v7.h | 2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
index d2cd35916dc5..c0166ee9a455 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
@@ -403,7 +403,7 @@
 #define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)/*  12KB */
 
 /* MFCv6 variant defines */
-#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V6 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V6(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V6 0x61
 #define MFC_NUM_PORTS_V6   1
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
index 1a5c6fdf7846..9f220769d970 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
@@ -34,7 +34,7 @@
 #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7  0xfdc4
 
 /* MFCv7 variant defines */
-#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V7 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V7(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V7 0x72
 #define MFC_NUM_PORTS_V7   1
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
index 4d1c3750eb5e..75f5f7511d72 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
@@ -116,7 +116,7 @@
 #define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64
 
 /* MFCv8 variant defines */
-#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V8 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V8(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V8 0x80
 #define MFC_NUM_PORTS_V8   1
-- 
1.9.1



[PATCH v3 04/16] media: s5p-mfc: Replace bank1/bank2 entries with an array

2017-03-20 Thread Marek Szyprowski
Internal MFC driver device structure contains two entries for keeping
addresses of the DMA memory banks. Replace them with the dma_base[] array
and use defines for accessing particular banks. This will help to simplify
code in the next patches.

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_common.h |  6 ++--
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 27 +++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 38 +
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 10 +++
 4 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 27d4c864e06e..da601a2dba2f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -273,8 +273,7 @@ struct s5p_mfc_priv_buf {
  * @queue: waitqueue for waiting for completion of device commands
  * @fw_size:   size of firmware
  * @fw_virt_addr:  virtual firmware address
- * @bank1: address of the beginning of bank 1 memory
- * @bank2: address of the beginning of bank 2 memory
+ * @dma_base[]:address of the beginning of memory banks
  * @hw_lock:   used for hardware locking
  * @ctx:   array of driver contexts
  * @curr_ctx:  number of the currently running context
@@ -315,8 +314,7 @@ struct s5p_mfc_dev {
wait_queue_head_t queue;
size_t fw_size;
void *fw_virt_addr;
-   dma_addr_t bank1;
-   dma_addr_t bank2;
+   dma_addr_t dma_base[BANK_CTX_NUM];
unsigned long hw_lock;
struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
int curr_ctx;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index cd1406c75d9a..c9bff3d0655f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -38,8 +38,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
}
 
dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX],
-   dev->fw_size, &dev->bank1, GFP_KERNEL);
-
+   dev->fw_size, &dev->dma_base[BANK1_CTX],
+   GFP_KERNEL);
if (!dev->fw_virt_addr) {
mfc_err("Allocating bitprocessor buffer failed\n");
return -ENOMEM;
@@ -52,7 +52,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size,
- dev->fw_virt_addr, dev->bank1);
+ dev->fw_virt_addr,
+ dev->dma_base[BANK1_CTX]);
dev->fw_virt_addr = NULL;
return -ENOMEM;
}
@@ -61,7 +62,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 * should not have address of bank2 - MFC will treat it as a 
null frame.
 * To avoid such situation we set bank2 address below the pool 
address.
 */
-   dev->bank2 = bank2_dma_addr - align_size;
+   dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size;
 
dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size,
  bank2_virt, bank2_dma_addr);
@@ -70,7 +71,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
/* In this case bank2 can point to the same address as bank1.
 * Firmware will always occupy the beginning of this area so it 
is
 * impossible having a video frame buffer with zero address. */
-   dev->bank2 = dev->bank1;
+   dev->dma_base[BANK2_CTX] = dev->dma_base[BANK1_CTX];
}
return 0;
 }
@@ -125,7 +126,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
if (!dev->fw_virt_addr)
return -EINVAL;
dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size,
- dev->fw_virt_addr, dev->bank1);
+ dev->fw_virt_addr, dev->dma_base[BANK1_CTX]);
dev->fw_virt_addr = NULL;
return 0;
 }
@@ -211,13 +212,17 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
 {
if (IS_MFCV6_PLUS(dev)) {
-   mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
-   

[PATCH v3 06/16] media: s5p-mfc: Move setting DMA max segment size to DMA configure function

2017-03-20 Thread Marek Szyprowski
Setting DMA max segment size to 32 bit mask is a part of DMA memory
configuration, so move those calls to s5p_mfc_configure_dma_memory()
function.

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 | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index c03ed1a737b7..1fe790d88e70 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1117,9 +1117,13 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
if (exynos_is_iommu_available(dev)) {
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret == 0)
+   if (ret == 0) {
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));
+   }
+
return ret;
}
 
@@ -1138,6 +1142,11 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return -ENODEV;
}
 
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX],
+   DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX],
+   DMA_BIT_MASK(32));
+
return 0;
 }
 
@@ -1147,11 +1156,14 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 
if (exynos_is_iommu_available(dev)) {
exynos_unconfigure_iommu(dev);
+   vb2_dma_contig_clear_max_seg_size(dev);
return;
}
 
device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
 }
 
 /* MFC probe function */
@@ -1209,11 +1221,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_dma;
}
 
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX],
-   DMA_BIT_MASK(32));
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX],
-   DMA_BIT_MASK(32));
-
mutex_init(&dev->mfc_mutex);
init_waitqueue_head(&dev->queue);
dev->hw_lock = 0;
@@ -1346,8 +1353,6 @@ static int s5p_mfc_remove(struct platform_device *pdev)
v4l2_device_unregister(&dev->v4l2_dev);
s5p_mfc_release_firmware(dev);
s5p_mfc_unconfigure_dma_memory(dev);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]);
 
s5p_mfc_final_pm(dev);
return 0;
-- 
1.9.1



[PATCH v3 16/16] ARM: dts: exynos: Remove MFC reserved buffers

2017-03-20 Thread Marek Szyprowski
During my research I found that some of the requirements for the memory
buffers for MFC v6+ devices were blindly copied from the previous (v5)
version and simply turned out to be excessive. The relaxed requirements
are applied by the recent patches to the MFC driver and the driver is
now fully functional even without the reserved memory blocks for all
v6+ variants. This patch removes those reserved memory nodes from all
boards having MFC v6+ hardware block.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
---
 arch/arm/boot/dts/exynos5250-arndale.dts   | 1 -
 arch/arm/boot/dts/exynos5250-smdk5250.dts  | 1 -
 arch/arm/boot/dts/exynos5250-spring.dts| 1 -
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  | 1 -
 arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 -
 arch/arm/boot/dts/exynos5420-smdk5420.dts  | 1 -
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 1 -
 arch/arm/boot/dts/exynos5800-peach-pi.dts  | 1 -
 8 files changed, 8 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts 
b/arch/arm/boot/dts/exynos5250-arndale.dts
index 6098dacd09f1..6a432460eb77 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Insignal Arndale evaluation board based on EXYNOS5250";
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a97a785ccc6b..6632f657394e 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -13,7 +13,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts 
b/arch/arm/boot/dts/exynos5250-spring.dts
index 4d7bdb735ed3..95c3bcace9dc 100644
--- a/arch/arm/boot/dts/exynos5250-spring.dts
+++ b/arch/arm/boot/dts/exynos5250-spring.dts
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Spring";
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 9cc83c51c925..ee1bb9b8b366 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts 
b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 1f964ec35c5e..2cd65699a29c 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -16,7 +16,6 @@
 #include 
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Peach Pit Rev 6+";
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts 
b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index aaccd0da41e5..08c8ab173e87 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -13,7 +13,6 @@
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
 #include 
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Samsung SMDK5420 board based on EXYNOS5420";
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 
b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
index 05b9afdd6757..657535e2e3cc 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
@@ -18,7 +18,6 @@
 #include 
 #include "exynos5800.dtsi"
 #include "exynos5422-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
memory@4000 {
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts 
b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index f9ff7f07ae0c..ecf1c916e8fc 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -16,7 +16,6 @@
 #include 
 #include "exynos5800.dtsi"
 #include "exynos5420-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Peach Pi Rev 10+";
-- 
1.9.1



[PATCH v3 02/16] media: s5p-mfc: Use generic of_device_get_match_data helper

2017-03-20 Thread Marek Szyprowski
Replace custom code with generic helper to retrieve driver data.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
Reviewed-by: Smitha T Murthy 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 17 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  4 ++--
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 4e9f349c1be3..af223b0a41a3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "s5p_mfc_common.h"
@@ -1152,8 +1153,6 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
device_unregister(mfc_dev->mem_dev_r);
 }
 
-static void *mfc_get_drv_data(struct platform_device *pdev);
-
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1177,7 +1176,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
return -ENODEV;
}
 
-   dev->variant = mfc_get_drv_data(pdev);
+   dev->variant = of_device_get_match_data(&pdev->dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1536,18 +1535,6 @@ static int s5p_mfc_resume(struct device *dev)
 };
 MODULE_DEVICE_TABLE(of, exynos_mfc_match);
 
-static void *mfc_get_drv_data(struct platform_device *pdev)
-{
-   struct s5p_mfc_variant *driver_data = NULL;
-   const struct of_device_id *match;
-
-   match = of_match_node(exynos_mfc_match, pdev->dev.of_node);
-   if (match)
-   driver_data = (struct s5p_mfc_variant *)match->data;
-
-   return driver_data;
-}
-
 static struct platform_driver s5p_mfc_driver = {
.probe  = s5p_mfc_probe,
.remove = s5p_mfc_remove,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 3e0e8eaf8bfe..2f1387a4c386 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -192,7 +192,7 @@ struct s5p_mfc_buf {
  */
 struct s5p_mfc_pm {
struct clk  *clock_gate;
-   const char  **clk_names;
+   const char * const *clk_names;
struct clk  *clocks[MFC_MAX_CLOCKS];
int num_clocks;
booluse_clock_gating;
@@ -304,7 +304,7 @@ struct s5p_mfc_dev {
struct v4l2_ctrl_handler dec_ctrl_handler;
struct v4l2_ctrl_handler enc_ctrl_handler;
struct s5p_mfc_pm   pm;
-   struct s5p_mfc_variant  *variant;
+   const struct s5p_mfc_variant*variant;
int num_inst;
spinlock_t irqlock; /* lock when operating on context */
spinlock_t condlock;/* lock when changing/checking if a context is
-- 
1.9.1



[PATCH v3 12/16] media: s5p-mfc: Add support for probe-time preallocated block based allocator

2017-03-20 Thread Marek Szyprowski
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);
+   

[PATCH v3 11/16] media: s5p-mfc: Split variant DMA memory configuration into separate functions

2017-03-20 Thread Marek Szyprowski
Move code for DMA memory configuration with IOMMU into separate function
to make it easier to compare what is being done in each case.

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 | 102 ++-
 1 file changed, 61 insertions(+), 41 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 16f4ba4f25ee..ff3bb8af2423 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1102,44 +1102,15 @@ static struct device *s5p_mfc_alloc_memdev(struct 
device *dev,
return NULL;
 }
 
-static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
void *bank2_virt;
dma_addr_t bank2_dma_addr;
unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
-   struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf;
int ret;
 
/*
-* When IOMMU is available, we cannot use the default configuration,
-* because of MFC firmware requirements: address space limited to
-* 256M and non-zero default start address.
-* This is still simplified, not optimal configuration, but for now
-* IOMMU core doesn't allow to configure device's IOMMUs channel
-* separately.
-*/
-   if (exynos_is_iommu_available(dev)) {
-   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
-S5P_MFC_IOMMU_DMA_SIZE);
-   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) {
-   exynos_unconfigure_iommu(dev);
-   return ret;
-   }
-
-   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
-   mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma;
-   vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   return 0;
-   }
-
-   /*
 * Create and initialize virtual devices for accessing
 * reserved memory regions.
 */
@@ -1162,7 +1133,7 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return ret;
}
 
-   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+   mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma;
 
bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size,
&bank2_dma_addr, GFP_KERNEL);
@@ -1191,22 +1162,71 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return 0;
 }
 
-static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev)
 {
-   struct device *dev = &mfc_dev->plat_dev->dev;
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
+}
 
-   s5p_mfc_release_firmware(mfc_dev);
+static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev)
+{
+   struct device *dev = &mfc_dev->plat_dev->dev;
+   /*
+* When IOMMU is available, we cannot use the default configuration,
+* because of MFC firmware requirements: address space limited to
+* 256M and non-zero default start address.
+* This is still simplified, not optimal configuration, but for now
+* IOMMU core doesn't allow to configure device's IOMMUs channel
+* separately.
+*/
+   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
+S5P_MFC_IOMMU_DMA_SIZE);
+   if (ret)
+   return ret;
 
-   if (exynos_is_iommu_available(dev)) {
+   mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev;
+   ret = s5p_mfc_alloc_firmware(mfc_dev);
+   if (ret) {
exynos_unconfigure_iommu(dev);
-   vb2_dma_contig_clear_max_seg_size(dev);
-   return;
+   return ret;
}
 
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
-   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
-   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
-   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
+   mfc_dev->dma_base[BANK1_CTX] = mfc_dev-

[PATCH v3 15/16] media: s5p-mfc: Rename BANK1/2 to BANK_L/R to better match documentation

2017-03-20 Thread Marek Szyprowski
Documentation for MFC hardware still uses 'left' and 'right' names for
the memory channel/banks, so replace BANK1/2 defines with more appropriate
BANK_L/R names.

Suggested-by: Shuah Khan 
Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 54 -
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 13 +++---
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c|  8 ++--
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c| 10 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 28 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c |  6 +--
 7 files changed, 62 insertions(+), 61 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index a56031c3263e..dc1f6a96877a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1118,34 +1118,34 @@ static int s5p_mfc_configure_2port_memory(struct 
s5p_mfc_dev *mfc_dev)
 * Create and initialize virtual devices for accessing
 * reserved memory regions.
 */
-   mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left",
-  BANK1_CTX);
-   if (!mfc_dev->mem_dev[BANK1_CTX])
+   mfc_dev->mem_dev[BANK_L_CTX] = s5p_mfc_alloc_memdev(dev, "left",
+  BANK_L_CTX);
+   if (!mfc_dev->mem_dev[BANK_L_CTX])
return -ENODEV;
-   mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right",
-  BANK2_CTX);
-   if (!mfc_dev->mem_dev[BANK2_CTX]) {
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   mfc_dev->mem_dev[BANK_R_CTX] = s5p_mfc_alloc_memdev(dev, "right",
+  BANK_R_CTX);
+   if (!mfc_dev->mem_dev[BANK_R_CTX]) {
+   device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
return -ENODEV;
}
 
/* Allocate memory for firmware and initialize both banks addresses */
ret = s5p_mfc_alloc_firmware(mfc_dev);
if (ret) {
-   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
return ret;
}
 
-   mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma;
+   mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->fw_buf.dma;
 
-   bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size,
-   &bank2_dma_addr, GFP_KERNEL);
+   bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK_R_CTX],
+  align_size, &bank2_dma_addr, GFP_KERNEL);
if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
s5p_mfc_release_firmware(mfc_dev);
-   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
return -ENOMEM;
}
 
@@ -1153,14 +1153,14 @@ static int s5p_mfc_configure_2port_memory(struct 
s5p_mfc_dev *mfc_dev)
 * should not have address of bank2 - MFC will treat it as a null frame.
 * To avoid such situation we set bank2 address below the pool address.
 */
-   mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size;
+   mfc_dev->dma_base[BANK_R_CTX] = bank2_dma_addr - align_size;
 
-   dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt,
+   dma_free_coherent(mfc_dev->mem_dev[BANK_R_CTX], align_size, bank2_virt,
  bank2_dma_addr);
 
-   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX],
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX],
DMA_BIT_MASK(32));
-   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX],
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX],
DMA_BIT_MASK(32));
 
return 0;
@@ -1168,10 +1168,10 @@ static int s5p_mfc_configure_2port_memory(struct 
s5p_mfc_dev *mfc_dev)
 
 static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev)
 {
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
-   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
-   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);

[PATCH v3 14/16] media: s5p-mfc: Use preallocated block allocator always for MFC v6+

2017-03-20 Thread Marek Szyprowski
It turned out that all versions of MFC v6+ hardware doesn't have a strict
requirement for ALL buffers to be allocated on higher addresses than the
firmware base like it was documented for MFC v5. 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. Basing on this fact, the
special DMA configuration based on two reserved memory regions is not
really needed for MFC v6+ devices, because the memory requirements for the
firmware, device and per-context buffers can be fulfilled by the simple
probe-time pre-allocated block allocator instroduced in previous patch.

This patch enables support for such pre-allocated block based allocator
always for MFC v6+ devices. Due to the limitations of the memory management
subsystem the largest supported size of the pre-allocated buffer when no
CMA (Contiguous Memory Allocator) is enabled is 4MiB.

This patch also removes the requirement to provide two reserved memory
regions for MFC v6+ devices in device tree. Now the driver is fully
functional without them.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
Acked-by: Andrzej Hajda 
Tested-by: Smitha T Murthy 
---
 Documentation/devicetree/bindings/media/s5p-mfc.txt | 2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 9 ++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt 
b/Documentation/devicetree/bindings/media/s5p-mfc.txt
index 2c901286d818..d3404b5d4d17 100644
--- a/Documentation/devicetree/bindings/media/s5p-mfc.txt
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -28,7 +28,7 @@ Optional properties:
   - memory-region : from reserved memory binding: phandles to two reserved
memory regions, first is for "left" mfc memory bus interfaces,
second if for the "right" mfc memory bus, used when no SYSMMU
-   support is available
+   support is available; used only by MFC v5 present in Exynos4 SoCs
 
 Obsolete properties:
   - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index f1528054a713..a56031c3263e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1177,9 +1177,12 @@ 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 long mem_size = SZ_4M;
unsigned int bitmap_size;
 
+   if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev))
+   mem_size = SZ_8M;
+
if (mfc_mem_size)
mem_size = memparse(mfc_mem_size, NULL);
 
@@ -1239,7 +1242,7 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
 
-   if (exynos_is_iommu_available(dev))
+   if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
return s5p_mfc_configure_common_memory(mfc_dev);
else
return s5p_mfc_configure_2port_memory(mfc_dev);
@@ -1250,7 +1253,7 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
struct device *dev = &mfc_dev->plat_dev->dev;
 
s5p_mfc_release_firmware(mfc_dev);
-   if (exynos_is_iommu_available(dev))
+   if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
s5p_mfc_unconfigure_common_memory(mfc_dev);
else
s5p_mfc_unconfigure_2port_memory(mfc_dev);
-- 
1.9.1



Re: [PATCH 14/15] media: s5p-mfc: Use preallocated block allocator always for MFC v6+

2017-02-27 Thread Marek Szyprowski

Hi Shuah,

On 2017-02-24 15:23, Shuah Khan wrote:

On Thu, Feb 23, 2017 at 11:26 PM, Marek Szyprowski
 wrote:

On 2017-02-23 22:43, Shuah Khan wrote:

On Tue, Feb 14, 2017 at 12:52 AM, Marek Szyprowski
 wrote:

It turned out that all versions of MFC v6+ hardware doesn't have a strict
requirement for ALL buffers to be allocated on higher addresses than the
firmware base like it was documented for MFC v5. 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. Basing on this fact, the
special DMA configuration based on two reserved memory regions is not
really needed for MFC v6+ devices, because the memory requirements for
the
firmware, device and per-context buffers can be fulfilled by the simple
probe-time pre-allocated block allocator instroduced in previous patch.

This patch enables support for such pre-allocated block based allocator
always for MFC v6+ devices. Due to the limitations of the memory
management
subsystem the largest supported size of the pre-allocated buffer when no
CMA (Contiguous Memory Allocator) is enabled is 4MiB.

This patch also removes the requirement to provide two reserved memory
regions for MFC v6+ devices in device tree. Now the driver is fully
functional without them.

Signed-off-by: Marek Szyprowski 

Hi Marek,

This patch breaks display manager. exynos_drm_gem_create() isn't happy.
dmesg and console are flooded with

odroid login: [  209.170566] [drm:exynos_drm_gem_create] *ERROR* failed to
allo.
[  212.173222] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  215.354790] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  218.736464] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  221.837128] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  226.284827] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  229.242498] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  232.063150] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  235.73] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  239.472061] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  242.567465] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  246.500541] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  249.996018] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  253.837272] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  257.048782] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  260.084819] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  263.448611] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  266.271074] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  269.011558] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  272.039066] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  275.404938] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  278.339033] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  281.274751] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  284.641202] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  287.461039] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  291.062011] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  294.746870] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.
[  298.246570] [drm:exynos_drm_gem_create] *ERROR* failed to allocate
buffer.

I don't think this is an acceptable behavior. It is a regression.


This is a really poor bug report... Could you elaborate a bit how to
reproduce
this? Could you provide your kernel config and information about test
environment?

Yeah. I should have give you more information. My bad.


I suspect that you use CMA without IOMMU and you have too small global CMA
region.

Yes. I have CMA and using exynos_defconfig. Nothing fancy. I think
what's happening is s5p_mfc pre-allocates and there is nothing left
when disaply manager starts requestuing gem buffers. This failure
happens when systemd kicks off lightdm.


After this patch MFC driver uses global CMA region instead of the MFC's
private
ones, so one has to ensure that the global region is large enough.

This is still a regression since it requires users to take some
action. I think we need some kind of checks to warn users there isn't
a large enough CMA region. This is the same config I have been using
forever and with this patch, it breaks.

Easy to reproduce on odroid-xu4 with HDMI display. You just have to
boot the system with exynos_defconfig. Display manager will fail when
it requests buffers.


That is still a bit strange. MFC pre-allocates 8MiB buffer. The default CMA
global region size is 64MiB, which should be enough for a few display

Re: [PATCH 14/15] media: s5p-mfc: Use preallocated block allocator always for MFC v6+

2017-02-23 Thread Marek Szyprowski

Hi Shuah


On 2017-02-23 22:43, Shuah Khan wrote:

On Tue, Feb 14, 2017 at 12:52 AM, Marek Szyprowski
 wrote:

It turned out that all versions of MFC v6+ hardware doesn't have a strict
requirement for ALL buffers to be allocated on higher addresses than the
firmware base like it was documented for MFC v5. 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. Basing on this fact, the
special DMA configuration based on two reserved memory regions is not
really needed for MFC v6+ devices, because the memory requirements for the
firmware, device and per-context buffers can be fulfilled by the simple
probe-time pre-allocated block allocator instroduced in previous patch.

This patch enables support for such pre-allocated block based allocator
always for MFC v6+ devices. Due to the limitations of the memory management
subsystem the largest supported size of the pre-allocated buffer when no
CMA (Contiguous Memory Allocator) is enabled is 4MiB.

This patch also removes the requirement to provide two reserved memory
regions for MFC v6+ devices in device tree. Now the driver is fully
functional without them.

Signed-off-by: Marek Szyprowski 

Hi Marek,

This patch breaks display manager. exynos_drm_gem_create() isn't happy.
dmesg and console are flooded with

odroid login: [  209.170566] [drm:exynos_drm_gem_create] *ERROR* failed to allo.
[  212.173222] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  215.354790] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  218.736464] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  221.837128] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  226.284827] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  229.242498] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  232.063150] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  235.73] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  239.472061] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  242.567465] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  246.500541] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  249.996018] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  253.837272] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  257.048782] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  260.084819] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  263.448611] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  266.271074] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  269.011558] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  272.039066] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  275.404938] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  278.339033] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  281.274751] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  284.641202] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  287.461039] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  291.062011] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  294.746870] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.
[  298.246570] [drm:exynos_drm_gem_create] *ERROR* failed to allocate buffer.

I don't think this is an acceptable behavior. It is a regression.


This is a really poor bug report... Could you elaborate a bit how to 
reproduce
this? Could you provide your kernel config and information about test 
environment?


I suspect that you use CMA without IOMMU and you have too small global 
CMA region.
After this patch MFC driver uses global CMA region instead of the MFC's 
private

ones, so one has to ensure that the global region is large enough.

> [...]

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] media: mfc: Fix race between interrupt routine and device functions

2017-02-23 Thread Marek Szyprowski
Interrupt routine must wake process waiting for given interrupt AFTER
updating driver's internal structures and contexts. Doing it in-between
is a serious bug. This patch moves all calls to the wake() function to
the end of the interrupt processing block to avoid potential and real
races, especially on multi-core platforms. This also fixes following issue
reported from clock core (clocks were disabled in interrupt after being
unprepared from the other place in the driver, the stack trace however
points to the different place than s5p_mfc driver because of the race):

WARNING: CPU: 1 PID: 18 at drivers/clk/clk.c:544 clk_core_unprepare+0xc8/0x108
Modules linked in:
CPU: 1 PID: 18 Comm: kworker/1:0 Not tainted 
4.10.0-next-20170223-00070-g04e18bc99ab9-dirty #2154
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
Workqueue: pm pm_runtime_work
[] (unwind_backtrace) from [] (show_stack+0x10/0x14)
[] (show_stack) from [] (dump_stack+0x74/0x94)
[] (dump_stack) from [] (__warn+0xd4/0x100)
[] (__warn) from [] (warn_slowpath_null+0x20/0x28)
[] (warn_slowpath_null) from [] 
(clk_core_unprepare+0xc8/0x108)
[] (clk_core_unprepare) from [] (clk_unprepare+0x24/0x2c)
[] (clk_unprepare) from [] (exynos_sysmmu_suspend+0x48/0x60)
[] (exynos_sysmmu_suspend) from [] 
(pm_generic_runtime_suspend+0x2c/0x38)
[] (pm_generic_runtime_suspend) from [] 
(genpd_runtime_suspend+0x94/0x220)
[] (genpd_runtime_suspend) from [] 
(__rpm_callback+0x134/0x208)
[] (__rpm_callback) from [] (rpm_callback+0x20/0x80)
[] (rpm_callback) from [] (rpm_suspend+0xdc/0x458)
[] (rpm_suspend) from [] (pm_runtime_work+0x80/0x90)
[] (pm_runtime_work) from [] (process_one_work+0x120/0x318)
[] (process_one_work) from [] (worker_thread+0x2c/0x4ac)
[] (worker_thread) from [] (kthread+0xfc/0x134)
[] (kthread) from [] (ret_from_fork+0x14/0x3c)
---[ end trace 1ead49a7bb83f0d8 ]---

Signed-off-by: Marek Szyprowski 
Fixes: af93574678108 ("[media] MFC: Add MFC 5.1 V4L2 driver")
CC: sta...@vger.kernel.org # v4.5+
---
This issue was there from the beggining of the driver, but this patch applies
only to v4.5+ kernels.
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 9e0685beb048..d6cb315dac60 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -657,9 +657,9 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
break;
}
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-   wake_up_ctx(ctx, reason, err);
WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
s5p_mfc_clock_off();
+   wake_up_ctx(ctx, reason, err);
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
} else {
s5p_mfc_handle_frame(ctx, reason, err);
@@ -673,15 +673,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
ctx->state = MFCINST_GOT_INST;
-   clear_work_bit(ctx);
-   wake_up(&ctx->queue);
goto irq_cleanup_hw;
 
case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
-   clear_work_bit(ctx);
ctx->inst_no = MFC_NO_INSTANCE_SET;
ctx->state = MFCINST_FREE;
-   wake_up(&ctx->queue);
goto irq_cleanup_hw;
 
case S5P_MFC_R2H_CMD_SYS_INIT_RET:
@@ -691,9 +687,9 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
if (ctx)
clear_work_bit(ctx);
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-   wake_up_dev(dev, reason, err);
clear_bit(0, &dev->hw_lock);
clear_bit(0, &dev->enter_suspend);
+   wake_up_dev(dev, reason, err);
break;
 
case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
@@ -708,9 +704,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
break;
 
case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
-   clear_work_bit(ctx);
ctx->state = MFCINST_RUNNING;
-   wake_up(&ctx->queue);
goto irq_cleanup_hw;
 
default:
@@ -729,6 +723,8 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
mfc_err("Failed to unlock hw\n");
 
s5p_mfc_clock_off();
+   clear_work_bit(ctx);
+   wake_up(&ctx->queue);
 
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
spin_unlock(&dev->irqlock);
-- 
1.9.1



Re: [PATCH v2 08/15] media: s5p-mfc: Move firmware allocation to DMA configure function

2017-02-22 Thread Marek Szyprowski

Hi Shuah,


On 2017-02-22 19:07, Shuah Khan wrote:

On Mon, Feb 20, 2017 at 6:38 AM, Marek Szyprowski
 wrote:

To complete DMA memory configuration for MFC device, allocation of the
firmware buffer is needed, because some parameters are dependant on its base
address. Till now, this has been handled in the s5p_mfc_alloc_firmware()
function. This patch moves that logic to s5p_mfc_configure_dma_memory() to
keep DMA memory related operations in a single place. This way
s5p_mfc_alloc_firmware() is simplified and does what it name says. The
other consequence of this change is moving s5p_mfc_alloc_firmware() call
from the s5p_mfc_probe() function to the s5p_mfc_configure_dma_memory().

Overall looks good. This patch makes subtle change in the dma and firwmare
initialization sequence. Might be okay, but wanted to call out just in case,

Before this change:
vb2_dma_contig_set_max_seg_size() is done for both iommu and non-iommu
case before s5p_mfc_alloc_firmware(). With this change setting
dma_contig max size happens after s5p_mfc_alloc_firmware(). From what
I can tell this might not be an issue.
vb2_dma_contig_clear_max_seg_size() still happens after
s5p_mfc_release_firmware(), so that part hasn't changed.

Do any of the dma_* calls made from s5p_mfc_alloc_firmware() and later
during the dma congiguration sequence depend on dmap_parms being
allocated? Doesn't looks like it from what I can tell, but safe to
ask.


Firmware allocation doesn't depend on dma max segment size at all. The only
calls which might depend on it are dma_map_sg(), which are performed much
later as a part of video buffer allocation/preparation in videobuf2, when
dma-buf or user pointer v4l2 modes are selected.

> [...]

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] dma-buf: add support for compat ioctl

2017-02-21 Thread Marek Szyprowski

Dear All,

On 2017-02-21 15:37, Marek Szyprowski wrote:

Hi Christian,

On 2017-02-21 14:59, Christian König wrote:

Am 21.02.2017 um 14:21 schrieb Marek Szyprowski:
Add compat ioctl support to dma-buf. This lets one to use 
DMA_BUF_IOCTL_SYNC
ioctl from 32bit application on 64bit kernel. Data structures for 
both 32
and 64bit modes are same, so there is no need for additional 
translation

layer.


Well I might be wrong, but IIRC compat_ioctl was just optional and if 
not specified unlocked_ioctl was called instead.


If that is true your patch wouldn't have any effect at all.


Well, then why I got -ENOTTY in the 32bit test app for this ioctl on 
64bit ARM64 kernel without this patch?




I've checked in fs/compat_ioctl.c, I see no fallback in 
COMPAT_SYSCALL_DEFINE3,

so one has to provide compat_ioctl callback to have ioctl working with 32bit
apps.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] dma-buf: add support for compat ioctl

2017-02-21 Thread Marek Szyprowski

Hi Christian,

On 2017-02-21 14:59, Christian König wrote:

Am 21.02.2017 um 14:21 schrieb Marek Szyprowski:
Add compat ioctl support to dma-buf. This lets one to use 
DMA_BUF_IOCTL_SYNC
ioctl from 32bit application on 64bit kernel. Data structures for 
both 32

and 64bit modes are same, so there is no need for additional translation
layer.


Well I might be wrong, but IIRC compat_ioctl was just optional and if 
not specified unlocked_ioctl was called instead.


If that is true your patch wouldn't have any effect at all.


Well, then why I got -ENOTTY in the 32bit test app for this ioctl on 
64bit ARM64 kernel without this patch?


Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland



[PATCH] dma-buf: add support for compat ioctl

2017-02-21 Thread Marek Szyprowski
Add compat ioctl support to dma-buf. This lets one to use DMA_BUF_IOCTL_SYNC
ioctl from 32bit application on 64bit kernel. Data structures for both 32
and 64bit modes are same, so there is no need for additional translation
layer.

Signed-off-by: Marek Szyprowski 
---
 drivers/dma-buf/dma-buf.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 718f832a5c71..0007b792827b 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -325,6 +325,9 @@ static long dma_buf_ioctl(struct file *file,
.llseek = dma_buf_llseek,
.poll   = dma_buf_poll,
.unlocked_ioctl = dma_buf_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = dma_buf_ioctl,
+#endif
 };
 
 /*
-- 
1.9.1



[PATCH v2 06/15] media: s5p-mfc: Move setting DMA max segment size to DMA configure function

2017-02-20 Thread Marek Szyprowski
Setting DMA max segment size to 32 bit mask is a part of DMA memory
configuration, so move those calls to s5p_mfc_configure_dma_memory()
function.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index f7664910f12c..bc1aeb25ebeb 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1122,9 +1122,13 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
if (exynos_is_iommu_available(dev)) {
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret == 0)
+   if (ret == 0) {
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));
+   }
+
return ret;
}
 
@@ -1143,6 +1147,11 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return -ENODEV;
}
 
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX],
+   DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX],
+   DMA_BIT_MASK(32));
+
return 0;
 }
 
@@ -1152,11 +1161,14 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 
if (exynos_is_iommu_available(dev)) {
exynos_unconfigure_iommu(dev);
+   vb2_dma_contig_clear_max_seg_size(dev);
return;
}
 
device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
 }
 
 /* MFC probe function */
@@ -1214,11 +1226,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_dma;
}
 
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX],
-   DMA_BIT_MASK(32));
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX],
-   DMA_BIT_MASK(32));
-
mutex_init(&dev->mfc_mutex);
init_waitqueue_head(&dev->queue);
dev->hw_lock = 0;
@@ -1351,8 +1358,6 @@ static int s5p_mfc_remove(struct platform_device *pdev)
v4l2_device_unregister(&dev->v4l2_dev);
s5p_mfc_release_firmware(dev);
s5p_mfc_unconfigure_dma_memory(dev);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]);
 
s5p_mfc_final_pm(dev);
return 0;
-- 
1.9.1



[PATCH v2 03/15] media: s5p-mfc: Replace mem_dev_* entries with an array

2017-02-20 Thread Marek Szyprowski
Internal MFC driver device structure contains two pointers to devices used
for DMA memory allocation: mem_dev_l and mem_dev_r. Replace them with the
mem_dev[] array and use defines for accessing particular banks. This will
help to simplify code in the next patches.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 31 +---
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 11 -
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 23 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c|  8 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c| 10 
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 32 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 ++--
 7 files changed, 69 insertions(+), 61 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index ad3d7377f40d..f7664910f12c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1123,7 +1123,8 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
if (ret == 0)
-   mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev;
+   mfc_dev->mem_dev[BANK1_CTX] =
+   mfc_dev->mem_dev[BANK2_CTX] = dev;
return ret;
}
 
@@ -1131,14 +1132,14 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 * Create and initialize virtual devices for accessing
 * reserved memory regions.
 */
-   mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left",
- MFC_BANK1_ALLOC_CTX);
-   if (!mfc_dev->mem_dev_l)
+   mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left",
+  BANK1_CTX);
+   if (!mfc_dev->mem_dev[BANK1_CTX])
return -ENODEV;
-   mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right",
- MFC_BANK2_ALLOC_CTX);
-   if (!mfc_dev->mem_dev_r) {
-   device_unregister(mfc_dev->mem_dev_l);
+   mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right",
+  BANK2_CTX);
+   if (!mfc_dev->mem_dev[BANK2_CTX]) {
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
return -ENODEV;
}
 
@@ -1154,8 +1155,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return;
}
 
-   device_unregister(mfc_dev->mem_dev_l);
-   device_unregister(mfc_dev->mem_dev_r);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
 }
 
 /* MFC probe function */
@@ -1213,8 +1214,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
goto err_dma;
}
 
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32));
-   vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX],
+   DMA_BIT_MASK(32));
+   vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX],
+   DMA_BIT_MASK(32));
 
mutex_init(&dev->mfc_mutex);
init_waitqueue_head(&dev->queue);
@@ -1348,8 +1351,8 @@ static int s5p_mfc_remove(struct platform_device *pdev)
v4l2_device_unregister(&dev->v4l2_dev);
s5p_mfc_release_firmware(dev);
s5p_mfc_unconfigure_dma_memory(dev);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l);
-   vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r);
+   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]);
 
s5p_mfc_final_pm(dev);
return 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 2f1387a4c386..27d4c864e06e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -33,8 +33,9 @@
 *  while mmaping */
 #define DST_QUEUE_OFF_BASE (1 << 30)
 
-#define MFC_BANK1_ALLOC_CTX0
-#define MFC_BANK2_ALLOC_CTX1
+#define BANK1_CTX  0
+#define BANK2_CTX  1
+#define BANK_CTX_NUM   2
 
 #define MFC_BANK1_ALIGN_ORDER  13
 #define MFC_BANK2_ALIGN_ORDER  13
@@ -254,8 +255,7 @@ struct s5p_mf

[PATCH v2 02/15] media: s5p-mfc: Use generic of_device_get_match_data helper

2017-02-20 Thread Marek Szyprowski
Replace custom code with generic helper to retrieve driver data.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 17 ++---
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  4 ++--
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 3e1f22eb4339..ad3d7377f40d 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "s5p_mfc_common.h"
@@ -1157,8 +1158,6 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
device_unregister(mfc_dev->mem_dev_r);
 }
 
-static void *mfc_get_drv_data(struct platform_device *pdev);
-
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1182,7 +1181,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
return -ENODEV;
}
 
-   dev->variant = mfc_get_drv_data(pdev);
+   dev->variant = of_device_get_match_data(&pdev->dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1541,18 +1540,6 @@ static int s5p_mfc_resume(struct device *dev)
 };
 MODULE_DEVICE_TABLE(of, exynos_mfc_match);
 
-static void *mfc_get_drv_data(struct platform_device *pdev)
-{
-   struct s5p_mfc_variant *driver_data = NULL;
-   const struct of_device_id *match;
-
-   match = of_match_node(exynos_mfc_match, pdev->dev.of_node);
-   if (match)
-   driver_data = (struct s5p_mfc_variant *)match->data;
-
-   return driver_data;
-}
-
 static struct platform_driver s5p_mfc_driver = {
.probe  = s5p_mfc_probe,
.remove = s5p_mfc_remove,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 3e0e8eaf8bfe..2f1387a4c386 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -192,7 +192,7 @@ struct s5p_mfc_buf {
  */
 struct s5p_mfc_pm {
struct clk  *clock_gate;
-   const char  **clk_names;
+   const char * const *clk_names;
struct clk  *clocks[MFC_MAX_CLOCKS];
int num_clocks;
booluse_clock_gating;
@@ -304,7 +304,7 @@ struct s5p_mfc_dev {
struct v4l2_ctrl_handler dec_ctrl_handler;
struct v4l2_ctrl_handler enc_ctrl_handler;
struct s5p_mfc_pm   pm;
-   struct s5p_mfc_variant  *variant;
+   const struct s5p_mfc_variant*variant;
int num_inst;
spinlock_t irqlock; /* lock when operating on context */
spinlock_t condlock;/* lock when changing/checking if a context is
-- 
1.9.1



[PATCH v2 10/15] media: s5p-mfc: Reduce firmware buffer size for MFC v6+ variants

2017-02-20 Thread Marek Szyprowski
Firmware for MFC v6+ variants is not larger than 400 KiB, so there is no
need to allocate a full 1 MiB buffer for it. Reduce it to 512 KiB to keep
proper alignment of allocated buffer.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v7.h | 2 +-
 drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
index d2cd35916dc5..c0166ee9a455 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
@@ -403,7 +403,7 @@
 #define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)/*  12KB */
 
 /* MFCv6 variant defines */
-#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V6 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V6(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V6 0x61
 #define MFC_NUM_PORTS_V6   1
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
index 1a5c6fdf7846..9f220769d970 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
@@ -34,7 +34,7 @@
 #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7  0xfdc4
 
 /* MFCv7 variant defines */
-#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V7 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V7(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V7 0x72
 #define MFC_NUM_PORTS_V7   1
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h 
b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
index 4d1c3750eb5e..75f5f7511d72 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
@@ -116,7 +116,7 @@
 #define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64
 
 /* MFCv8 variant defines */
-#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */
+#define MAX_FW_SIZE_V8 (SZ_512K)   /* 512KB */
 #define MAX_CPB_SIZE_V8(3 * SZ_1M) /* 3MB */
 #define MFC_VERSION_V8 0x80
 #define MFC_NUM_PORTS_V8   1
-- 
1.9.1



[PATCH v2 07/15] media: s5p-mfc: Put firmware to private buffer structure

2017-02-20 Thread Marek Szyprowski
Use s5p_mfc_priv_buf structure for keeping the firmware image. This will
help handling of firmware buffer allocation in the next patches.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c |  2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h |  3 +--
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c   | 36 -
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
index 8c4739ca16d6..4c80bb4243be 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
@@ -47,7 +47,7 @@ static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
struct s5p_mfc_cmd_args h2r_args;
 
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-   h2r_args.arg[0] = dev->fw_size;
+   h2r_args.arg[0] = dev->fw_buf.size;
return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
&h2r_args);
 }
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 9cf860f34c71..cea17a737ef7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -314,8 +314,7 @@ struct s5p_mfc_dev {
int int_type;
unsigned int int_err;
wait_queue_head_t queue;
-   size_t fw_size;
-   void *fw_virt_addr;
+   struct s5p_mfc_priv_buf fw_buf;
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_ctrl.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index c9bff3d0655f..50d698968049 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -29,21 +29,22 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
void *bank2_virt;
dma_addr_t bank2_dma_addr;
unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER;
+   struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
 
-   dev->fw_size = dev->variant->buf_size->fw;
+   fw_buf->size = dev->variant->buf_size->fw;
 
-   if (dev->fw_virt_addr) {
+   if (fw_buf->virt) {
mfc_err("Attempting to allocate firmware when it seems that it 
is already loaded\n");
return -ENOMEM;
}
 
-   dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX],
-   dev->fw_size, &dev->dma_base[BANK1_CTX],
-   GFP_KERNEL);
-   if (!dev->fw_virt_addr) {
+   fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size,
+&fw_buf->dma, GFP_KERNEL);
+   if (!fw_buf->virt) {
mfc_err("Allocating bitprocessor buffer failed\n");
return -ENOMEM;
}
+   dev->dma_base[BANK1_CTX] = fw_buf->dma;
 
if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX],
@@ -51,10 +52,9 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 
if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
-   dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size,
- dev->fw_virt_addr,
- dev->dma_base[BANK1_CTX]);
-   dev->fw_virt_addr = NULL;
+   dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size,
+ fw_buf->virt, fw_buf->dma);
+   fw_buf->virt = NULL;
return -ENOMEM;
}
 
@@ -101,17 +101,17 @@ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
mfc_err("Firmware is not present in the /lib/firmware directory 
nor compiled in kernel\n");
return -EINVAL;
}
-   if (fw_blob->size > dev->fw_size) {
+   if (fw_blob->size > dev->fw_buf.size) {
mfc_err("MFC firmware is too big to be loaded\n");
release_firmware(fw_blob);
return -ENOMEM;
}
-   if (!dev->fw_virt_addr) {
+   if (!dev->fw_buf.virt) {
mfc_err("MFC firmware is not allocated\n");
release_firmware(fw_blob);
return -EINVAL;
}
-   memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
+   memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->

[PATCH v2 13/15] media: s5p-mfc: Remove special configuration of IOMMU domain

2017-02-20 Thread Marek Szyprowski
The main reason for using special configuration of IOMMU domain was the
problem with MFC firmware, which failed to operate properly when placed
at 0 DMA address. Instead of adding custom code for configuring each
variant of IOMMU domain and architecture specific glue code, simply use
what arch code provides and if the DMA base address equals zero, skip
first 128 KiB to keep required alignment. This patch also make the driver
operational on ARM64 architecture, because it no longer depends on ARM
specific DMA-mapping and IOMMU glue code functions.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c   | 30 +++
 drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h | 51 +-
 2 files changed, 14 insertions(+), 67 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 1c5ec8257f4f..b70cbd637851 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1184,18 +1184,6 @@ 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
-* 256M and non-zero default start address.
-* This is still simplified, not optimal configuration, but for now
-* IOMMU core doesn't allow to configure device's IOMMUs channel
-* separately.
-*/
-   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
-S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret)
-   return ret;
 
if (mfc_mem_size)
mem_size = memparse(mfc_mem_size, NULL);
@@ -1203,10 +1191,8 @@ static int s5p_mfc_configure_common_memory(struct 
s5p_mfc_dev *mfc_dev)
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);
+   if (!mfc_dev->mem_bitmap)
return -ENOMEM;
-   }
 
mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size,
   &mfc_dev->mem_base, GFP_KERNEL);
@@ -1214,13 +1200,24 @@ static int s5p_mfc_configure_common_memory(struct 
s5p_mfc_dev *mfc_dev)
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;
 
+   /*
+* MFC hardware cannot handle 0 as a base address, so mark first 128K
+* as used (to keep required base alignment) and adjust base address
+*/
+   if (mfc_dev->mem_base == (dma_addr_t)0) {
+   unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER;
+
+   bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT);
+   mfc_dev->dma_base[BANK1_CTX] += offset;
+   mfc_dev->dma_base[BANK2_CTX] += offset;
+   }
+
/* Firmware allocation cannot fail in this case */
s5p_mfc_alloc_firmware(mfc_dev);
 
@@ -1237,7 +1234,6 @@ 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);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h 
b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
index 6962132ae8fa..76667924ee2a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
@@ -11,54 +11,13 @@
 #ifndef S5P_MFC_IOMMU_H_
 #define S5P_MFC_IOMMU_H_
 
-#define S5P_MFC_IOMMU_DMA_BASE 0x2000lu
-#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M
-
-#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU)
-
-#include 
+#if defined(CONFIG_EXYNOS_IOMMU)
 
 static inline bool exynos_is_iommu_available(struct device *dev)
 {
return dev->archdata.iommu != NULL;
 }
 
-static inline void exynos_unconfigure_iommu(struct device *dev)
-{
-   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
-
-   arm_iommu_detach_device(dev);
-   arm_iommu_release_mapp

[PATCH v2 11/15] media: s5p-mfc: Split variant DMA memory configuration into separate functions

2017-02-20 Thread Marek Szyprowski
Move code for DMA memory configuration with IOMMU into separate function
to make it easier to compare what is being done in each case.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 102 ++-
 1 file changed, 61 insertions(+), 41 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 4403487a494a..04067bcc3feb 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1107,44 +1107,15 @@ static struct device *s5p_mfc_alloc_memdev(struct 
device *dev,
return NULL;
 }
 
-static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
void *bank2_virt;
dma_addr_t bank2_dma_addr;
unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
-   struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf;
int ret;
 
/*
-* When IOMMU is available, we cannot use the default configuration,
-* because of MFC firmware requirements: address space limited to
-* 256M and non-zero default start address.
-* This is still simplified, not optimal configuration, but for now
-* IOMMU core doesn't allow to configure device's IOMMUs channel
-* separately.
-*/
-   if (exynos_is_iommu_available(dev)) {
-   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
-S5P_MFC_IOMMU_DMA_SIZE);
-   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) {
-   exynos_unconfigure_iommu(dev);
-   return ret;
-   }
-
-   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
-   mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma;
-   vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-   return 0;
-   }
-
-   /*
 * Create and initialize virtual devices for accessing
 * reserved memory regions.
 */
@@ -1167,7 +1138,7 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return ret;
}
 
-   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+   mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma;
 
bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size,
&bank2_dma_addr, GFP_KERNEL);
@@ -1196,22 +1167,71 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return 0;
 }
 
-static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev)
 {
-   struct device *dev = &mfc_dev->plat_dev->dev;
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
+   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
+}
 
-   s5p_mfc_release_firmware(mfc_dev);
+static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev)
+{
+   struct device *dev = &mfc_dev->plat_dev->dev;
+   /*
+* When IOMMU is available, we cannot use the default configuration,
+* because of MFC firmware requirements: address space limited to
+* 256M and non-zero default start address.
+* This is still simplified, not optimal configuration, but for now
+* IOMMU core doesn't allow to configure device's IOMMUs channel
+* separately.
+*/
+   int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
+S5P_MFC_IOMMU_DMA_SIZE);
+   if (ret)
+   return ret;
 
-   if (exynos_is_iommu_available(dev)) {
+   mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev;
+   ret = s5p_mfc_alloc_firmware(mfc_dev);
+   if (ret) {
exynos_unconfigure_iommu(dev);
-   vb2_dma_contig_clear_max_seg_size(dev);
-   return;
+   return ret;
}
 
-   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
-   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
-   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]);
-   vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]);
+   mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma;
+   mfc_dev->dma_b

[PATCH v2 08/15] media: s5p-mfc: Move firmware allocation to DMA configure function

2017-02-20 Thread Marek Szyprowski
To complete DMA memory configuration for MFC device, allocation of the
firmware buffer is needed, because some parameters are dependant on its base
address. Till now, this has been handled in the s5p_mfc_alloc_firmware()
function. This patch moves that logic to s5p_mfc_configure_dma_memory() to
keep DMA memory related operations in a single place. This way
s5p_mfc_alloc_firmware() is simplified and does what it name says. The
other consequence of this change is moving s5p_mfc_alloc_firmware() call
from the s5p_mfc_probe() function to the s5p_mfc_configure_dma_memory().

Signed-off-by: Marek Szyprowski 
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c  | 62 +--
 drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 31 --
 2 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index bc1aeb25ebeb..4403487a494a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1110,6 +1110,11 @@ static struct device *s5p_mfc_alloc_memdev(struct device 
*dev,
 static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
+   void *bank2_virt;
+   dma_addr_t bank2_dma_addr;
+   unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
+   struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf;
+   int ret;
 
/*
 * When IOMMU is available, we cannot use the default configuration,
@@ -1122,14 +1127,21 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
if (exynos_is_iommu_available(dev)) {
int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE,
 S5P_MFC_IOMMU_DMA_SIZE);
-   if (ret == 0) {
-   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));
+   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) {
+   exynos_unconfigure_iommu(dev);
+   return ret;
}
 
-   return ret;
+   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+   mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma;
+   vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+   return 0;
}
 
/*
@@ -1147,6 +1159,35 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
return -ENODEV;
}
 
+   /* Allocate memory for firmware and initialize both banks addresses */
+   ret = s5p_mfc_alloc_firmware(mfc_dev);
+   if (ret) {
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   return ret;
+   }
+
+   mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma;
+
+   bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size,
+   &bank2_dma_addr, GFP_KERNEL);
+   if (!bank2_virt) {
+   mfc_err("Allocating bank2 base failed\n");
+   s5p_mfc_release_firmware(mfc_dev);
+   device_unregister(mfc_dev->mem_dev[BANK2_CTX]);
+   device_unregister(mfc_dev->mem_dev[BANK1_CTX]);
+   return -ENOMEM;
+   }
+
+   /* Valid buffers passed to MFC encoder with LAST_FRAME command
+* should not have address of bank2 - MFC will treat it as a null frame.
+* To avoid such situation we set bank2 address below the pool address.
+*/
+   mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size;
+
+   dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt,
+ bank2_dma_addr);
+
vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX],
DMA_BIT_MASK(32));
vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX],
@@ -1159,6 +1200,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
 
+   s5p_mfc_release_firmware(mfc_dev);
+
if (exynos_is_iommu_available(dev)) {
exynos_unconfigure_iommu(dev);
vb2_dma_contig_clear_max_seg_size(dev);
@@ -1235,10 +1278,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
dev->watchdog_timer.data = (unsigned long)dev;
dev->watchdog_timer.function = s5p_mfc_watch

[PATCH v2 15/15] ARM: dts: exynos: Remove MFC reserved buffers

2017-02-20 Thread Marek Szyprowski
During my research I found that some of the requirements for the memory
buffers for MFC v6+ devices were blindly copied from the previous (v5)
version and simply turned out to be excessive. The relaxed requirements
are applied by the recent patches to the MFC driver and the driver is
now fully functional even without the reserved memory blocks for all
v6+ variants. This patch removes those reserved memory nodes from all
boards having MFC v6+ hardware block.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 arch/arm/boot/dts/exynos5250-arndale.dts   | 1 -
 arch/arm/boot/dts/exynos5250-smdk5250.dts  | 1 -
 arch/arm/boot/dts/exynos5250-spring.dts| 1 -
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  | 1 -
 arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 -
 arch/arm/boot/dts/exynos5420-smdk5420.dts  | 1 -
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 1 -
 arch/arm/boot/dts/exynos5800-peach-pi.dts  | 1 -
 8 files changed, 8 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts 
b/arch/arm/boot/dts/exynos5250-arndale.dts
index 6098dacd09f1..6a432460eb77 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Insignal Arndale evaluation board based on EXYNOS5250";
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a97a785ccc6b..6632f657394e 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -13,7 +13,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts 
b/arch/arm/boot/dts/exynos5250-spring.dts
index 4d7bdb735ed3..95c3bcace9dc 100644
--- a/arch/arm/boot/dts/exynos5250-spring.dts
+++ b/arch/arm/boot/dts/exynos5250-spring.dts
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include "exynos5250.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Spring";
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 9cc83c51c925..ee1bb9b8b366 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Insignal Arndale Octa evaluation board based on EXYNOS5420";
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts 
b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 1f964ec35c5e..2cd65699a29c 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -16,7 +16,6 @@
 #include 
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Peach Pit Rev 6+";
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts 
b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index aaccd0da41e5..08c8ab173e87 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -13,7 +13,6 @@
 #include "exynos5420.dtsi"
 #include "exynos5420-cpus.dtsi"
 #include 
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Samsung SMDK5420 board based on EXYNOS5420";
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 
b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
index 05b9afdd6757..657535e2e3cc 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
@@ -18,7 +18,6 @@
 #include 
 #include "exynos5800.dtsi"
 #include "exynos5422-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
memory@4000 {
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts 
b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index f9ff7f07ae0c..ecf1c916e8fc 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -16,7 +16,6 @@
 #include 
 #include "exynos5800.dtsi"
 #include "exynos5420-cpus.dtsi"
-#include "exynos-mfc-reserved-memory.dtsi"
 
 / {
model = "Google Peach Pi Rev 10+";
-- 
1.9.1



[PATCH v2 14/15] media: s5p-mfc: Use preallocated block allocator always for MFC v6+

2017-02-20 Thread Marek Szyprowski
It turned out that all versions of MFC v6+ hardware doesn't have a strict
requirement for ALL buffers to be allocated on higher addresses than the
firmware base like it was documented for MFC v5. 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. Basing on this fact, the
special DMA configuration based on two reserved memory regions is not
really needed for MFC v6+ devices, because the memory requirements for the
firmware, device and per-context buffers can be fulfilled by the simple
probe-time pre-allocated block allocator instroduced in previous patch.

This patch enables support for such pre-allocated block based allocator
always for MFC v6+ devices. Due to the limitations of the memory management
subsystem the largest supported size of the pre-allocated buffer when no
CMA (Contiguous Memory Allocator) is enabled is 4MiB.

This patch also removes the requirement to provide two reserved memory
regions for MFC v6+ devices in device tree. Now the driver is fully
functional without them.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Javier Martinez Canillas 
Tested-by: Javier Martinez Canillas 
---
 Documentation/devicetree/bindings/media/s5p-mfc.txt | 2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc.c| 9 ++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt 
b/Documentation/devicetree/bindings/media/s5p-mfc.txt
index 2c901286d818..d3404b5d4d17 100644
--- a/Documentation/devicetree/bindings/media/s5p-mfc.txt
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -28,7 +28,7 @@ Optional properties:
   - memory-region : from reserved memory binding: phandles to two reserved
memory regions, first is for "left" mfc memory bus interfaces,
second if for the "right" mfc memory bus, used when no SYSMMU
-   support is available
+   support is available; used only by MFC v5 present in Exynos4 SoCs
 
 Obsolete properties:
   - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index b70cbd637851..b4a13e4cc9d4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1182,9 +1182,12 @@ 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 long mem_size = SZ_4M;
unsigned int bitmap_size;
 
+   if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev))
+   mem_size = SZ_8M;
+
if (mfc_mem_size)
mem_size = memparse(mfc_mem_size, NULL);
 
@@ -1244,7 +1247,7 @@ static int s5p_mfc_configure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
 {
struct device *dev = &mfc_dev->plat_dev->dev;
 
-   if (exynos_is_iommu_available(dev))
+   if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
return s5p_mfc_configure_common_memory(mfc_dev);
else
return s5p_mfc_configure_2port_memory(mfc_dev);
@@ -1255,7 +1258,7 @@ static void s5p_mfc_unconfigure_dma_memory(struct 
s5p_mfc_dev *mfc_dev)
struct device *dev = &mfc_dev->plat_dev->dev;
 
s5p_mfc_release_firmware(mfc_dev);
-   if (exynos_is_iommu_available(dev))
+   if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
s5p_mfc_unconfigure_common_memory(mfc_dev);
else
s5p_mfc_unconfigure_2port_memory(mfc_dev);
-- 
1.9.1



[PATCH v2 12/15] media: s5p-mfc: Add support for probe-time preallocated block based allocator

2017-02-20 Thread Marek Szyprowski
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(-)

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

  1   2   3   4   5   6   7   8   9   10   >