[PATCH v5 9/9] dma_buf: heaps: restricted_heap_mtk: Add a new CMA heap

2024-05-15 Thread Yong Wu
Create a new MediaTek CMA heap from the CMA reserved buffer.

In this heap, When the first allocating buffer, use cma_alloc to prepare
whole the CMA range, then send its range to TEE to protect and manage.
For the later allocating, we just adds the cma_used_size.

When SVP done, cma_release will release the buffer, then kernel may
reuse it.

For the "CMA" restricted heap, "struct cma *cma" is a common property,
not just for MediaTek, so put it into "struct restricted_heap" instead of
our private data.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   2 +-
 drivers/dma-buf/heaps/restricted_heap.h |   4 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 121 +++-
 3 files changed, 123 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 84f748fb2856..58903bc62ac8 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -24,7 +24,7 @@ config DMABUF_HEAPS_RESTRICTED
 
 config DMABUF_HEAPS_RESTRICTED_MTK
bool "MediaTek DMA-BUF Restricted Heap"
-   depends on DMABUF_HEAPS_RESTRICTED && TEE=y
+   depends on DMABUF_HEAPS_RESTRICTED && DMA_CMA && TEE=y
help
  Enable restricted dma-buf heaps for MediaTek platform. This heap is 
backed by
  TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 8cb9211093c5..7dec4b8a471b 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -23,6 +23,10 @@ struct restricted_heap {
 
const struct restricted_heap_ops *ops;
 
+   struct cma  *cma;
+   unsigned long   cma_paddr;
+   unsigned long   cma_size;
+
void*priv_data;
 };
 
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
index e571eae719e0..6d8119828485 100644
--- a/drivers/dma-buf/heaps/restricted_heap_mtk.c
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -6,9 +6,11 @@
  */
 #define pr_fmt(fmt) "rheap_mtk: " fmt
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,6 +27,13 @@ enum mtk_secure_mem_type {
 * management is inside the TEE.
 */
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+   /*
+* MediaTek dynamic chunk memory carved out from CMA.
+* In normal case, the CMA could be used in kernel; When SVP start, we 
will
+* allocate whole this CMA and pass whole the CMA PA and size into TEE 
to
+* protect it, then the detail memory management also is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_CMA   = 2,
 };
 
 /* This structure also is synchronized with tee, thus not use the phys_addr_t 
*/
@@ -40,7 +49,8 @@ enum mtk_secure_buffer_tee_cmd {
 * [in]  value[0].a: The buffer size.
 *   value[0].b: alignment.
 * [in]  value[1].a: enum mtk_secure_mem_type.
-* [inout]
+* [inout] [in]  value[2].a: pa base in cma case.
+*   value[2].b: The buffer size in cma case.
 * [out] value[2].a: entry number of memory block.
 *   If this is 1, it means the memory is 
continuous.
 *   value[2].b: buffer PA base.
@@ -73,6 +83,9 @@ struct mtk_restricted_heap_data {
 
const enum mtk_secure_mem_type mem_type;
 
+   struct page *cma_page;
+   unsigned long   cma_used_size;
+   struct mutexlock; /* lock for cma_used_size */
 };
 
 static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
@@ -173,6 +186,10 @@ static int mtk_tee_restrict_memory(struct restricted_heap 
*rheap, struct restric
params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[1].u.value.a = data->mem_type;
params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+   if (rheap->cma && data->mem_type == MTK_SECURE_MEMORY_TYPE_CM_CMA) {
+   params[2].u.value.a = rheap->cma_paddr;
+   params[2].u.value.b = rheap->cma_size;
+   }
params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
ret = mtk_tee_service_call(data->tee_ctx, data->tee_session,
   MTK_TZCMD_SECMEM_ZALLOC, params);
@@ -265,6 +282,48 @@ mtk_restricted_memory_free(struct restricted_heap *rheap, 
struct restricted_buff
 {
 }
 
+static int mtk_restricted_memory_cma_allocate(struct restricted_heap *rheap,
+ struct restricted_buffer *buf)
+{
+   struct mtk_restricted_heap_data *data = rheap->priv_data;
+   int ret = 0;
+   /*
+* Allocate CMA only when allocating buffer for the first time, and jus

[PATCH v5 8/9] dma-buf: heaps: restricted_heap_mtk: Add TEE memory service call

2024-05-15 Thread Yong Wu
Add TEE service call for MediaTek heap. We have a limited number of
hardware entries to protect memory, therefore we cannot protect memory
arbitrarily, and our secure memory management is actually inside OPTEE.

Totally there are 3 commands:
1) MTK_TZCMD_SECMEM_ZALLOC: The kernel tells the TEE what size I want and
the TEE will return a "secure handle"/"secure address". To make the name
more general, We call it "restricted_addr" here. The restricted_addr is a
reference to the secure buffer within TEE.
2) MTK_TZCMD_SECMEM_FREE: Free the buffer. Match with the ALLOC command
above.
3) MTK_TZCMD_SECMEM_RETRIEVE_SG: If the tee buffer is discrete, this
command can retrieve the detailed PA list from the TEE with which the
kernel will initialize the sg table. Of course, if the tee buffer is
contiguous, the PA will be obtained directly from MTK_TZCMD_SECMEM_ZALLOC.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.h |   3 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 193 
 2 files changed, 196 insertions(+)

diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 2a33a1c7a48b..8cb9211093c5 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -13,6 +13,9 @@ struct restricted_buffer {
size_t  size;
 
struct sg_table sg_table;
+
+   /* A reference to a buffer in the trusted or secure world. */
+   u64 restricted_addr;
 };
 
 struct restricted_heap {
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
index 52e805eb9858..e571eae719e0 100644
--- a/drivers/dma-buf/heaps/restricted_heap_mtk.c
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -27,6 +27,46 @@ enum mtk_secure_mem_type {
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
 };
 
+/* This structure also is synchronized with tee, thus not use the phys_addr_t 
*/
+struct mtk_tee_scatterlist {
+   u64 pa;
+   u32 length;
+} __packed;
+
+enum mtk_secure_buffer_tee_cmd {
+   /*
+* Allocate the zeroed secure memory from TEE.
+*
+* [in]  value[0].a: The buffer size.
+*   value[0].b: alignment.
+* [in]  value[1].a: enum mtk_secure_mem_type.
+* [inout]
+* [out] value[2].a: entry number of memory block.
+*   If this is 1, it means the memory is 
continuous.
+*   value[2].b: buffer PA base.
+* [out] value[3].a: The secure handle.
+*/
+   MTK_TZCMD_SECMEM_ZALLOC = 0x1, /* MTK TEE Command ID Base */
+
+   /*
+* Free secure memory.
+*
+* [in]  value[0].a: The secure handle of this buffer, It's value[3].a 
of
+*   MTK_TZCMD_SECMEM_ZALLOC.
+* [out] value[1].a: return value, 0 means successful, otherwise fail.
+*/
+   MTK_TZCMD_SECMEM_FREE   = 0x10001,
+
+   /*
+* Get secure memory sg-list.
+*
+* [in]  value[0].a: The secure handle of this buffer, It's value[3].a 
of
+*   MTK_TZCMD_SECMEM_ZALLOC.
+* [out] value[1].a: The array of sg items (struct mtk_tee_scatterlist).
+*/
+   MTK_TZCMD_SECMEM_RETRIEVE_SG= 0x10002,
+};
+
 struct mtk_restricted_heap_data {
struct tee_context  *tee_ctx;
u32 tee_session;
@@ -76,6 +116,155 @@ static int mtk_tee_session_init(struct 
mtk_restricted_heap_data *data)
return ret;
 }
 
+static int mtk_tee_service_call(struct tee_context *tee_ctx, u32 session,
+   unsigned int command, struct tee_param *params)
+{
+   struct tee_ioctl_invoke_arg arg = {0};
+   int ret;
+
+   arg.num_params = TEE_PARAM_NUM;
+   arg.session = session;
+   arg.func = command;
+
+   ret = tee_client_invoke_func(tee_ctx, , params);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: cmd 0x%x ret %d:%x.\n", __func__, command, ret, 
arg.ret);
+   ret = -EOPNOTSUPP;
+   }
+   return ret;
+}
+
+static int mtk_tee_secmem_free(struct restricted_heap *rheap, u64 
restricted_addr)
+{
+   struct mtk_restricted_heap_data *data = rheap->priv_data;
+   struct tee_param params[TEE_PARAM_NUM] = {0};
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = restricted_addr;
+   params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+   mtk_tee_service_call(data->tee_ctx, data->tee_session,
+MTK_TZCMD_SECMEM_FREE, params);
+   if (params[1].u.value.a) {
+   pr_err("%s, SECMEM_FREE buffer(0x%llx) fail(%lld) from TEE.\n",
+  rheap->name, restricted_addr, params[1].u.value.a);
+  

[PATCH v5 7/9] dma-buf: heaps: restricted_heap: Add MediaTek restricted heap and heap_init

2024-05-15 Thread Yong Wu
Add a MediaTek restricted heap which uses TEE service call to restrict
buffer. Currently this restricted heap is NULL, Prepare for the later
patch. Mainly there are two changes:
a) Add a heap_init ops since TEE probe late than restricted heap, thus
   initialize the heap when we require the buffer the first time.
b) Add a priv_data for each heap, like the special data used by MTK
   (such as "TEE session") can be placed in priv_data.

Currently our heap depends on CMA which could only be bool, thus
depend on "TEE=y".

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   7 ++
 drivers/dma-buf/heaps/Makefile  |   1 +
 drivers/dma-buf/heaps/restricted_heap.c |  11 ++
 drivers/dma-buf/heaps/restricted_heap.h |   2 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 115 
 5 files changed, 136 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/restricted_heap_mtk.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index e54506f480ea..84f748fb2856 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -21,3 +21,10 @@ config DMABUF_HEAPS_RESTRICTED
  heap is to manage buffers that are inaccessible to the kernel and 
user space.
  There may be several ways to restrict it, for example it may be 
encrypted or
  protected by a TEE or hypervisor. If in doubt, say N.
+
+config DMABUF_HEAPS_RESTRICTED_MTK
+   bool "MediaTek DMA-BUF Restricted Heap"
+   depends on DMABUF_HEAPS_RESTRICTED && TEE=y
+   help
+ Enable restricted dma-buf heaps for MediaTek platform. This heap is 
backed by
+ TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index a2437c1817e2..0028aa9d875f 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED)  += restricted_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED_MTK)  += restricted_heap_mtk.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index 4e45d46a6467..8bc8a5e3f969 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -151,11 +151,22 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
struct restricted_heap *rheap = dma_heap_get_drvdata(heap);
+   const struct restricted_heap_ops *ops = rheap->ops;
struct restricted_buffer *restricted_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
 
+   /*
+* In some implements, TEE is required to protect buffer. However TEE 
probe
+* may be late, Thus heap_init is performed when the first buffer is 
requested.
+*/
+   if (ops->heap_init) {
+   ret = ops->heap_init(rheap);
+   if (ret)
+   return ERR_PTR(ret);
+   }
+
restricted_buf = kzalloc(sizeof(*restricted_buf), GFP_KERNEL);
if (!restricted_buf)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 6d9599a4a34e..2a33a1c7a48b 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -19,6 +19,8 @@ struct restricted_heap {
const char  *name;
 
const struct restricted_heap_ops *ops;
+
+   void*priv_data;
 };
 
 struct restricted_heap_ops {
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
new file mode 100644
index ..52e805eb9858
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF restricted heap exporter for MediaTek
+ *
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+#define pr_fmt(fmt) "rheap_mtk: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "restricted_heap.h"
+
+#define TZ_TA_MEM_UUID_MTK "4477588a-8476-11e2-ad15-e41f1390d676"
+
+#define TEE_PARAM_NUM  4
+
+enum mtk_secure_mem_type {
+   /*
+* MediaTek static chunk memory carved out for TrustZone. The memory
+* management is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+};
+
+struct mtk_restricted_heap_data {
+   struct tee_context  *tee_ctx;
+   u32 tee_session;
+
+   const enum mtk_secure_mem_type mem_type;
+
+};
+
+static int mtk_tee_ctx_match(struct tee_ioctl_version_data

[PATCH v5 6/9] dma-buf: heaps: restricted_heap: Add dma_ops

2024-05-15 Thread Yong Wu
Add the dma_ops for this restricted heap. For restricted buffer,
1) cache_ops/mmap are not allowed, thus return EPERM for them.
2) In map_dma_buf, use DMA_ATTR_SKIP_CPU_SYNC to skip cache sync since
   the buffer is protected.
This type buffers are marked by sg_dma_mark_restricted, the user could
check if this is a restricted buffer by sg_dma_is_restricted.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.c | 102 
 drivers/dma-buf/heaps/restricted_heap.h |   2 +
 2 files changed, 104 insertions(+)

diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index 8bb3c1876a69..4e45d46a6467 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -8,10 +8,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "restricted_heap.h"
 
+struct restricted_heap_attachment {
+   struct sg_table *table;
+   struct device   *dev;
+};
+
 static int
 restricted_heap_memory_allocate(struct restricted_heap *rheap, struct 
restricted_buffer *buf)
 {
@@ -45,6 +51,101 @@ restricted_heap_memory_free(struct restricted_heap *rheap, 
struct restricted_buf
ops->free(rheap, buf);
 }
 
+static int restricted_heap_attach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct restricted_buffer *restricted_buf = dmabuf->priv;
+   struct restricted_heap_attachment *a;
+   struct sg_table *table;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = sg_dup_table(_buf->sg_table);
+   if (!table) {
+   kfree(a);
+   return -ENOMEM;
+   }
+
+   sg_dma_mark_restricted(table->sgl);
+   a->table = table;
+   a->dev = attachment->dev;
+   attachment->priv = a;
+
+   return 0;
+}
+
+static void restricted_heap_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *
+restricted_heap_map_dma_buf(struct dma_buf_attachment *attachment,
+   enum dma_data_direction direction)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+   struct sg_table *table = a->table;
+   int ret;
+
+   ret = dma_map_sgtable(attachment->dev, table, direction, 
DMA_ATTR_SKIP_CPU_SYNC);
+   if (ret)
+   return ERR_PTR(ret);
+   return table;
+}
+
+static void
+restricted_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct 
sg_table *table,
+ enum dma_data_direction direction)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+
+   WARN_ON(a->table != table);
+
+   dma_unmap_sgtable(attachment->dev, table, direction, 
DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static int
+restricted_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int
+restricted_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int restricted_heap_dma_buf_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
+{
+   return -EPERM;
+}
+
+static void restricted_heap_free(struct dma_buf *dmabuf)
+{
+   struct restricted_buffer *restricted_buf = dmabuf->priv;
+   struct restricted_heap *rheap = 
dma_heap_get_drvdata(restricted_buf->heap);
+
+   restricted_heap_memory_free(rheap, restricted_buf);
+   kfree(restricted_buf);
+}
+
+static const struct dma_buf_ops restricted_heap_buf_ops = {
+   .attach = restricted_heap_attach,
+   .detach = restricted_heap_detach,
+   .map_dma_buf= restricted_heap_map_dma_buf,
+   .unmap_dma_buf  = restricted_heap_unmap_dma_buf,
+   .begin_cpu_access = restricted_heap_dma_buf_begin_cpu_access,
+   .end_cpu_access = restricted_heap_dma_buf_end_cpu_access,
+   .mmap   = restricted_heap_dma_buf_mmap,
+   .release= restricted_heap_free,
+};
+
 static struct dma_buf *
 restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
@@ -66,6 +167,7 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
if (ret)
goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.ops = _heap_buf_ops;
exp_info.size = restricted_buf->size;
exp_info.flags = fd_flags;
exp_info.priv = restricted_buf;
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 5783275d5714..6d9599a4a34e 100644
--- a/drivers/dma-buf/heaps/restrict

[PATCH v5 5/9] dma-buf: heaps: restricted_heap: Add private heap ops

2024-05-15 Thread Yong Wu
Add "struct restricted_heap_ops". For the restricted memory, totally there
are two steps:
a) alloc: Allocate the buffer in kernel;
b) restrict_buf: Restrict/Protect/Secure that buffer.
The "alloc" is mandatory while "restrict_buf" is optional since it may
be part of "alloc".

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.c | 41 -
 drivers/dma-buf/heaps/restricted_heap.h | 12 
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index c2ae19ba7d7e..8bb3c1876a69 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -12,10 +12,44 @@
 
 #include "restricted_heap.h"
 
+static int
+restricted_heap_memory_allocate(struct restricted_heap *rheap, struct 
restricted_buffer *buf)
+{
+   const struct restricted_heap_ops *ops = rheap->ops;
+   int ret;
+
+   ret = ops->alloc(rheap, buf);
+   if (ret)
+   return ret;
+
+   if (ops->restrict_buf) {
+   ret = ops->restrict_buf(rheap, buf);
+   if (ret)
+   goto buf_free;
+   }
+   return 0;
+
+buf_free:
+   ops->free(rheap, buf);
+   return ret;
+}
+
+static void
+restricted_heap_memory_free(struct restricted_heap *rheap, struct 
restricted_buffer *buf)
+{
+   const struct restricted_heap_ops *ops = rheap->ops;
+
+   if (ops->unrestrict_buf)
+   ops->unrestrict_buf(rheap, buf);
+
+   ops->free(rheap, buf);
+}
+
 static struct dma_buf *
 restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
+   struct restricted_heap *rheap = dma_heap_get_drvdata(heap);
struct restricted_buffer *restricted_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
@@ -28,6 +62,9 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned long 
size,
restricted_buf->size = ALIGN(size, PAGE_SIZE);
restricted_buf->heap = heap;
 
+   ret = restricted_heap_memory_allocate(rheap, restricted_buf);
+   if (ret)
+   goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = restricted_buf->size;
exp_info.flags = fd_flags;
@@ -36,11 +73,13 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
dmabuf = dma_buf_export(_info);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
-   goto err_free_buf;
+   goto err_free_rstrd_mem;
}
 
return dmabuf;
 
+err_free_rstrd_mem:
+   restricted_heap_memory_free(rheap, restricted_buf);
 err_free_buf:
kfree(restricted_buf);
return ERR_PTR(ret);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index b448f77616ac..5783275d5714 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -15,6 +15,18 @@ struct restricted_buffer {
 
 struct restricted_heap {
const char  *name;
+
+   const struct restricted_heap_ops *ops;
+};
+
+struct restricted_heap_ops {
+   int (*heap_init)(struct restricted_heap *rheap);
+
+   int (*alloc)(struct restricted_heap *rheap, struct 
restricted_buffer *buf);
+   void(*free)(struct restricted_heap *rheap, struct restricted_buffer 
*buf);
+
+   int (*restrict_buf)(struct restricted_heap *rheap, struct 
restricted_buffer *buf);
+   void(*unrestrict_buf)(struct restricted_heap *rheap, struct 
restricted_buffer *buf);
 };
 
 int restricted_heap_add(struct restricted_heap *rheap);
-- 
2.25.1



[PATCH v5 4/9] dma-buf: heaps: Initialize a restricted heap

2024-05-15 Thread Yong Wu
Initialize a restricted heap. Currently just add a null heap, Prepare for
the later patches.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |  9 
 drivers/dma-buf/heaps/Makefile  |  3 +-
 drivers/dma-buf/heaps/restricted_heap.c | 67 +
 drivers/dma-buf/heaps/restricted_heap.h | 22 
 4 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.c
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..e54506f480ea 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -12,3 +12,12 @@ config DMABUF_HEAPS_CMA
  Choose this option to enable dma-buf CMA heap. This heap is backed
  by the Contiguous Memory Allocator (CMA). If your system has these
  regions, you should say Y here.
+
+config DMABUF_HEAPS_RESTRICTED
+   bool "DMA-BUF Restricted Heap"
+   depends on DMABUF_HEAPS
+   help
+ Choose this option to enable dma-buf restricted heap. The purpose of 
this
+ heap is to manage buffers that are inaccessible to the kernel and 
user space.
+ There may be several ways to restrict it, for example it may be 
encrypted or
+ protected by a TEE or hypervisor. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..a2437c1817e2 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED)  += restricted_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
new file mode 100644
index ..c2ae19ba7d7e
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF restricted heap exporter
+ *
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "restricted_heap.h"
+
+static struct dma_buf *
+restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
+unsigned long fd_flags, unsigned long heap_flags)
+{
+   struct restricted_buffer *restricted_buf;
+   DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+   struct dma_buf *dmabuf;
+   int ret;
+
+   restricted_buf = kzalloc(sizeof(*restricted_buf), GFP_KERNEL);
+   if (!restricted_buf)
+   return ERR_PTR(-ENOMEM);
+
+   restricted_buf->size = ALIGN(size, PAGE_SIZE);
+   restricted_buf->heap = heap;
+
+   exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.size = restricted_buf->size;
+   exp_info.flags = fd_flags;
+   exp_info.priv = restricted_buf;
+
+   dmabuf = dma_buf_export(_info);
+   if (IS_ERR(dmabuf)) {
+   ret = PTR_ERR(dmabuf);
+   goto err_free_buf;
+   }
+
+   return dmabuf;
+
+err_free_buf:
+   kfree(restricted_buf);
+   return ERR_PTR(ret);
+}
+
+static const struct dma_heap_ops rheap_ops = {
+   .allocate = restricted_heap_allocate,
+};
+
+int restricted_heap_add(struct restricted_heap *rheap)
+{
+   struct dma_heap_export_info exp_info;
+   struct dma_heap *heap;
+
+   exp_info.name = rheap->name;
+   exp_info.ops = _ops;
+   exp_info.priv = (void *)rheap;
+
+   heap = dma_heap_add(_info);
+   if (IS_ERR(heap))
+   return PTR_ERR(heap);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(restricted_heap_add);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
new file mode 100644
index ..b448f77616ac
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Restricted heap Header.
+ *
+ * Copyright (C) 2024 MediaTek, Inc.
+ */
+
+#ifndef _DMABUF_RESTRICTED_HEAP_H_
+#define _DMABUF_RESTRICTED_HEAP_H_
+
+struct restricted_buffer {
+   struct dma_heap *heap;
+   size_t  size;
+};
+
+struct restricted_heap {
+   const char  *name;
+};
+
+int restricted_heap_add(struct restricted_heap *rheap);
+
+#endif
-- 
2.25.1



[PATCH v5 3/9] lib/scatterlist: Add sg_dup_table

2024-05-15 Thread Yong Wu
Prepare for the restricted heap to reuse, move it out from system_heap.c.
To keep the function name consistent, rename it to sg_dup_table.

Cc: Andrew Morton 
Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/system_heap.c | 27 +--
 include/linux/scatterlist.h |  2 ++
 lib/scatterlist.c   | 26 ++
 3 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/drivers/dma-buf/heaps/system_heap.c 
b/drivers/dma-buf/heaps/system_heap.c
index 9076d47ed2ef..204e55f92330 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -54,31 +54,6 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, 
HIGH_ORDER_GFP, LOW_ORDER_GFP};
 static const unsigned int orders[] = {8, 4, 0};
 #define NUM_ORDERS ARRAY_SIZE(orders)
 
-static struct sg_table *dup_sg_table(struct sg_table *table)
-{
-   struct sg_table *new_table;
-   int ret, i;
-   struct scatterlist *sg, *new_sg;
-
-   new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
-   if (!new_table)
-   return ERR_PTR(-ENOMEM);
-
-   ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL);
-   if (ret) {
-   kfree(new_table);
-   return ERR_PTR(-ENOMEM);
-   }
-
-   new_sg = new_table->sgl;
-   for_each_sgtable_sg(table, sg, i) {
-   sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset);
-   new_sg = sg_next(new_sg);
-   }
-
-   return new_table;
-}
-
 static int system_heap_attach(struct dma_buf *dmabuf,
  struct dma_buf_attachment *attachment)
 {
@@ -90,7 +65,7 @@ static int system_heap_attach(struct dma_buf *dmabuf,
if (!a)
return -ENOMEM;
 
-   table = dup_sg_table(>sg_table);
+   table = sg_dup_table(>sg_table);
if (IS_ERR(table)) {
kfree(a);
return -ENOMEM;
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index a6ad9018eca0..53a4cdc11f4f 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -538,6 +538,8 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned 
int nents,
 size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents,
   size_t buflen, off_t skip);
 
+struct sg_table *sg_dup_table(struct sg_table *table);
+
 /*
  * Maximum number of entries that will be allocated in one piece, if
  * a list larger than this is required then chaining will be utilized.
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 7bc2220fea80..3efcf728c13b 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -1100,6 +1100,32 @@ size_t sg_zero_buffer(struct scatterlist *sgl, unsigned 
int nents,
 }
 EXPORT_SYMBOL(sg_zero_buffer);
 
+struct sg_table *sg_dup_table(struct sg_table *table)
+{
+   struct sg_table *new_table;
+   int ret, i;
+   struct scatterlist *sg, *new_sg;
+
+   new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
+   if (!new_table)
+   return ERR_PTR(-ENOMEM);
+
+   ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL);
+   if (ret) {
+   kfree(new_table);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   new_sg = new_table->sgl;
+   for_each_sgtable_sg(table, sg, i) {
+   sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset);
+   new_sg = sg_next(new_sg);
+   }
+
+   return new_table;
+}
+EXPORT_SYMBOL(sg_dup_table);
+
 /*
  * Extract and pin a list of up to sg_max pages from UBUF- or IOVEC-class
  * iterators, and add them to the scatterlist.
-- 
2.25.1



[PATCH v5 2/9] scatterlist: Add a flag for the restricted memory

2024-05-15 Thread Yong Wu
Introduce a FLAG for the restricted memory which means the memory is
protected by TEE or hypervisor, then it's inaccessiable for kernel.

Currently we don't use sg_dma_unmark_restricted, thus this interface
has not been added.

Signed-off-by: Yong Wu 
---
 include/linux/scatterlist.h | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 77df3d7b18a6..a6ad9018eca0 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -282,6 +282,7 @@ static inline void sg_unmark_end(struct scatterlist *sg)
 
 #define SG_DMA_BUS_ADDRESS (1 << 0)
 #define SG_DMA_SWIOTLB (1 << 1)
+#define SG_DMA_RESTRICTED  (2 << 1)
 
 /**
  * sg_dma_is_bus_address - Return whether a given segment was marked
@@ -352,6 +353,31 @@ static inline void sg_dma_mark_swiotlb(struct scatterlist 
*sg)
sg->dma_flags |= SG_DMA_SWIOTLB;
 }
 
+/**
+ * sg_dma_mark_restricted - Mark the scatterlist for restricted buffer.
+ * @sg:SG entry
+ *
+ * Description:
+ *   Marks a a scatterlist for the restricted buffer that may be inaccessiable
+ *   in kernel if it is protected.
+ */
+static inline void sg_dma_mark_restricted(struct scatterlist *sg)
+{
+   sg->dma_flags |= SG_DMA_RESTRICTED;
+}
+
+/**
+ * sg_dma_is_restricted - Return whether the scatterlist was marked as 
restricted
+ *buffer.
+ * @sg:SG entry
+ *
+ * Description:
+ *   Returns true if the scatterlist was marked as restricted buffer.
+ */
+static inline bool sg_dma_is_restricted(struct scatterlist *sg)
+{
+   return sg->dma_flags & SG_DMA_RESTRICTED;
+}
 #else
 
 static inline bool sg_dma_is_bus_address(struct scatterlist *sg)
@@ -372,6 +398,14 @@ static inline void sg_dma_mark_swiotlb(struct scatterlist 
*sg)
 {
 }
 
+static inline bool sg_dma_is_restricted(struct scatterlist *sg)
+{
+   return false;
+}
+
+static inline void sg_dma_mark_restrited(struct scatterlist *sg)
+{
+}
 #endif /* CONFIG_NEED_SG_DMA_FLAGS */
 
 /**
-- 
2.25.1



[PATCH v5 1/9] dt-bindings: reserved-memory: Add mediatek, dynamic-restricted-region

2024-05-15 Thread Yong Wu
Add a binding for describing the dynamic restricted reserved memory range.
The memory range also will be defined in the TEE firmware. It means the TEE
will be configured with the same address/size that is being set in this
DT node. Regarding to the detail TEE command, Please search
MTK_TZCMD_SECMEM_ZALLOC and MTK_TZCMD_SECMEM_FREE.

Signed-off-by: Yong Wu 
---
 .../mediatek,dynamic-restricted-region.yaml   | 43 +++
 1 file changed, 43 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
new file mode 100644
index ..5cbe3a5637fa
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: 
http://devicetree.org/schemas/reserved-memory/mediatek,dynamic-restricted-region.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Dynamic Reserved Region
+
+description:
+  A memory region that can dynamically transition as a whole between
+  secure and non-secure states. This memory will be protected by OP-TEE
+  when allocations are active and unprotected otherwise.
+
+maintainers:
+  - Yong Wu 
+
+allOf:
+  - $ref: reserved-memory.yaml
+
+properties:
+  compatible:
+const: mediatek,dynamic-restricted-region
+
+required:
+  - compatible
+  - reg
+  - reusable
+
+unevaluatedProperties: false
+
+examples:
+  - |
+reserved-memory {
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+reserved-memory@8000 {
+compatible = "mediatek,dynamic-restricted-region";
+reg = <0x8000 0x1800>;
+reusable;
+};
+};
-- 
2.25.1



[PATCH v5 0/9] dma-buf: heaps: Add restricted heap

2024-05-15 Thread Yong Wu
The purpose of this patchset is for MediaTek secure video playback, and
also to enable other potential uses of this in the future. The 'restricted
dma-heap' will be used to allocate dma_buf objects that reference memory
in the secure world that is inaccessible/unmappable by the non-secure
(i.e. kernel/userspace) world.  That memory will be used by the secure/
trusted world to store secure information (i.e. decrypted media content).
The dma_bufs allocated from the kernel will be passed to V4L2 for video
decoding (as input and output). They will also be used by the drm
system for rendering of the content.

This patchset adds two MediaTek restricted heaps and they will be used in
v4l2[1] and drm[2].
1) restricted_mtk_cm: secure chunk memory for MediaTek SVP (Secure Video
   Path). The buffer is reserved for the secure world after bootup and it
   is used for vcodec's ES/working buffer;
2) restricted_mtk_cma: secure CMA memory for MediaTek SVP. This buffer is
   dynamically reserved for the secure world and will be got when we start
   playing secure videos. Once the security video playing is complete, the
   CMA will be released. This heap is used for the vcodec's frame buffer. 

[1] 
https://lore.kernel.org/linux-mediatek/20240412090851.24999-1-yunfei.d...@mediatek.com/
[2] 
https://lore.kernel.org/linux-mediatek/20240403102701.369-1-shawn.s...@mediatek.com/

Change note:
v5: 1) Reconstruct TEE commands to allow the kernel to obtain the PA of the
 TEE buffer to initialize a valid sg table.
2) Previously, PA was hidden from the kernel. Then the kernel checks if
 this is restricted buffer by "if (sg_page(sg) == NULL)".
 In this version, we will add a new explicit interface
 (sg_dma_is_restricted) for users to determine whether this is a
 restricted buffer.
3) some words improve, like using "rheap".
Rebase on v6.9-rc7.

v4: 
https://lore.kernel.org/linux-mediatek/20240112092014.23999-1-yong...@mediatek.com/
1) Rename the heap name from "secure" to "restricted". suggested from
 Simon/Pekka. There are still several "secure" string in MTK file
 since we use ARM platform in which we call this "secure world"/
 "secure command".

v3: 
https://lore.kernel.org/linux-mediatek/20231212024607.3681-1-yong...@mediatek.com/
1) Separate the secure heap to a common file(secure_heap.c) and mtk
 special file (secure_heap_mtk.c),  and put all the tee related code
 into our special file.
2) About dt-binding, Add "mediatek," prefix since this is Mediatek TEE
 firmware definition.
3) Remove the normal CMA heap which is a draft for qcom.
Rebase on v6.7-rc1.

v2: 
https://lore.kernel.org/linux-mediatek/2023111559.8218-1-yong...@mediatek.com/
1) Move John's patches into the vcodec patchset since they use the new
   dma heap interface directly.
   
https://lore.kernel.org/linux-mediatek/20231106120423.23364-1-yunfei.d...@mediatek.com/
2) Reword the dt-binding description.
3) Rename the heap name from mtk_svp to secure_mtk_cm.
   This means the current vcodec/DRM upstream code doesn't match this.
4) Add a normal CMA heap. currently it should be a draft version.
5) Regarding the UUID, I still use hard code, but put it in a private
data which allow the others could set their own UUID. What's more, UUID
is necessary for the session with TEE. If we don't have it, we can't
communicate with the TEE, including the get_uuid interface, which tries
to make uuid more generic, not working. If there is other way to make
UUID more general, please free to tell me.

v1: 
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
Base on v6.6-rc1.

Yong Wu (9):
  dt-bindings: reserved-memory: Add mediatek,dynamic-restricted-region
  scatterlist: Add a flag for the restricted memory
  lib/scatterlist: Add sg_dup_table
  dma-buf: heaps: Initialize a restricted heap
  dma-buf: heaps: restricted_heap: Add private heap ops
  dma-buf: heaps: restricted_heap: Add dma_ops
  dma-buf: heaps: restricted_heap: Add MediaTek restricted heap and
heap_init
  dma-buf: heaps: restricted_heap_mtk: Add TEE memory service call
  dma_buf: heaps: restricted_heap_mtk: Add a new CMA heap

 .../mediatek,dynamic-restricted-region.yaml   |  43 ++
 drivers/dma-buf/heaps/Kconfig |  16 +
 drivers/dma-buf/heaps/Makefile|   4 +-
 drivers/dma-buf/heaps/restricted_heap.c   | 219 +
 drivers/dma-buf/heaps/restricted_heap.h   |  45 ++
 drivers/dma-buf/heaps/restricted_heap_mtk.c   | 423 ++
 drivers/dma-buf/heaps/system_heap.c   |  27 +-
 include/linux/scatterlist.h   |  36 ++
 lib/scatterlist.c |  26 ++
 9 files changed, 812 insertions(+), 27 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/m

[PATCH v4 7/7] dma_buf: heaps: restricted_heap_mtk: Add a new CMA heap

2024-01-12 Thread Yong Wu
Create a new MediaTek CMA heap from the CMA reserved buffer.

In this heap, When the first allocating buffer, use cma_alloc to prepare
whole the CMA range, then send its range to TEE to protect and manage.
For the later allocating, we just adds the cma_used_size.

When SVP done, cma_release will release the buffer, then kernel may
reuse it.

For the "CMA" restricted heap, "struct cma *cma" is a common property,
not just for MediaTek, so put it into "struct restricted_heap" instead of
our private data.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   2 +-
 drivers/dma-buf/heaps/restricted_heap.h |   4 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 120 +++-
 3 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 84f748fb2856..58903bc62ac8 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -24,7 +24,7 @@ config DMABUF_HEAPS_RESTRICTED
 
 config DMABUF_HEAPS_RESTRICTED_MTK
bool "MediaTek DMA-BUF Restricted Heap"
-   depends on DMABUF_HEAPS_RESTRICTED && TEE=y
+   depends on DMABUF_HEAPS_RESTRICTED && DMA_CMA && TEE=y
help
  Enable restricted dma-buf heaps for MediaTek platform. This heap is 
backed by
  TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 6c93f6d257dc..8d17c39b65de 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -21,6 +21,10 @@ struct restricted_heap {
 
const struct restricted_heap_ops *ops;
 
+   struct cma  *cma;
+   unsigned long   cma_paddr;
+   unsigned long   cma_size;
+
void*priv_data;
 };
 
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
index 902add95bb7e..0180d04076e2 100644
--- a/drivers/dma-buf/heaps/restricted_heap_mtk.c
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -4,9 +4,11 @@
  *
  * Copyright (C) 2024 MediaTek Inc.
  */
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +25,13 @@ enum mtk_secure_mem_type {
 * management is inside the TEE.
 */
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+   /*
+* MediaTek dynamic chunk memory carved out from CMA.
+* In normal case, the CMA could be used in kernel; When SVP start, we 
will
+* allocate whole this CMA and pass whole the CMA PA and size into TEE 
to
+* protect it, then the detail memory management also is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_CMA   = 2,
 };
 
 enum mtk_secure_buffer_tee_cmd {
@@ -32,6 +41,8 @@ enum mtk_secure_buffer_tee_cmd {
 * [in]  value[0].a: The buffer size.
 *   value[0].b: alignment.
 * [in]  value[1].a: enum mtk_secure_mem_type.
+* [in]  value[2].a: pa base in cma case.
+*   value[2].b: The buffer size in cma case.
 * [out] value[3].a: The secure handle.
 */
MTK_TZCMD_SECMEM_ZALLOC = 0x1, /* MTK TEE Command ID Base */
@@ -52,6 +63,9 @@ struct mtk_restricted_heap_data {
 
const enum mtk_secure_mem_type mem_type;
 
+   struct page *cma_page;
+   unsigned long   cma_used_size;
+   struct mutexlock; /* lock for cma_used_size */
 };
 
 static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
@@ -125,6 +139,10 @@ static int mtk_tee_restrict_memory(struct restricted_heap 
*heap, struct restrict
params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[1].u.value.a = data->mem_type;
params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   if (heap->cma && data->mem_type == MTK_SECURE_MEMORY_TYPE_CM_CMA) {
+   params[2].u.value.a = heap->cma_paddr;
+   params[2].u.value.b = heap->cma_size;
+   }
params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
ret = mtk_tee_service_call(data->tee_ctx, data->tee_session,
   MTK_TZCMD_SECMEM_ZALLOC, params);
@@ -163,6 +181,48 @@ mtk_restricted_memory_free(struct restricted_heap *heap, 
struct restricted_buffe
 {
 }
 
+static int mtk_restricted_memory_cma_allocate(struct restricted_heap *heap,
+ struct restricted_buffer *buf)
+{
+   struct mtk_restricted_heap_data *data = heap->priv_data;
+   int ret = 0;
+   /*
+* Allocate CMA only when allocating buffer for the first time, and just
+* increase cma_used_size at the other time, Actually the memory
+* allocating is within the TEE.
+*/
+   mutex_lock(>lock);
+   if (!data-&g

[PATCH v4 6/7] dma-buf: heaps: restricted_heap_mtk: Add TEE memory service call

2024-01-12 Thread Yong Wu
Add TEE service call for MediaTek heap. We have a limited number of
hardware entries to protect memory, therefore we cannot protect memory
arbitrarily, and our secure memory management is actually inside OPTEE.

The kernel just tells the TEE what size I want and the TEE will return a
"secure handle"/"secure address". To make the name more general, We call
it "restricted_addr" here. The restricted_addr is a reference to a secure
buffer within TEE. We put it in the sg_dma_address, please see the comment
in code.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.c | 17 
 drivers/dma-buf/heaps/restricted_heap.h |  3 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 93 +
 3 files changed, 113 insertions(+)

diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index 4e9869ab4a85..148dbf5662c2 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -96,8 +96,23 @@ static struct sg_table *
 restricted_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direct)
 {
struct restricted_heap_attachment *a = attachment->priv;
+   struct dma_buf *dmabuf = attachment->dmabuf;
+   struct restricted_buffer *restricted_buf = dmabuf->priv;
struct sg_table *table = a->table;
 
+   /*
+* Technically dma_address refers to the address used by HW, But for 
restricted buffer
+* we don't know its dma_address in kernel, Instead, we may know its 
restricted address
+* which refers to the real buffer in the trusted or secure world. Here 
use this property
+* to save the restricted address, and the user will use it to obtain 
the real address in
+* trusted or secure world.
+*
+* Note: CONFIG_DMA_API_DEBUG requires this to be aligned with 
PAGE_SIZE.
+*/
+   if (restricted_buf->restricted_addr) {
+   sg_dma_address(table->sgl) = restricted_buf->restricted_addr;
+   sg_dma_len(table->sgl) = restricted_buf->size;
+   }
return table;
 }
 
@@ -108,6 +123,8 @@ restricted_heap_unmap_dma_buf(struct dma_buf_attachment 
*attachment, struct sg_t
struct restricted_heap_attachment *a = attachment->priv;
 
WARN_ON(a->table != table);
+   sg_dma_address(table->sgl) = 0;
+   sg_dma_len(table->sgl) = 0;
 }
 
 static int
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index cf5865f829fc..6c93f6d257dc 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -11,6 +11,9 @@
 struct restricted_buffer {
struct dma_heap *heap;
size_t  size;
+
+   /* A reference to a buffer in the trusted or secure world. */
+   u64 restricted_addr;
 };
 
 struct restricted_heap {
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
index a5f5365059cd..902add95bb7e 100644
--- a/drivers/dma-buf/heaps/restricted_heap_mtk.c
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -25,6 +25,27 @@ enum mtk_secure_mem_type {
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
 };
 
+enum mtk_secure_buffer_tee_cmd {
+   /*
+* Allocate the zeroed secure memory from TEE.
+*
+* [in]  value[0].a: The buffer size.
+*   value[0].b: alignment.
+* [in]  value[1].a: enum mtk_secure_mem_type.
+* [out] value[3].a: The secure handle.
+*/
+   MTK_TZCMD_SECMEM_ZALLOC = 0x1, /* MTK TEE Command ID Base */
+
+   /*
+* Free secure memory.
+*
+* [in]  value[0].a: The secure handle of this buffer, It's value[3].a 
of
+*   MTK_TZCMD_SECMEM_ZALLOC.
+* [out] value[1].a: return value, 0 means successful, otherwise fail.
+*/
+   MTK_TZCMD_SECMEM_FREE   = 0x10001,
+};
+
 struct mtk_restricted_heap_data {
struct tee_context  *tee_ctx;
u32 tee_session;
@@ -74,6 +95,74 @@ static int mtk_tee_session_init(struct 
mtk_restricted_heap_data *data)
return ret;
 }
 
+static int mtk_tee_service_call(struct tee_context *tee_ctx, u32 session,
+   unsigned int command, struct tee_param *params)
+{
+   struct tee_ioctl_invoke_arg arg = {0};
+   int ret;
+
+   arg.num_params = TEE_PARAM_NUM;
+   arg.session = session;
+   arg.func = command;
+
+   ret = tee_client_invoke_func(tee_ctx, , params);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: cmd %d ret %d:%x.\n", __func__, command, ret, 
arg.ret);
+   ret = -EOPNOTSUPP;
+   }
+   return ret;
+}
+
+static int mtk_tee_restrict_memory(struct restricted_heap *heap, struct 
restricted_buffer *buf)
+{
+  

[PATCH v4 5/7] dma-buf: heaps: restricted_heap: Add MediaTek restricted heap and heap_init

2024-01-12 Thread Yong Wu
Add a Mediatek restricted heap which uses TEE service call to restrict
buffer. Currently this restricted heap is NULL, Prepare for the later
patch. Mainly there are two changes:
a) Add a heap_init ops since TEE probe late than restricted heap, thus
   initialize the heap when we require the buffer the first time.
b) Add a priv_data for each heap, like the special data used by MTK
   (such as "TEE session") can be placed in priv_data.

Currently our heap depends on CMA which could only be bool, thus
depend on "TEE=y".

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   7 ++
 drivers/dma-buf/heaps/Makefile  |   1 +
 drivers/dma-buf/heaps/restricted_heap.c |  11 ++
 drivers/dma-buf/heaps/restricted_heap.h |   2 +
 drivers/dma-buf/heaps/restricted_heap_mtk.c | 113 
 5 files changed, 134 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/restricted_heap_mtk.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index e54506f480ea..84f748fb2856 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -21,3 +21,10 @@ config DMABUF_HEAPS_RESTRICTED
  heap is to manage buffers that are inaccessible to the kernel and 
user space.
  There may be several ways to restrict it, for example it may be 
encrypted or
  protected by a TEE or hypervisor. If in doubt, say N.
+
+config DMABUF_HEAPS_RESTRICTED_MTK
+   bool "MediaTek DMA-BUF Restricted Heap"
+   depends on DMABUF_HEAPS_RESTRICTED && TEE=y
+   help
+ Enable restricted dma-buf heaps for MediaTek platform. This heap is 
backed by
+ TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index a2437c1817e2..0028aa9d875f 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED)  += restricted_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED_MTK)  += restricted_heap_mtk.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index ec4c63d2112d..4e9869ab4a85 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -152,11 +152,22 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
struct restricted_heap *restricted_heap = dma_heap_get_drvdata(heap);
+   const struct restricted_heap_ops *ops = restricted_heap->ops;
struct restricted_buffer *restricted_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
 
+   /*
+* In some implements, TEE is required to protect buffer. However TEE 
probe
+* may be late, Thus heap_init is performed when the first buffer is 
requested.
+*/
+   if (ops->heap_init) {
+   ret = ops->heap_init(restricted_heap);
+   if (ret)
+   return ERR_PTR(ret);
+   }
+
restricted_buf = kzalloc(sizeof(*restricted_buf), GFP_KERNEL);
if (!restricted_buf)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index ddeaf9805708..cf5865f829fc 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -17,6 +17,8 @@ struct restricted_heap {
const char  *name;
 
const struct restricted_heap_ops *ops;
+
+   void*priv_data;
 };
 
 struct restricted_heap_ops {
diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c 
b/drivers/dma-buf/heaps/restricted_heap_mtk.c
new file mode 100644
index ..a5f5365059cd
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF restricted heap exporter for MediaTek
+ *
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "restricted_heap.h"
+
+#define TZ_TA_MEM_UUID_MTK "4477588a-8476-11e2-ad15-e41f1390d676"
+
+#define TEE_PARAM_NUM  4
+
+enum mtk_secure_mem_type {
+   /*
+* MediaTek static chunk memory carved out for TrustZone. The memory
+* management is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+};
+
+struct mtk_restricted_heap_data {
+   struct tee_context  *tee_ctx;
+   u32 tee_session;
+
+   const enum mtk_secure_mem_type mem_type;
+
+};
+
+static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
+{

[PATCH v4 4/7] dma-buf: heaps: restricted_heap: Add dma_ops

2024-01-12 Thread Yong Wu
Add the dma_ops for this restricted heap. For restricted buffer,
cache_ops/mmap are not allowed, thus return EPERM for them.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.c | 103 
 1 file changed, 103 insertions(+)

diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index 8c266a0f6192..ec4c63d2112d 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -12,6 +12,10 @@
 
 #include "restricted_heap.h"
 
+struct restricted_heap_attachment {
+   struct sg_table *table;
+};
+
 static int
 restricted_heap_memory_allocate(struct restricted_heap *heap, struct 
restricted_buffer *buf)
 {
@@ -45,6 +49,104 @@ restricted_heap_memory_free(struct restricted_heap *heap, 
struct restricted_buff
ops->memory_free(heap, buf);
 }
 
+static int restricted_heap_attach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct restricted_buffer *restricted_buf = dmabuf->priv;
+   struct restricted_heap_attachment *a;
+   struct sg_table *table;
+   int ret;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = kzalloc(sizeof(*table), GFP_KERNEL);
+   if (!table) {
+   ret = -ENOMEM;
+   goto err_free_attach;
+   }
+
+   ret = sg_alloc_table(table, 1, GFP_KERNEL);
+   if (ret)
+   goto err_free_sgt;
+   sg_set_page(table->sgl, NULL, restricted_buf->size, 0);
+
+   a->table = table;
+   attachment->priv = a;
+
+   return 0;
+
+err_free_sgt:
+   kfree(table);
+err_free_attach:
+   kfree(a);
+   return ret;
+}
+
+static void restricted_heap_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *
+restricted_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direct)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+   struct sg_table *table = a->table;
+
+   return table;
+}
+
+static void
+restricted_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct 
sg_table *table,
+ enum dma_data_direction direction)
+{
+   struct restricted_heap_attachment *a = attachment->priv;
+
+   WARN_ON(a->table != table);
+}
+
+static int
+restricted_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int
+restricted_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int restricted_heap_dma_buf_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
+{
+   return -EPERM;
+}
+
+static void restricted_heap_free(struct dma_buf *dmabuf)
+{
+   struct restricted_buffer *restricted_buf = dmabuf->priv;
+   struct restricted_heap *heap = 
dma_heap_get_drvdata(restricted_buf->heap);
+
+   restricted_heap_memory_free(heap, restricted_buf);
+   kfree(restricted_buf);
+}
+
+static const struct dma_buf_ops restricted_heap_buf_ops = {
+   .attach = restricted_heap_attach,
+   .detach = restricted_heap_detach,
+   .map_dma_buf= restricted_heap_map_dma_buf,
+   .unmap_dma_buf  = restricted_heap_unmap_dma_buf,
+   .begin_cpu_access = restricted_heap_dma_buf_begin_cpu_access,
+   .end_cpu_access = restricted_heap_dma_buf_end_cpu_access,
+   .mmap   = restricted_heap_dma_buf_mmap,
+   .release= restricted_heap_free,
+};
+
 static struct dma_buf *
 restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
@@ -66,6 +168,7 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
if (ret)
goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.ops = _heap_buf_ops;
exp_info.size = restricted_buf->size;
exp_info.flags = fd_flags;
exp_info.priv = restricted_buf;
-- 
2.25.1



[PATCH v4 3/7] dma-buf: heaps: restricted_heap: Add private heap ops

2024-01-12 Thread Yong Wu
Add "struct restricted_heap_ops". For the restricted memory, totally there
are two steps:
a) memory_alloc: Allocate the buffer in kernel;
b) memory_restrict: Restrict/Protect/Secure that buffer.
The memory_alloc is mandatory while memory_restrict is optinal since it may
be part of memory_alloc.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/restricted_heap.c | 41 -
 drivers/dma-buf/heaps/restricted_heap.h | 12 
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
index fd7c82abd42e..8c266a0f6192 100644
--- a/drivers/dma-buf/heaps/restricted_heap.c
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -12,10 +12,44 @@
 
 #include "restricted_heap.h"
 
+static int
+restricted_heap_memory_allocate(struct restricted_heap *heap, struct 
restricted_buffer *buf)
+{
+   const struct restricted_heap_ops *ops = heap->ops;
+   int ret;
+
+   ret = ops->memory_alloc(heap, buf);
+   if (ret)
+   return ret;
+
+   if (ops->memory_restrict) {
+   ret = ops->memory_restrict(heap, buf);
+   if (ret)
+   goto memory_free;
+   }
+   return 0;
+
+memory_free:
+   ops->memory_free(heap, buf);
+   return ret;
+}
+
+static void
+restricted_heap_memory_free(struct restricted_heap *heap, struct 
restricted_buffer *buf)
+{
+   const struct restricted_heap_ops *ops = heap->ops;
+
+   if (ops->memory_unrestrict)
+   ops->memory_unrestrict(heap, buf);
+
+   ops->memory_free(heap, buf);
+}
+
 static struct dma_buf *
 restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
+   struct restricted_heap *restricted_heap = dma_heap_get_drvdata(heap);
struct restricted_buffer *restricted_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
@@ -28,6 +62,9 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned long 
size,
restricted_buf->size = ALIGN(size, PAGE_SIZE);
restricted_buf->heap = heap;
 
+   ret = restricted_heap_memory_allocate(restricted_heap, restricted_buf);
+   if (ret)
+   goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = restricted_buf->size;
exp_info.flags = fd_flags;
@@ -36,11 +73,13 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned 
long size,
dmabuf = dma_buf_export(_info);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
-   goto err_free_buf;
+   goto err_free_restricted_mem;
}
 
return dmabuf;
 
+err_free_restricted_mem:
+   restricted_heap_memory_free(restricted_heap, restricted_buf);
 err_free_buf:
kfree(restricted_buf);
return ERR_PTR(ret);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
index 443028f6ba3b..ddeaf9805708 100644
--- a/drivers/dma-buf/heaps/restricted_heap.h
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -15,6 +15,18 @@ struct restricted_buffer {
 
 struct restricted_heap {
const char  *name;
+
+   const struct restricted_heap_ops *ops;
+};
+
+struct restricted_heap_ops {
+   int (*heap_init)(struct restricted_heap *heap);
+
+   int (*memory_alloc)(struct restricted_heap *heap, struct 
restricted_buffer *buf);
+   void(*memory_free)(struct restricted_heap *heap, struct 
restricted_buffer *buf);
+
+   int (*memory_restrict)(struct restricted_heap *heap, struct 
restricted_buffer *buf);
+   void(*memory_unrestrict)(struct restricted_heap *heap, struct 
restricted_buffer *buf);
 };
 
 int restricted_heap_add(struct restricted_heap *rstrd_heap);
-- 
2.25.1



[PATCH v4 2/7] dma-buf: heaps: Initialize a restricted heap

2024-01-12 Thread Yong Wu
Initialize a restricted heap. Currently just add a null heap, Prepare for
the later patches.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |  9 
 drivers/dma-buf/heaps/Makefile  |  3 +-
 drivers/dma-buf/heaps/restricted_heap.c | 67 +
 drivers/dma-buf/heaps/restricted_heap.h | 22 
 4 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.c
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..e54506f480ea 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -12,3 +12,12 @@ config DMABUF_HEAPS_CMA
  Choose this option to enable dma-buf CMA heap. This heap is backed
  by the Contiguous Memory Allocator (CMA). If your system has these
  regions, you should say Y here.
+
+config DMABUF_HEAPS_RESTRICTED
+   bool "DMA-BUF Restricted Heap"
+   depends on DMABUF_HEAPS
+   help
+ Choose this option to enable dma-buf restricted heap. The purpose of 
this
+ heap is to manage buffers that are inaccessible to the kernel and 
user space.
+ There may be several ways to restrict it, for example it may be 
encrypted or
+ protected by a TEE or hypervisor. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..a2437c1817e2 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED)  += restricted_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
diff --git a/drivers/dma-buf/heaps/restricted_heap.c 
b/drivers/dma-buf/heaps/restricted_heap.c
new file mode 100644
index ..fd7c82abd42e
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF restricted heap exporter
+ *
+ * Copyright (C) 2024 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "restricted_heap.h"
+
+static struct dma_buf *
+restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
+unsigned long fd_flags, unsigned long heap_flags)
+{
+   struct restricted_buffer *restricted_buf;
+   DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+   struct dma_buf *dmabuf;
+   int ret;
+
+   restricted_buf = kzalloc(sizeof(*restricted_buf), GFP_KERNEL);
+   if (!restricted_buf)
+   return ERR_PTR(-ENOMEM);
+
+   restricted_buf->size = ALIGN(size, PAGE_SIZE);
+   restricted_buf->heap = heap;
+
+   exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.size = restricted_buf->size;
+   exp_info.flags = fd_flags;
+   exp_info.priv = restricted_buf;
+
+   dmabuf = dma_buf_export(_info);
+   if (IS_ERR(dmabuf)) {
+   ret = PTR_ERR(dmabuf);
+   goto err_free_buf;
+   }
+
+   return dmabuf;
+
+err_free_buf:
+   kfree(restricted_buf);
+   return ERR_PTR(ret);
+}
+
+static const struct dma_heap_ops restricted_heap_ops = {
+   .allocate = restricted_heap_allocate,
+};
+
+int restricted_heap_add(struct restricted_heap *rstrd_heap)
+{
+   struct dma_heap_export_info exp_info;
+   struct dma_heap *heap;
+
+   exp_info.name = rstrd_heap->name;
+   exp_info.ops = _heap_ops;
+   exp_info.priv = (void *)rstrd_heap;
+
+   heap = dma_heap_add(_info);
+   if (IS_ERR(heap))
+   return PTR_ERR(heap);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(restricted_heap_add);
diff --git a/drivers/dma-buf/heaps/restricted_heap.h 
b/drivers/dma-buf/heaps/restricted_heap.h
new file mode 100644
index ..443028f6ba3b
--- /dev/null
+++ b/drivers/dma-buf/heaps/restricted_heap.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Restricted heap Header.
+ *
+ * Copyright (C) 2024 MediaTek, Inc.
+ */
+
+#ifndef _DMABUF_RESTRICTED_HEAP_H_
+#define _DMABUF_RESTRICTED_HEAP_H_
+
+struct restricted_buffer {
+   struct dma_heap *heap;
+   size_t  size;
+};
+
+struct restricted_heap {
+   const char  *name;
+};
+
+int restricted_heap_add(struct restricted_heap *rstrd_heap);
+
+#endif
-- 
2.25.1



[PATCH v4 1/7] dt-bindings: reserved-memory: Add mediatek, dynamic-restricted-region

2024-01-12 Thread Yong Wu
Add a binding for describing the dynamic restricted reserved memory range.
The memory range also will be defined in the TEE firmware. It means the TEE
will be configured with the same address/size that is being set in this
DT node. Regarding to the detail TEE command, Please search
MTK_TZCMD_SECMEM_ZALLOC and MTK_TZCMD_SECMEM_FREE.

Signed-off-by: Yong Wu 
---
 .../mediatek,dynamic-restricted-region.yaml   | 43 +++
 1 file changed, 43 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
new file mode 100644
index ..5cbe3a5637fa
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: 
http://devicetree.org/schemas/reserved-memory/mediatek,dynamic-restricted-region.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Dynamic Reserved Region
+
+description:
+  A memory region that can dynamically transition as a whole between
+  secure and non-secure states. This memory will be protected by OP-TEE
+  when allocations are active and unprotected otherwise.
+
+maintainers:
+  - Yong Wu 
+
+allOf:
+  - $ref: reserved-memory.yaml
+
+properties:
+  compatible:
+const: mediatek,dynamic-restricted-region
+
+required:
+  - compatible
+  - reg
+  - reusable
+
+unevaluatedProperties: false
+
+examples:
+  - |
+reserved-memory {
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+reserved-memory@8000 {
+compatible = "mediatek,dynamic-restricted-region";
+reg = <0x8000 0x1800>;
+reusable;
+};
+};
-- 
2.25.1



[PATCH v4 0/7] dma-buf: heaps: Add restricted heap

2024-01-12 Thread Yong Wu
The purpose of this patchset is for MediaTek secure video playback, and
also to enable other potential uses of this in the future. The 'restricted
dma-heap' will be used to allocate dma_buf objects that reference memory
in the secure world that is inaccessible/unmappable by the non-secure
(i.e. kernel/userspace) world.  That memory will be used by the secure/
trusted world to store secure information (i.e. decrypted media content).
The dma_bufs allocated from the kernel will be passed to V4L2 for video
decoding (as input and output). They will also be used by the drm
system for rendering of the content.

This patchset adds two MediaTek restricted heaps and they will be used in
v4l2[1] and drm[2].
1) restricted_mtk_cm: secure chunk memory for MediaTek SVP (Secure Video
   Path). The buffer is reserved for the secure world after bootup and it
   is used for vcodec's ES/working buffer;
2) restricted_mtk_cma: secure CMA memory for MediaTek SVP. This buffer is
   dynamically reserved for the secure world and will be got when we start
   playing secure videos. Once the security video playing is complete, the
   CMA will be released. This heap is used for the vcodec's frame buffer. 

[1] 
https://lore.kernel.org/linux-mediatek/20231206081538.17056-1-yunfei.d...@mediatek.com/
[2] 
https://lore.kernel.org/all/20231223182932.27683-1-jason-jh@mediatek.com/

Change note:
v4: 1) Rename the heap name from "secure" to "restricted". suggested from
 Simon/Pekka. There are still several "secure" string in MTK file
 since we use ARM platform in which we call this "secure world"/
 "secure command".

v3: 
https://lore.kernel.org/linux-mediatek/20231212024607.3681-1-yong...@mediatek.com/
1) Separate the secure heap to a common file(secure_heap.c) and mtk
 special file (secure_heap_mtk.c),  and put all the tee related code
 into our special file.
2) About dt-binding, Add "mediatek," prefix since this is Mediatek TEE
 firmware definition.
3) Remove the normal CMA heap which is a draft for qcom.
Rebase on v6.7-rc1.

v2: 
https://lore.kernel.org/linux-mediatek/2023111559.8218-1-yong...@mediatek.com/
1) Move John's patches into the vcodec patchset since they use the new
   dma heap interface directly.
   
https://lore.kernel.org/linux-mediatek/20231106120423.23364-1-yunfei.d...@mediatek.com/
2) Reword the dt-binding description.
3) Rename the heap name from mtk_svp to secure_mtk_cm.
   This means the current vcodec/DRM upstream code doesn't match this.
4) Add a normal CMA heap. currently it should be a draft version.
5) Regarding the UUID, I still use hard code, but put it in a private
data which allow the others could set their own UUID. What's more, UUID
is necessary for the session with TEE. If we don't have it, we can't
communicate with the TEE, including the get_uuid interface, which tries
to make uuid more generic, not working. If there is other way to make
UUID more general, please free to tell me.

v1: 
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
Base on v6.6-rc1.

Yong Wu (7):
  dt-bindings: reserved-memory: Add mediatek,dynamic-restricted-region
  dma-buf: heaps: Initialize a restricted heap
  dma-buf: heaps: restricted_heap: Add private heap ops
  dma-buf: heaps: restricted_heap: Add dma_ops
  dma-buf: heaps: restricted_heap: Add MediaTek restricted heap and
heap_init
  dma-buf: heaps: restricted_heap_mtk: Add TEE memory service call
  dma_buf: heaps: restricted_heap_mtk: Add a new CMA heap

 .../mediatek,dynamic-restricted-region.yaml   |  43 +++
 drivers/dma-buf/heaps/Kconfig |  16 +
 drivers/dma-buf/heaps/Makefile|   4 +-
 drivers/dma-buf/heaps/restricted_heap.c   | 237 +
 drivers/dma-buf/heaps/restricted_heap.h   |  43 +++
 drivers/dma-buf/heaps/restricted_heap_mtk.c   | 322 ++
 6 files changed, 664 insertions(+), 1 deletion(-)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-restricted-region.yaml
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.c
 create mode 100644 drivers/dma-buf/heaps/restricted_heap.h
 create mode 100644 drivers/dma-buf/heaps/restricted_heap_mtk.c

-- 
2.18.0




[PATCH v3 7/7] dma_buf: heaps: secure_heap_mtk: Add a new CMA heap

2023-12-11 Thread Yong Wu
Create a new MediaTek CMA heap from the CMA reserved buffer.

In this heap, When the first allocating buffer, use cma_alloc to prepare
whole the CMA range, then send its range to TEE to protect and manage.
For the later allocating, we just adds the cma_used_size.

When SVP done, cma_release will release the buffer, then kernel may
reuse it.

For the "CMA" secure heap, "struct cma *cma" is a common property, not just
for MediaTek, so put it into "struct secure_heap" instead of our private
data.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   2 +-
 drivers/dma-buf/heaps/secure_heap.h |   4 +
 drivers/dma-buf/heaps/secure_heap_mtk.c | 119 +++-
 3 files changed, 122 insertions(+), 3 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 12962189878e..f117d91a0a9d 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -21,7 +21,7 @@ config DMABUF_HEAPS_SECURE
 
 config DMABUF_HEAPS_SECURE_MTK
bool "MediaTek DMA-BUF Secure Heap"
-   depends on DMABUF_HEAPS_SECURE && TEE=y
+   depends on DMABUF_HEAPS_SECURE && DMA_CMA && TEE=y
help
  Enable secure dma-buf heaps for MediaTek platform. This heap is 
backed by
  TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/secure_heap.h 
b/drivers/dma-buf/heaps/secure_heap.h
index 374fd276bdd7..9f80edcd3e1f 100644
--- a/drivers/dma-buf/heaps/secure_heap.h
+++ b/drivers/dma-buf/heaps/secure_heap.h
@@ -20,6 +20,10 @@ struct secure_heap {
 
const struct secure_heap_ops *ops;
 
+   struct cma  *cma;
+   unsigned long   cma_paddr;
+   unsigned long   cma_size;
+
void*priv_data;
 };
 
diff --git a/drivers/dma-buf/heaps/secure_heap_mtk.c 
b/drivers/dma-buf/heaps/secure_heap_mtk.c
index 2c6aaeaf469f..58148120f4ed 100644
--- a/drivers/dma-buf/heaps/secure_heap_mtk.c
+++ b/drivers/dma-buf/heaps/secure_heap_mtk.c
@@ -4,9 +4,11 @@
  *
  * Copyright (C) 2023 MediaTek Inc.
  */
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +25,13 @@ enum mtk_secure_mem_type {
 * management is inside the TEE.
 */
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+   /*
+* MediaTek dynamic chunk memory carved out from CMA.
+* In normal case, the CMA could be used in kernel; When SVP start, we 
will
+* allocate whole this CMA and pass whole the CMA PA and size into TEE 
to
+* protect it, then the detail memory management also is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_CMA   = 2,
 };
 
 enum mtk_secure_buffer_tee_cmd {
@@ -32,6 +41,8 @@ enum mtk_secure_buffer_tee_cmd {
 * [in]  value[0].a: The buffer size.
 *   value[0].b: alignment.
 * [in]  value[1].a: enum mtk_secure_mem_type.
+* [in]  value[2].a: pa base in cma case.
+*   value[2].b: The buffer size in cma case.
 * [out] value[3].a: The secure handle.
 */
MTK_TZCMD_SECMEM_ZALLOC = 0x1, /* MTK TEE Command ID Base */
@@ -52,6 +63,9 @@ struct mtk_secure_heap_data {
 
const enum mtk_secure_mem_type mem_type;
 
+   struct page *cma_page;
+   unsigned long   cma_used_size;
+   struct mutexlock; /* lock for cma_used_size */
 };
 
 static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
@@ -126,6 +140,10 @@ static int mtk_tee_secure_memory(struct secure_heap 
*sec_heap, struct secure_buf
params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[1].u.value.a = data->mem_type;
params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   if (sec_heap->cma && data->mem_type == MTK_SECURE_MEMORY_TYPE_CM_CMA) {
+   params[2].u.value.a = sec_heap->cma_paddr;
+   params[2].u.value.b = sec_heap->cma_size;
+   }
params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
ret = mtk_tee_service_call(data->tee_ctx, data->tee_session,
   MTK_TZCMD_SECMEM_ZALLOC, params);
@@ -162,6 +180,48 @@ static void mtk_secure_memory_free(struct secure_heap 
*sec_heap, struct secure_b
 {
 }
 
+static int mtk_secure_memory_cma_allocate(struct secure_heap *sec_heap,
+ struct secure_buffer *sec_buf)
+{
+   struct mtk_secure_heap_data *data = sec_heap->priv_data;
+   int ret = 0;
+   /*
+* Allocate CMA only when allocating buffer for the first time, and just
+* increase cma_used_size at the other time, Actually the memory
+* allocating is within the TEE.
+*/
+   mutex_lock(>lock);
+   if (!data->cma_used_size) {
+   data->cma_page = cma_alloc(sec_heap->cm

[PATCH v3 6/7] dma-buf: heaps: secure_heap_mtk: Add tee memory service call

2023-12-11 Thread Yong Wu
Add TEE service call for MediaTek heap. We have a limited number of
hardware entries to protect memory, therefore we cannot protect memory
arbitrarily, then our secure memory management is actually inside OPTEE.
The kernel just tells the TEE what size I want and the TEE will return a
"secure address". The secure_address is a reference to a secure buffer
within TEE. We put it in the sg_dma_address, please see the comment in
code.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 16 +
 drivers/dma-buf/heaps/secure_heap.h |  2 +
 drivers/dma-buf/heaps/secure_heap_mtk.c | 92 +
 3 files changed, 110 insertions(+)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index ca4b433fb3f1..e2b8b97ad4dc 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -94,8 +94,22 @@ static struct sg_table *
 secure_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direction)
 {
struct secure_heap_attachment *a = attachment->priv;
+   struct dma_buf *dmabuf = attachment->dmabuf;
+   struct secure_buffer *sec_buf = dmabuf->priv;
struct sg_table *table = a->table;
 
+   /*
+* Technically dma_address refers to the address used by HW, But for 
secure buffer
+* we don't know its dma_address in kernel, Instead, we only know its 
"secure handle".
+* Thus use this property to save the "secure handle", and the user 
will use it to
+* obtain the real address in secure world.
+*
+* Note: CONFIG_DMA_API_DEBUG requires it to be aligned with PAGE_SIZE.
+*/
+   if (sec_buf->secure_address) {
+   sg_dma_address(table->sgl) = sec_buf->secure_address;
+   sg_dma_len(table->sgl) = sec_buf->size;
+   }
return table;
 }
 
@@ -106,6 +120,8 @@ secure_heap_unmap_dma_buf(struct dma_buf_attachment 
*attachment, struct sg_table
struct secure_heap_attachment *a = attachment->priv;
 
WARN_ON(a->table != table);
+   sg_dma_address(table->sgl) = 0;
+   sg_dma_len(table->sgl) = 0;
 }
 
 static int
diff --git a/drivers/dma-buf/heaps/secure_heap.h 
b/drivers/dma-buf/heaps/secure_heap.h
index 1ce9c431d989..374fd276bdd7 100644
--- a/drivers/dma-buf/heaps/secure_heap.h
+++ b/drivers/dma-buf/heaps/secure_heap.h
@@ -11,6 +11,8 @@
 struct secure_buffer {
struct dma_heap *heap;
size_t  size;
+
+   u64 secure_address; /* A reference to the buffer in 
the secure world */
 };
 
 struct secure_heap {
diff --git a/drivers/dma-buf/heaps/secure_heap_mtk.c 
b/drivers/dma-buf/heaps/secure_heap_mtk.c
index c7e609dd7bd3..2c6aaeaf469f 100644
--- a/drivers/dma-buf/heaps/secure_heap_mtk.c
+++ b/drivers/dma-buf/heaps/secure_heap_mtk.c
@@ -25,6 +25,27 @@ enum mtk_secure_mem_type {
MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
 };
 
+enum mtk_secure_buffer_tee_cmd {
+   /*
+* Allocate the zeroed secure memory from TEE.
+*
+* [in]  value[0].a: The buffer size.
+*   value[0].b: alignment.
+* [in]  value[1].a: enum mtk_secure_mem_type.
+* [out] value[3].a: The secure handle.
+*/
+   MTK_TZCMD_SECMEM_ZALLOC = 0x1, /* MTK TEE Command ID Base */
+
+   /*
+* Free secure memory.
+*
+* [in]  value[0].a: The secure handle of this buffer, It's value[3].a 
of
+*   MTK_TZCMD_SECMEM_ZALLOC.
+* [out] value[1].a: return value, 0 means successful, otherwise fail.
+*/
+   MTK_TZCMD_SECMEM_FREE   = 0x10001,
+};
+
 struct mtk_secure_heap_data {
struct tee_context  *tee_ctx;
u32 tee_session;
@@ -74,6 +95,73 @@ static int mtk_tee_session_init(struct mtk_secure_heap_data 
*data)
return ret;
 }
 
+static int
+mtk_tee_service_call(struct tee_context *tee_ctx, u32 session,
+unsigned int command, struct tee_param *params)
+{
+   struct tee_ioctl_invoke_arg arg = {0};
+   int ret;
+
+   arg.num_params = TEE_PARAM_NUM;
+   arg.session = session;
+   arg.func = command;
+
+   ret = tee_client_invoke_func(tee_ctx, , params);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: cmd %d ret %d:%x.\n", __func__, command, ret, 
arg.ret);
+   ret = -EOPNOTSUPP;
+   }
+   return ret;
+}
+
+static int mtk_tee_secure_memory(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf)
+{
+   struct mtk_secure_heap_data *data = sec_heap->priv_data;
+   struct tee_param params[TEE_PARAM_NUM] = {0};
+   int ret;
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = sec_buf->size;
+   params[0].u.value.b = PAGE_SIZE;
+   params[1].attr = TEE_IOCTL_PAR

[PATCH v3 5/7] dma-buf: heaps: secure_heap: Add MediaTek secure heap and heap_init

2023-12-11 Thread Yong Wu
Add a Mediatek secure heap which uses TEE service call to protect
buffer. Currently this secure heap is NULL, Prepare for the later patch.
Mainly there are two changes:
a) Add a heap_init ops since TEE probe late than secure heap, thus
   initialize the heap when we require the buffer the first time.
b) Add a priv_data for each heap, like the special data used by MTK
   (such as "TEE session") can be placed in priv_data.

Currently our heap depends on CMA which could only be bool, thus
depend on "TEE=y".

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   7 ++
 drivers/dma-buf/heaps/Makefile  |   1 +
 drivers/dma-buf/heaps/secure_heap.c |  11 +++
 drivers/dma-buf/heaps/secure_heap.h |   4 +
 drivers/dma-buf/heaps/secure_heap_mtk.c | 114 
 5 files changed, 137 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/secure_heap_mtk.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 3a9943e94200..12962189878e 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -18,3 +18,10 @@ config DMABUF_HEAPS_SECURE
depends on DMABUF_HEAPS
help
  Choose this option to enable dma-buf secure heap. If in doubt, say N.
+
+config DMABUF_HEAPS_SECURE_MTK
+   bool "MediaTek DMA-BUF Secure Heap"
+   depends on DMABUF_HEAPS_SECURE && TEE=y
+   help
+ Enable secure dma-buf heaps for MediaTek platform. This heap is 
backed by
+ TEE client interfaces. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index b1ad9d1f2fbe..9751dea345df 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DMABUF_HEAPS_SECURE)  += secure_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_SECURE_MTK)  += secure_heap_mtk.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 7cb4db3e55c2..ca4b433fb3f1 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -150,11 +150,22 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
struct secure_heap *sec_heap = dma_heap_get_drvdata(heap);
+   const struct secure_heap_ops *ops = sec_heap->ops;
struct secure_buffer *sec_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
 
+   /*
+* In some implements, TEE is required to protect buffer. However TEE 
probe
+* may be late, Thus heap_init is performed when the first buffer is 
requested.
+*/
+   if (ops->heap_init) {
+   ret = ops->heap_init(sec_heap);
+   if (ret)
+   return ERR_PTR(ret);
+   }
+
sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
if (!sec_buf)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/dma-buf/heaps/secure_heap.h 
b/drivers/dma-buf/heaps/secure_heap.h
index ec5349cd28d0..1ce9c431d989 100644
--- a/drivers/dma-buf/heaps/secure_heap.h
+++ b/drivers/dma-buf/heaps/secure_heap.h
@@ -17,9 +17,13 @@ struct secure_heap {
const char  *name;
 
const struct secure_heap_ops *ops;
+
+   void*priv_data;
 };
 
 struct secure_heap_ops {
+   int (*heap_init)(struct secure_heap *sec_heap);
+
int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
 
diff --git a/drivers/dma-buf/heaps/secure_heap_mtk.c 
b/drivers/dma-buf/heaps/secure_heap_mtk.c
new file mode 100644
index ..c7e609dd7bd3
--- /dev/null
+++ b/drivers/dma-buf/heaps/secure_heap_mtk.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF MediaTek secure heap exporter
+ *
+ * Copyright (C) 2023 MediaTek Inc.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "secure_heap.h"
+
+#define TZ_TA_MEM_UUID_MTK "4477588a-8476-11e2-ad15-e41f1390d676"
+
+#define TEE_PARAM_NUM  4
+
+enum mtk_secure_mem_type {
+   /*
+* MediaTek static chunk memory carved out for TrustZone. The memory
+* management is inside the TEE.
+*/
+   MTK_SECURE_MEMORY_TYPE_CM_TZ= 1,
+};
+
+struct mtk_secure_heap_data {
+   struct tee_context  *tee_ctx;
+   u32 tee_session;
+
+   const enum mtk_secure_mem_type mem_type;
+
+};
+
+static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
+{
+   return ver->impl_id == TEE_IMPL_ID_OPTEE;
+}
+
+static int mtk

[PATCH v3 4/7] dma-buf: heaps: secure_heap: Add dma_ops

2023-12-11 Thread Yong Wu
Add the dma_ops for this secure heap. For secure buffer, cache_ops/mmap
are not allowed, thus return EPERM for them.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 103 
 1 file changed, 103 insertions(+)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 925cf8e1c7ce..7cb4db3e55c2 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -12,6 +12,10 @@
 
 #include "secure_heap.h"
 
+struct secure_heap_attachment {
+   struct sg_table *table;
+};
+
 static int secure_heap_memory_allocate(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf)
 {
const struct secure_heap_ops *ops = sec_heap->ops;
@@ -43,6 +47,104 @@ static void secure_heap_memory_free(struct secure_heap 
*sec_heap, struct secure_
ops->memory_free(sec_heap, sec_buf);
 }
 
+static int secure_heap_attach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct secure_buffer *sec_buf = dmabuf->priv;
+   struct secure_heap_attachment *a;
+   struct sg_table *table;
+   int ret;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = kzalloc(sizeof(*table), GFP_KERNEL);
+   if (!table) {
+   ret = -ENOMEM;
+   goto err_free_attach;
+   }
+
+   ret = sg_alloc_table(table, 1, GFP_KERNEL);
+   if (ret)
+   goto err_free_sgt;
+   sg_set_page(table->sgl, NULL, sec_buf->size, 0);
+
+   a->table = table;
+   attachment->priv = a;
+
+   return 0;
+
+err_free_sgt:
+   kfree(table);
+err_free_attach:
+   kfree(a);
+   return ret;
+}
+
+static void secure_heap_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *
+secure_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direction)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+   struct sg_table *table = a->table;
+
+   return table;
+}
+
+static void
+secure_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct 
sg_table *table,
+ enum dma_data_direction direction)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+
+   WARN_ON(a->table != table);
+}
+
+static int
+secure_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int
+secure_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int secure_heap_dma_buf_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
+{
+   return -EPERM;
+}
+
+static void secure_heap_free(struct dma_buf *dmabuf)
+{
+   struct secure_buffer *sec_buf = dmabuf->priv;
+   struct secure_heap *sec_heap = dma_heap_get_drvdata(sec_buf->heap);
+
+   secure_heap_memory_free(sec_heap, sec_buf);
+   kfree(sec_buf);
+}
+
+static const struct dma_buf_ops sec_heap_buf_ops = {
+   .attach = secure_heap_attach,
+   .detach = secure_heap_detach,
+   .map_dma_buf= secure_heap_map_dma_buf,
+   .unmap_dma_buf  = secure_heap_unmap_dma_buf,
+   .begin_cpu_access = secure_heap_dma_buf_begin_cpu_access,
+   .end_cpu_access = secure_heap_dma_buf_end_cpu_access,
+   .mmap   = secure_heap_dma_buf_mmap,
+   .release= secure_heap_free,
+};
+
 static struct dma_buf *
 secure_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
@@ -64,6 +166,7 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
if (ret)
goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.ops = _heap_buf_ops;
exp_info.size = sec_buf->size;
exp_info.flags = fd_flags;
exp_info.priv = sec_buf;
-- 
2.25.1



[PATCH v3 3/7] dma-buf: heaps: secure_heap: Add private heap ops

2023-12-11 Thread Yong Wu
Add "struct secure_heap_ops". For the secure memory, totally there are
two steps:
a) memory_alloc: Allocate the buffer in kernel;
b) secure_the_memory: Secure/Proect that buffer.
The memory_alloc is mandatory while secure_the_memory is optinal since
it may be part of memory_alloc.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 39 -
 drivers/dma-buf/heaps/secure_heap.h | 11 
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index e087da5638aa..925cf8e1c7ce 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -12,10 +12,42 @@
 
 #include "secure_heap.h"
 
+static int secure_heap_memory_allocate(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf)
+{
+   const struct secure_heap_ops *ops = sec_heap->ops;
+   int ret;
+
+   ret = ops->memory_alloc(sec_heap, sec_buf);
+   if (ret)
+   return ret;
+
+   if (ops->secure_the_memory) {
+   ret = ops->secure_the_memory(sec_heap, sec_buf);
+   if (ret)
+   goto sec_memory_free;
+   }
+   return 0;
+
+sec_memory_free:
+   ops->memory_free(sec_heap, sec_buf);
+   return ret;
+}
+
+static void secure_heap_memory_free(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf)
+{
+   const struct secure_heap_ops *ops = sec_heap->ops;
+
+   if (ops->unsecure_the_memory)
+   ops->unsecure_the_memory(sec_heap, sec_buf);
+
+   ops->memory_free(sec_heap, sec_buf);
+}
+
 static struct dma_buf *
 secure_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
+   struct secure_heap *sec_heap = dma_heap_get_drvdata(heap);
struct secure_buffer *sec_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
@@ -28,6 +60,9 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
sec_buf->size = ALIGN(size, PAGE_SIZE);
sec_buf->heap = heap;
 
+   ret = secure_heap_memory_allocate(sec_heap, sec_buf);
+   if (ret)
+   goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = sec_buf->size;
exp_info.flags = fd_flags;
@@ -36,11 +71,13 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
dmabuf = dma_buf_export(_info);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
-   goto err_free_buf;
+   goto err_free_sec_mem;
}
 
return dmabuf;
 
+err_free_sec_mem:
+   secure_heap_memory_free(sec_heap, sec_buf);
 err_free_buf:
kfree(sec_buf);
return ERR_PTR(ret);
diff --git a/drivers/dma-buf/heaps/secure_heap.h 
b/drivers/dma-buf/heaps/secure_heap.h
index 50733dc6d4db..ec5349cd28d0 100644
--- a/drivers/dma-buf/heaps/secure_heap.h
+++ b/drivers/dma-buf/heaps/secure_heap.h
@@ -15,6 +15,17 @@ struct secure_buffer {
 
 struct secure_heap {
const char  *name;
+
+   const struct secure_heap_ops *ops;
+};
+
+struct secure_heap_ops {
+   int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+   void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+
+   /* Protect/unprotect the memory */
+   int (*secure_the_memory)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+   void(*unsecure_the_memory)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
 };
 
 int secure_heap_add(struct secure_heap *sec_heap);
-- 
2.25.1



[PATCH v3 1/7] dt-bindings: reserved-memory: Add mediatek, dynamic-secure-region

2023-12-11 Thread Yong Wu
Add a binding for describing the dynamic secure reserved memory range. The
memory range also will be defined in the TEE firmware. It means the TEE
will be configured with the same address/size that is being set in this
DT node. Regarding to the detail TEE command, Please search
MTK_TZCMD_SECMEM_ZALLOC and MTK_TZCMD_SECMEM_FREE.

Signed-off-by: Yong Wu 
---
 .../mediatek,dynamic-secure-region.yaml   | 43 +++
 1 file changed, 43 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-secure-region.yaml

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-secure-region.yaml
 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-secure-region.yaml
new file mode 100644
index ..4a735aeafc62
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-secure-region.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: 
http://devicetree.org/schemas/reserved-memory/mediatek,dynamic-secure-region.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Dynamic Reserved Region
+
+description:
+  A memory region that can dynamically transition as a whole between
+  secure and non-secure states. This memory will be protected by OP-TEE
+  when allocations are active and unprotected otherwise.
+
+maintainers:
+  - Yong Wu 
+
+allOf:
+  - $ref: reserved-memory.yaml
+
+properties:
+  compatible:
+const: mediatek,dynamic-secure-region
+
+required:
+  - compatible
+  - reg
+  - reusable
+
+unevaluatedProperties: false
+
+examples:
+  - |
+reserved-memory {
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+reserved-memory@8000 {
+compatible = "mediatek,dynamic-secure-region";
+reg = <0x8000 0x1800>;
+reusable;
+};
+};
-- 
2.25.1



[PATCH v3 2/7] dma-buf: heaps: Initialize a secure heap

2023-12-11 Thread Yong Wu
Initialize a secure heap. Currently just add a null heap, Prepare for
the later patches.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |  6 +++
 drivers/dma-buf/heaps/Makefile  |  1 +
 drivers/dma-buf/heaps/secure_heap.c | 67 +
 drivers/dma-buf/heaps/secure_heap.h | 22 ++
 4 files changed, 96 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/secure_heap.c
 create mode 100644 drivers/dma-buf/heaps/secure_heap.h

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..3a9943e94200 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -12,3 +12,9 @@ config DMABUF_HEAPS_CMA
  Choose this option to enable dma-buf CMA heap. This heap is backed
  by the Contiguous Memory Allocator (CMA). If your system has these
  regions, you should say Y here.
+
+config DMABUF_HEAPS_SECURE
+   bool "DMA-BUF Secure Heap"
+   depends on DMABUF_HEAPS
+   help
+ Choose this option to enable dma-buf secure heap. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..b1ad9d1f2fbe 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_SECURE)  += secure_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
new file mode 100644
index ..e087da5638aa
--- /dev/null
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF secure heap exporter
+ *
+ * Copyright (C) 2023 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "secure_heap.h"
+
+static struct dma_buf *
+secure_heap_allocate(struct dma_heap *heap, unsigned long size,
+unsigned long fd_flags, unsigned long heap_flags)
+{
+   struct secure_buffer *sec_buf;
+   DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+   struct dma_buf *dmabuf;
+   int ret;
+
+   sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
+   if (!sec_buf)
+   return ERR_PTR(-ENOMEM);
+
+   sec_buf->size = ALIGN(size, PAGE_SIZE);
+   sec_buf->heap = heap;
+
+   exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.size = sec_buf->size;
+   exp_info.flags = fd_flags;
+   exp_info.priv = sec_buf;
+
+   dmabuf = dma_buf_export(_info);
+   if (IS_ERR(dmabuf)) {
+   ret = PTR_ERR(dmabuf);
+   goto err_free_buf;
+   }
+
+   return dmabuf;
+
+err_free_buf:
+   kfree(sec_buf);
+   return ERR_PTR(ret);
+}
+
+static const struct dma_heap_ops sec_heap_ops = {
+   .allocate = secure_heap_allocate,
+};
+
+int secure_heap_add(struct secure_heap *sec_heap)
+{
+   struct dma_heap_export_info exp_info;
+   struct dma_heap *heap;
+
+   exp_info.name = sec_heap->name;
+   exp_info.ops = _heap_ops;
+   exp_info.priv = (void *)sec_heap;
+
+   heap = dma_heap_add(_info);
+   if (IS_ERR(heap))
+   return PTR_ERR(heap);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(secure_heap_add);
diff --git a/drivers/dma-buf/heaps/secure_heap.h 
b/drivers/dma-buf/heaps/secure_heap.h
new file mode 100644
index ..50733dc6d4db
--- /dev/null
+++ b/drivers/dma-buf/heaps/secure_heap.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Secure heap Header.
+ *
+ * Copyright (C) 2023 MediaTek, Inc.
+ */
+
+#ifndef _DMABUF_SECURE_HEAP_H_
+#define _DMABUF_SECURE_HEAP_H_
+
+struct secure_buffer {
+   struct dma_heap *heap;
+   size_t  size;
+};
+
+struct secure_heap {
+   const char  *name;
+};
+
+int secure_heap_add(struct secure_heap *sec_heap);
+
+#endif
-- 
2.25.1



[PATCH v3 0/7] dma-buf: heaps: Add secure heap

2023-12-11 Thread Yong Wu
This patchset is for secure video playback and enables other potential
uses in the future. The 'secure dma-heap' will be used to allocate dma_buf
objects that reference memory in the secure world that is inaccessible/
unmappable by the non-secure (i.e.kernel/userspace) world.  That memory
will be used by the secure world to store secure information (i.e.
decrypted media content). The dma_bufs allocated from the kernel will be
passed to V4L2 for video decoding (as input and output). They will also be
used by the drm system for rendering of the content.

This patchset adds two secure heaps and they will be used v4l2[1] and drm[2].
1) secure_mtk_cm: secure chunk memory for MediaTek SVP (Secure Video Path).
   The buffer is reserved for the secure world after bootup and it is used
   for vcodec's ES/working buffer;
2) secure_mtk_cma: secure CMA memory for MediaTek SVP. This buffer is
   dynamically reserved for the secure world and will be got when we start
   playing secure videos, Once the security video playing is complete, the
   CMA will be released. This heap is used for the vcodec's frame buffer.

[1] 
https://lore.kernel.org/linux-mediatek/20231206081538.17056-1-yunfei.d...@mediatek.com/
[2] 
https://lore.kernel.org/linux-mediatek/20231023044549.21412-1-jason-jh@mediatek.com/

Change note:
v3: Base on v6.7-rc1.
1) Separate the secure heap into a common file(secure_heap.c) and a mtk 
special file
   (secure_heap_mtk.c), and put all tee related code into our special file.
2) About dt-binding,
   a) Add "mediatek," prefix since this is Mediatek TEE firmware definition.
   b) Mute dt-binding check waring.
3) Remove the normal CMA heap which is a draft for qcom.

v2: 
https://lore.kernel.org/linux-mediatek/2023111559.8218-1-yong...@mediatek.com/
1) Move John's patches into the vcodec patchset since they use the new
   dma heap interface directly.
   
https://lore.kernel.org/linux-mediatek/20231106120423.23364-1-yunfei.d...@mediatek.com/
2) Reword the dt-binding description.
3) Rename the heap name from mtk_svp to secure_mtk_cm.
   This means the current vcodec/DRM upstream code doesn't match this.
4) Add a normal CMA heap. currently it should be a draft version.
5) Regarding the UUID, I still use hard code, but put it in a private
data which allow the others could set their own UUID. What's more, UUID
is necessary for the session with TEE. If we don't have it, we can't
communicate with the TEE, including the get_uuid interface, which tries
to make uuid more generic, not working. If there is other way to make
UUID more general, please free to tell me.

v1: 
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
Base on v6.6-rc1.

Yong Wu (7):
  dt-bindings: reserved-memory: Add mediatek,dynamic-secure-region
  dma-buf: heaps: Initialize a secure heap
  dma-buf: heaps: secure_heap: Add private heap ops
  dma-buf: heaps: secure_heap: Add dma_ops
  dma-buf: heaps: secure_heap: Add MediaTek secure heap and heap_init
  dma-buf: heaps: secure_heap_mtk: Add tee memory service call
  dma_buf: heaps: secure_heap_mtk: Add a new CMA heap

 .../mediatek,dynamic-secure-region.yaml   |  43 +++
 drivers/dma-buf/heaps/Kconfig |  13 +
 drivers/dma-buf/heaps/Makefile|   2 +
 drivers/dma-buf/heaps/secure_heap.c   | 234 +
 drivers/dma-buf/heaps/secure_heap.h   |  43 +++
 drivers/dma-buf/heaps/secure_heap_mtk.c   | 321 ++
 6 files changed, 656 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,dynamic-secure-region.yaml
 create mode 100644 drivers/dma-buf/heaps/secure_heap.c
 create mode 100644 drivers/dma-buf/heaps/secure_heap.h
 create mode 100644 drivers/dma-buf/heaps/secure_heap_mtk.c

-- 
2.18.0




[PATCH v2 8/8] dma-buf: heaps: secure_heap: Add normal CMA heap

2023-11-11 Thread Yong Wu
Add a normal CMA heap which use the standard cma allocate.

Signed-off-by: Yong Wu 
---
Hi Vijay and Jaskaran,

For this heap,
1) It uses sec_heap_buf_ops currently. I guess we cann't use the
cma_heap_buf_ops. since if it is secure buffer, some operations such
as mmap should not be allowed.
2) I didn't add how to protect/secure the buffer.

Please feel free to change to meet your requirements.
Thanks.
---
 drivers/dma-buf/heaps/secure_heap.c | 38 -
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index f8b84fd16288..8989ad5d03e9 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -43,6 +43,8 @@ enum secure_buffer_tee_cmd { /* PARAM NUM always is 4. */
 };
 
 enum secure_memory_type {
+   /* CMA for the secure memory, Use the normal cma ops to alloc/free. */
+   SECURE_MEMORY_TYPE_CMA  = 0,
/*
 * MediaTek static chunk memory carved out for TrustZone. The memory
 * management is inside the TEE.
@@ -65,6 +67,7 @@ struct secure_buffer {
 * a value got from TEE.
 */
u32 sec_handle;
+   struct page *cma_page;
 };
 
 #define TEE_MEM_COMMAND_ID_BASE_MTK0x1
@@ -287,6 +290,33 @@ const struct secure_heap_prv_data mtk_sec_mem_data = {
.unsecure_the_memory= secure_heap_tee_unsecure_memory,
 };
 
+static int cma_secure_memory_allocate(struct secure_heap *sec_heap,
+ struct secure_buffer *sec_buf)
+{
+   if (!sec_heap->cma)
+   return -EINVAL;
+
+   sec_buf->cma_page = cma_alloc(sec_heap->cma, sec_buf->size >> 
PAGE_SHIFT,
+ get_order(PAGE_SIZE), false);
+   if (!sec_buf->cma_page)
+   return -ENOMEM;
+
+   memset(page_address(sec_buf->cma_page), 0, sec_buf->size);
+   return 0;
+}
+
+static void cma_secure_memory_free(struct secure_heap *sec_heap,
+  struct secure_buffer *sec_buf)
+{
+   cma_release(sec_heap->cma, sec_buf->cma_page, sec_buf->size >> 
PAGE_SHIFT);
+}
+
+const struct secure_heap_prv_data cma_sec_mem_data = {
+   .memory_alloc   = cma_secure_memory_allocate,
+   .memory_free= cma_secure_memory_free,
+   /* TODO : secure the buffer. */
+};
+
 static int secure_heap_secure_memory_allocate(struct secure_heap *sec_heap,
  struct secure_buffer *sec_buf)
 {
@@ -496,6 +526,11 @@ static const struct dma_heap_ops sec_heap_ops = {
 };
 
 static struct secure_heap secure_heaps[] = {
+   {
+   .name   = "secure_cma",
+   .mem_type   = SECURE_MEMORY_TYPE_CMA,
+   .data   = _sec_mem_data,
+   },
{
.name   = "secure_mtk_cm",
.mem_type   = SECURE_MEMORY_TYPE_MTK_CM_TZ,
@@ -522,7 +557,8 @@ static int __init secure_cma_init(struct reserved_mem *rmem)
}
 
for (i = 0; i < ARRAY_SIZE(secure_heaps); i++, sec_heap++) {
-   if (sec_heap->mem_type != SECURE_MEMORY_TYPE_MTK_CM_CMA)
+   if (sec_heap->mem_type != SECURE_MEMORY_TYPE_MTK_CM_CMA &&
+   sec_heap->mem_type != SECURE_MEMORY_TYPE_CMA)
continue;
 
sec_heap->cma = sec_cma;
-- 
2.25.1



[PATCH v2 7/8] dma_buf: heaps: secure_heap: Add a new MediaTek CMA heap

2023-11-11 Thread Yong Wu
Create a new MediaTek CMA heap from the CMA reserved buffer.

In this heap, When the first allocating buffer, use cma_alloc to prepare
whole the CMA range, then send its range to TEE to protect and manage.
For the later allocating, we just adds the cma_used_size_mtk.

This CMA flow may be different with the normal CMA heap of next patch.
So I named the variable with _mtk suffix like cma_page_mtk/
cma_used_size_mtk. This is also to distinguish it from the cma_page of
the buffer structure in the next patch.

When SVP done, cma_release will release the buffer, then kernel may
reuse it.

Meanwhile, this patch adds a "heap_init" pointer, while allows some heap
initialization operations. This case also checks if the CMA range is
ready.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 124 +++-
 1 file changed, 122 insertions(+), 2 deletions(-)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 25cc95442c56..f8b84fd16288 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -4,11 +4,12 @@
  *
  * Copyright (C) 2023 MediaTek Inc.
  */
-
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,6 +26,8 @@ enum secure_buffer_tee_cmd { /* PARAM NUM always is 4. */
 * [in]  value[0].a: The buffer size.
 *   value[0].b: alignment.
 * [in]  value[1].a: enum secure_memory_type.
+* [in]  value[2].a: pa base in cma case.
+*   value[2].b: The buffer size in cma case.
 * [out] value[3].a: The secure handle.
 */
TZCMD_SECMEM_ZALLOC = 0,
@@ -45,6 +48,13 @@ enum secure_memory_type {
 * management is inside the TEE.
 */
SECURE_MEMORY_TYPE_MTK_CM_TZ= 1,
+   /*
+* MediaTek dynamic chunk memory carved out from CMA.
+* In normal case, the CMA could be used in kernel; When SVP start, we 
will
+* allocate whole this CMA and pass whole the CMA PA and size into TEE 
to
+* protect it, then the detail memory management also is inside the TEE.
+*/
+   SECURE_MEMORY_TYPE_MTK_CM_CMA   = 2,
 };
 
 struct secure_buffer {
@@ -70,6 +80,7 @@ struct secure_heap_prv_data {
 */
const int   tee_command_id_base;
 
+   int (*heap_init)(struct secure_heap *sec_heap);
int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
 
@@ -86,6 +97,13 @@ struct secure_heap {
u32 tee_session;
 
const struct secure_heap_prv_data *data;
+
+   struct cma  *cma;
+   struct page *cma_page_mtk;
+   unsigned long   cma_paddr;
+   unsigned long   cma_size;
+   unsigned long   cma_used_size_mtk;
+   struct mutexlock; /* lock for cma_used_size_mtk */
 };
 
 struct secure_heap_attachment {
@@ -168,7 +186,10 @@ static int secure_heap_tee_secure_memory(struct 
secure_heap *sec_heap,
params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[1].u.value.a = sec_heap->mem_type;
params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
-
+   if (sec_heap->cma && sec_heap->mem_type == 
SECURE_MEMORY_TYPE_MTK_CM_CMA) {
+   params[2].u.value.a = sec_heap->cma_paddr;
+   params[2].u.value.b = sec_heap->cma_size;
+   }
params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
ret = secure_heap_tee_service_call(sec_heap->tee_ctx, 
sec_heap->tee_session,
   data->tee_command_id_base + 
TZCMD_SECMEM_ZALLOC,
@@ -197,6 +218,66 @@ static void secure_heap_tee_unsecure_memory(struct 
secure_heap *sec_heap,
   sec_heap->name, sec_buf->sec_handle, 
params[1].u.value.a);
 }
 
+static int mtk_secure_memory_cma_allocate(struct secure_heap *sec_heap,
+ struct secure_buffer *sec_buf)
+{
+   /*
+* Allocate CMA only when allocating buffer for the first time, and just
+* increase cma_used_size_mtk at the other time.
+*/
+   mutex_lock(_heap->lock);
+   if (sec_heap->cma_used_size_mtk)
+   goto add_size;
+
+   mutex_unlock(_heap->lock);
+   sec_heap->cma_page_mtk = cma_alloc(sec_heap->cma, sec_heap->cma_size >> 
PAGE_SHIFT,
+  get_order(PAGE_SIZE), false);
+   if (!sec_heap->cma_page_mtk)
+   return -ENOMEM;
+
+   mutex_lock(_heap->lock);
+add_size:
+   sec_heap->cma_used_size_mtk += sec_buf->size;
+   mutex_unlock(_heap->lock);
+
+   return 0;
+}
+
+static void mtk_secure_memory_cma_free(struct secu

[PATCH v2 6/8] dt-bindings: reserved-memory: Add secure CMA reserved memory range

2023-11-11 Thread Yong Wu
Add a binding for describing the secure CMA reserved memory range. The
memory range also will be defined in the TEE firmware. It means the TEE
will be configured with the same address/size that is being set in this
DT node.

Signed-off-by: Yong Wu 
---
 .../reserved-memory/secure_cma_region.yaml| 44 +++
 1 file changed, 44 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/secure_cma_region.yaml

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/secure_cma_region.yaml 
b/Documentation/devicetree/bindings/reserved-memory/secure_cma_region.yaml
new file mode 100644
index ..8ab559595fbe
--- /dev/null
+++ b/Documentation/devicetree/bindings/reserved-memory/secure_cma_region.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reserved-memory/secure_cma_region.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Secure Reserved CMA Region
+
+description:
+  This binding describes a CMA region that can dynamically transition
+between secure and non-secure states that a TEE can allocate memory
+from.
+
+maintainers:
+  - Yong Wu 
+
+allOf:
+  - $ref: reserved-memory.yaml
+
+properties:
+  compatible:
+const: secure_cma_region
+
+required:
+  - compatible
+  - reg
+  - reusable
+
+unevaluatedProperties: false
+
+examples:
+  - |
+
+reserved-memory {
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+reserved-memory@8000 {
+compatible = "secure_cma_region";
+reusable;
+reg = <0x8000 0x1800>;
+};
+};
-- 
2.25.1



[PATCH v2 5/8] dma-buf: heaps: secure_heap: Add dma_ops

2023-11-11 Thread Yong Wu
Add the dma_ops for this secure heap.
a) For secure buffer, cache_ops/mmap are not allowed, thus return
EPERM for them.
b) The secure buffer can't be accessed in kernel, thus it doesn't
have va/dma_address for it. Use the dma_address property to save the
"secure handle".

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 120 
 1 file changed, 120 insertions(+)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 05062c14e7c7..25cc95442c56 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -87,6 +88,10 @@ struct secure_heap {
const struct secure_heap_prv_data *data;
 };
 
+struct secure_heap_attachment {
+   struct sg_table *table;
+};
+
 static int tee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
 {
const struct secure_heap_prv_data *d = data;
@@ -238,6 +243,120 @@ static void secure_heap_secure_memory_free(struct 
secure_heap *sec_heap,
data->memory_free(sec_heap, sec_buf);
 }
 
+static int secure_heap_attach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct secure_buffer *sec_buf = dmabuf->priv;
+   struct secure_heap_attachment *a;
+   struct sg_table *table;
+   int ret;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = kzalloc(sizeof(*table), GFP_KERNEL);
+   if (!table) {
+   ret = -ENOMEM;
+   goto err_free_attach;
+   }
+
+   ret = sg_alloc_table(table, 1, GFP_KERNEL);
+   if (ret)
+   goto err_free_sgt;
+   sg_set_page(table->sgl, 0, sec_buf->size, 0);
+
+   a->table = table;
+   attachment->priv = a;
+
+   return 0;
+
+err_free_sgt:
+   kfree(table);
+err_free_attach:
+   kfree(a);
+   return ret;
+}
+
+static void secure_heap_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *
+secure_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direction)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+   struct dma_buf *dmabuf = attachment->dmabuf;
+   struct secure_buffer *sec_buf = dmabuf->priv;
+   struct sg_table *table = a->table;
+
+   /*
+* Technically dma_address refers to the address used by HW, But for 
secure buffer
+* we don't know its dma_address in kernel, Instead, we only know its 
"secure handle".
+* Thus use this property to save the "secure handle", and the user 
will use it to
+* obtain the real address in secure world.
+*
+* Note: CONFIG_DMA_API_DEBUG requires it to be aligned with PAGE_SIZE.
+*/
+   if (sec_buf->sec_handle) {
+   sg_dma_address(table->sgl) = sec_buf->sec_handle;
+   sg_dma_len(table->sgl) = sec_buf->size;
+   }
+   return table;
+}
+
+static void
+secure_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct 
sg_table *table,
+ enum dma_data_direction direction)
+{
+   struct secure_heap_attachment *a = attachment->priv;
+
+   WARN_ON(a->table != table);
+   sg_dma_address(table->sgl) = 0;
+   sg_dma_len(table->sgl) = 0;
+}
+
+static int
+secure_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int
+secure_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int secure_heap_dma_buf_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
+{
+   return -EPERM;
+}
+
+static void secure_heap_free(struct dma_buf *dmabuf)
+{
+   struct secure_buffer *sec_buf = dmabuf->priv;
+   struct secure_heap *sec_heap = dma_heap_get_drvdata(sec_buf->heap);
+
+   secure_heap_secure_memory_free(sec_heap, sec_buf);
+   kfree(sec_buf);
+}
+
+static const struct dma_buf_ops sec_heap_buf_ops = {
+   .attach = secure_heap_attach,
+   .detach = secure_heap_detach,
+   .map_dma_buf= secure_heap_map_dma_buf,
+   .unmap_dma_buf  = secure_heap_unmap_dma_buf,
+   .begin_cpu_access = secure_heap_dma_buf_begin_cpu_access,
+   .end_cpu_access = secure_heap_dma_buf_end_cpu_access,
+   .mmap   = secure_heap_dma_buf_mmap,
+   .release= secure_heap_free,
+};
+
 static struct dma_buf *
 secure_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigne

[PATCH v2 4/8] dma-buf: heaps: secure_heap: Add tee memory service call

2023-11-11 Thread Yong Wu
Add TEE service call. In the case of MediaTek, secure memory management is
located within the TEE. The kernel just needs to tell TEE what size it
needs and the TEE will return a "security handle" to kernel.

To be consistent with the cma heap later, we put the tee ops into the ops
of secure_the_memory.

It seems that secure_heap_tee_service_call could be a more general
interface, but it could be a new topic.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 97 +
 1 file changed, 97 insertions(+)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 2a037fc54004..05062c14e7c7 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -17,6 +17,27 @@
 
 #define TEE_PARAM_NUM  4
 
+enum secure_buffer_tee_cmd { /* PARAM NUM always is 4. */
+   /*
+* TZCMD_SECMEM_ZALLOC: Allocate the zeroed secure memory from TEE.
+*
+* [in]  value[0].a: The buffer size.
+*   value[0].b: alignment.
+* [in]  value[1].a: enum secure_memory_type.
+* [out] value[3].a: The secure handle.
+*/
+   TZCMD_SECMEM_ZALLOC = 0,
+
+   /*
+* TZCMD_SECMEM_FREE: Free secure memory.
+*
+* [in]  value[0].a: The secure handle of this buffer, It's value[3].a 
of
+*   TZCMD_SECMEM_ZALLOC.
+* [out] value[1].a: return value, 0 means successful, otherwise fail.
+*/
+   TZCMD_SECMEM_FREE = 1,
+};
+
 enum secure_memory_type {
/*
 * MediaTek static chunk memory carved out for TrustZone. The memory
@@ -28,13 +49,25 @@ enum secure_memory_type {
 struct secure_buffer {
struct dma_heap *heap;
size_t  size;
+   /*
+* The secure handle is a reference to a buffer within the TEE, this is
+* a value got from TEE.
+*/
+   u32 sec_handle;
 };
 
+#define TEE_MEM_COMMAND_ID_BASE_MTK0x1
+
 struct secure_heap;
 
 struct secure_heap_prv_data {
const char  *uuid;
const int   tee_impl_id;
+   /*
+* Different TEEs may implement different commands, and this provides 
an opportunity
+* for TEEs to use the same enum secure_buffer_tee_cmd.
+*/
+   const int   tee_command_id_base;
 
int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
@@ -98,10 +131,74 @@ static int secure_heap_tee_session_init(struct secure_heap 
*sec_heap)
return ret;
 }
 
+static int
+secure_heap_tee_service_call(struct tee_context *tee_ctx, u32 session,
+unsigned int command, struct tee_param *params)
+{
+   struct tee_ioctl_invoke_arg arg = {0};
+   int ret;
+
+   arg.num_params = TEE_PARAM_NUM;
+   arg.session = session;
+   arg.func = command;
+
+   ret = tee_client_invoke_func(tee_ctx, , params);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: cmd %d ret %d:%x.\n", __func__, command, ret, 
arg.ret);
+   ret = -EOPNOTSUPP;
+   }
+   return ret;
+}
+
+static int secure_heap_tee_secure_memory(struct secure_heap *sec_heap,
+struct secure_buffer *sec_buf)
+{
+   const struct secure_heap_prv_data *data = sec_heap->data;
+   struct tee_param params[TEE_PARAM_NUM] = {0};
+   int ret;
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = sec_buf->size;
+   params[0].u.value.b = PAGE_SIZE;
+   params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[1].u.value.a = sec_heap->mem_type;
+   params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+
+   params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+   ret = secure_heap_tee_service_call(sec_heap->tee_ctx, 
sec_heap->tee_session,
+  data->tee_command_id_base + 
TZCMD_SECMEM_ZALLOC,
+  params);
+   if (ret)
+   return -ENOMEM;
+
+   sec_buf->sec_handle = params[3].u.value.a;
+   return 0;
+}
+
+static void secure_heap_tee_unsecure_memory(struct secure_heap *sec_heap,
+   struct secure_buffer *sec_buf)
+{
+   struct tee_param params[TEE_PARAM_NUM] = {0};
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = sec_buf->sec_handle;
+   params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+   secure_heap_tee_service_call(sec_heap->tee_ctx, sec_heap->tee_session,
+sec_heap->data->tee_command_id_base + 
TZC

[PATCH v2 3/8] dma-buf: heaps: secure_heap: Initialize tee session

2023-11-11 Thread Yong Wu
The TEE probe later than dma-buf heap, and PROBE_DEDER doesn't work
here since this is not a platform driver, therefore initialize the TEE
context/session while we allocate the first secure buffer.

Add our special UUID and tee type in the private data.

If the uuid is zero, it means that it doesn't enter TEE to protect the
buffer, there may be other ways to protect the buffer.

All the MTK chrome projects use this UUID. The UUID is only used in the
kernelspace while userspace never use it. The userspace could allocate the
secure memory via the existing dma-buf ioctl.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 75 +
 1 file changed, 75 insertions(+)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index 87ac23072e9e..2a037fc54004 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -10,6 +10,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#define TZ_TA_MEM_UUID_MTK "4477588a-8476-11e2-ad15-e41f1390d676"
+
+#define TEE_PARAM_NUM  4
 
 enum secure_memory_type {
/*
@@ -27,6 +33,9 @@ struct secure_buffer {
 struct secure_heap;
 
 struct secure_heap_prv_data {
+   const char  *uuid;
+   const int   tee_impl_id;
+
int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
 
@@ -39,9 +48,62 @@ struct secure_heap {
const char  *name;
const enum secure_memory_type   mem_type;
 
+   struct tee_context  *tee_ctx;
+   u32 tee_session;
+
const struct secure_heap_prv_data *data;
 };
 
+static int tee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+   const struct secure_heap_prv_data *d = data;
+
+   return ver->impl_id == d->tee_impl_id;
+}
+
+static int secure_heap_tee_session_init(struct secure_heap *sec_heap)
+{
+   struct tee_param t_param[TEE_PARAM_NUM] = {0};
+   struct tee_ioctl_open_session_arg arg = {0};
+   const struct secure_heap_prv_data *data = sec_heap->data;
+   uuid_t ta_mem_uuid;
+   int ret;
+
+   sec_heap->tee_ctx = tee_client_open_context(NULL, tee_ctx_match, data, 
NULL);
+   if (IS_ERR(sec_heap->tee_ctx)) {
+   pr_err_once("%s: open context failed, ret=%ld\n", 
sec_heap->name,
+   PTR_ERR(sec_heap->tee_ctx));
+   return -ENODEV;
+   }
+
+   arg.num_params = TEE_PARAM_NUM;
+   arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+   ret = uuid_parse(data->uuid, _mem_uuid);
+   if (ret)
+   goto close_context;
+   memcpy(, _mem_uuid.b, sizeof(ta_mem_uuid));
+
+   ret = tee_client_open_session(sec_heap->tee_ctx, , t_param);
+   if (ret < 0 || arg.ret) {
+   pr_err_once("%s: open session failed, ret=%d:%d\n",
+   sec_heap->name, ret, arg.ret);
+   ret = -EINVAL;
+   goto close_context;
+   }
+   sec_heap->tee_session = arg.session;
+   return 0;
+
+close_context:
+   tee_client_close_context(sec_heap->tee_ctx);
+   return ret;
+}
+
+/* The memory allocating is within the TEE. */
+const struct secure_heap_prv_data mtk_sec_mem_data = {
+   .uuid   = TZ_TA_MEM_UUID_MTK,
+   .tee_impl_id= TEE_IMPL_ID_OPTEE,
+};
+
 static int secure_heap_secure_memory_allocate(struct secure_heap *sec_heap,
  struct secure_buffer *sec_buf)
 {
@@ -84,11 +146,23 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
struct secure_heap *sec_heap = dma_heap_get_drvdata(heap);
+   const struct secure_heap_prv_data *data = sec_heap->data;
struct secure_buffer *sec_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
 
+   /*
+* If uuid is valid, It requires enter TEE to protect buffers. However
+* TEE probe may be late. Initialize the secure session the first time
+* we request the secure buffer.
+*/
+   if (data->uuid && !sec_heap->tee_session) {
+   ret = secure_heap_tee_session_init(sec_heap);
+   if (ret)
+   return ERR_PTR(ret);
+   }
+
sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
if (!sec_buf)
return ERR_PTR(-ENOMEM);
@@ -127,6 +201,7 @@ static struct secure_heap secure_heaps[] = {
{
.name   = "secure_mtk_cm",
.mem_type   = SECURE_MEMORY_TYPE_MTK_CM_TZ,
+   .data   = _sec_mem_data,
},
 };
 
-- 
2.25.1



[PATCH v2 2/8] dma-buf: heaps: secure_heap: Add private heap ops

2023-11-11 Thread Yong Wu
For the secure memory, there are two steps:
a) Allocate buffers in kernel side;
b) Secure that buffer.
Different heaps may have different buffer allocation methods and
different memory protection methods. Here abstract the memory
allocation and securing operations.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/secure_heap.c | 58 -
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
index a634051a0a67..87ac23072e9e 100644
--- a/drivers/dma-buf/heaps/secure_heap.c
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -24,15 +24,66 @@ struct secure_buffer {
size_t  size;
 };
 
+struct secure_heap;
+
+struct secure_heap_prv_data {
+   int (*memory_alloc)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+   void(*memory_free)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+
+   /* Protect/unprotect the memory */
+   int (*secure_the_memory)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+   void(*unsecure_the_memory)(struct secure_heap *sec_heap, struct 
secure_buffer *sec_buf);
+};
+
 struct secure_heap {
const char  *name;
const enum secure_memory_type   mem_type;
+
+   const struct secure_heap_prv_data *data;
 };
 
+static int secure_heap_secure_memory_allocate(struct secure_heap *sec_heap,
+ struct secure_buffer *sec_buf)
+{
+   const struct secure_heap_prv_data *data = sec_heap->data;
+   int ret;
+
+   if (data->memory_alloc) {
+   ret = data->memory_alloc(sec_heap, sec_buf);
+   if (ret)
+   return ret;
+   }
+
+   if (data->secure_the_memory) {
+   ret = data->secure_the_memory(sec_heap, sec_buf);
+   if (ret)
+   goto sec_memory_free;
+   }
+   return 0;
+
+sec_memory_free:
+   if (data->memory_free)
+   data->memory_free(sec_heap, sec_buf);
+   return ret;
+}
+
+static void secure_heap_secure_memory_free(struct secure_heap *sec_heap,
+  struct secure_buffer *sec_buf)
+{
+   const struct secure_heap_prv_data *data = sec_heap->data;
+
+   if (data->unsecure_the_memory)
+   data->unsecure_the_memory(sec_heap, sec_buf);
+
+   if (data->memory_free)
+   data->memory_free(sec_heap, sec_buf);
+}
+
 static struct dma_buf *
 secure_heap_allocate(struct dma_heap *heap, unsigned long size,
 unsigned long fd_flags, unsigned long heap_flags)
 {
+   struct secure_heap *sec_heap = dma_heap_get_drvdata(heap);
struct secure_buffer *sec_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
@@ -45,6 +96,9 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
sec_buf->size = ALIGN(size, PAGE_SIZE);
sec_buf->heap = heap;
 
+   ret = secure_heap_secure_memory_allocate(sec_heap, sec_buf);
+   if (ret)
+   goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = sec_buf->size;
exp_info.flags = fd_flags;
@@ -53,11 +107,13 @@ secure_heap_allocate(struct dma_heap *heap, unsigned long 
size,
dmabuf = dma_buf_export(_info);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
-   goto err_free_buf;
+   goto err_free_sec_mem;
}
 
return dmabuf;
 
+err_free_sec_mem:
+   secure_heap_secure_memory_free(sec_heap, sec_buf);
 err_free_buf:
kfree(sec_buf);
return ERR_PTR(ret);
-- 
2.25.1



[PATCH v2 1/8] dma-buf: heaps: Initialize a secure heap

2023-11-11 Thread Yong Wu
Initialize a secure heap. Currently just add a null heap, Prepare for
the later patches.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |  7 +++
 drivers/dma-buf/heaps/Makefile  |  1 +
 drivers/dma-buf/heaps/secure_heap.c | 98 +
 3 files changed, 106 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/secure_heap.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..e358bf711145 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -12,3 +12,10 @@ config DMABUF_HEAPS_CMA
  Choose this option to enable dma-buf CMA heap. This heap is backed
  by the Contiguous Memory Allocator (CMA). If your system has these
  regions, you should say Y here.
+
+config DMABUF_HEAPS_SECURE
+   bool "DMA-BUF Secure Heap"
+   depends on DMABUF_HEAPS && TEE
+   help
+ Choose this option to enable dma-buf secure heap. This heap is backed 
by
+ TEE client interfaces or CMA. If in doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..b1ad9d1f2fbe 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DMABUF_HEAPS_SECURE)  += secure_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
new file mode 100644
index ..a634051a0a67
--- /dev/null
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF secure heap exporter
+ *
+ * Copyright (C) 2023 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum secure_memory_type {
+   /*
+* MediaTek static chunk memory carved out for TrustZone. The memory
+* management is inside the TEE.
+*/
+   SECURE_MEMORY_TYPE_MTK_CM_TZ= 1,
+};
+
+struct secure_buffer {
+   struct dma_heap *heap;
+   size_t  size;
+};
+
+struct secure_heap {
+   const char  *name;
+   const enum secure_memory_type   mem_type;
+};
+
+static struct dma_buf *
+secure_heap_allocate(struct dma_heap *heap, unsigned long size,
+unsigned long fd_flags, unsigned long heap_flags)
+{
+   struct secure_buffer *sec_buf;
+   DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+   struct dma_buf *dmabuf;
+   int ret;
+
+   sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
+   if (!sec_buf)
+   return ERR_PTR(-ENOMEM);
+
+   sec_buf->size = ALIGN(size, PAGE_SIZE);
+   sec_buf->heap = heap;
+
+   exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.size = sec_buf->size;
+   exp_info.flags = fd_flags;
+   exp_info.priv = sec_buf;
+
+   dmabuf = dma_buf_export(_info);
+   if (IS_ERR(dmabuf)) {
+   ret = PTR_ERR(dmabuf);
+   goto err_free_buf;
+   }
+
+   return dmabuf;
+
+err_free_buf:
+   kfree(sec_buf);
+   return ERR_PTR(ret);
+}
+
+static const struct dma_heap_ops sec_heap_ops = {
+   .allocate = secure_heap_allocate,
+};
+
+static struct secure_heap secure_heaps[] = {
+   {
+   .name   = "secure_mtk_cm",
+   .mem_type   = SECURE_MEMORY_TYPE_MTK_CM_TZ,
+   },
+};
+
+static int secure_heap_init(void)
+{
+   struct secure_heap *sec_heap = secure_heaps;
+   struct dma_heap_export_info exp_info;
+   struct dma_heap *heap;
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(secure_heaps); i++, sec_heap++) {
+   exp_info.name = sec_heap->name;
+   exp_info.ops = _heap_ops;
+   exp_info.priv = (void *)sec_heap;
+
+   heap = dma_heap_add(_info);
+   if (IS_ERR(heap))
+   return PTR_ERR(heap);
+   }
+   return 0;
+}
+
+module_init(secure_heap_init);
+MODULE_DESCRIPTION("Secure Heap Driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1



[PATCH v2 0/8] dma-buf: heaps: Add secure heap

2023-11-11 Thread Yong Wu
This patchset adds three secure heaps:
1) secure_mtk_cm: secure chunk memory for MediaTek SVP (Secure Video Path).
   The buffer is reserved for the secure world after bootup and it is used
   for vcodec's ES/working buffer;
2) secure_mtk_cma: secure CMA memory for MediaTek SVP. This buffer is
   dynamically reserved for the secure world and will be got when we start
   playing secure videos, Once the security video playing is complete, the
   CMA will be released. This heap is used for the vcodec's frame buffer. 
3) secure_cma: Use the kerne CMA ops as the allocation ops. 
   currently it is a draft version for Vijay and Jaskaran.

For the first two MediaTek heaps will be used v4l2[1] and drm[2], thus we
cannot put it in v4l2 or drm, and create a common heap for them. Meanwhile
We have a limited number of hardware entries to protect memory, we cannot
protect memory arbitrarily, thus the secure memory management is actually
inside OPTEE. The kernel just tells the TEE what size I want and the TEE
will return a "secure handle".

[1] 
https://lore.kernel.org/linux-mediatek/20231106120423.23364-1-yunfei.d...@mediatek.com/
[2] 
https://lore.kernel.org/linux-mediatek/20231023044549.21412-1-jason-jh@mediatek.com/

Change note:
v2: 1) Move John's patches into the vcodec patchset since they use the new
   dma heap interface directly.
   
https://lore.kernel.org/linux-mediatek/20231106120423.23364-1-yunfei.d...@mediatek.com/
2) Reword the dt-binding description.
3) Rename the heap name from mtk_svp to secure_mtk_cm.
   This means the current vcodec/DRM upstream code doesn't match this.
4) Add a normal CMA heap. currently it should be a draft version.
5) Regarding the UUID, I still use hard code, but put it in a private
data which allow the others could set their own UUID. What's more, UUID
is necessary for the session with TEE. If we don't have it, we can't
communicate with the TEE, including the get_uuid interface, which tries
to make uuid more generic, not working. If there is other way to make
UUID more general, please free to tell me.

v1: 
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
Base on v6.6-rc1.

Yong Wu (8):
  dma-buf: heaps: Initialize a secure heap
  dma-buf: heaps: secure_heap: Add private heap ops
  dma-buf: heaps: secure_heap: Initialize tee session
  dma-buf: heaps: secure_heap: Add tee memory service call
  dma-buf: heaps: secure_heap: Add dma_ops
  dt-bindings: reserved-memory: Add secure CMA reserved memory range
  dma_buf: heaps: secure_heap: Add a new MediaTek CMA heap
  dma-buf: heaps: secure_heap: Add normal CMA heap

 .../reserved-memory/secure_cma_region.yaml|  44 ++
 drivers/dma-buf/heaps/Kconfig |   7 +
 drivers/dma-buf/heaps/Makefile|   1 +
 drivers/dma-buf/heaps/secure_heap.c   | 602 ++
 4 files changed, 654 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/secure_cma_region.yaml
 create mode 100644 drivers/dma-buf/heaps/secure_heap.c

-- 
2.25.1



[PATCH 9/9] dma_buf: heaps: mtk_sec_heap: Add a new CMA heap

2023-09-10 Thread Yong Wu
Create a new mtk_svp_cma heap from the CMA reserved buffer.

When the first allocating buffer, use cma_alloc to prepare whole the
CMA range, then send its range to TEE to protect and manage.
For the later allocating, we just adds the cma_used_size.

When SVP done, cma_release will release the buffer, then kernel may
reuse it.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |   2 +-
 drivers/dma-buf/heaps/mtk_secure_heap.c | 121 +++-
 2 files changed, 119 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 729c0cf3eb7c..e101f788ecbf 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -15,7 +15,7 @@ config DMABUF_HEAPS_CMA
 
 config DMABUF_HEAPS_MTK_SECURE
bool "DMA-BUF MediaTek Secure Heap"
-   depends on DMABUF_HEAPS && TEE
+   depends on DMABUF_HEAPS && TEE && CMA
help
  Choose this option to enable dma-buf MediaTek secure heap for Secure
  Video Path. This heap is backed by TEE client interfaces. If in
diff --git a/drivers/dma-buf/heaps/mtk_secure_heap.c 
b/drivers/dma-buf/heaps/mtk_secure_heap.c
index daf6cf2121a1..3f568fe6b569 100644
--- a/drivers/dma-buf/heaps/mtk_secure_heap.c
+++ b/drivers/dma-buf/heaps/mtk_secure_heap.c
@@ -4,11 +4,12 @@
  *
  * Copyright (C) 2023 MediaTek Inc.
  */
-
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,9 +26,11 @@
  * MediaTek secure (chunk) memory type
  *
  * @KREE_MEM_SEC_CM_TZ: static chunk memory carved out for trustzone.
+ * @KREE_MEM_SEC_CM_CMA: dynamic chunk memory carved out from CMA.
  */
 enum kree_mem_type {
KREE_MEM_SEC_CM_TZ = 1,
+   KREE_MEM_SEC_CM_CMA,
 };
 
 struct mtk_secure_heap_buffer {
@@ -42,6 +45,13 @@ struct mtk_secure_heap {
const enum kree_mem_type mem_type;
u32  mem_session;
struct tee_context  *tee_ctx;
+
+   struct cma  *cma;
+   struct page *cma_page;
+   unsigned long   cma_paddr;
+   unsigned long   cma_size;
+   unsigned long   cma_used_size;
+   struct mutexlock; /* lock for cma_used_size */
 };
 
 struct mtk_secure_heap_attachment {
@@ -90,6 +100,42 @@ static int mtk_kree_secure_session_init(struct 
mtk_secure_heap *sec_heap)
return ret;
 }
 
+static int mtk_sec_mem_cma_allocate(struct mtk_secure_heap *sec_heap, size_t 
size)
+{
+   /*
+* Allocate CMA only when allocating buffer for the first time, and just
+* increase cma_used_size at the other times.
+*/
+   mutex_lock(_heap->lock);
+   if (sec_heap->cma_used_size)
+   goto add_size;
+
+   mutex_unlock(_heap->lock);
+   sec_heap->cma_page = cma_alloc(sec_heap->cma, sec_heap->cma_size >> 
PAGE_SHIFT,
+  get_order(PAGE_SIZE), false);
+   if (!sec_heap->cma_page)
+   return -ENOMEM;
+
+   mutex_lock(_heap->lock);
+add_size:
+   sec_heap->cma_used_size += size;
+   mutex_unlock(_heap->lock);
+   return sec_heap->cma_used_size;
+}
+
+static void mtk_sec_mem_cma_free(struct mtk_secure_heap *sec_heap, size_t size)
+{
+   bool cma_is_empty;
+
+   mutex_lock(_heap->lock);
+   sec_heap->cma_used_size -= size;
+   cma_is_empty = !sec_heap->cma_used_size;
+   mutex_unlock(_heap->lock);
+
+   if (cma_is_empty)
+   cma_release(sec_heap->cma, sec_heap->cma_page, 
sec_heap->cma_size >> PAGE_SHIFT);
+}
+
 static int
 mtk_sec_mem_tee_service_call(struct tee_context *tee_ctx, u32 session,
 unsigned int command, struct tee_param *params)
@@ -114,23 +160,47 @@ static int mtk_sec_mem_allocate(struct mtk_secure_heap 
*sec_heap,
 {
struct tee_param params[MTK_TEE_PARAM_NUM] = {0};
u32 mem_session = sec_heap->mem_session;
+   bool cma_frst_alloc = false;
int ret;
 
+   if (sec_heap->cma) {
+   ret = mtk_sec_mem_cma_allocate(sec_heap, sec_buf->size);
+   if (ret < 0)
+   return ret;
+   /*
+* When CMA allocates for the first time, pass the CMA range to 
TEE
+* to protect it. It's the first allocating if the 
cma_used_size is equal
+* to this required buffer size.
+*/
+   cma_frst_alloc = (ret == sec_buf->size);
+   }
+
params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[0].u.value.a = SZ_4K;/* alignment */
params[0].u.value.b = sec_heap->mem_type;   /* memory type */
params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
params[1].u.value.a = sec_buf->size;
params[2].attr = 

[PATCH 8/9] dt-bindings: reserved-memory: MediaTek: Add reserved memory for SVP

2023-09-10 Thread Yong Wu
This adds the binding for describing a CMA memory for MediaTek SVP(Secure
Video Path).

Signed-off-by: Yong Wu 
---
 .../mediatek,secure_cma_chunkmem.yaml | 42 +++
 1 file changed, 42 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,secure_cma_chunkmem.yaml

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/mediatek,secure_cma_chunkmem.yaml
 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,secure_cma_chunkmem.yaml
new file mode 100644
index ..cc10e00d35c4
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/reserved-memory/mediatek,secure_cma_chunkmem.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: 
http://devicetree.org/schemas/reserved-memory/mediatek,secure_cma_chunkmem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Secure Video Path Reserved Memory
+
+description:
+  This binding describes the reserved memory for secure video path.
+
+maintainers:
+  - Yong Wu 
+
+allOf:
+  - $ref: reserved-memory.yaml
+
+properties:
+  compatible:
+const: mediatek,secure_cma_chunkmem
+
+required:
+  - compatible
+  - reg
+  - reusable
+
+unevaluatedProperties: false
+
+examples:
+  - |
+
+reserved-memory {
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+reserved-memory@8000 {
+compatible = "mediatek,secure_cma_chunkmem";
+reusable;
+reg = <0x8000 0x1800>;
+};
+};
-- 
2.25.1



[PATCH 7/9] dma-buf: heaps: mtk_sec_heap: Add dma_ops

2023-09-10 Thread Yong Wu
Add the dma_ops for this secure heap.
a) For secure buffer, cache_ops/mmap are not allowed, thus return
EPERM for them.
b) The secure buffer can't be accessed in kernel, thus it doesn't
have va/dma_address for it. Use the dma_address property to save the
"secure handle".

Signed-off-by: Anan Sun 
Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/mtk_secure_heap.c | 116 
 1 file changed, 116 insertions(+)

diff --git a/drivers/dma-buf/heaps/mtk_secure_heap.c 
b/drivers/dma-buf/heaps/mtk_secure_heap.c
index 14c2a16a7164..daf6cf2121a1 100644
--- a/drivers/dma-buf/heaps/mtk_secure_heap.c
+++ b/drivers/dma-buf/heaps/mtk_secure_heap.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,6 +44,10 @@ struct mtk_secure_heap {
struct tee_context  *tee_ctx;
 };
 
+struct mtk_secure_heap_attachment {
+   struct sg_table *table;
+};
+
 static int mtk_optee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
 {
return ver->impl_id == TEE_IMPL_ID_OPTEE;
@@ -142,6 +147,116 @@ static void mtk_sec_mem_release(struct mtk_secure_heap 
*sec_heap,
 TZCMD_MEM_SECURECM_UNREF, params);
 }
 
+static int mtk_sec_heap_attach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct mtk_secure_heap_buffer *sec_buf = dmabuf->priv;
+   struct mtk_secure_heap_attachment *a;
+   struct sg_table *table;
+   int ret = 0;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = kzalloc(sizeof(*table), GFP_KERNEL);
+   if (!table) {
+   ret = -ENOMEM;
+   goto err_free_attach;
+   }
+
+   ret = sg_alloc_table(table, 1, GFP_KERNEL);
+   if (ret)
+   goto err_free_sgt;
+   sg_set_page(table->sgl, 0, sec_buf->size, 0);
+
+   a->table = table;
+   attachment->priv = a;
+
+   return 0;
+
+err_free_sgt:
+   kfree(table);
+err_free_attach:
+   kfree(a);
+   return ret;
+}
+
+static void mtk_sec_heap_detach(struct dma_buf *dmabuf, struct 
dma_buf_attachment *attachment)
+{
+   struct mtk_secure_heap_attachment *a = attachment->priv;
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *
+mtk_sec_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum 
dma_data_direction direction)
+{
+   struct mtk_secure_heap_attachment *a = attachment->priv;
+   struct dma_buf *dmabuf = attachment->dmabuf;
+   struct mtk_secure_heap_buffer *sec_buf = dmabuf->priv;
+   struct sg_table *table = a->table;
+
+   /*
+* Technically dma_address refers to the address used by HW, But for 
secure buffer
+* we don't know its dma_address in kernel, Instead, we only know its 
"secure handle".
+* Thus use this property to save the "secure handle", and the user 
will use it to
+* obtain the real address in secure world.
+*/
+   sg_dma_address(table->sgl) = sec_buf->sec_handle;
+   sg_dma_len(table->sgl) = sec_buf->size;
+
+   return table;
+}
+
+static void
+mtk_sec_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct 
sg_table *table,
+  enum dma_data_direction direction)
+{
+   struct mtk_secure_heap_attachment *a = attachment->priv;
+
+   WARN_ON(a->table != table);
+   sg_dma_address(table->sgl) = 0;
+}
+
+static int
+mtk_sec_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int
+mtk_sec_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum 
dma_data_direction direction)
+{
+   return -EPERM;
+}
+
+static int mtk_sec_heap_dma_buf_mmap(struct dma_buf *dmabuf, struct 
vm_area_struct *vma)
+{
+   return -EPERM;
+}
+
+static void mtk_sec_heap_free(struct dma_buf *dmabuf)
+{
+   struct mtk_secure_heap_buffer *sec_buf = dmabuf->priv;
+   struct mtk_secure_heap *sec_heap = dma_heap_get_drvdata(sec_buf->heap);
+
+   mtk_sec_mem_release(sec_heap, sec_buf);
+   kfree(sec_buf);
+}
+
+static const struct dma_buf_ops mtk_sec_heap_buf_ops = {
+   .attach = mtk_sec_heap_attach,
+   .detach = mtk_sec_heap_detach,
+   .map_dma_buf= mtk_sec_heap_map_dma_buf,
+   .unmap_dma_buf  = mtk_sec_heap_unmap_dma_buf,
+   .begin_cpu_access = mtk_sec_heap_dma_buf_begin_cpu_access,
+   .end_cpu_access = mtk_sec_heap_dma_buf_end_cpu_access,
+   .mmap   = mtk_sec_heap_dma_buf_mmap,
+   .release= mtk_sec_heap_free,
+};
+
 static struct dma_buf *
 mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
  unsigned long fd_flags, unsigned long heap_flags)
@@ -173,6 +288,7 @@ mtk_sec_heap_allocate(struct dma_heap *

[PATCH 6/9] dma-buf: heaps: mtk_sec_heap: Add tee service call for buffer allocating/freeing

2023-09-10 Thread Yong Wu
Add TEE service call for secure memory allocating/freeing.

Signed-off-by: Anan Sun 
Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/mtk_secure_heap.c | 69 -
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/drivers/dma-buf/heaps/mtk_secure_heap.c 
b/drivers/dma-buf/heaps/mtk_secure_heap.c
index e3da33a3d083..14c2a16a7164 100644
--- a/drivers/dma-buf/heaps/mtk_secure_heap.c
+++ b/drivers/dma-buf/heaps/mtk_secure_heap.c
@@ -17,6 +17,9 @@
 
 #define MTK_TEE_PARAM_NUM  4
 
+#define TZCMD_MEM_SECURECM_UNREF   7
+#define TZCMD_MEM_SECURECM_ZALLOC  15
+
 /*
  * MediaTek secure (chunk) memory type
  *
@@ -29,6 +32,8 @@ enum kree_mem_type {
 struct mtk_secure_heap_buffer {
struct dma_heap *heap;
size_t  size;
+
+   u32 sec_handle;
 };
 
 struct mtk_secure_heap {
@@ -80,6 +85,63 @@ static int mtk_kree_secure_session_init(struct 
mtk_secure_heap *sec_heap)
return ret;
 }
 
+static int
+mtk_sec_mem_tee_service_call(struct tee_context *tee_ctx, u32 session,
+unsigned int command, struct tee_param *params)
+{
+   struct tee_ioctl_invoke_arg arg = {0};
+   int ret;
+
+   arg.num_params = MTK_TEE_PARAM_NUM;
+   arg.session = session;
+   arg.func = command;
+
+   ret = tee_client_invoke_func(tee_ctx, , params);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: cmd %d ret %d:%x.\n", __func__, command, ret, 
arg.ret);
+   ret = -EOPNOTSUPP;
+   }
+   return ret;
+}
+
+static int mtk_sec_mem_allocate(struct mtk_secure_heap *sec_heap,
+   struct mtk_secure_heap_buffer *sec_buf)
+{
+   struct tee_param params[MTK_TEE_PARAM_NUM] = {0};
+   u32 mem_session = sec_heap->mem_session;
+   int ret;
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = SZ_4K;/* alignment */
+   params[0].u.value.b = sec_heap->mem_type;   /* memory type */
+   params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[1].u.value.a = sec_buf->size;
+   params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+
+   /* Always request zeroed buffer */
+   ret = mtk_sec_mem_tee_service_call(sec_heap->tee_ctx, mem_session,
+  TZCMD_MEM_SECURECM_ZALLOC, params);
+   if (ret)
+   return -ENOMEM;
+
+   sec_buf->sec_handle = params[2].u.value.a;
+   return 0;
+}
+
+static void mtk_sec_mem_release(struct mtk_secure_heap *sec_heap,
+   struct mtk_secure_heap_buffer *sec_buf)
+{
+   struct tee_param params[MTK_TEE_PARAM_NUM] = {0};
+   u32 mem_session = sec_heap->mem_session;
+
+   params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+   params[0].u.value.a = sec_buf->sec_handle;
+   params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+   mtk_sec_mem_tee_service_call(sec_heap->tee_ctx, mem_session,
+TZCMD_MEM_SECURECM_UNREF, params);
+}
+
 static struct dma_buf *
 mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
  unsigned long fd_flags, unsigned long heap_flags)
@@ -107,6 +169,9 @@ mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
sec_buf->size = size;
sec_buf->heap = heap;
 
+   ret = mtk_sec_mem_allocate(sec_heap, sec_buf);
+   if (ret)
+   goto err_free_buf;
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = sec_buf->size;
exp_info.flags = fd_flags;
@@ -115,11 +180,13 @@ mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
dmabuf = dma_buf_export(_info);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
-   goto err_free_buf;
+   goto err_free_sec_mem;
}
 
return dmabuf;
 
+err_free_sec_mem:
+   mtk_sec_mem_release(sec_heap, sec_buf);
 err_free_buf:
kfree(sec_buf);
return ERR_PTR(ret);
-- 
2.25.1



[PATCH 5/9] dma-buf: heaps: mtk_sec_heap: Initialise tee session

2023-09-10 Thread Yong Wu
The TEE probe later than dma-buf heap, and PROBE_DEDER doesn't work
here since this is not a platform driver, therefore initialise the TEE
context/session while we allocate the first secure buffer.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/mtk_secure_heap.c | 61 +
 1 file changed, 61 insertions(+)

diff --git a/drivers/dma-buf/heaps/mtk_secure_heap.c 
b/drivers/dma-buf/heaps/mtk_secure_heap.c
index bbf1c8dce23e..e3da33a3d083 100644
--- a/drivers/dma-buf/heaps/mtk_secure_heap.c
+++ b/drivers/dma-buf/heaps/mtk_secure_heap.c
@@ -10,6 +10,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#define TZ_TA_MEM_UUID "4477588a-8476-11e2-ad15-e41f1390d676"
+
+#define MTK_TEE_PARAM_NUM  4
 
 /*
  * MediaTek secure (chunk) memory type
@@ -28,17 +34,72 @@ struct mtk_secure_heap_buffer {
 struct mtk_secure_heap {
const char  *name;
const enum kree_mem_type mem_type;
+   u32  mem_session;
+   struct tee_context  *tee_ctx;
 };
 
+static int mtk_optee_ctx_match(struct tee_ioctl_version_data *ver, const void 
*data)
+{
+   return ver->impl_id == TEE_IMPL_ID_OPTEE;
+}
+
+static int mtk_kree_secure_session_init(struct mtk_secure_heap *sec_heap)
+{
+   struct tee_param t_param[MTK_TEE_PARAM_NUM] = {0};
+   struct tee_ioctl_open_session_arg arg = {0};
+   uuid_t ta_mem_uuid;
+   int ret;
+
+   sec_heap->tee_ctx = tee_client_open_context(NULL, mtk_optee_ctx_match,
+   NULL, NULL);
+   if (IS_ERR(sec_heap->tee_ctx)) {
+   pr_err("%s: open context failed, ret=%ld\n", sec_heap->name,
+  PTR_ERR(sec_heap->tee_ctx));
+   return -ENODEV;
+   }
+
+   arg.num_params = MTK_TEE_PARAM_NUM;
+   arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+   ret = uuid_parse(TZ_TA_MEM_UUID, _mem_uuid);
+   if (ret)
+   goto close_context;
+   memcpy(, _mem_uuid.b, sizeof(ta_mem_uuid));
+
+   ret = tee_client_open_session(sec_heap->tee_ctx, , t_param);
+   if (ret < 0 || arg.ret) {
+   pr_err("%s: open session failed, ret=%d:%d\n",
+  sec_heap->name, ret, arg.ret);
+   ret = -EINVAL;
+   goto close_context;
+   }
+   sec_heap->mem_session = arg.session;
+   return 0;
+
+close_context:
+   tee_client_close_context(sec_heap->tee_ctx);
+   return ret;
+}
+
 static struct dma_buf *
 mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
  unsigned long fd_flags, unsigned long heap_flags)
 {
+   struct mtk_secure_heap *sec_heap = dma_heap_get_drvdata(heap);
struct mtk_secure_heap_buffer *sec_buf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
 
+   /*
+* TEE probe may be late. Initialise the secure session in the first
+* allocating secure buffer.
+*/
+   if (!sec_heap->mem_session) {
+   ret = mtk_kree_secure_session_init(sec_heap);
+   if (ret)
+   return ERR_PTR(ret);
+   }
+
sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
if (!sec_buf)
return ERR_PTR(-ENOMEM);
-- 
2.25.1



[PATCH 4/9] dma-buf: heaps: Initialise MediaTek secure heap

2023-09-10 Thread Yong Wu
Initialise a mtk_svp heap. Currently just add a null heap, Prepare for
the later patches.

Signed-off-by: Yong Wu 
---
 drivers/dma-buf/heaps/Kconfig   |  8 ++
 drivers/dma-buf/heaps/Makefile  |  1 +
 drivers/dma-buf/heaps/mtk_secure_heap.c | 99 +
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/mtk_secure_heap.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index a5eef06c4226..729c0cf3eb7c 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -12,3 +12,11 @@ config DMABUF_HEAPS_CMA
  Choose this option to enable dma-buf CMA heap. This heap is backed
  by the Contiguous Memory Allocator (CMA). If your system has these
  regions, you should say Y here.
+
+config DMABUF_HEAPS_MTK_SECURE
+   bool "DMA-BUF MediaTek Secure Heap"
+   depends on DMABUF_HEAPS && TEE
+   help
+ Choose this option to enable dma-buf MediaTek secure heap for Secure
+ Video Path. This heap is backed by TEE client interfaces. If in
+ doubt, say N.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 974467791032..df559dbe33fe 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_MTK_SECURE)  += mtk_secure_heap.o
diff --git a/drivers/dma-buf/heaps/mtk_secure_heap.c 
b/drivers/dma-buf/heaps/mtk_secure_heap.c
new file mode 100644
index ..bbf1c8dce23e
--- /dev/null
+++ b/drivers/dma-buf/heaps/mtk_secure_heap.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF mtk_secure_heap exporter
+ *
+ * Copyright (C) 2023 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * MediaTek secure (chunk) memory type
+ *
+ * @KREE_MEM_SEC_CM_TZ: static chunk memory carved out for trustzone.
+ */
+enum kree_mem_type {
+   KREE_MEM_SEC_CM_TZ = 1,
+};
+
+struct mtk_secure_heap_buffer {
+   struct dma_heap *heap;
+   size_t  size;
+};
+
+struct mtk_secure_heap {
+   const char  *name;
+   const enum kree_mem_type mem_type;
+};
+
+static struct dma_buf *
+mtk_sec_heap_allocate(struct dma_heap *heap, size_t size,
+ unsigned long fd_flags, unsigned long heap_flags)
+{
+   struct mtk_secure_heap_buffer *sec_buf;
+   DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+   struct dma_buf *dmabuf;
+   int ret;
+
+   sec_buf = kzalloc(sizeof(*sec_buf), GFP_KERNEL);
+   if (!sec_buf)
+   return ERR_PTR(-ENOMEM);
+
+   sec_buf->size = size;
+   sec_buf->heap = heap;
+
+   exp_info.exp_name = dma_heap_get_name(heap);
+   exp_info.size = sec_buf->size;
+   exp_info.flags = fd_flags;
+   exp_info.priv = sec_buf;
+
+   dmabuf = dma_buf_export(_info);
+   if (IS_ERR(dmabuf)) {
+   ret = PTR_ERR(dmabuf);
+   goto err_free_buf;
+   }
+
+   return dmabuf;
+
+err_free_buf:
+   kfree(sec_buf);
+   return ERR_PTR(ret);
+}
+
+static const struct dma_heap_ops mtk_sec_heap_ops = {
+   .allocate   = mtk_sec_heap_allocate,
+};
+
+static struct mtk_secure_heap mtk_sec_heap[] = {
+   {
+   .name   = "mtk_svp",
+   .mem_type   = KREE_MEM_SEC_CM_TZ,
+   },
+};
+
+static int mtk_sec_heap_init(void)
+{
+   struct mtk_secure_heap *sec_heap = mtk_sec_heap;
+   struct dma_heap_export_info exp_info;
+   struct dma_heap *heap;
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(mtk_sec_heap); i++, sec_heap++) {
+   exp_info.name = sec_heap->name;
+   exp_info.ops = _sec_heap_ops;
+   exp_info.priv = (void *)sec_heap;
+
+   heap = dma_heap_add(_info);
+   if (IS_ERR(heap))
+   return PTR_ERR(heap);
+   }
+   return 0;
+}
+
+module_init(mtk_sec_heap_init);
+MODULE_DESCRIPTION("MediaTek Secure Heap Driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1



[PATCH 3/9] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

2023-09-10 Thread Yong Wu
From: John Stultz 

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Fix the checkpatch alignment warning]
---
 drivers/dma-buf/dma-heap.c | 60 --
 include/linux/dma-heap.h   | 25 
 2 files changed, 69 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index dcc0e38c61fa..908bb30dc864 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -53,12 +53,15 @@ static dev_t dma_heap_devt;
 static struct class *dma_heap_class;
 static DEFINE_XARRAY_ALLOC(dma_heap_minors);
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-unsigned int fd_flags,
-unsigned int heap_flags)
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags)
 {
-   struct dma_buf *dmabuf;
-   int fd;
+   if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+   return ERR_PTR(-EINVAL);
+
+   if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+   return ERR_PTR(-EINVAL);
 
/*
 * Allocations from all heaps have to begin
@@ -66,9 +69,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 */
len = PAGE_ALIGN(len);
if (!len)
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
 
-   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_GPL(dma_heap_buffer_alloc);
+
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+  unsigned int fd_flags,
+  unsigned int heap_flags)
+{
+   struct dma_buf *dmabuf;
+   int fd;
+
+   dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
 
@@ -106,15 +120,9 @@ static long dma_heap_ioctl_allocate(struct file *file, 
void *data)
if (heap_allocation->fd)
return -EINVAL;
 
-   if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-   return -EINVAL;
-
-   if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-   return -EINVAL;
-
-   fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-  heap_allocation->fd_flags,
-  heap_allocation->heap_flags);
+   fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+heap_allocation->fd_flags,
+heap_allocation->heap_flags);
if (fd < 0)
return fd;
 
@@ -205,6 +213,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_name);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
@@ -290,6 +299,24 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
 }
+EXPORT_SYMBOL_GPL(dma_heap_add);
+
+struct dma_heap *dma_heap_find(const char *name)
+{
+   struct dma_heap *h;
+
+   mutex_lock(_list_lock);
+   list_for_each_entry(h, _list, list) {
+   if (!strcmp(h->name, name)) {
+   kref_get(>refcount);
+   mutex_unlock(_list_lock);
+   return h;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(dma_heap_find);
 
 static void dma_heap_release(struct kref *ref)
 {
@@ -315,6 +342,7 @@ void dma_heap_put(struct dma_heap *h)
kref_put(>refcount, dma_heap_release);
mutex_unlock(_list_lock);
 }
+EXPORT_SYMBOL_GPL(dma_heap_put);
 
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index f3c678892c5c..59e70f6c7a60 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -64,10 +64,35 @@ const char *dma_heap_get_name(struct dma_heap *heap);
  */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ *

[PATCH 2/9] dma-heap: Add proper kref handling on dma-buf heaps

2023-09-10 Thread Yong Wu
From: John Stultz 

Add proper refcounting on the dma_heap structure.
While existing heaps are built-in, we may eventually
have heaps loaded from modules, and we'll need to be
able to properly handle the references to the heaps

Also moves minor tracking into the heap structure so
we can properly free things.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add comment for "minor" and "refcount"]
---
 drivers/dma-buf/dma-heap.c | 38 ++
 include/linux/dma-heap.h   |  6 ++
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 51030f6c9d6e..dcc0e38c61fa 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,8 @@
  * @heap_devt: heap device node
  * @list:  list head connecting to list of heaps
  * @heap_cdev: heap char device
+ * @minor: heap device node minor number
+ * @refcount:  reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +43,8 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   int minor;
+   struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -205,7 +210,6 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
struct device *dev_ret;
-   unsigned int minor;
int ret;
 
if (!exp_info->name || !strcmp(exp_info->name, "")) {
@@ -222,12 +226,13 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
if (!heap)
return ERR_PTR(-ENOMEM);
 
+   kref_init(>refcount);
heap->name = exp_info->name;
heap->ops = exp_info->ops;
heap->priv = exp_info->priv;
 
/* Find unused minor number */
-   ret = xa_alloc(_heap_minors, , heap,
+   ret = xa_alloc(_heap_minors, >minor, heap,
   XA_LIMIT(0, NUM_HEAP_MINORS - 1), GFP_KERNEL);
if (ret < 0) {
pr_err("dma_heap: Unable to get minor number for heap\n");
@@ -236,7 +241,7 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
}
 
/* Create device */
-   heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), minor);
+   heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor);
 
cdev_init(>heap_cdev, _heap_fops);
ret = cdev_add(>heap_cdev, heap->heap_devt, 1);
@@ -280,12 +285,37 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
 err2:
cdev_del(>heap_cdev);
 err1:
-   xa_erase(_heap_minors, minor);
+   xa_erase(_heap_minors, heap->minor);
 err0:
kfree(heap);
return err_ret;
 }
 
+static void dma_heap_release(struct kref *ref)
+{
+   struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+
+   /* Note, we already holding the heap_list_lock here */
+   list_del(>list);
+
+   device_destroy(dma_heap_class, heap->heap_devt);
+   cdev_del(>heap_cdev);
+   xa_erase(_heap_minors, heap->minor);
+
+   kfree(heap);
+}
+
+void dma_heap_put(struct dma_heap *h)
+{
+   /*
+* Take the heap_list_lock now to avoid racing with code
+* scanning the list and then taking a kref.
+*/
+   mutex_lock(_list_lock);
+   kref_put(>refcount, dma_heap_release);
+   mutex_unlock(_list_lock);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index c7c29b724ad6..f3c678892c5c 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -64,4 +64,10 @@ const char *dma_heap_get_name(struct dma_heap *heap);
  */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: the heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap);
+
 #endif /* _DMA_HEAPS_H */
-- 
2.25.1



[PATCH 1/9] dma-buf: heaps: Deduplicate docs and adopt common format

2023-09-10 Thread Yong Wu
From: "T.J. Mercier" 

The docs for dma_heap_get_name were incorrect, and since they were
duplicated in the implementation file they were wrong there too.

The docs formatting was inconsistent so I tried to make it more
consistent across functions since I'm already in here doing cleanup.

Remove multiple unused includes.

Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add a comment for "priv" to mute build warning]
---
 drivers/dma-buf/dma-heap.c | 29 +++--
 include/linux/dma-heap.h   | 11 +--
 2 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..51030f6c9d6e 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -7,17 +7,15 @@
  */
 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
+#include 
+#include 
 #include 
 
 #define DEVNAME "dma_heap"
@@ -28,9 +26,10 @@
  * struct dma_heap - represents a dmabuf heap in the system
  * @name:  used for debugging/device-node name
  * @ops:   ops struct for this heap
- * @heap_devt  heap device node
- * @list   list head connecting to list of heaps
- * @heap_cdev  heap char device
+ * @priv:  private data for this heap
+ * @heap_devt: heap device node
+ * @list:  list head connecting to list of heaps
+ * @heap_cdev: heap char device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -192,25 +191,11 @@ static const struct file_operations dma_heap_fops = {
 #endif
 };
 
-/**
- * dma_heap_get_drvdata() - get per-subdriver data for the heap
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The per-subdriver data for the heap.
- */
 void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
return heap->priv;
 }
 
-/**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The char* for the heap name.
- */
 const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 0c05561cad6e..c7c29b724ad6 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -9,14 +9,13 @@
 #ifndef _DMA_HEAPS_H
 #define _DMA_HEAPS_H
 
-#include 
 #include 
 
 struct dma_heap;
 
 /**
  * struct dma_heap_ops - ops to operate on a given heap
- * @allocate:  allocate dmabuf and return struct dma_buf ptr
+ * @allocate: allocate dmabuf and return struct dma_buf ptr
  *
  * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
  */
@@ -42,7 +41,7 @@ struct dma_heap_export_info {
 };
 
 /**
- * dma_heap_get_drvdata() - get per-heap driver data
+ * dma_heap_get_drvdata - get per-heap driver data
  * @heap: DMA-Heap to retrieve private data for
  *
  * Returns:
@@ -51,8 +50,8 @@ struct dma_heap_export_info {
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
 /**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
+ * dma_heap_get_name - get heap name
+ * @heap: DMA-Heap to retrieve the name of
  *
  * Returns:
  * The char* for the heap name.
@@ -61,7 +60,7 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
- * @exp_info:  information needed to register this heap
+ * @exp_info: information needed to register this heap
  */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
-- 
2.25.1



[PATCH 0/9] dma-buf: heaps: Add MediaTek secure heap

2023-09-10 Thread Yong Wu
This patchset consists of two parts, the first is from John and TJ.
It adds some heap interfaces, then our kernel users could allocate buffer
from special heap. The second part is adding MTK secure heap for SVP
(Secure Video Path). A total of two heaps are added, one is mtk_svp and
the other is mtk_svp_cma. The mtk_svp buffer is reserved for the secure
world after bootup and it is used for ES/working buffer, while the
mtk_svp_cma buffer is dynamically reserved for the secure world and will
be get ready when we start playing secure videos, this heap is used for the
frame buffer. Once the security video playing is complete, the CMA will be
released.

For easier viewing, I've split the new heap file into several patches.

The consumers of new heap and new interfaces are our codec and drm which
will send upstream soon, probably this week.

Base on v6.6-rc1.

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate
dmabufs from specific heaps

T.J. Mercier (1):
  dma-buf: heaps: Deduplicate docs and adopt common format

Yong Wu (6):
  dma-buf: heaps: Initialise MediaTek secure heap
  dma-buf: heaps: mtk_sec_heap: Initialise tee session
  dma-buf: heaps: mtk_sec_heap: Add tee service call for buffer
allocating/freeing
  dma-buf: heaps: mtk_sec_heap: Add dma_ops
  dt-bindings: reserved-memory: MediaTek: Add reserved memory for SVP
  dma_buf: heaps: mtk_sec_heap: Add a new CMA heap

 .../mediatek,secure_cma_chunkmem.yaml |  42 ++
 drivers/dma-buf/dma-heap.c| 127 +++--
 drivers/dma-buf/heaps/Kconfig |   8 +
 drivers/dma-buf/heaps/Makefile|   1 +
 drivers/dma-buf/heaps/mtk_secure_heap.c   | 458 ++
 include/linux/dma-heap.h  |  42 +-
 6 files changed, 630 insertions(+), 48 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/reserved-memory/mediatek,secure_cma_chunkmem.yaml
 create mode 100644 drivers/dma-buf/heaps/mtk_secure_heap.c

-- 
2.18.0




[RFC PATCH] component: Add common helpers for compare/release functions

2022-01-28 Thread Yong Wu
The component requires the compare/release functions, there are so many
copy in current kernel. Just define three common helpers for them.
No functional change.

Signed-off-by: Yong Wu 
---
Base on v5.17-rc1
---
 .../gpu/drm/arm/display/komeda/komeda_drv.c|  5 -
 drivers/gpu/drm/arm/hdlcd_drv.c|  7 +--
 drivers/gpu/drm/armada/armada_drv.c|  5 -
 drivers/gpu/drm/drm_of.c   |  8 +---
 drivers/gpu/drm/etnaviv/etnaviv_drv.c  |  7 ---
 drivers/gpu/drm/exynos/exynos_drm_drv.c|  5 -
 .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c|  5 -
 drivers/gpu/drm/imx/imx-drm-core.c |  4 ++--
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c  |  5 -
 drivers/gpu/drm/mcde/mcde_drv.c|  7 +--
 drivers/gpu/drm/mediatek/mtk_drm_drv.c |  5 -
 drivers/gpu/drm/meson/meson_drv.c  |  8 
 drivers/gpu/drm/msm/msm_drv.c  |  9 -
 drivers/gpu/drm/omapdrm/dss/dss.c  |  8 +---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c|  5 -
 drivers/gpu/drm/sti/sti_drv.c  |  5 -
 drivers/gpu/drm/sun4i/sun4i_drv.c  |  9 -
 drivers/gpu/drm/vc4/vc4_drv.c  |  5 -
 drivers/iommu/mtk_iommu.h  | 10 --
 drivers/power/supply/ab8500_charger.c  |  8 +---
 drivers/video/fbdev/omap2/omapfb/dss/dss.c |  8 +---
 include/linux/component.h  | 18 ++
 sound/soc/codecs/wcd938x.c | 16 ++--
 23 files changed, 28 insertions(+), 144 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index e7933930a657..fe5b97107417 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -92,11 +92,6 @@ static const struct component_master_ops komeda_master_ops = 
{
.unbind = komeda_unbind,
 };
 
-static int compare_of(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
 static void komeda_add_slave(struct device *master,
 struct component_match **match,
 struct device_node *np,
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 479c2422a2e0..36d84c439df8 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -372,11 +372,6 @@ static const struct component_master_ops hdlcd_master_ops 
= {
.unbind = hdlcd_drm_unbind,
 };
 
-static int compare_dev(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
 static int hdlcd_probe(struct platform_device *pdev)
 {
struct device_node *port;
@@ -387,7 +382,7 @@ static int hdlcd_probe(struct platform_device *pdev)
if (!port)
return -ENODEV;
 
-   drm_of_component_match_add(>dev, , compare_dev, port);
+   drm_of_component_match_add(>dev, , compare_of, port);
of_node_put(port);
 
return component_master_add_with_match(>dev, _master_ops,
diff --git a/drivers/gpu/drm/armada/armada_drv.c 
b/drivers/gpu/drm/armada/armada_drv.c
index 8e3e98f13db4..9edc4912c1a0 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -177,11 +177,6 @@ static void armada_drm_unbind(struct device *dev)
drm_mm_takedown(>linear);
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
 static int compare_dev_name(struct device *dev, void *data)
 {
const char *name = data;
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 59d368ea006b..f958f48f8ba4 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -18,11 +18,6 @@
  * properties.
  */
 
-static void drm_release_of(struct device *dev, void *data)
-{
-   of_node_put(data);
-}
-
 /**
  * drm_of_crtc_port_mask - find the mask of a registered CRTC by port OF node
  * @dev: DRM device
@@ -94,8 +89,7 @@ void drm_of_component_match_add(struct device *master,
struct device_node *node)
 {
of_node_get(node);
-   component_match_add_release(master, matchptr, drm_release_of,
-   compare, node);
+   component_match_add_release(master, matchptr, release_of, compare, 
node);
 }
 EXPORT_SYMBOL_GPL(drm_of_component_match_add);
 
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c 
b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 0b756ecb1bc2..15351e26ab00 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -574,13 +574,6 @@ static const struct component_master_ops 
etnaviv_master_ops = {
.unbind = etnaviv_unbind,
 };
 
-static int compare_of(struct device *dev, void *data)
-{
-   struct d

Re: [PATCH v9 12/15] media: mtk-vcodec: enc: Remove mtk_vcodec_release_enc_pm

2022-01-17 Thread Yong Wu
On Thu, 2022-01-13 at 17:10 +0100, Matthias Brugger wrote:
> Hi Hans,
> 
> On 13/01/2022 11:15, Hans Verkuil wrote:
> > On 13/01/2022 11:11, AngeloGioacchino Del Regno wrote:
> > > Il 11/01/22 11:57, AngeloGioacchino Del Regno ha scritto:
> > > > Il 12/11/21 11:55, Yong Wu ha scritto:
> > > > > After this patchset, mtk_vcodec_release_enc_pm has only one
> > > > > line.
> > > > > then remove that function, use pm_runtime_disable instead.
> > > > > 
> > > > > meanwhile, mtk_vcodec_init_enc_pm only operate for the
> > > > > clocks,
> > > > > rename it from the _pm to _clk.
> > > > > 
> > > > > No functional change.
> > > > > 
> > > > > CC: Tiffany Lin 
> > > > > CC: Irui Wang 
> > > > > Signed-off-by: Yong Wu 
> > > > 
> > > > Reviewed-by: AngeloGioacchino Del Regno <
> > > > angelogioacchino.delre...@collabora.com>
> > > > 
> > > 
> > > Hello Yong,
> > > the mtk-vcodec patches were merged in Yunfei's vcodec patch
> > > series and Hans has
> > > scheduled that for v5.18.
> > > 
> > > Can you please send a v10 and drop patches 10/15, 11/15, 12/15
> > > (all of the
> > > media: mtk-vcodec: *) from this series?

Hi Angelo,

   I have dropped 11/15 and 12/15 in v10 and rebase 10/15 on media tree
manually, thus I didn't keep your A-y for that one.

   Please take a look at that one.
 
   Thanks.

> > > 
> > > For the records, I think that after sending v10 this series is
> > > ready to be merged,
> > > as it was well reviewed and also tested on many MTK platforms.
> > 
> > Good to know. When I have the v10 I'll try to prioritize reviewing
> > it and running
> > my usual tests.

Hi Hans/Matthias,

v10: 
https://patchwork.linuxtv.org/project/linux-media/list/?series=7130

Please help take a look that one.

> > 
> > Yong, please make sure you run 'checkpatch.pl --strict' over the
> > v10 patches and fix
> > any issues (using common sense).

   Have run this on v10.

Thanks.
> > 
> 
> Can you please take me in the look when you take the patches. I'll
> take the DTS 
> related as soon as you queue up the others.
> 
> Thanks!
> Matthias
> 
> > Regards,
> > 
> > Hans
> > 
> > > 
> > > Thank you,
> > > - Angelo



[PATCH v10 13/13] arm64: dts: mediatek: Get rid of mediatek, larb for MM nodes

2022-01-16 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi,
the mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Reviewed-by: AngeloGioacchino Del Regno 

---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 16 
 arch/arm64/boot/dts/mediatek/mt8183.dtsi |  6 --
 2 files changed, 22 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi 
b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index dee66e5f054c..417e82891a70 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -1010,7 +1010,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA0>;
-   mediatek,larb = <>;
mediatek,vpu = <>;
};
 
@@ -1021,7 +1020,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA1>;
-   mediatek,larb = <>;
};
 
mdp_rsz0: rsz@14003000 {
@@ -1051,7 +1049,6 @@
clocks = < CLK_MM_MDP_WDMA>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WDMA>;
-   mediatek,larb = <>;
};
 
mdp_wrot0: wrot@14007000 {
@@ -1060,7 +1057,6 @@
clocks = < CLK_MM_MDP_WROT0>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT0>;
-   mediatek,larb = <>;
};
 
mdp_wrot1: wrot@14008000 {
@@ -1069,7 +1065,6 @@
clocks = < CLK_MM_MDP_WROT1>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT1>;
-   mediatek,larb = <>;
};
 
ovl0: ovl@1400c000 {
@@ -1079,7 +1074,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xc000 
0x1000>;
};
 
@@ -1090,7 +1084,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xd000 
0x1000>;
};
 
@@ -1101,7 +1094,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xe000 
0x1000>;
};
 
@@ -1112,7 +1104,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xf000 
0x1000>;
};
 
@@ -1123,7 +1114,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0 
0x1000>;
};
 
@@ -1134,7 +1124,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x1000 
0x1000>;
};
 
@@ -1145,7 +1134,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x2000 
0x1000>;
};
 
@@ -1397,7 +1385,6 @@

[PATCH v10 12/13] arm: dts: mediatek: Get rid of mediatek, larb for MM nodes

2022-01-16 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi, the
mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 arch/arm/boot/dts/mt2701.dtsi  | 2 --
 arch/arm/boot/dts/mt7623n.dtsi | 5 -
 2 files changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 4776f85d6d5b..ef583cfd3baf 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -564,7 +564,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -577,7 +576,6 @@
clocks =  < CLK_IMG_VENC>;
clock-names = "jpgenc";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGENC_RDMA>,
 < MT2701_M4U_PORT_JPGENC_BSDMA>;
};
diff --git a/arch/arm/boot/dts/mt7623n.dtsi b/arch/arm/boot/dts/mt7623n.dtsi
index bcb0846e29fd..3adab5cd1fef 100644
--- a/arch/arm/boot/dts/mt7623n.dtsi
+++ b/arch/arm/boot/dts/mt7623n.dtsi
@@ -121,7 +121,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -144,7 +143,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_OVL>;
iommus = < MT2701_M4U_PORT_DISP_OVL_0>;
-   mediatek,larb = <>;
};
 
rdma0: rdma@14008000 {
@@ -154,7 +152,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA>;
iommus = < MT2701_M4U_PORT_DISP_RDMA>;
-   mediatek,larb = <>;
};
 
wdma@14009000 {
@@ -164,7 +161,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_WDMA>;
iommus = < MT2701_M4U_PORT_DISP_WDMA>;
-   mediatek,larb = <>;
};
 
bls: pwm@1400a000 {
@@ -215,7 +211,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < MT2701_M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
};
 
dpi0: dpi@14014000 {
-- 
2.18.0



[PATCH v10 11/13] memory: mtk-smi: Get rid of mtk_smi_larb_get/put

2022-01-16 Thread Yong Wu
After adding device_link between the iommu consumer and smi-larb,
the pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. we can get rid of mtk_smi_larb_get/put.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Krzysztof Kozlowski 
Acked-by: Matthias Brugger 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/memory/mtk-smi.c   | 14 --
 include/soc/mediatek/smi.h | 20 
 2 files changed, 34 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index b883dcc0bbfa..1b348bb93f0b 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -149,20 +149,6 @@ struct mtk_smi_larb { /* larb: local arbiter */
unsigned char   *bank;
 };
 
-int mtk_smi_larb_get(struct device *larbdev)
-{
-   int ret = pm_runtime_resume_and_get(larbdev);
-
-   return (ret < 0) ? ret : 0;
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
-
-void mtk_smi_larb_put(struct device *larbdev)
-{
-   pm_runtime_put_sync(larbdev);
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
-
 static int
 mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 {
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 15e3397cec58..11f7d6b59642 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -19,26 +19,6 @@ struct mtk_smi_larb_iommu {
unsigned char  bank[32];
 };
 
-/*
- * mtk_smi_larb_get: Enable the power domain and clocks for this local arbiter.
- *   It also initialize some basic setting(like iommu).
- * mtk_smi_larb_put: Disable the power domain and clocks for this local 
arbiter.
- * Both should be called in non-atomic context.
- *
- * Returns 0 if successful, negative on failure.
- */
-int mtk_smi_larb_get(struct device *larbdev);
-void mtk_smi_larb_put(struct device *larbdev);
-
-#else
-
-static inline int mtk_smi_larb_get(struct device *larbdev)
-{
-   return 0;
-}
-
-static inline void mtk_smi_larb_put(struct device *larbdev) { }
-
 #endif
 
 #endif
-- 
2.18.0



[PATCH v10 10/13] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put

2022-01-16 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the vcodec devices call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Tiffany Lin 
CC: Irui Wang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Tiffany Lin 
Reviewed-by: Dafna Hirschfeld 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  2 -
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.c   |  1 -
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 41 +++--
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 --
 .../platform/mtk-vcodec/mtk_vcodec_enc.c  |  1 -
 .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c  |  2 -
 .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   | 45 +++
 7 files changed, 12 insertions(+), 83 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 86b639d82be8..8d11510e441e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -450,7 +450,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
destroy_workqueue(dev->core_workqueue);
 err_res:
pm_runtime_disable(dev->pm.dev);
-   put_device(dev->pm.larbvdec);
 err_dec_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -494,7 +493,6 @@ static int mtk_vcodec_dec_remove(struct platform_device 
*pdev)
 
v4l2_device_unregister(>v4l2_dev);
pm_runtime_disable(dev->pm.dev);
-   put_device(dev->pm.larbvdec);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
index 7b5da3e4cac2..8d2a641d92f1 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_hw.c
@@ -184,7 +184,6 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
return 0;
 err:
pm_runtime_disable(subdev_dev->pm.dev);
-   put_device(subdev_dev->pm.larbvdec);
return ret;
 }
 
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 44035a50e335..7e0c2644bf7b 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_vcodec_dec_hw.h"
 #include "mtk_vcodec_dec_pm.h"
@@ -17,25 +16,11 @@
 
 int mtk_vcodec_init_dec_clk(struct platform_device *pdev, struct mtk_vcodec_pm 
*pm)
 {
-   struct device_node *node;
-   struct platform_device *larb_pdev;
struct mtk_vcodec_clk *dec_clk;
struct mtk_vcodec_clk_info *clk_info;
-   int i = 0, ret = 0;
+   int i = 0, ret;
 
dec_clk = >vdec_clk;
-   node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
-   if (!node) {
-   mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
-   return -1;
-   }
-
-   larb_pdev = of_find_device_by_node(node);
-   of_node_put(node);
-   if (WARN_ON(!larb_pdev))
-   return -1;
-
-   pm->larbvdec = _pdev->dev;
pm->dev = >dev;
 
dec_clk->clk_num =
@@ -44,14 +29,11 @@ int mtk_vcodec_init_dec_clk(struct platform_device *pdev, 
struct mtk_vcodec_pm *
dec_clk->clk_info = devm_kcalloc(>dev,
dec_clk->clk_num, sizeof(*clk_info),
GFP_KERNEL);
-   if (!dec_clk->clk_info) {
-   ret = -ENOMEM;
-   goto put_device;
-   }
+   if (!dec_clk->clk_info)
+   return -ENOMEM;
} else {
mtk_v4l2_err("Failed to get vdec clock count");
-   ret = -EINVAL;
-   goto put_device;
+   return -EINVAL;
}
 
for (i = 0; i < dec_clk->clk_num; i++) {
@@ -60,22 +42,18 @@ int mtk_vcodec_init_dec_clk(struct platform_device *pdev, 
struct mtk_vcodec_pm *
"clock-names", i, _info->clk_name);
if (ret) {
mtk_v4l2_err("Failed to get clock name id = %d", i);
-   goto put_device;
+   return ret;
}
clk_info->vcodec_clk = devm_clk_get(>dev,
clk_info->clk_name);
if (IS_ERR(clk_info->vcodec_clk)) {
mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
clk_info->clk_name);
-   ret = PTR_ERR(clk_info->vcodec_clk);
- 

[PATCH v10 09/13] drm/mediatek: Get rid of mtk_smi_larb_get/put

2022-01-16 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the drm device calls the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: CK Hu 
CC: Philipp Zabel 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Chun-Kuang Hu 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 10 --
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 36 ++---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |  1 -
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  5 +--
 4 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index ce5bbd6918cf..12c6a2097142 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -10,7 +10,6 @@
 #include 
 
 #include 
-#include 
 
 #include 
 #include 
@@ -548,22 +547,14 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
-   ret = mtk_smi_larb_get(comp->larb_dev);
-   if (ret) {
-   DRM_ERROR("Failed to get larb: %d\n", ret);
-   return;
-   }
-
ret = pm_runtime_resume_and_get(comp->dev);
if (ret < 0) {
-   mtk_smi_larb_put(comp->larb_dev);
DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
return;
}
 
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
-   mtk_smi_larb_put(comp->larb_dev);
pm_runtime_put(comp->dev);
return;
}
@@ -600,7 +591,6 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
-   mtk_smi_larb_put(comp->larb_dev);
ret = pm_runtime_put(comp->dev);
if (ret < 0)
DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 99cbf44463e4..48642e814370 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -414,37 +414,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct 
drm_device *drm,
return ret;
 }
 
-static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp 
*comp,
-   struct device *dev)
-{
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", 
node);
-   return -EINVAL;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   return -EPROBE_DEFER;
-   }
-   of_node_put(larb_node);
-   comp->larb_dev = _pdev->dev;
-
-   return 0;
-}
-
 int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
  enum mtk_ddp_comp_id comp_id)
 {
struct platform_device *comp_pdev;
enum mtk_ddp_comp_type type;
struct mtk_ddp_comp_dev *priv;
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
int ret;
+#endif
 
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -460,16 +438,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct 
mtk_ddp_comp *comp,
}
comp->dev = _pdev->dev;
 
-   /* Only DMA capable components need the LARB property */
-   if (type == MTK_DISP_OVL ||
-   type == MTK_DISP_OVL_2L ||
-   type == MTK_DISP_RDMA ||
-   type == MTK_DISP_WDMA) {
-   ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
-   if (ret)
-   return ret;
-   }
-
if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS ||
type == MTK_DISP_CCORR ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index bb914d976cf5..1b582262b682 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -70,7 +70,6 @@ struct mtk_ddp_comp_funcs {
 struct mtk_ddp_comp {
struct device *dev;
int irq;
-   struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
 };
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index aec3972

[PATCH v10 08/13] drm/mediatek: Add pm runtime support for ovl and rdma

2022-01-16 Thread Yong Wu
From: Yongqiang Niu 

Prepare for smi cleaning up "mediatek,larb".

Display use the dispsys device to call pm_rumtime_get_sync before.
This patch add pm_runtime_xx with ovl and rdma device whose nodes has
"iommus" property, then display could help pm_runtime_get for smi via
ovl or rdma device.

CC: CK Hu 
Signed-off-by: Yongqiang Niu 
Signed-off-by: Yong Wu 
(Yong: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync)
Acked-by: Chun-Kuang Hu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c  |  8 +++-
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c |  9 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c  | 13 -
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 5326989d5206..716eac6831f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -414,9 +415,13 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_ovl_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -424,6 +429,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 static int mtk_disp_ovl_remove(struct platform_device *pdev)
 {
component_del(>dev, _disp_ovl_component_ops);
+   pm_runtime_disable(>dev);
 
return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c 
b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 75d7f45579e2..251f034acb09 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -327,9 +328,13 @@ static int mtk_disp_rdma_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, priv);
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_rdma_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -338,6 +343,8 @@ static int mtk_disp_rdma_remove(struct platform_device 
*pdev)
 {
component_del(>dev, _disp_rdma_component_ops);
 
+   pm_runtime_disable(>dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index a4e80e499674..ce5bbd6918cf 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -554,9 +554,17 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
return;
}
 
+   ret = pm_runtime_resume_and_get(comp->dev);
+   if (ret < 0) {
+   mtk_smi_larb_put(comp->larb_dev);
+   DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
+   return;
+   }
+
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
mtk_smi_larb_put(comp->larb_dev);
+   pm_runtime_put(comp->dev);
return;
}
 
@@ -569,7 +577,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 {
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-   int i;
+   int i, ret;
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
@@ -593,6 +601,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
mtk_smi_larb_put(comp->larb_dev);
+   ret = pm_runtime_put(comp->dev);
+   if (ret < 0)
+   DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
 
mtk_crtc->enabled = false;
 }
-- 
2.18.0



[PATCH v10 07/13] media: mtk-mdp: Get rid of mtk_smi_larb_get/put

2022-01-16 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the mdp device calls the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Minghsiu Tsai 
CC: Houlong Wei 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Reviewed-by: Houlong Wei 
Reviewed-by: Dafna Hirschfeld 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 40 ---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h |  2 -
 drivers/media/platform/mtk-mdp/mtk_mdp_core.c |  1 -
 3 files changed, 43 deletions(-)

diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
index b3426a551bea..1e3833f1c9ae 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_comp.h"
 
@@ -18,14 +17,6 @@ void mtk_mdp_comp_clock_on(struct device *dev, struct 
mtk_mdp_comp *comp)
 {
int i, err;
 
-   if (comp->larb_dev) {
-   err = mtk_smi_larb_get(comp->larb_dev);
-   if (err)
-   dev_err(dev,
-   "failed to get larb, err %d. type:%d\n",
-   err, comp->type);
-   }
-
for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
if (IS_ERR(comp->clk[i]))
continue;
@@ -46,17 +37,12 @@ void mtk_mdp_comp_clock_off(struct device *dev, struct 
mtk_mdp_comp *comp)
continue;
clk_disable_unprepare(comp->clk[i]);
}
-
-   if (comp->larb_dev)
-   mtk_smi_larb_put(comp->larb_dev);
 }
 
 int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
  struct mtk_mdp_comp *comp,
  enum mtk_mdp_comp_type comp_type)
 {
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
int ret;
int i;
 
@@ -77,32 +63,6 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node 
*node,
break;
}
 
-   /* Only DMA capable components need the LARB property */
-   comp->larb_dev = NULL;
-   if (comp->type != MTK_MDP_RDMA &&
-   comp->type != MTK_MDP_WDMA &&
-   comp->type != MTK_MDP_WROT)
-   return 0;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev,
-   "Missing mediadek,larb phandle in %pOF node\n", node);
-   ret = -EINVAL;
-   goto put_dev;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   ret = -EPROBE_DEFER;
-   goto put_dev;
-   }
-   of_node_put(larb_node);
-
-   comp->larb_dev = _pdev->dev;
-
return 0;
 
 put_dev:
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
index 7897766c96bb..ae41dd3cd72a 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
@@ -26,14 +26,12 @@ enum mtk_mdp_comp_type {
  * @node:  list node to track sibing MDP components
  * @dev_node:  component device node
  * @clk:   clocks required for component
- * @larb_dev:  SMI device required for component
  * @type:  component type
  */
 struct mtk_mdp_comp {
struct list_headnode;
struct device_node  *dev_node;
struct clk  *clk[2];
-   struct device   *larb_dev;
enum mtk_mdp_comp_type  type;
 };
 
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
index 976aa1f4829b..70a8eab16863 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
@@ -17,7 +17,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_core.h"
 #include "mtk_mdp_m2m.h"
-- 
2.18.0



[PATCH v10 06/13] media: mtk-jpeg: Get rid of mtk_smi_larb_get/put

2022-01-16 Thread Yong Wu
MediaTek IOMMU has already added device_link between the consumer
and smi-larb device. If the jpg device calls the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

After removing the larb_get operations, then mtk_jpeg_clk_init is
also unnecessary. Remove it too.

CC: Rick Chang 
CC: Xia Jiang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Rick Chang 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Acked-by: AngeloGioacchino Del Regno 
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 45 +--
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h   |  2 -
 2 files changed, 2 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index af994b9913a6..1e29ca0aad77 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -22,7 +22,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_jpeg_enc_hw.h"
 #include "mtk_jpeg_dec_hw.h"
@@ -1055,10 +1054,6 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
int ret;
 
-   ret = mtk_smi_larb_get(jpeg->larb);
-   if (ret)
-   dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
-
ret = clk_bulk_prepare_enable(jpeg->variant->num_clks,
  jpeg->variant->clks);
if (ret)
@@ -1069,7 +1064,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
clk_bulk_disable_unprepare(jpeg->variant->num_clks,
   jpeg->variant->clks);
-   mtk_smi_larb_put(jpeg->larb);
 }
 
 static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
@@ -1284,35 +1278,6 @@ static struct clk_bulk_data mtk_jpeg_clocks[] = {
{ .id = "jpgenc" },
 };
 
-static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
-{
-   struct device_node *node;
-   struct platform_device *pdev;
-   int ret;
-
-   node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0);
-   if (!node)
-   return -EINVAL;
-   pdev = of_find_device_by_node(node);
-   if (WARN_ON(!pdev)) {
-   of_node_put(node);
-   return -EINVAL;
-   }
-   of_node_put(node);
-
-   jpeg->larb = >dev;
-
-   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
-   jpeg->variant->clks);
-   if (ret) {
-   dev_err(>dev, "failed to get jpeg clock:%d\n", ret);
-   put_device(>dev);
-   return ret;
-   }
-
-   return 0;
-}
-
 static void mtk_jpeg_job_timeout_work(struct work_struct *work)
 {
struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1333,11 +1298,6 @@ static void mtk_jpeg_job_timeout_work(struct work_struct 
*work)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
-static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
-{
-   put_device(jpeg->larb);
-}
-
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
struct mtk_jpeg_dev *jpeg;
@@ -1374,7 +1334,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_req_irq;
}
 
-   ret = mtk_jpeg_clk_init(jpeg);
+   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
+   jpeg->variant->clks);
if (ret) {
dev_err(>dev, "Failed to init clk, err %d\n", ret);
goto err_clk_init;
@@ -1440,7 +1401,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
v4l2_device_unregister(>v4l2_dev);
 
 err_dev_register:
-   mtk_jpeg_clk_release(jpeg);
 
 err_clk_init:
 
@@ -1458,7 +1418,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
video_device_release(jpeg->vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(>v4l2_dev);
-   mtk_jpeg_clk_release(jpeg);
 
return 0;
 }
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 595f7f10c9fd..3e4811a41ba2 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -85,7 +85,6 @@ struct mtk_jpeg_variant {
  * @alloc_ctx: videobuf2 memory allocator's context
  * @vdev:  video device node for jpeg mem2mem mode
  * @reg_base:  JPEG registers mapping
- * @larb:  SMI device
  * @job_timeout_work:  IRQ timeout structure
  * @variant:   driver variant to be used
  */
@@ -99,7 +98,6 @@ struct mtk_jpeg_dev {
void*alloc_ctx;
struct video_device *vdev;
void __iomem*reg_base;
-   struct device   *larb;
struct delayed_work job_timeout_work;
const struct mtk_jpeg_variant *variant;
 };
-- 
2.18.0



[PATCH v10 05/13] iommu/mediatek: Add device_link between the consumer and the larb devices

2022-01-16 Thread Yong Wu
MediaTek IOMMU-SMI diagram is like below. all the consumer connect with
smi-larb, then connect with smi-common.

M4U
 |
smi-common
 |
  -
  | |...
  | |
larb1 larb2
  | |
vdec   venc

When the consumer works, it should enable the smi-larb's power which
also need enable the smi-common's power firstly.

Thus, First of all, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

This patch adds device_link between the consumer and the larbs.

When device_link_add, I add the flag DL_FLAG_STATELESS to avoid calling
pm_runtime_xx to keep the original status of clocks. It can avoid two
issues:
1) Display HW show fastlogo abnormally reported in [1]. At the beggining,
all the clocks are enabled before entering kernel, but the clocks for
display HW(always in larb0) will be gated after clk_enable and clk_disable
called from device_link_add(->pm_runtime_resume) and rpm_idle. The clock
operation happened before display driver probe. At that time, the display
HW will be abnormal.

2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to skip
pm_runtime_xx to avoid the deadlock.

Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
device_link_removed should be added explicitly.

Meanwhile, Currently we don't have a device connect with 2 larbs at the
same time. Disallow this case, print the error log.

[1] https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
[2] https://lore.kernel.org/patchwork/patch/1086569/

Suggested-by: Tomasz Figa 
Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Acked-by: Joerg Roedel 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c| 30 ++
 drivers/iommu/mtk_iommu_v1.c | 29 -
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 5cff5bc556d4..77df61092be3 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -562,22 +562,52 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_data *data;
+   struct device_link *link;
+   struct device *larbdev;
+   unsigned int larbid, larbidx, i;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return ERR_PTR(-ENODEV); /* Not a iommu client device */
 
data = dev_iommu_priv_get(dev);
 
+   /*
+* Link the consumer device with the smi-larb device(supplier).
+* The device that connects with each a larb is a independent HW.
+* All the ports in each a device should be in the same larbs.
+*/
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   for (i = 1; i < fwspec->num_ids; i++) {
+   larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]);
+   if (larbid != larbidx) {
+   dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
+   larbid, larbidx);
+   return ERR_PTR(-EINVAL);
+   }
+   }
+   larbdev = data->larb_imu[larbid].dev;
+   link = device_link_add(dev, larbdev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link)
+   dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
return >iommu;
 }
 
 static void mtk_iommu_release_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   struct mtk_iommu_data *data;
+   struct device *larbdev;
+   unsigned int larbid;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return;
 
+   data = dev_iommu_priv_get(dev);
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   larbdev = data->larb_imu[larbid].dev;
+   device_link_remove(dev, larbdev);
+
iommu_fwspec_free(dev);
 }
 
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 4089077256f4..4052aad75a81 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -423,7 +423,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct of_phandle_args iommu_spec;
struct mtk_iommu_data *data;
-   int err, idx = 0;
+   int err, idx = 0, larbid, larbidx;
+   struct device_link *link;
+   struct device *larbdev;
 
/*
 * In the deferred case, free the existed fwspec.
@@ -453,6 +455,23 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 
data = dev_iommu_priv_get(dev);
 
+   /* Link the consumer device with the smi-larb device(supplier) */
+   larbid = mt2701_m4u_to_larb(fwspec->i

[PATCH v10 04/13] iommu/mediatek: Add probe_defer for smi-larb

2022-01-16 Thread Yong Wu
Prepare for adding device_link.

The iommu consumer should use device_link to connect with the
smi-larb(supplier). then the smi-larb should run before the iommu
consumer. Here we delay the iommu driver until the smi driver is ready,
then all the iommu consumers always are after the smi driver.

When there is no this patch, if some consumer drivers run before
smi-larb, the supplier link_status is DL_DEV_NO_DRIVER(0) in the
device_link_add, then device_links_driver_bound will use WARN_ON
to complain that the link_status of supplier is not right.

device_is_bound may be more elegant here. but it is not allowed to
EXPORT from https://lore.kernel.org/patchwork/patch/1334670/.

Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Acked-by: Joerg Roedel 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c| 4 
 drivers/iommu/mtk_iommu_v1.c | 4 
 2 files changed, 8 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 77ae20ff9b35..5cff5bc556d4 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -850,6 +850,10 @@ static int mtk_iommu_probe(struct platform_device *pdev)
of_node_put(larbnode);
return -ENODEV;
}
+   if (!plarbdev->dev.driver) {
+   of_node_put(larbnode);
+   return -EPROBE_DEFER;
+   }
data->larb_imu[id].dev = >dev;
 
component_match_add_release(dev, , release_of,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 68bf02f87cfd..4089077256f4 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -606,6 +606,10 @@ static int mtk_iommu_probe(struct platform_device *pdev)
of_node_put(larbnode);
return -ENODEV;
}
+   if (!plarbdev->dev.driver) {
+   of_node_put(larbnode);
+   return -EPROBE_DEFER;
+   }
data->larb_imu[i].dev = >dev;
 
component_match_add_release(dev, , release_of,
-- 
2.18.0



[PATCH v10 03/13] iommu/mediatek: Return ENODEV if the device is NULL

2022-01-16 Thread Yong Wu
The platform device is created at:
of_platform_default_populate_init:  arch_initcall_sync
  ->of_platform_populate
->of_platform_device_create_pdata

When entering our probe, all the devices should be already created.
if it is null, means NODEV. Currently we don't get the fail case.
It's a minor fix, no need add fixes tags.

Signed-off-by: Yong Wu 
Acked-by: Joerg Roedel 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c| 2 +-
 drivers/iommu/mtk_iommu_v1.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 25b834104790..77ae20ff9b35 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -848,7 +848,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
plarbdev = of_find_device_by_node(larbnode);
if (!plarbdev) {
of_node_put(larbnode);
-   return -EPROBE_DEFER;
+   return -ENODEV;
}
data->larb_imu[id].dev = >dev;
 
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 1467ba1e4417..68bf02f87cfd 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -604,7 +604,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
plarbdev = of_find_device_by_node(larbnode);
if (!plarbdev) {
of_node_put(larbnode);
-   return -EPROBE_DEFER;
+   return -ENODEV;
}
data->larb_imu[i].dev = >dev;
 
-- 
2.18.0



[PATCH v10 02/13] iommu/mediatek-v1: Free the existed fwspec if the master dev already has

2022-01-16 Thread Yong Wu
When the iommu master device enters of_iommu_xlate, the ops may be
NULL(iommu dev is defered), then it will initialize the fwspec here:

[] (dev_iommu_fwspec_set) from []
(iommu_fwspec_init+0xbc/0xd4)
[] (iommu_fwspec_init) from []
(of_iommu_xlate+0x7c/0x12c)
[] (of_iommu_xlate) from []
(of_iommu_configure+0x144/0x1e8)

BUT the mtk_iommu_v1.c only supports arm32, the probing flow still is a bit
weird. We always expect create the fwspec internally. otherwise it will
enter here and return fail.

static int mtk_iommu_create_mapping(struct device *dev,
struct of_phandle_args *args)
{
...
if (!fwspec) {

} else if (dev_iommu_fwspec_get(dev)->ops != _iommu_ops) {
>>>>>>>>>>Enter here. return fail.<<<<<<<<<<<<
return -EINVAL;
}
...
}

Thus, Free the existed fwspec if the master device already has fwspec.

This issue is reported at:
https://lore.kernel.org/linux-mediatek/trinity-7d9ebdc9-4849-4d93-bfb5-429dcb4ee449-1626253158870@3c-app-gmx-bs01/

Reported-by: Frank Wunderlich 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Signed-off-by: Yong Wu 
Acked-by: Joerg Roedel 
Acked-by: AngeloGioacchino Del Regno 
---
 drivers/iommu/mtk_iommu_v1.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index be22fcf988ce..1467ba1e4417 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -425,6 +425,15 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct mtk_iommu_data *data;
int err, idx = 0;
 
+   /*
+* In the deferred case, free the existed fwspec.
+* Always initialize the fwspec internally.
+*/
+   if (fwspec) {
+   iommu_fwspec_free(dev);
+   fwspec = dev_iommu_fwspec_get(dev);
+   }
+
while (!of_parse_phandle_with_args(dev->of_node, "iommus",
   "#iommu-cells",
   idx, _spec)) {
-- 
2.18.0



[PATCH v10 01/13] dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW

2022-01-16 Thread Yong Wu
After adding device_link between the consumer with the smi-larbs,
if the consumer call its owner pm_runtime_get(_sync), the
pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. Thus, the consumer don't need this property.

And IOMMU also know which larb this consumer connects with from
iommu id in the "iommus=" property.

Signed-off-by: Yong Wu 
Reviewed-by: Rob Herring 
Reviewed-by: Evan Green 
Acked-by: AngeloGioacchino Del Regno 
---
 .../bindings/display/mediatek/mediatek,disp.txt  | 9 -
 .../bindings/media/mediatek,vcodec-decoder.yaml  | 7 ---
 .../bindings/media/mediatek,vcodec-encoder.yaml  | 8 
 .../devicetree/bindings/media/mediatek-jpeg-decoder.yaml | 9 -
 .../devicetree/bindings/media/mediatek-jpeg-encoder.yaml | 9 -
 Documentation/devicetree/bindings/media/mediatek-mdp.txt | 8 
 6 files changed, 50 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
index 78044c340e20..8b575e11bcec 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
@@ -61,8 +61,6 @@ Required properties (DMA function blocks):
"mediatek,-disp-rdma"
"mediatek,-disp-wdma"
   the supported chips are mt2701, mt8167 and mt8173.
-- larb: Should contain a phandle pointing to the local arbiter device as 
defined
-  in 
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
 - iommus: Should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
   for details.
@@ -91,7 +89,6 @@ ovl0: ovl@1400c000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
 };
 
 ovl1: ovl@1400d000 {
@@ -101,7 +98,6 @@ ovl1: ovl@1400d000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
 };
 
 rdma0: rdma@1400e000 {
@@ -111,7 +107,6 @@ rdma0: rdma@1400e000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,rdma-fifosize = <8192>;
 };
 
@@ -122,7 +117,6 @@ rdma1: rdma@1400f000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
 };
 
 rdma2: rdma@1401 {
@@ -132,7 +126,6 @@ rdma2: rdma@1401 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
 };
 
 wdma0: wdma@14011000 {
@@ -142,7 +135,6 @@ wdma0: wdma@14011000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
 };
 
 wdma1: wdma@14012000 {
@@ -152,7 +144,6 @@ wdma1: wdma@14012000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
 };
 
 color0: color@14013000 {
diff --git 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
index df1d677098fd..9b179bb44dfb 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-decoder.yaml
@@ -61,12 +61,6 @@ properties:
 description: |
   Describes the physical address space of IOMMU maps to memory.
 
-  mediatek,larb:
-$ref: /schemas/types.yaml#/definitions/phandle
-maxItems: 1
-description: |
-  Must contain the local arbiters in the current Socs.
-
   mediatek,vpu:
 $ref: /schemas/types.yaml#/definitions/phandle
 maxItems: 1
@@ -137,7 +131,6 @@ examples:
   <0x16027800 0x800>,   /*VP8_VL*/
   <0x16028400 0x400>;   /*VP9_VD*/
   interrupts = ;
-  mediatek,larb = <>;
   iommus = < M4U_PORT_HW_VDEC_MC_EXT>,
  < M4U_PORT_HW_VDEC_PP_EXT>,
  < M4U_PORT_HW_VDEC_AVC_MV_EXT>,
diff --git 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
index b72c1a50e89e..e7b65a91c92c 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
+++ b/Documentation/devicetree/bindings/med

[PATCH v10 00/13] Clean up "mediatek,larb"

2022-01-16 Thread Yong Wu
MediaTek IOMMU block diagram always like below:

M4U
 |
smi-common
 |
  -
  | |  ...
  | |
larb1 larb2
  | |
vdec   venc

All the consumer connect with smi-larb, then connect with smi-common.

When the consumer works, it should enable the smi-larb's power which also
need enable the smi-common's power firstly.

Thus, Firstly, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

After adding the device_link, then "mediatek,larb" property can be removed.
the iommu consumer don't need call the mtk_smi_larb_get/put to enable
the power and clock of smi-larb and smi-common.

Base on the media branch [1] and a jpeg dtbinding patchset[2] that already got
the necessary R-b.

[1] git://linuxtv.org/hverkuil/media_tree.git tags/br-v5.18d
[2] 
https://lore.kernel.org/linux-mediatek/20211206130425.184420-1-hsi...@chromium.org/

Change notes:
v10: a) Rebase on the media tree. Respin the "media: mtk-vcodec:" patches. 
 b) Add Joerg's Ack for iommu patches.

v9: 
https://lore.kernel.org/linux-mediatek/2022105509.12010-1-yong...@mediatek.com/
1) Add return -ENODEV when the dev is null.
2) Add more strict about the case that a iommu consume device use the ports 
in
different larbs. Don't allow this case.
3) Remove two codec interface: mtk_vcodec_release_enc/dec_pm since it only 
has one
line now.

v8: 
https://lore.kernel.org/linux-mediatek/20210929013719.25120-1-yong...@mediatek.com/
1) Rebase on v5.15-rc1.
2) Don't rebase the below mdp patchset that may still need more discuss.

https://lore.kernel.org/linux-mediatek/20210709022324.1607884-1-ei...@chromium.org/
3) Add Frank's Tested-by. Remove Dafna's Tested-by as he requested.

v7: 
https://lore.kernel.org/linux-mediatek/20210730025238.22456-1-yong...@mediatek.com/
1) Fix a arm32 boot fail issue. reported from Frank.
2) Add a return fail in the mtk drm. suggested by Dafna.

v6: 
https://lore.kernel.org/linux-mediatek/20210714025626.5528-1-yong...@mediatek.com/
1) rebase on v5.14-rc1.
2) Fix the issue commented in v5 from Dafna and Hsin-Yi.
3) Remove the patches about using pm_runtime_resume_and_get since they have
   already been merged by other patches.

v5: 
https://lore.kernel.org/linux-mediatek/20210410091128.31823-1-yong...@mediatek.com/
1) Base v5.12-rc2.
2) Remove changing the mtk-iommu to module_platform_driver patch, It have 
already been a
independent patch.

v4: 
https://lore.kernel.org/linux-mediatek/1590826218-23653-1-git-send-email-yong...@mediatek.com/
 
base on v5.7-rc1.
  1) Move drm PM patch before smi patchs.
  2) Change builtin_platform_driver to module_platform_driver since we may need
 build as module.
  3) Rebase many patchset as above.

v3: 
https://lore.kernel.org/linux-iommu/1567503456-24725-1-git-send-email-yong...@mediatek.com/
1) rebase on v5.3-rc1 and the latest mt8183 patchset.
2) Use device_is_bound to check whether the driver is ready from Matthias.  
  
3) Add DL_FLAG_STATELESS flag when calling device_link_add and explain the
   reason in the commit message[3/14].
4) Add a display patch[12/14] into this series. otherwise it may affect
   display HW fastlogo even though it don't happen in mt8183.
   
v2: 
https://lore.kernel.org/linux-iommu/1560171313-28299-1-git-send-email-yong...@mediatek.com/
   1) rebase on v5.2-rc1.
   2) Move adding device_link between the consumer and smi-larb into
iommu_add_device from Robin.
   3) add DL_FLAG_AUTOREMOVE_CONSUMER even though the smi is built-in from Evan.
   4) Remove the shutdown callback in iommu.   

v1: 
https://lore.kernel.org/linux-iommu/1546318276-18993-1-git-send-email-yong...@mediatek.com/

Yong Wu (12):
  dt-binding: mediatek: Get rid of mediatek,larb for multimedia HW
  iommu/mediatek-v1: Free the existed fwspec if the master dev already
has
  iommu/mediatek: Return ENODEV if the device is NULL
  iommu/mediatek: Add probe_defer for smi-larb
  iommu/mediatek: Add device_link between the consumer and the larb
devices
  media: mtk-jpeg: Get rid of mtk_smi_larb_get/put
  media: mtk-mdp: Get rid of mtk_smi_larb_get/put
  drm/mediatek: Get rid of mtk_smi_larb_get/put
  media: mtk-vcodec: Get rid of mtk_smi_larb_get/put
  memory: mtk-smi: Get rid of mtk_smi_larb_get/put
  arm: dts: mediatek: Get rid of mediatek,larb for MM nodes
  arm64: dts: mediatek: Get rid of mediatek,larb for MM nodes

Yongqiang Niu (1):
  drm/mediatek: Add pm runtime support for ovl and rdma

 .../display/mediatek/mediatek,disp.txt|  9 
 .../media/mediatek,vcodec-decoder.yaml|  7 ---
 .../media/mediatek,vcodec-encoder.yaml|  8 
 .../bindings/media/mediatek-jpeg-decoder.yaml |  9 
 .../bindings/media/mediatek-jpeg-encoder.yaml |  9 
 .../bindings/media/mediatek-mdp.txt   |  8 
 arch/arm/

Re: [PATCH v5 25/32] iommu/mtk: Migrate to aggregate driver

2022-01-14 Thread Yong Wu
On Fri, 2022-01-14 at 15:30 -0600, Stephen Boyd wrote:
> Quoting Yong Wu (2022-01-14 01:06:31)
> > On Wed, 2022-01-12 at 20:25 -0800, Stephen Boyd wrote:
> > > > 
> > > > [2.654526] [ cut here ]
> > > > [2.68] refcount_t: addition on 0; use-after-free.
> > > > 
> > > > After this patch, the aggregate_driver flow looks ok. But our
> > > > driver
> > > > still aborts like this:
> > > > 
> > > > [2.721316] Unable to handle kernel NULL pointer dereference
> > > > at
> > > > virtual address 
> > > > ...
> > > > [2.731658] pc :
> > > > mtk_smi_larb_config_port_gen2_general+0xa4/0x138
> > > > [2.732434] lr : mtk_smi_larb_resume+0x54/0x98
> > > > ...
> > > > [2.742457] Call trace:
> > > > [2.742768]  mtk_smi_larb_config_port_gen2_general+0xa4/0x13
> > > > 8
> > > > [2.743496]  pm_generic_runtime_resume+0x2c/0x48
> > > > [2.744090]  __genpd_runtime_resume+0x30/0xa8
> > > > [2.744648]  genpd_runtime_resume+0x94/0x2c8
> > > > [2.745191]  __rpm_callback+0x44/0x150
> > > > [2.745669]  rpm_callback+0x6c/0x78
> > > > [2.746114]  rpm_resume+0x314/0x558
> > > > [2.746559]  __pm_runtime_resume+0x3c/0x88
> > > > [2.747080]  pm_runtime_get_suppliers+0x7c/0x110
> > > > [2.747668]  __driver_probe_device+0x4c/0xe8
> > > > [2.748212]  driver_probe_device+0x44/0x130
> > > > [2.748745]  __device_attach_driver+0x98/0xd0
> > > > [2.749300]  bus_for_each_drv+0x68/0xd0
> > > > [2.749787]  __device_attach+0xec/0x148
> > > > [2.750277]  device_attach+0x14/0x20
> > > > [2.750733]  bus_rescan_devices_helper+0x50/0x90
> > > > [2.751319]  bus_for_each_dev+0x7c/0xd8
> > > > [2.751806]  bus_rescan_devices+0x20/0x30
> > > > [2.752315]  __component_add+0x7c/0xa0
> > > > [2.752795]  component_add+0x14/0x20
> > > > [2.753253]  mtk_smi_larb_probe+0xe0/0x120
> > > > 
> > > > This is because the device runtime_resume is called before the
> > > > bind
> > > > operation(In our case this detailed function is
> > > > mtk_smi_larb_bind).
> > > > The issue doesn't happen without this patchset. I'm not sure
> > > > the
> > > > right
> > > > sequence. If we should fix in mediatek driver, the patch could
> > > > be:
> > > 
> > > Oh, the runtime PM is moved around with these patches. The
> > > aggregate
> > > device is runtime PM enabled before the probe is called,
> > 
> > In our case, the component device may probe before the aggregate
> > device. thus the component device runtime PM has already been
> > enabled
> > when aggregate device probe.
> 
> This is always the case. The component device always probes before
> the
> aggregate device because the component device registers with the
> component framework. But the component device can decide to enable
> runtime PM during driver probe or during component bind.
> 
> > 
> > > and there are
> > > supplier links made to each component, so each component is
> > > runtime
> > > resumed before the aggregate probe function is called.
> > 
> > Yes. This is the current flow.
> 
> Got it.
> 
> > 
> > > It means that all
> > > the component drivers need to have their resources ready to power
> > > on
> > > before their component_bind() callback is made.
> > 
> > Sorry, I don't understand here well. In this case, The component
> > drivers prepare the resource for power on in the component_bind
> > since
> > the resource comes from the aggregate driver. Thus, we expect the
> > component_bind run before the runtime resume callback.
> 
> What resource comes from the aggregate device that the component
> device manages in runtime PM?

Here the aggregate device is the iommu device. It knows who enabled the
iommu from the dtsi, then transfers this information to the
component(smi_larb) devices. smi_larb will configure the registers to
enable iommu for these masters in the runtime resume.

> > 
> > Another solution is moving the component's pm_runtime_enable into
> > the
> > component_bind(It's mtk_smi_larb_bind here), then the runtime
> > callback
> > is called after component_bind in which the resource for power on
>

Re: [PATCH v5 25/32] iommu/mtk: Migrate to aggregate driver

2022-01-14 Thread Yong Wu
On Wed, 2022-01-12 at 20:25 -0800, Stephen Boyd wrote:
> > 
> > [2.654526] [ cut here ]
> > [2.68] refcount_t: addition on 0; use-after-free.
> > 
> > After this patch, the aggregate_driver flow looks ok. But our
> > driver
> > still aborts like this:
> > 
> > [2.721316] Unable to handle kernel NULL pointer dereference at
> > virtual address 
> > ...
> > [2.731658] pc :
> > mtk_smi_larb_config_port_gen2_general+0xa4/0x138
> > [2.732434] lr : mtk_smi_larb_resume+0x54/0x98
> > ...
> > [2.742457] Call trace:
> > [2.742768]  mtk_smi_larb_config_port_gen2_general+0xa4/0x138
> > [2.743496]  pm_generic_runtime_resume+0x2c/0x48
> > [2.744090]  __genpd_runtime_resume+0x30/0xa8
> > [2.744648]  genpd_runtime_resume+0x94/0x2c8
> > [2.745191]  __rpm_callback+0x44/0x150
> > [2.745669]  rpm_callback+0x6c/0x78
> > [2.746114]  rpm_resume+0x314/0x558
> > [2.746559]  __pm_runtime_resume+0x3c/0x88
> > [2.747080]  pm_runtime_get_suppliers+0x7c/0x110
> > [2.747668]  __driver_probe_device+0x4c/0xe8
> > [2.748212]  driver_probe_device+0x44/0x130
> > [2.748745]  __device_attach_driver+0x98/0xd0
> > [2.749300]  bus_for_each_drv+0x68/0xd0
> > [2.749787]  __device_attach+0xec/0x148
> > [2.750277]  device_attach+0x14/0x20
> > [2.750733]  bus_rescan_devices_helper+0x50/0x90
> > [2.751319]  bus_for_each_dev+0x7c/0xd8
> > [2.751806]  bus_rescan_devices+0x20/0x30
> > [2.752315]  __component_add+0x7c/0xa0
> > [2.752795]  component_add+0x14/0x20
> > [2.753253]  mtk_smi_larb_probe+0xe0/0x120
> > 
> > This is because the device runtime_resume is called before the bind
> > operation(In our case this detailed function is mtk_smi_larb_bind).
> > The issue doesn't happen without this patchset. I'm not sure the
> > right
> > sequence. If we should fix in mediatek driver, the patch could be:
> 
> Oh, the runtime PM is moved around with these patches. The aggregate
> device is runtime PM enabled before the probe is called, 

In our case, the component device may probe before the aggregate
device. thus the component device runtime PM has already been enabled
when aggregate device probe.

> and there are
> supplier links made to each component, so each component is runtime
> resumed before the aggregate probe function is called. 

Yes. This is the current flow.

> It means that all
> the component drivers need to have their resources ready to power on
> before their component_bind() callback is made. 

Sorry, I don't understand here well. In this case, The component
drivers prepare the resource for power on in the component_bind since
the resource comes from the aggregate driver. Thus, we expect the
component_bind run before the runtime resume callback.

Another solution is moving the component's pm_runtime_enable into the
component_bind(It's mtk_smi_larb_bind here), then the runtime callback
is called after component_bind in which the resource for power on is
ready.

> Thinking more about it
> that may be wrong if something from the aggregate device is needed to
> fully power on the component. Is that what is happening here?
> 
> > diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> > index b883dcc0bbfa..288841555067 100644
> > --- a/drivers/memory/mtk-smi.c
> > +++ b/drivers/memory/mtk-smi.c
> > @@ -483,8 +483,9 @@ static int __maybe_unused
> > mtk_smi_larb_resume(struct device *dev)
> > if (ret < 0)
> > return ret;
> > 
> > -   /* Configure the basic setting for this larb */
> > -   larb_gen->config_port(dev);
> > +   /* Configure the basic setting for this larb after it binds
> > with iommu */
> > +   if (larb->mmu)
> > +   larb_gen->config_port(dev);
> > 
> > return 0;
> >  }
> > 



Re: [PATCH v5 25/32] iommu/mtk: Migrate to aggregate driver

2022-01-12 Thread Yong Wu
On Tue, 2022-01-11 at 16:27 -0800, Stephen Boyd wrote:
> Quoting Yong Wu (2022-01-11 04:22:23)
> > Hi Stephen,
> > 
> > Thanks for helping update here.
> > 
> > On Thu, 2022-01-06 at 13:45 -0800, Stephen Boyd wrote:
> > > Use an aggregate driver instead of component ops so that we can
> > > get
> > > proper driver probe ordering of the aggregate device with respect
> > > to
> > > all
> > > the component devices that make up the aggregate device.
> > > 
> > > Cc: Yong Wu 
> > > Cc: Joerg Roedel 
> > > Cc: Will Deacon 
> > > Cc: Daniel Vetter 
> > > Cc: "Rafael J. Wysocki" 
> > > Cc: Rob Clark 
> > > Cc: Russell King 
> > > Cc: Saravana Kannan 
> > > Signed-off-by: Stephen Boyd 
> > 
> > When I test this on mt8195 which have two IOMMU HWs(calling
> > component_aggregate_regsiter twice), it will abort like this. Then
> > what
> > should we do if we have two instances?
> > 
> 
> Thanks for testing it out. We can't register the struct driver more
> than
> once but this driver is calling the component_aggregate_register()
> function from the driver probe and there are two devices bound to the
> mtk-iommu driver so we try to register it more than once. Sigh!
> 
> I see a couple options. One is to do a deep copy of the driver
> structure
> and change the driver name. Then it's a one to one relationship
> between
> device and driver. That's not very great because it leaves around
> junk
> so it should probably be avoided.
> 
> Another option is to reference count the driver registration calls
> when
> component_aggregate_register() is called multiple times. Then we
> would
> only register the driver once and keep it pinned until the last
> unregister call is made, but still remove devices that are created
> for
> the match table.
> 
> Can you try the attached patch? It is based on the next version of
> this
> patch series so the include part of the patch may not apply cleanly.
> 
> ---8<---
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index 64ad7478c67a..97f253a41bdf 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -492,15 +492,30 @@ static struct aggregate_device
> *__aggregate_find(struct device *parent)
>   return dev ? to_aggregate_device(dev) : NULL;
>  }
> 
> +static DEFINE_MUTEX(aggregate_mutex);
> +
>  static int aggregate_driver_register(struct aggregate_driver *adrv)
>  {
> - adrv->driver.bus = _bus_type;
> - return driver_register(>driver);
> + int ret = 0;
> +
> + mutex_lock(_mutex);
> + if (!refcount_inc_not_zero(>count)) {
> + adrv->driver.bus = _bus_type;
> + ret = driver_register(>driver);
> + if (!ret)
> + refcount_inc(>count);

This should be refcount_set(>count, 1)?

Otherwise, it will warning like this:

[2.654526] [ cut here ]
[2.68] refcount_t: addition on 0; use-after-free.
[2.656219] WARNING: CPU: 7 PID: 74 at ../v5.16-
rc1/kernel/mediatek/lib/refcount.c:25
refcount_warn_saturate+0x128/0x148
...
[2.672227] Call trace:
[2.672539]  refcount_warn_saturate+0x128/0x148
[2.673118]  component_aggregate_register+0x388/0x390
[2.673763]  mtk_iommu_probe+0x638/0x690

[2.686467] [ cut here ]
[2.687049] refcount_t: saturated; leaking memory.
[2.687666] WARNING: CPU: 5 PID: 74 at ../v5.16-
rc1/kernel/mediatek/lib/refcount.c:19 refcount_warn_saturate+0xfc/0x148

[2.703805] Call trace:
[2.704117]  refcount_warn_saturate+0xfc/0x148
[2.704685]  component_aggregate_register+0x1fc/0x390
[2.705330]  mtk_iommu_probe+0x638/0x690

> + }
> + mutex_unlock(_mutex);
> +
> + return ret;
>  }
> 
>  static void aggregate_driver_unregister(struct aggregate_driver
> *adrv)
>  {
> - driver_unregister(>driver);
> + if (refcount_dec_and_mutex_lock(>count,
> _mutex)) {
> + driver_unregister(>driver);
> + mutex_unlock(_mutex);
> + }
>  }
> 
>  static struct aggregate_device *aggregate_device_add(struct device
> *parent,
> diff --git a/include/linux/component.h b/include/linux/component.h
> index 53d81203c095..b061341938aa 100644
> --- a/include/linux/component.h
> +++ b/include/linux/component.h
> @@ -4,6 +4,7 @@
> 
>  #include 
>  #include 
> +#include 
> 
>  struct aggregate_device;
> 
> @@ -66,6 +67,7 @@ struct device *aggregate_device_parent(const struct
> aggregate_device *adev);
> 
>  /**
>   * struct aggregate_driver - Aggregat

Re: [PATCH v5 25/32] iommu/mtk: Migrate to aggregate driver

2022-01-11 Thread Yong Wu
Hi Stephen,

Thanks for helping update here.

On Thu, 2022-01-06 at 13:45 -0800, Stephen Boyd wrote:
> Use an aggregate driver instead of component ops so that we can get
> proper driver probe ordering of the aggregate device with respect to
> all
> the component devices that make up the aggregate device.
> 
> Cc: Yong Wu 
> Cc: Joerg Roedel 
> Cc: Will Deacon 
> Cc: Daniel Vetter 
> Cc: "Rafael J. Wysocki" 
> Cc: Rob Clark 
> Cc: Russell King 
> Cc: Saravana Kannan 
> Signed-off-by: Stephen Boyd 

When I test this on mt8195 which have two IOMMU HWs(calling
component_aggregate_regsiter twice), it will abort like this. Then what
should we do if we have two instances?
Thanks.

[2.652424] Error: Driver 'mtk_iommu_agg' is already registered,
aborting...
[2.654033] mtk-iommu: probe of 1c01f000.iommu failed with error -16
[2.662034] Unable to handle kernel NULL pointer dereference at
virtual address 0020
...
[2.672413] pc : aggregate_device_match+0xa8/0x1c8
[2.673027] lr : aggregate_device_match+0x68/0x1c8
...
[2.683091] Call trace:
[2.683403]  aggregate_device_match+0xa8/0x1c8
[2.683970]  __device_attach_driver+0x38/0xd0
[2.684526]  bus_for_each_drv+0x68/0xd0
[2.685015]  __device_attach+0xec/0x148
[2.685503]  device_attach+0x14/0x20
[2.685960]  bus_rescan_devices_helper+0x50/0x90
[2.686545]  bus_for_each_dev+0x7c/0xd8
[2.687033]  bus_rescan_devices+0x20/0x30
[2.687542]  __component_add+0x7c/0xa0
[2.688022]  component_add+0x14/0x20
[2.688479]  mtk_smi_larb_probe+0xe0/0x120


> ---
>  drivers/iommu/mtk_iommu.c| 14 +-
>  drivers/iommu/mtk_iommu.h|  6 --
>  drivers/iommu/mtk_iommu_v1.c | 14 +-
>  3 files changed, 22 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 25b834104790..8e722898cbe2 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -752,9 +752,13 @@ static int mtk_iommu_hw_init(const struct
> mtk_iommu_data *data)
>   return 0;
>  }
>  
> -static const struct component_master_ops mtk_iommu_com_ops = {
> - .bind   = mtk_iommu_bind,
> - .unbind = mtk_iommu_unbind,
> +static struct aggregate_driver mtk_iommu_aggregate_driver = {
> + .probe  = mtk_iommu_bind,
> + .remove = mtk_iommu_unbind,
> + .driver = {
> + .name   = "mtk_iommu_agg",
> + .owner  = THIS_MODULE,
> + },
>  };
>  
>  static int mtk_iommu_probe(struct platform_device *pdev)
> @@ -895,7 +899,7 @@ static int mtk_iommu_probe(struct platform_device
> *pdev)
>   goto out_list_del;
>   }
>  
> - ret = component_master_add_with_match(dev, _iommu_com_ops,
> match);
> + ret = component_aggregate_register(dev,
> _iommu_aggregate_driver, match);
>   if (ret)
>   goto out_bus_set_null;
>   return ret;
> @@ -928,7 +932,7 @@ static int mtk_iommu_remove(struct
> platform_device *pdev)
>   device_link_remove(data->smicomm_dev, >dev);
>   pm_runtime_disable(>dev);
>   devm_free_irq(>dev, data->irq, data);
> - component_master_del(>dev, _iommu_com_ops);
> + component_aggregate_unregister(>dev,
> _iommu_aggregate_driver);
>   return 0;
>  }
>  
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index f81fa8862ed0..064fd4f4eade 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -94,15 +94,17 @@ static inline void release_of(struct device *dev,
> void *data)
>   of_node_put(data);
>  }
>  
> -static inline int mtk_iommu_bind(struct device *dev)
> +static inline int mtk_iommu_bind(struct aggregate_device *adev)
>  {
> + struct device *dev = adev->parent;
>   struct mtk_iommu_data *data = dev_get_drvdata(dev);
>  
>   return component_bind_all(dev, >larb_imu);
>  }
>  
> -static inline void mtk_iommu_unbind(struct device *dev)
> +static inline void mtk_iommu_unbind(struct aggregate_device *adev)
>  {
> + struct device *dev = adev->parent;
>   struct mtk_iommu_data *data = dev_get_drvdata(dev);
>  
>   component_unbind_all(dev, >larb_imu);
> diff --git a/drivers/iommu/mtk_iommu_v1.c
> b/drivers/iommu/mtk_iommu_v1.c
> index be22fcf988ce..5fb29058a165 100644
> --- a/drivers/iommu/mtk_iommu_v1.c
> +++ b/drivers/iommu/mtk_iommu_v1.c
> @@ -534,9 +534,13 @@ static const struct of_device_id
> mtk_iommu_of_ids[] = {
>   {}
>  };
>  
> -static const struct component_master_ops mtk_iommu_com_ops = {
> - .bind   = mtk_iommu_bind,
> - .unbind = mtk_iommu

[PATCH v9 15/15] arm64: dts: mediatek: Get rid of mediatek, larb for MM nodes

2021-11-12 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi,
the mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 16 
 arch/arm64/boot/dts/mediatek/mt8183.dtsi |  6 --
 2 files changed, 22 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi 
b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index d9e005ae5bb0..205c221696a6 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -1009,7 +1009,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA0>;
-   mediatek,larb = <>;
mediatek,vpu = <>;
};
 
@@ -1020,7 +1019,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA1>;
-   mediatek,larb = <>;
};
 
mdp_rsz0: rsz@14003000 {
@@ -1050,7 +1048,6 @@
clocks = < CLK_MM_MDP_WDMA>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WDMA>;
-   mediatek,larb = <>;
};
 
mdp_wrot0: wrot@14007000 {
@@ -1059,7 +1056,6 @@
clocks = < CLK_MM_MDP_WROT0>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT0>;
-   mediatek,larb = <>;
};
 
mdp_wrot1: wrot@14008000 {
@@ -1068,7 +1064,6 @@
clocks = < CLK_MM_MDP_WROT1>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT1>;
-   mediatek,larb = <>;
};
 
ovl0: ovl@1400c000 {
@@ -1078,7 +1073,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xc000 
0x1000>;
};
 
@@ -1089,7 +1083,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xd000 
0x1000>;
};
 
@@ -1100,7 +1093,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xe000 
0x1000>;
};
 
@@ -,7 +1103,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xf000 
0x1000>;
};
 
@@ -1122,7 +1113,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0 
0x1000>;
};
 
@@ -1133,7 +1123,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x1000 
0x1000>;
};
 
@@ -1144,7 +1133,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x2000 
0x1000>;
};
 
@@ -1395,7 +1383,6 @@
  <0 0x16027800 0 0x800>,   /* VDEC_HWB */
 

[PATCH v9 14/15] arm: dts: mediatek: Get rid of mediatek, larb for MM nodes

2021-11-12 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi, the
mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 arch/arm/boot/dts/mt2701.dtsi  | 2 --
 arch/arm/boot/dts/mt7623n.dtsi | 5 -
 2 files changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 4776f85d6d5b..ef583cfd3baf 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -564,7 +564,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -577,7 +576,6 @@
clocks =  < CLK_IMG_VENC>;
clock-names = "jpgenc";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGENC_RDMA>,
 < MT2701_M4U_PORT_JPGENC_BSDMA>;
};
diff --git a/arch/arm/boot/dts/mt7623n.dtsi b/arch/arm/boot/dts/mt7623n.dtsi
index bcb0846e29fd..3adab5cd1fef 100644
--- a/arch/arm/boot/dts/mt7623n.dtsi
+++ b/arch/arm/boot/dts/mt7623n.dtsi
@@ -121,7 +121,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -144,7 +143,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_OVL>;
iommus = < MT2701_M4U_PORT_DISP_OVL_0>;
-   mediatek,larb = <>;
};
 
rdma0: rdma@14008000 {
@@ -154,7 +152,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA>;
iommus = < MT2701_M4U_PORT_DISP_RDMA>;
-   mediatek,larb = <>;
};
 
wdma@14009000 {
@@ -164,7 +161,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_WDMA>;
iommus = < MT2701_M4U_PORT_DISP_WDMA>;
-   mediatek,larb = <>;
};
 
bls: pwm@1400a000 {
@@ -215,7 +211,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < MT2701_M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
};
 
dpi0: dpi@14014000 {
-- 
2.18.0



[PATCH v9 13/15] memory: mtk-smi: Get rid of mtk_smi_larb_get/put

2021-11-12 Thread Yong Wu
After adding device_link between the iommu consumer and smi-larb,
the pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. we can get rid of mtk_smi_larb_get/put.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Krzysztof Kozlowski 
Acked-by: Matthias Brugger 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/memory/mtk-smi.c   | 14 --
 include/soc/mediatek/smi.h | 20 
 2 files changed, 34 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index c5fb51f73b34..7c61c924e220 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -134,20 +134,6 @@ static void mtk_smi_clk_disable(const struct mtk_smi *smi)
clk_disable_unprepare(smi->clk_apb);
 }
 
-int mtk_smi_larb_get(struct device *larbdev)
-{
-   int ret = pm_runtime_resume_and_get(larbdev);
-
-   return (ret < 0) ? ret : 0;
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
-
-void mtk_smi_larb_put(struct device *larbdev)
-{
-   pm_runtime_put_sync(larbdev);
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
-
 static int
 mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 {
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 15e3397cec58..11f7d6b59642 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -19,26 +19,6 @@ struct mtk_smi_larb_iommu {
unsigned char  bank[32];
 };
 
-/*
- * mtk_smi_larb_get: Enable the power domain and clocks for this local arbiter.
- *   It also initialize some basic setting(like iommu).
- * mtk_smi_larb_put: Disable the power domain and clocks for this local 
arbiter.
- * Both should be called in non-atomic context.
- *
- * Returns 0 if successful, negative on failure.
- */
-int mtk_smi_larb_get(struct device *larbdev);
-void mtk_smi_larb_put(struct device *larbdev);
-
-#else
-
-static inline int mtk_smi_larb_get(struct device *larbdev)
-{
-   return 0;
-}
-
-static inline void mtk_smi_larb_put(struct device *larbdev) { }
-
 #endif
 
 #endif
-- 
2.18.0



[PATCH v9 12/15] media: mtk-vcodec: enc: Remove mtk_vcodec_release_enc_pm

2021-11-12 Thread Yong Wu
After this patchset, mtk_vcodec_release_enc_pm has only one line.
then remove that function, use pm_runtime_disable instead.

meanwhile, mtk_vcodec_init_enc_pm only operate for the clocks,
rename it from the _pm to _clk.

No functional change.

CC: Tiffany Lin 
CC: Irui Wang 
Signed-off-by: Yong Wu 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 6 +++---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  | 8 +---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  | 3 +--
 3 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
index 45d1870c83dd..136798051f21 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -272,7 +272,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
return PTR_ERR(dev->fw_handler);
 
dev->venc_pdata = of_device_get_match_data(>dev);
-   ret = mtk_vcodec_init_enc_pm(dev);
+   ret = mtk_vcodec_init_enc_clk(dev);
if (ret < 0) {
dev_err(>dev, "Failed to get mtk vcodec clock source!");
goto err_enc_pm;
@@ -384,7 +384,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
 err_enc_alloc:
v4l2_device_unregister(>v4l2_dev);
 err_res:
-   mtk_vcodec_release_enc_pm(dev);
+   pm_runtime_disable(>dev);
 err_enc_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -463,7 +463,7 @@ static int mtk_vcodec_enc_remove(struct platform_device 
*pdev)
video_unregister_device(dev->vfd_enc);
 
v4l2_device_unregister(>v4l2_dev);
-   mtk_vcodec_release_enc_pm(dev);
+   pm_runtime_disable(>dev);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
index dffb190267ed..12637908e5f6 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -12,7 +12,7 @@
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vcodec_util.h"
 
-int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
+int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
 {
struct platform_device *pdev;
struct mtk_vcodec_pm *pm;
@@ -60,12 +60,6 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
return 0;
 }
 
-void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
-{
-   pm_runtime_disable(mtkdev->pm.dev);
-}
-
-
 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
 {
struct mtk_vcodec_clk *enc_clk = >venc_clk;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
index b7ecdfd74823..bc455cefc0cd 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
@@ -9,8 +9,7 @@
 
 #include "mtk_vcodec_drv.h"
 
-int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *dev);
-void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *dev);
 
 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm);
-- 
2.18.0



[PATCH v9 11/15] media: mtk-vcodec: dec: Remove mtk_vcodec_release_dec_pm

2021-11-12 Thread Yong Wu
After this patchset, mtk_vcodec_release_dec_pm has only one line.
then remove that function. Use pm_runtime_disable directly instead.

For symmetry, move the pm_runtime_enable out from
mtk_vcodec_init_dec_pm, then mtk_vcodec_init_dec_pm only operate for
the clocks, rename it from the _pm to _clk.

No functional change.

CC: Tiffany Lin 
CC: Yunfei Dong 
Signed-off-by: Yong Wu 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 8 +---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c  | 9 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h  | 3 +--
 3 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index f87dc47d9e63..830c400b9830 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -240,12 +241,13 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
if (IS_ERR(dev->fw_handler))
return PTR_ERR(dev->fw_handler);
 
-   ret = mtk_vcodec_init_dec_pm(dev);
+   ret = mtk_vcodec_init_dec_clk(dev);
if (ret < 0) {
dev_err(>dev, "Failed to get mt vcodec clock source");
goto err_dec_pm;
}
 
+   pm_runtime_enable(>dev);
for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
dev->reg_base[i] = devm_platform_ioremap_resource(pdev, i);
if (IS_ERR((__force void *)dev->reg_base[i])) {
@@ -345,7 +347,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
 err_dec_alloc:
v4l2_device_unregister(>v4l2_dev);
 err_res:
-   mtk_vcodec_release_dec_pm(dev);
+   pm_runtime_disable(>dev);
 err_dec_pm:
mtk_vcodec_fw_release(dev->fw_handler);
return ret;
@@ -371,7 +373,7 @@ static int mtk_vcodec_dec_remove(struct platform_device 
*pdev)
video_unregister_device(dev->vfd_dec);
 
v4l2_device_unregister(>v4l2_dev);
-   mtk_vcodec_release_dec_pm(dev);
+   pm_runtime_disable(>dev);
mtk_vcodec_fw_release(dev->fw_handler);
return 0;
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index d0bf9aa3b29d..3df87944e9a2 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -12,7 +12,7 @@
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
-int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
+int mtk_vcodec_init_dec_clk(struct mtk_vcodec_dev *mtkdev)
 {
struct platform_device *pdev;
struct mtk_vcodec_pm *pm;
@@ -57,16 +57,9 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
return PTR_ERR(clk_info->vcodec_clk);
}
}
-
-   pm_runtime_enable(>dev);
return 0;
 }
 
-void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
-{
-   pm_runtime_disable(dev->pm.dev);
-}
-
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
 {
int ret;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
index 280aeaefdb65..dace91401e23 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -9,8 +9,7 @@
 
 #include "mtk_vcodec_drv.h"
 
-int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
-void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
+int mtk_vcodec_init_dec_clk(struct mtk_vcodec_dev *dev);
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
-- 
2.18.0



[PATCH v9 10/15] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put

2021-11-12 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the vcodec device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Tiffany Lin 
CC: Irui Wang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Tiffany Lin 
Reviewed-by: Dafna Hirschfeld 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 37 +++-
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 --
 .../platform/mtk-vcodec/mtk_vcodec_enc.c  |  1 -
 .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   | 44 +++
 4 files changed, 10 insertions(+), 75 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 6038db96f71c..d0bf9aa3b29d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -8,14 +8,12 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
 int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
 {
-   struct device_node *node;
struct platform_device *pdev;
struct mtk_vcodec_pm *pm;
struct mtk_vcodec_clk *dec_clk;
@@ -26,18 +24,7 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
pm = >pm;
pm->mtkdev = mtkdev;
dec_clk = >vdec_clk;
-   node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
-   if (!node) {
-   mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
-   return -1;
-   }
 
-   pdev = of_find_device_by_node(node);
-   of_node_put(node);
-   if (WARN_ON(!pdev)) {
-   return -1;
-   }
-   pm->larbvdec = >dev;
pdev = mtkdev->plat_dev;
pm->dev = >dev;
 
@@ -47,14 +34,11 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
dec_clk->clk_info = devm_kcalloc(>dev,
dec_clk->clk_num, sizeof(*clk_info),
GFP_KERNEL);
-   if (!dec_clk->clk_info) {
-   ret = -ENOMEM;
-   goto put_device;
-   }
+   if (!dec_clk->clk_info)
+   return -ENOMEM;
} else {
mtk_v4l2_err("Failed to get vdec clock count");
-   ret = -EINVAL;
-   goto put_device;
+   return -EINVAL;
}
 
for (i = 0; i < dec_clk->clk_num; i++) {
@@ -63,29 +47,24 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
"clock-names", i, _info->clk_name);
if (ret) {
mtk_v4l2_err("Failed to get clock name id = %d", i);
-   goto put_device;
+   return ret;
}
clk_info->vcodec_clk = devm_clk_get(>dev,
clk_info->clk_name);
if (IS_ERR(clk_info->vcodec_clk)) {
mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
clk_info->clk_name);
-   ret = PTR_ERR(clk_info->vcodec_clk);
-   goto put_device;
+   return PTR_ERR(clk_info->vcodec_clk);
}
}
 
pm_runtime_enable(>dev);
return 0;
-put_device:
-   put_device(pm->larbvdec);
-   return ret;
 }
 
 void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
 {
pm_runtime_disable(dev->pm.dev);
-   put_device(dev->pm.larbvdec);
 }
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
@@ -122,11 +101,6 @@ void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
}
}
 
-   ret = mtk_smi_larb_get(pm->larbvdec);
-   if (ret) {
-   mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
-   goto error;
-   }
return;
 
 error:
@@ -139,7 +113,6 @@ void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
struct mtk_vcodec_clk *dec_clk = >vdec_clk;
int i = 0;
 
-   mtk_smi_larb_put(pm->larbvdec);
for (i = dec_clk->clk_num - 1; i >= 0; i--)
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index c6c7672fecfb..64b73dd880ce 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -189,10 +189,7 @@ struct mtk_vcodec_clk {
  */
 struct mtk_vcodec_pm {
struct mtk_vcodec_clk   vdec_clk;
-   struct device   *larbvdec;
-
struct mtk_vcodec_clk   venc_clk;
-   struct device   *larbvenc;
  

[PATCH v9 09/15] drm/mediatek: Get rid of mtk_smi_larb_get/put

2021-11-12 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the drm device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: CK Hu 
CC: Philipp Zabel 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Chun-Kuang Hu 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 10 --
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 36 ++---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |  1 -
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  5 +--
 4 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 455ea23c6130..445c30cc823f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -12,7 +12,6 @@
 #include 
 
 #include 
-#include 
 
 #include 
 #include 
@@ -643,22 +642,14 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
-   ret = mtk_smi_larb_get(comp->larb_dev);
-   if (ret) {
-   DRM_ERROR("Failed to get larb: %d\n", ret);
-   return;
-   }
-
ret = pm_runtime_resume_and_get(comp->dev);
if (ret < 0) {
-   mtk_smi_larb_put(comp->larb_dev);
DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
return;
}
 
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
-   mtk_smi_larb_put(comp->larb_dev);
pm_runtime_put(comp->dev);
return;
}
@@ -695,7 +686,6 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
-   mtk_smi_larb_put(comp->larb_dev);
ret = pm_runtime_put(comp->dev);
if (ret < 0)
DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 99cbf44463e4..48642e814370 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -414,37 +414,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct 
drm_device *drm,
return ret;
 }
 
-static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp 
*comp,
-   struct device *dev)
-{
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", 
node);
-   return -EINVAL;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   return -EPROBE_DEFER;
-   }
-   of_node_put(larb_node);
-   comp->larb_dev = _pdev->dev;
-
-   return 0;
-}
-
 int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
  enum mtk_ddp_comp_id comp_id)
 {
struct platform_device *comp_pdev;
enum mtk_ddp_comp_type type;
struct mtk_ddp_comp_dev *priv;
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
int ret;
+#endif
 
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -460,16 +438,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct 
mtk_ddp_comp *comp,
}
comp->dev = _pdev->dev;
 
-   /* Only DMA capable components need the LARB property */
-   if (type == MTK_DISP_OVL ||
-   type == MTK_DISP_OVL_2L ||
-   type == MTK_DISP_RDMA ||
-   type == MTK_DISP_WDMA) {
-   ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
-   if (ret)
-   return ret;
-   }
-
if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS ||
type == MTK_DISP_CCORR ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index bb914d976cf5..1b582262b682 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -70,7 +70,6 @@ struct mtk_ddp_comp_funcs {
 struct mtk_ddp_comp {
struct device *dev;
int irq;
-   struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
 };
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index aec39724ebeb..c234293fc2c3 100644
--- a/drivers/g

[PATCH v9 08/15] drm/mediatek: Add pm runtime support for ovl and rdma

2021-11-12 Thread Yong Wu
From: Yongqiang Niu 

Prepare for smi cleaning up "mediatek,larb".

Display use the dispsys device to call pm_rumtime_get_sync before.
This patch add pm_runtime_xx with ovl and rdma device whose nodes has
"iommus" property, then display could help pm_runtime_get for smi via
ovl or rdma device.

CC: CK Hu 
Signed-off-by: Yongqiang Niu 
Signed-off-by: Yong Wu 
(Yong: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync)
Acked-by: Chun-Kuang Hu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c  |  8 +++-
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c |  9 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c  | 13 -
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 5326989d5206..716eac6831f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -414,9 +415,13 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_ovl_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -424,6 +429,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 static int mtk_disp_ovl_remove(struct platform_device *pdev)
 {
component_del(>dev, _disp_ovl_component_ops);
+   pm_runtime_disable(>dev);
 
return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c 
b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 75d7f45579e2..251f034acb09 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -327,9 +328,13 @@ static int mtk_disp_rdma_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, priv);
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_rdma_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -338,6 +343,8 @@ static int mtk_disp_rdma_remove(struct platform_device 
*pdev)
 {
component_del(>dev, _disp_rdma_component_ops);
 
+   pm_runtime_disable(>dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 5f81489fc60c..455ea23c6130 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -649,9 +649,17 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
return;
}
 
+   ret = pm_runtime_resume_and_get(comp->dev);
+   if (ret < 0) {
+   mtk_smi_larb_put(comp->larb_dev);
+   DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
+   return;
+   }
+
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
mtk_smi_larb_put(comp->larb_dev);
+   pm_runtime_put(comp->dev);
return;
}
 
@@ -664,7 +672,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 {
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-   int i;
+   int i, ret;
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
@@ -688,6 +696,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
mtk_smi_larb_put(comp->larb_dev);
+   ret = pm_runtime_put(comp->dev);
+   if (ret < 0)
+   DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
 
mtk_crtc->enabled = false;
 }
-- 
2.18.0



[PATCH v9 07/15] media: mtk-mdp: Get rid of mtk_smi_larb_get/put

2021-11-12 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the mdp device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Minghsiu Tsai 
CC: Houlong Wei 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Reviewed-by: Houlong Wei 
Reviewed-by: Dafna Hirschfeld 
---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 40 ---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h |  2 -
 drivers/media/platform/mtk-mdp/mtk_mdp_core.c |  1 -
 3 files changed, 43 deletions(-)

diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
index b3426a551bea..1e3833f1c9ae 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_comp.h"
 
@@ -18,14 +17,6 @@ void mtk_mdp_comp_clock_on(struct device *dev, struct 
mtk_mdp_comp *comp)
 {
int i, err;
 
-   if (comp->larb_dev) {
-   err = mtk_smi_larb_get(comp->larb_dev);
-   if (err)
-   dev_err(dev,
-   "failed to get larb, err %d. type:%d\n",
-   err, comp->type);
-   }
-
for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
if (IS_ERR(comp->clk[i]))
continue;
@@ -46,17 +37,12 @@ void mtk_mdp_comp_clock_off(struct device *dev, struct 
mtk_mdp_comp *comp)
continue;
clk_disable_unprepare(comp->clk[i]);
}
-
-   if (comp->larb_dev)
-   mtk_smi_larb_put(comp->larb_dev);
 }
 
 int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
  struct mtk_mdp_comp *comp,
  enum mtk_mdp_comp_type comp_type)
 {
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
int ret;
int i;
 
@@ -77,32 +63,6 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node 
*node,
break;
}
 
-   /* Only DMA capable components need the LARB property */
-   comp->larb_dev = NULL;
-   if (comp->type != MTK_MDP_RDMA &&
-   comp->type != MTK_MDP_WDMA &&
-   comp->type != MTK_MDP_WROT)
-   return 0;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev,
-   "Missing mediadek,larb phandle in %pOF node\n", node);
-   ret = -EINVAL;
-   goto put_dev;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   ret = -EPROBE_DEFER;
-   goto put_dev;
-   }
-   of_node_put(larb_node);
-
-   comp->larb_dev = _pdev->dev;
-
return 0;
 
 put_dev:
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
index 7897766c96bb..ae41dd3cd72a 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
@@ -26,14 +26,12 @@ enum mtk_mdp_comp_type {
  * @node:  list node to track sibing MDP components
  * @dev_node:  component device node
  * @clk:   clocks required for component
- * @larb_dev:  SMI device required for component
  * @type:  component type
  */
 struct mtk_mdp_comp {
struct list_headnode;
struct device_node  *dev_node;
struct clk  *clk[2];
-   struct device   *larb_dev;
enum mtk_mdp_comp_type  type;
 };
 
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
index 976aa1f4829b..70a8eab16863 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
@@ -17,7 +17,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_core.h"
 #include "mtk_mdp_m2m.h"
-- 
2.18.0



[PATCH v9 06/15] media: mtk-jpeg: Get rid of mtk_smi_larb_get/put

2021-11-12 Thread Yong Wu
MediaTek IOMMU has already added device_link between the consumer
and smi-larb device. If the jpg device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

After removing the larb_get operations, then mtk_jpeg_clk_init is
also unnecessary. Remove it too.

CC: Rick Chang 
CC: Xia Jiang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Rick Chang 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 45 +--
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h   |  2 -
 2 files changed, 2 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index a89c7b206eef..4fea2c512434 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -22,7 +22,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_jpeg_enc_hw.h"
 #include "mtk_jpeg_dec_hw.h"
@@ -1055,10 +1054,6 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
int ret;
 
-   ret = mtk_smi_larb_get(jpeg->larb);
-   if (ret)
-   dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
-
ret = clk_bulk_prepare_enable(jpeg->variant->num_clks,
  jpeg->variant->clks);
if (ret)
@@ -1069,7 +1064,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
clk_bulk_disable_unprepare(jpeg->variant->num_clks,
   jpeg->variant->clks);
-   mtk_smi_larb_put(jpeg->larb);
 }
 
 static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
@@ -1284,35 +1278,6 @@ static struct clk_bulk_data mtk_jpeg_clocks[] = {
{ .id = "jpgenc" },
 };
 
-static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
-{
-   struct device_node *node;
-   struct platform_device *pdev;
-   int ret;
-
-   node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0);
-   if (!node)
-   return -EINVAL;
-   pdev = of_find_device_by_node(node);
-   if (WARN_ON(!pdev)) {
-   of_node_put(node);
-   return -EINVAL;
-   }
-   of_node_put(node);
-
-   jpeg->larb = >dev;
-
-   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
-   jpeg->variant->clks);
-   if (ret) {
-   dev_err(>dev, "failed to get jpeg clock:%d\n", ret);
-   put_device(>dev);
-   return ret;
-   }
-
-   return 0;
-}
-
 static void mtk_jpeg_job_timeout_work(struct work_struct *work)
 {
struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1333,11 +1298,6 @@ static void mtk_jpeg_job_timeout_work(struct work_struct 
*work)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
-static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
-{
-   put_device(jpeg->larb);
-}
-
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
struct mtk_jpeg_dev *jpeg;
@@ -1376,7 +1336,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_req_irq;
}
 
-   ret = mtk_jpeg_clk_init(jpeg);
+   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
+   jpeg->variant->clks);
if (ret) {
dev_err(>dev, "Failed to init clk, err %d\n", ret);
goto err_clk_init;
@@ -1442,7 +1403,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
v4l2_device_unregister(>v4l2_dev);
 
 err_dev_register:
-   mtk_jpeg_clk_release(jpeg);
 
 err_clk_init:
 
@@ -1460,7 +1420,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
video_device_release(jpeg->vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(>v4l2_dev);
-   mtk_jpeg_clk_release(jpeg);
 
return 0;
 }
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 595f7f10c9fd..3e4811a41ba2 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -85,7 +85,6 @@ struct mtk_jpeg_variant {
  * @alloc_ctx: videobuf2 memory allocator's context
  * @vdev:  video device node for jpeg mem2mem mode
  * @reg_base:  JPEG registers mapping
- * @larb:  SMI device
  * @job_timeout_work:  IRQ timeout structure
  * @variant:   driver variant to be used
  */
@@ -99,7 +98,6 @@ struct mtk_jpeg_dev {
void*alloc_ctx;
struct video_device *vdev;
void __iomem*reg_base;
-   struct device   *larb;
struct delayed_work job_timeout_work;
const struct mtk_jpeg_variant *variant;
 };
-- 
2.18.0



[PATCH v9 05/15] iommu/mediatek: Add device_link between the consumer and the larb devices

2021-11-12 Thread Yong Wu
MediaTek IOMMU-SMI diagram is like below. all the consumer connect with
smi-larb, then connect with smi-common.

M4U
 |
smi-common
 |
  -
  | |...
  | |
larb1 larb2
  | |
vdec   venc

When the consumer works, it should enable the smi-larb's power which
also need enable the smi-common's power firstly.

Thus, First of all, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

This patch adds device_link between the consumer and the larbs.

When device_link_add, I add the flag DL_FLAG_STATELESS to avoid calling
pm_runtime_xx to keep the original status of clocks. It can avoid two
issues:
1) Display HW show fastlogo abnormally reported in [1]. At the beggining,
all the clocks are enabled before entering kernel, but the clocks for
display HW(always in larb0) will be gated after clk_enable and clk_disable
called from device_link_add(->pm_runtime_resume) and rpm_idle. The clock
operation happened before display driver probe. At that time, the display
HW will be abnormal.

2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to skip
pm_runtime_xx to avoid the deadlock.

Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
device_link_removed should be added explicitly.

Meanwhile, Currently we don't have a device connect with 2 larbs at the
same time. Disallow this case, print the error log.

[1] https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
[2] https://lore.kernel.org/patchwork/patch/1086569/

Suggested-by: Tomasz Figa 
Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/iommu/mtk_iommu.c| 30 ++
 drivers/iommu/mtk_iommu_v1.c | 29 -
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 0033c0634e5e..5fed0b64ddd0 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -560,22 +560,52 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_data *data;
+   struct device_link *link;
+   struct device *larbdev;
+   unsigned int larbid, larbidx, i;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return ERR_PTR(-ENODEV); /* Not a iommu client device */
 
data = dev_iommu_priv_get(dev);
 
+   /*
+* Link the consumer device with the smi-larb device(supplier).
+* The device that connects with each a larb is a independent HW.
+* All the ports in each a device should be in the same larbs.
+*/
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   for (i = 1; i < fwspec->num_ids; i++) {
+   larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]);
+   if (larbid != larbidx) {
+   dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
+   larbid, larbidx);
+   return ERR_PTR(-EINVAL);
+   }
+   }
+   larbdev = data->larb_imu[larbid].dev;
+   link = device_link_add(dev, larbdev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link)
+   dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
return >iommu;
 }
 
 static void mtk_iommu_release_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   struct mtk_iommu_data *data;
+   struct device *larbdev;
+   unsigned int larbid;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return;
 
+   data = dev_iommu_priv_get(dev);
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   larbdev = data->larb_imu[larbid].dev;
+   device_link_remove(dev, larbdev);
+
iommu_fwspec_free(dev);
 }
 
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 4089077256f4..4052aad75a81 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -423,7 +423,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct of_phandle_args iommu_spec;
struct mtk_iommu_data *data;
-   int err, idx = 0;
+   int err, idx = 0, larbid, larbidx;
+   struct device_link *link;
+   struct device *larbdev;
 
/*
 * In the deferred case, free the existed fwspec.
@@ -453,6 +455,23 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 
data = dev_iommu_priv_get(dev);
 
+   /* Link the consumer device with the smi-larb device(supplier) */
+   larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
+   for (idx = 1; idx < fwspec->num_ids; idx++) 

[PATCH v9 04/15] iommu/mediatek: Add probe_defer for smi-larb

2021-11-12 Thread Yong Wu
Prepare for adding device_link.

The iommu consumer should use device_link to connect with the
smi-larb(supplier). then the smi-larb should run before the iommu
consumer. Here we delay the iommu driver until the smi driver is ready,
then all the iommu consumers always are after the smi driver.

When there is no this patch, if some consumer drivers run before
smi-larb, the supplier link_status is DL_DEV_NO_DRIVER(0) in the
device_link_add, then device_links_driver_bound will use WARN_ON
to complain that the link_status of supplier is not right.

device_is_bound may be more elegant here. but it is not allowed to
EXPORT from https://lore.kernel.org/patchwork/patch/1334670/.

Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/iommu/mtk_iommu.c| 4 
 drivers/iommu/mtk_iommu_v1.c | 4 
 2 files changed, 8 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 8f566d2e72e5..0033c0634e5e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -848,6 +848,10 @@ static int mtk_iommu_probe(struct platform_device *pdev)
of_node_put(larbnode);
return -ENODEV;
}
+   if (!plarbdev->dev.driver) {
+   of_node_put(larbnode);
+   return -EPROBE_DEFER;
+   }
data->larb_imu[id].dev = >dev;
 
component_match_add_release(dev, , release_of,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 68bf02f87cfd..4089077256f4 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -606,6 +606,10 @@ static int mtk_iommu_probe(struct platform_device *pdev)
of_node_put(larbnode);
return -ENODEV;
}
+   if (!plarbdev->dev.driver) {
+   of_node_put(larbnode);
+   return -EPROBE_DEFER;
+   }
data->larb_imu[i].dev = >dev;
 
component_match_add_release(dev, , release_of,
-- 
2.18.0



[PATCH v9 03/15] iommu/mediatek: Return ENODEV if the device is NULL

2021-11-12 Thread Yong Wu
The platform device is created at:
of_platform_default_populate_init:  arch_initcall_sync
  ->of_platform_populate
->of_platform_device_create_pdata

When entering our probe, all the devices should be already created.
if it is null, means NODEV. Currently we don't get the fail case.
It's a minor fix, no need add fixes tags.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c| 2 +-
 drivers/iommu/mtk_iommu_v1.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d837adfd1da5..8f566d2e72e5 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -846,7 +846,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
plarbdev = of_find_device_by_node(larbnode);
if (!plarbdev) {
of_node_put(larbnode);
-   return -EPROBE_DEFER;
+   return -ENODEV;
}
data->larb_imu[id].dev = >dev;
 
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 1467ba1e4417..68bf02f87cfd 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -604,7 +604,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
plarbdev = of_find_device_by_node(larbnode);
if (!plarbdev) {
of_node_put(larbnode);
-   return -EPROBE_DEFER;
+   return -ENODEV;
}
data->larb_imu[i].dev = >dev;
 
-- 
2.18.0



[PATCH v9 02/15] iommu/mediatek-v1: Free the existed fwspec if the master dev already has

2021-11-12 Thread Yong Wu
When the iommu master device enters of_iommu_xlate, the ops may be
NULL(iommu dev is defered), then it will initialize the fwspec here:

[] (dev_iommu_fwspec_set) from []
(iommu_fwspec_init+0xbc/0xd4)
[] (iommu_fwspec_init) from []
(of_iommu_xlate+0x7c/0x12c)
[] (of_iommu_xlate) from []
(of_iommu_configure+0x144/0x1e8)

BUT the mtk_iommu_v1.c only supports arm32, the probing flow still is a bit
weird. We always expect create the fwspec internally. otherwise it will
enter here and return fail.

static int mtk_iommu_create_mapping(struct device *dev,
struct of_phandle_args *args)
{
...
if (!fwspec) {

} else if (dev_iommu_fwspec_get(dev)->ops != _iommu_ops) {
>>>>>>>>>>Enter here. return fail.<<<<<<<<<<<<
return -EINVAL;
}
...
}

Thus, Free the existed fwspec if the master device already has fwspec.

This issue is reported at:
https://lore.kernel.org/linux-mediatek/trinity-7d9ebdc9-4849-4d93-bfb5-429dcb4ee449-1626253158870@3c-app-gmx-bs01/

Reported-by: Frank Wunderlich 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu_v1.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index be22fcf988ce..1467ba1e4417 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -425,6 +425,15 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct mtk_iommu_data *data;
int err, idx = 0;
 
+   /*
+* In the deferred case, free the existed fwspec.
+* Always initialize the fwspec internally.
+*/
+   if (fwspec) {
+   iommu_fwspec_free(dev);
+   fwspec = dev_iommu_fwspec_get(dev);
+   }
+
while (!of_parse_phandle_with_args(dev->of_node, "iommus",
   "#iommu-cells",
   idx, _spec)) {
-- 
2.18.0



[PATCH v9 01/15] dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW

2021-11-12 Thread Yong Wu
After adding device_link between the consumer with the smi-larbs,
if the consumer call its owner pm_runtime_get(_sync), the
pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. Thus, the consumer don't need this property.

And IOMMU also know which larb this consumer connects with from
iommu id in the "iommus=" property.

Signed-off-by: Yong Wu 
Reviewed-by: Rob Herring 
Reviewed-by: Evan Green 
---
 .../bindings/display/mediatek/mediatek,disp.txt  | 9 -
 .../devicetree/bindings/media/mediatek-jpeg-decoder.yaml | 9 -
 .../devicetree/bindings/media/mediatek-jpeg-encoder.yaml | 9 -
 Documentation/devicetree/bindings/media/mediatek-mdp.txt | 8 
 .../devicetree/bindings/media/mediatek-vcodec.txt| 4 
 5 files changed, 39 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
index fbb59c9ddda6..867bd82e2f03 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
@@ -61,8 +61,6 @@ Required properties (DMA function blocks):
"mediatek,-disp-rdma"
"mediatek,-disp-wdma"
   the supported chips are mt2701, mt8167 and mt8173.
-- larb: Should contain a phandle pointing to the local arbiter device as 
defined
-  in 
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
 - iommus: Should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
   for details.
@@ -91,7 +89,6 @@ ovl0: ovl@1400c000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
 };
 
 ovl1: ovl@1400d000 {
@@ -101,7 +98,6 @@ ovl1: ovl@1400d000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
 };
 
 rdma0: rdma@1400e000 {
@@ -111,7 +107,6 @@ rdma0: rdma@1400e000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,rdma-fifosize = <8192>;
 };
 
@@ -122,7 +117,6 @@ rdma1: rdma@1400f000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
 };
 
 rdma2: rdma@1401 {
@@ -132,7 +126,6 @@ rdma2: rdma@1401 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
 };
 
 wdma0: wdma@14011000 {
@@ -142,7 +135,6 @@ wdma0: wdma@14011000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
 };
 
 wdma1: wdma@14012000 {
@@ -152,7 +144,6 @@ wdma1: wdma@14012000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
 };
 
 color0: color@14013000 {
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
index 9b87f036f178..052e752157b4 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
@@ -42,13 +42,6 @@ properties:
   power-domains:
 maxItems: 1
 
-  mediatek,larb:
-$ref: '/schemas/types.yaml#/definitions/phandle'
-description: |
-  Must contain the local arbiters in the current Socs, see
-  
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
-  for details.
-
   iommus:
 maxItems: 2
 description: |
@@ -63,7 +56,6 @@ required:
   - clocks
   - clock-names
   - power-domains
-  - mediatek,larb
   - iommus
 
 additionalProperties: false
@@ -83,7 +75,6 @@ examples:
   clock-names = "jpgdec-smi",
 "jpgdec";
   power-domains = < MT2701_POWER_DOMAIN_ISP>;
-  mediatek,larb = <>;
   iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
< MT2701_M4U_PORT_JPGDEC_BSDMA>;
 };
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
index fcd9b829e036..8bfdfdfaba59 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/me

[PATCH v9 00/15] Clean up "mediatek,larb"

2021-11-12 Thread Yong Wu
MediaTek IOMMU block diagram always like below:

M4U
 |
smi-common
 |
  -
  | |  ...
  | |
larb1 larb2
  | |
vdec   venc

All the consumer connect with smi-larb, then connect with smi-common.

When the consumer works, it should enable the smi-larb's power which also
need enable the smi-common's power firstly.

Thus, Firstly, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

After adding the device_link, then "mediatek,larb" property can be removed.
the iommu consumer don't need call the mtk_smi_larb_get/put to enable
the power and clock of smi-larb and smi-common.

Base on a jpeg dt-bing patchset[1] that already got the necessary R-b.

This patchset cross several tree, From [2], the media tree should be a good 
choice.

[1] 
https://lore.kernel.org/linux-mediatek/20210702102304.3346429-1-hsi...@chromium.org/
[2] 
https://lore.kernel.org/linux-mediatek/e7269c80-5437-6ab9-c1db-df0b94eb9...@gmail.com/

Change notes:
v9: 1) Add return -ENODEV when the dev is null.
2) Add more strict about the case that a iommu consume device use the ports 
in
different larbs. Don't allow this case.
3) Remove two codec interface: mtk_vcodec_release_enc/dec_pm since it only 
has one
line now.

v8: 
https://lore.kernel.org/linux-mediatek/20210929013719.25120-1-yong...@mediatek.com/
1) Rebase on v5.15-rc1.
2) Don't rebase the below mdp patchset that may still need more discuss.

https://lore.kernel.org/linux-mediatek/20210709022324.1607884-1-ei...@chromium.org/
3) Add Frank's Tested-by. Remove Dafna's Tested-by as he requested.

v7: 
https://lore.kernel.org/linux-mediatek/20210730025238.22456-1-yong...@mediatek.com/
1) Fix a arm32 boot fail issue. reported from Frank.
2) Add a return fail in the mtk drm. suggested by Dafna.

v6: 
https://lore.kernel.org/linux-mediatek/20210714025626.5528-1-yong...@mediatek.com/
1) rebase on v5.14-rc1.
2) Fix the issue commented in v5 from Dafna and Hsin-Yi.
3) Remove the patches about using pm_runtime_resume_and_get since they have
   already been merged by other patches.

v5: 
https://lore.kernel.org/linux-mediatek/20210410091128.31823-1-yong...@mediatek.com/
1) Base v5.12-rc2.
2) Remove changing the mtk-iommu to module_platform_driver patch, It have 
already been a
independent patch.

v4: 
https://lore.kernel.org/linux-mediatek/1590826218-23653-1-git-send-email-yong...@mediatek.com/
 
base on v5.7-rc1.
  1) Move drm PM patch before smi patchs.
  2) Change builtin_platform_driver to module_platform_driver since we may need
 build as module.
  3) Rebase many patchset as above.

v3: 
https://lore.kernel.org/linux-iommu/1567503456-24725-1-git-send-email-yong...@mediatek.com/
1) rebase on v5.3-rc1 and the latest mt8183 patchset.
2) Use device_is_bound to check whether the driver is ready from Matthias.  
  
3) Add DL_FLAG_STATELESS flag when calling device_link_add and explain the
   reason in the commit message[3/14].
4) Add a display patch[12/14] into this series. otherwise it may affect
   display HW fastlogo even though it don't happen in mt8183.
   
v2: 
https://lore.kernel.org/linux-iommu/1560171313-28299-1-git-send-email-yong...@mediatek.com/
   1) rebase on v5.2-rc1.
   2) Move adding device_link between the consumer and smi-larb into
iommu_add_device from Robin.
   3) add DL_FLAG_AUTOREMOVE_CONSUMER even though the smi is built-in from Evan.
   4) Remove the shutdown callback in iommu.   

v1: 
https://lore.kernel.org/linux-iommu/1546318276-18993-1-git-send-email-yong...@mediatek.com/

Yong Wu (14):
  dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW
  iommu/mediatek-v1: Free the existed fwspec if the master dev already
has
  iommu/mediatek: Return ENODEV if the device is NULL
  iommu/mediatek: Add probe_defer for smi-larb
  iommu/mediatek: Add device_link between the consumer and the larb
devices
  media: mtk-jpeg: Get rid of mtk_smi_larb_get/put
  media: mtk-mdp: Get rid of mtk_smi_larb_get/put
  drm/mediatek: Get rid of mtk_smi_larb_get/put
  media: mtk-vcodec: Get rid of mtk_smi_larb_get/put
  media: mtk-vcodec: dec: Remove mtk_vcodec_release_dec_pm
  media: mtk-vcodec: enc: Remove mtk_vcodec_release_enc_pm
  memory: mtk-smi: Get rid of mtk_smi_larb_get/put
  arm: dts: mediatek: Get rid of mediatek, larb for MM nodes
  arm64: dts: mediatek: Get rid of mediatek, larb for MM nodes

Yongqiang Niu (1):
  drm/mediatek: Add pm runtime support for ovl and rdma

 .../display/mediatek/mediatek,disp.txt|  9 
 .../bindings/media/mediatek-jpeg-decoder.yaml |  9 
 .../bindings/media/mediatek-jpeg-encoder.yaml |  9 
 .../bindings/media/mediatek-mdp.txt   |  8 ---
 .../bindings/media/mediatek-vcodec.txt|  4 --
 arch/arm/boot/dts/mt2701.dtsi |  2 -
 arch/arm/boot/dts/mt7623n.dtsi  

Re: [PATCH v8 04/12] iommu/mediatek: Add device_link between the consumer and the larb devices

2021-10-24 Thread Yong Wu
On Mon, 2021-10-18 at 09:13 +0200, Dafna Hirschfeld wrote:
> 
> On 16.10.21 04:23, Yong Wu wrote:
> > On Mon, 2021-10-11 at 14:36 +0200, Dafna Hirschfeld wrote:
> > > 
> > > On 29.09.21 03:37, Yong Wu wrote:
> > > > MediaTek IOMMU-SMI diagram is like below. all the consumer
> > > > connect
> > > > with
> > > > smi-larb, then connect with smi-common.
> > > > 
> > > >   M4U
> > > >|
> > > >   smi-common
> > > >|
> > > > -
> > > > | |...
> > > > | |
> > > > larb1 larb2
> > > > | |
> > > > vdec   venc
> > > > 
> > > > When the consumer works, it should enable the smi-larb's power
> > > > which
> > > > also need enable the smi-common's power firstly.
> > > > 
> > > > Thus, First of all, use the device link connect the consumer
> > > > and
> > > > the
> > > > smi-larbs. then add device link between the smi-larb and smi-
> > > > common.
> > > > 
> > > > This patch adds device_link between the consumer and the larbs.
> > > > 
> > > > When device_link_add, I add the flag DL_FLAG_STATELESS to avoid
> > > > calling
> > > > pm_runtime_xx to keep the original status of clocks. It can
> > > > avoid
> > > > two
> > > > issues:
> > > > 1) Display HW show fastlogo abnormally reported in [1]. At the
> > > > beggining,
> > > > all the clocks are enabled before entering kernel, but the
> > > > clocks
> > > > for
> > > > display HW(always in larb0) will be gated after clk_enable and
> > > > clk_disable
> > > > called from device_link_add(->pm_runtime_resume) and rpm_idle.
> > > > The
> > > > clock
> > > > operation happened before display driver probe. At that time,
> > > > the
> > > > display
> > > > HW will be abnormal.
> > > > 
> > > > 2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to
> > > > skip
> > > > pm_runtime_xx to avoid the deadlock.
> > > > 
> > > > Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
> > > > device_link_removed should be added explicitly.
> > > > 
> > > > [1]
> > > > 
https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
> > > > [2] https://lore.kernel.org/patchwork/patch/1086569/
> > > > 
> > > > Suggested-by: Tomasz Figa 
> > > > Signed-off-by: Yong Wu 
> > > > Tested-by: Frank Wunderlich  # BPI-
> > > > R2/MT7623
> > > > ---
> > > >drivers/iommu/mtk_iommu.c| 22 ++
> > > >drivers/iommu/mtk_iommu_v1.c | 20 +++-
> > > >2 files changed, 41 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/drivers/iommu/mtk_iommu.c
> > > > b/drivers/iommu/mtk_iommu.c
> > > > index d5848f78a677..a2fa55899434 100644
> > > > --- a/drivers/iommu/mtk_iommu.c
> > > > +++ b/drivers/iommu/mtk_iommu.c
> > > > @@ -560,22 +560,44 @@ static struct iommu_device
> > > > *mtk_iommu_probe_device(struct device *dev)
> > > >{
> > > > struct iommu_fwspec *fwspec =
> > > > dev_iommu_fwspec_get(dev);
> > > > struct mtk_iommu_data *data;
> > > > +   struct device_link *link;
> > > > +   struct device *larbdev;
> > > > +   unsigned int larbid;
> > > >
> > > > if (!fwspec || fwspec->ops != _iommu_ops)
> > > > return ERR_PTR(-ENODEV); /* Not a iommu client
> > > > device
> > > > */
> > > >
> > > > data = dev_iommu_priv_get(dev);
> > > >
> > > > +   /*
> > > > +* Link the consumer device with the smi-larb
> > > > device(supplier)
> > > > +* The device in each a larb is a independent HW. thus
> > > > only
> > > > link
> > > > +* one larb here.
> > > > +*/
> > > > +   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
> > > 
> > > so larbid is always the same for all the ids of a device?
> > 
> > Yes. For me, each a dtsi node should represent a HW unit which can
> > only
> > connect one larb.
> > 
> > > If so maybe it worth testing it and return error if this is not
> > > the
> > > case.
> > 
> > Thanks for the suggestion. This is very helpful. I did see someone
> > put
> > the different larbs in one node. I will check this, and add return
> 
> I am working on bugs found on media drivers, could you please point
> me to
> that wrong node?
> Will you send a fix to that node in the dtsi?

sorry. I mean it happened in the internal branch and it has already
been fixed internally,  all the upstream nodes are ok for this.

Thanks
> 
> 
> Thanks,
> Dafna
> 
> > EINVAL for this case.
> 
> 
> 
> > 
> > > 
> > > Thanks,
> > > Dafna
> > 
> >   
> > > > 


Re: [PATCH v8 04/12] iommu/mediatek: Add device_link between the consumer and the larb devices

2021-10-15 Thread Yong Wu
On Mon, 2021-10-11 at 14:36 +0200, Dafna Hirschfeld wrote:
> 
> On 29.09.21 03:37, Yong Wu wrote:
> > MediaTek IOMMU-SMI diagram is like below. all the consumer connect
> > with
> > smi-larb, then connect with smi-common.
> > 
> >  M4U
> >   |
> >  smi-common
> >   |
> >-
> >| |...
> >| |
> > larb1 larb2
> >| |
> > vdec   venc
> > 
> > When the consumer works, it should enable the smi-larb's power
> > which
> > also need enable the smi-common's power firstly.
> > 
> > Thus, First of all, use the device link connect the consumer and
> > the
> > smi-larbs. then add device link between the smi-larb and smi-
> > common.
> > 
> > This patch adds device_link between the consumer and the larbs.
> > 
> > When device_link_add, I add the flag DL_FLAG_STATELESS to avoid
> > calling
> > pm_runtime_xx to keep the original status of clocks. It can avoid
> > two
> > issues:
> > 1) Display HW show fastlogo abnormally reported in [1]. At the
> > beggining,
> > all the clocks are enabled before entering kernel, but the clocks
> > for
> > display HW(always in larb0) will be gated after clk_enable and
> > clk_disable
> > called from device_link_add(->pm_runtime_resume) and rpm_idle. The
> > clock
> > operation happened before display driver probe. At that time, the
> > display
> > HW will be abnormal.
> > 
> > 2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to skip
> > pm_runtime_xx to avoid the deadlock.
> > 
> > Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
> > device_link_removed should be added explicitly.
> > 
> > [1] 
> > https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
> > [2] https://lore.kernel.org/patchwork/patch/1086569/
> > 
> > Suggested-by: Tomasz Figa 
> > Signed-off-by: Yong Wu 
> > Tested-by: Frank Wunderlich  # BPI-
> > R2/MT7623
> > ---
> >   drivers/iommu/mtk_iommu.c| 22 ++
> >   drivers/iommu/mtk_iommu_v1.c | 20 +++-
> >   2 files changed, 41 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index d5848f78a677..a2fa55899434 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -560,22 +560,44 @@ static struct iommu_device
> > *mtk_iommu_probe_device(struct device *dev)
> >   {
> > struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> > struct mtk_iommu_data *data;
> > +   struct device_link *link;
> > +   struct device *larbdev;
> > +   unsigned int larbid;
> >   
> > if (!fwspec || fwspec->ops != _iommu_ops)
> > return ERR_PTR(-ENODEV); /* Not a iommu client device
> > */
> >   
> > data = dev_iommu_priv_get(dev);
> >   
> > +   /*
> > +* Link the consumer device with the smi-larb device(supplier)
> > +* The device in each a larb is a independent HW. thus only
> > link
> > +* one larb here.
> > +*/
> > +   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
> 
> so larbid is always the same for all the ids of a device? 

Yes. For me, each a dtsi node should represent a HW unit which can only
connect one larb.

> If so maybe it worth testing it and return error if this is not the
> case.

Thanks for the suggestion. This is very helpful. I did see someone put
the different larbs in one node. I will check this, and add return
EINVAL for this case.

> 
> Thanks,
> Dafna
 
> > 


Re: [PATCH v8 09/12] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put

2021-10-06 Thread Yong Wu
On Thu, 2021-09-30 at 12:57 +0200, Dafna Hirschfeld wrote:
> 
> On 30.09.21 05:28, Yong Wu wrote:
> > Hi Dafna,
> > 
> > Thanks very much for the review.
> > 
> > On Wed, 2021-09-29 at 14:13 +0200, Dafna Hirschfeld wrote:
> > > 
> > > On 29.09.21 03:37, Yong Wu wrote:
> > > > MediaTek IOMMU has already added the device_link between the
> > > > consumer
> > > > and smi-larb device. If the vcodec device call the
> > > > pm_runtime_get_sync,
> > > > the smi-larb's pm_runtime_get_sync also be called
> > > > automatically.
> > > > 
> > > > CC: Tiffany Lin 
> > > > CC: Irui Wang 
> > > > Signed-off-by: Yong Wu 
> > > > Reviewed-by: Evan Green 
> > > > Acked-by: Tiffany Lin 
> > > > Reviewed-by: Dafna Hirschfeld 
> > > > ---
> > > >.../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 37 +++
> > > > ---
> > > > --
> > > >.../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 --
> > > >.../platform/mtk-vcodec/mtk_vcodec_enc.c  |  1 -
> > > >.../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   | 44 +++
> > > > ---

[snip]

> > > >void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
> > > >{
> > > > pm_runtime_disable(dev->pm.dev);
> > > > -   put_device(dev->pm.larbvdec);
> > > >}
> > > 
> > > Now that functions only do  'pm_runtime_disable(dev->pm.dev);' so
> > > it
> > > will be more
> > > readable to remove the function mtk_vcodec_release_dec_pm
> > > and replace with pm_runtime_disable(dev->pm.dev);
> > > Same for the 'enc' equivalent.
> > 
> > Make sense. But It may be not proper if using pm_runtime_disable
> > as the symmetry with mtk_vcodec_init_dec_pm in the
> > mtk_vcodec_probe.
> > 
> > Maybe we should move pm_runtime_enable out from
> > mtk_vcodec_init_dec_pm
> > into mtk_vcodec_probe. I could do a new patch for this. Is this ok
> > for
> > you?
> 
> yes, there is also asymettry when calling pm_runtime* in general,
> I see in the decoder it is called from mtk_vcodec_dec_pm.c
> but in the encoder it is called from mtk_vcodec_enc.c,
> 
> I think all calls to pm_runtime* should be out of the *_pm.c files

OK. I will try this.

> since for example 'mtk_vcodec_dec_pw_on' also do just one call to
> pm_runtime_resume_and_get so this function can also be removed.

I guess this one should be reserved to vcodec guys. I see this function
is changed at [1]. Let's keep this patchset clean.

[1] 
https://patchwork.kernel.org/project/linux-mediatek/patch/20210901083215.25984-10-yunfei.d...@mediatek.com/

> 
> thanks,
> Dafna
> 
> > 
> > > 
> > > Thanks,
> > > Dafna
> > 
> > [snip]
> > ___
> > Linux-mediatek mailing list
> > linux-media...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek
> > 


Re: [PATCH v8 03/12] iommu/mediatek: Add probe_defer for smi-larb

2021-09-30 Thread Yong Wu
On Wed, 2021-09-29 at 18:33 +0200, Dafna Hirschfeld wrote:
> 
> On 29.09.21 03:37, Yong Wu wrote:
> > Prepare for adding device_link.
> > 
> > The iommu consumer should use device_link to connect with the
> > smi-larb(supplier). then the smi-larb should run before the iommu
> > consumer. Here we delay the iommu driver until the smi driver is
> > ready,
> > then all the iommu consumers always are after the smi driver.
> > 
> > When there is no this patch, if some consumer drivers run before
> > smi-larb, the supplier link_status is DL_DEV_NO_DRIVER(0) in the
> > device_link_add, then device_links_driver_bound will use WARN_ON
> > to complain that the link_status of supplier is not right.
> > 
> > device_is_bound may be more elegant here. but it is not allowed to
> > EXPORT from https://lore.kernel.org/patchwork/patch/1334670/.
> > 
> > Signed-off-by: Yong Wu 
> > Tested-by: Frank Wunderlich  # BPI-
> > R2/MT7623
> > ---
> >   drivers/iommu/mtk_iommu.c| 2 +-
> >   drivers/iommu/mtk_iommu_v1.c | 2 +-
> >   2 files changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index d837adfd1da5..d5848f78a677 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -844,7 +844,7 @@ static int mtk_iommu_probe(struct
> > platform_device *pdev)
> > id = i;
> >   
> > plarbdev = of_find_device_by_node(larbnode);
> > -   if (!plarbdev) {
> > +   if (!plarbdev || !plarbdev->dev.driver) {
> > of_node_put(larbnode);
> > return -EPROBE_DEFER;
> 
> if plarbdev is null doesn't that mean that the device does not exist?

This is probe function, Is it possible the platform device is not ready
at this time?

I checked the platform device should be created at:

of_platform_default_populate_init:  arch_initcall_sync
  ->of_platform_populate
  ->of_platform_device_create_pdata

Not sure if this may be delayed for some device. If not, it should be
ENODEV here.

> so we should return -ENODEV in that case?
> 
> thanks,
> Dafna
> 
> > }
> > diff --git a/drivers/iommu/mtk_iommu_v1.c
> > b/drivers/iommu/mtk_iommu_v1.c
> > index 1467ba1e4417..4d7809432239 100644
> > --- a/drivers/iommu/mtk_iommu_v1.c
> > +++ b/drivers/iommu/mtk_iommu_v1.c
> > @@ -602,7 +602,7 @@ static int mtk_iommu_probe(struct
> > platform_device *pdev)
> > }
> >   
> > plarbdev = of_find_device_by_node(larbnode);
> > -   if (!plarbdev) {
> > +   if (!plarbdev || !plarbdev->dev.driver) {
> > of_node_put(larbnode);
> > return -EPROBE_DEFER;
> > }
> > 
> 
> ___
> Linux-mediatek mailing list
> linux-media...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek


Re: [PATCH v8 09/12] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put

2021-09-29 Thread Yong Wu
Hi Dafna,

Thanks very much for the review.

On Wed, 2021-09-29 at 14:13 +0200, Dafna Hirschfeld wrote:
> 
> On 29.09.21 03:37, Yong Wu wrote:
> > MediaTek IOMMU has already added the device_link between the
> > consumer
> > and smi-larb device. If the vcodec device call the
> > pm_runtime_get_sync,
> > the smi-larb's pm_runtime_get_sync also be called automatically.
> > 
> > CC: Tiffany Lin 
> > CC: Irui Wang 
> > Signed-off-by: Yong Wu 
> > Reviewed-by: Evan Green 
> > Acked-by: Tiffany Lin 
> > Reviewed-by: Dafna Hirschfeld 
> > ---
> >   .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 37 +++---
> > --
> >   .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 --
> >   .../platform/mtk-vcodec/mtk_vcodec_enc.c  |  1 -
> >   .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   | 44 +++---
> > -
> >   4 files changed, 10 insertions(+), 75 deletions(-)
> > 
> > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> > b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> > index 6038db96f71c..d0bf9aa3b29d 100644
> > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
> > @@ -8,14 +8,12 @@
> >   #include 
> >   #include 
> >   #include 
> > -#include 
> >   
> >   #include "mtk_vcodec_dec_pm.h"
> >   #include "mtk_vcodec_util.h"
> >   
> >   int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
> >   {
> > -   struct device_node *node;
> > struct platform_device *pdev;
> > struct mtk_vcodec_pm *pm;
> > struct mtk_vcodec_clk *dec_clk;
> > @@ -26,18 +24,7 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev
> > *mtkdev)
> > pm = >pm;
> > pm->mtkdev = mtkdev;
> > dec_clk = >vdec_clk;
> > -   node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
> > -   if (!node) {
> > -   mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
> > -   return -1;
> > -   }
> >   
> > -   pdev = of_find_device_by_node(node);
> > -   of_node_put(node);
> > -   if (WARN_ON(!pdev)) {
> > -   return -1;
> > -   }
> > -   pm->larbvdec = >dev;
> > pdev = mtkdev->plat_dev;
> > pm->dev = >dev;
> >   
> > @@ -47,14 +34,11 @@ int mtk_vcodec_init_dec_pm(struct
> > mtk_vcodec_dev *mtkdev)
> > dec_clk->clk_info = devm_kcalloc(>dev,
> > dec_clk->clk_num, sizeof(*clk_info),
> > GFP_KERNEL);
> > -   if (!dec_clk->clk_info) {
> > -   ret = -ENOMEM;
> > -   goto put_device;
> > -   }
> > +   if (!dec_clk->clk_info)
> > +   return -ENOMEM;
> > } else {
> > mtk_v4l2_err("Failed to get vdec clock count");
> > -   ret = -EINVAL;
> > -   goto put_device;
> > +   return -EINVAL;
> > }
> >   
> > for (i = 0; i < dec_clk->clk_num; i++) {
> > @@ -63,29 +47,24 @@ int mtk_vcodec_init_dec_pm(struct
> > mtk_vcodec_dev *mtkdev)
> > "clock-names", i, _info->clk_name);
> > if (ret) {
> > mtk_v4l2_err("Failed to get clock name id =
> > %d", i);
> > -   goto put_device;
> > +   return ret;
> > }
> > clk_info->vcodec_clk = devm_clk_get(>dev,
> > clk_info->clk_name);
> > if (IS_ERR(clk_info->vcodec_clk)) {
> > mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
> > clk_info->clk_name);
> > -   ret = PTR_ERR(clk_info->vcodec_clk);
> > -   goto put_device;
> > +   return PTR_ERR(clk_info->vcodec_clk);
> > }
> > }
> >   
> > pm_runtime_enable(>dev);
> > return 0;
> > -put_device:
> > -   put_device(pm->larbvdec);
> > -   return ret;
> >   }
> >   
> >   void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
> >   {
> > pm_runtime_disable(dev->pm.dev);
> > -   put_device(dev->pm.larbvdec);
> >   }
> 
> Now that functions only do  'pm_runtime_disable(dev->pm.dev);' so it
> will be more
> readable to remove the function mtk_vcodec_release_dec_pm
> and replace with pm_runtime_disable(dev->pm.dev);
> Same for the 'enc' equivalent.

Make sense. But It may be not proper if using pm_runtime_disable
as the symmetry with mtk_vcodec_init_dec_pm in the mtk_vcodec_probe.

Maybe we should move pm_runtime_enable out from mtk_vcodec_init_dec_pm
into mtk_vcodec_probe. I could do a new patch for this. Is this ok for
you?

> 
> Thanks,
> Dafna

[snip]


[PATCH v8 12/12] arm64: dts: mediatek: Get rid of mediatek, larb for MM nodes

2021-09-28 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi,
the mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 16 
 arch/arm64/boot/dts/mediatek/mt8183.dtsi |  6 --
 2 files changed, 22 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi 
b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index d9e005ae5bb0..205c221696a6 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -1009,7 +1009,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA0>;
-   mediatek,larb = <>;
mediatek,vpu = <>;
};
 
@@ -1020,7 +1019,6 @@
 < CLK_MM_MUTEX_32K>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_RDMA1>;
-   mediatek,larb = <>;
};
 
mdp_rsz0: rsz@14003000 {
@@ -1050,7 +1048,6 @@
clocks = < CLK_MM_MDP_WDMA>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WDMA>;
-   mediatek,larb = <>;
};
 
mdp_wrot0: wrot@14007000 {
@@ -1059,7 +1056,6 @@
clocks = < CLK_MM_MDP_WROT0>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT0>;
-   mediatek,larb = <>;
};
 
mdp_wrot1: wrot@14008000 {
@@ -1068,7 +1064,6 @@
clocks = < CLK_MM_MDP_WROT1>;
power-domains = < MT8173_POWER_DOMAIN_MM>;
iommus = < M4U_PORT_MDP_WROT1>;
-   mediatek,larb = <>;
};
 
ovl0: ovl@1400c000 {
@@ -1078,7 +1073,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xc000 
0x1000>;
};
 
@@ -1089,7 +1083,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xd000 
0x1000>;
};
 
@@ -1100,7 +1093,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xe000 
0x1000>;
};
 
@@ -,7 +1103,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1400 0xf000 
0x1000>;
};
 
@@ -1122,7 +1113,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0 
0x1000>;
};
 
@@ -1133,7 +1123,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x1000 
0x1000>;
};
 
@@ -1144,7 +1133,6 @@
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
mediatek,gce-client-reg = < SUBSYS_1401 0x2000 
0x1000>;
};
 
@@ -1395,7 +1383,6 @@
  <0 0x16027800 0 0x800>,   /* VDEC_HWB */
 

[PATCH v8 11/12] arm: dts: mediatek: Get rid of mediatek, larb for MM nodes

2021-09-28 Thread Yong Wu
After adding device_link between the IOMMU consumer and smi, the
mediatek,larb is unnecessary now.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 arch/arm/boot/dts/mt2701.dtsi  | 2 --
 arch/arm/boot/dts/mt7623n.dtsi | 5 -
 2 files changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 4776f85d6d5b..ef583cfd3baf 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -564,7 +564,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -577,7 +576,6 @@
clocks =  < CLK_IMG_VENC>;
clock-names = "jpgenc";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGENC_RDMA>,
 < MT2701_M4U_PORT_JPGENC_BSDMA>;
};
diff --git a/arch/arm/boot/dts/mt7623n.dtsi b/arch/arm/boot/dts/mt7623n.dtsi
index bcb0846e29fd..3adab5cd1fef 100644
--- a/arch/arm/boot/dts/mt7623n.dtsi
+++ b/arch/arm/boot/dts/mt7623n.dtsi
@@ -121,7 +121,6 @@
clock-names = "jpgdec-smi",
  "jpgdec";
power-domains = < MT2701_POWER_DOMAIN_ISP>;
-   mediatek,larb = <>;
iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
 < MT2701_M4U_PORT_JPGDEC_BSDMA>;
};
@@ -144,7 +143,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_OVL>;
iommus = < MT2701_M4U_PORT_DISP_OVL_0>;
-   mediatek,larb = <>;
};
 
rdma0: rdma@14008000 {
@@ -154,7 +152,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA>;
iommus = < MT2701_M4U_PORT_DISP_RDMA>;
-   mediatek,larb = <>;
};
 
wdma@14009000 {
@@ -164,7 +161,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_WDMA>;
iommus = < MT2701_M4U_PORT_DISP_WDMA>;
-   mediatek,larb = <>;
};
 
bls: pwm@1400a000 {
@@ -215,7 +211,6 @@
interrupts = ;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < MT2701_M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
};
 
dpi0: dpi@14014000 {
-- 
2.18.0



[PATCH v8 10/12] memory: mtk-smi: Get rid of mtk_smi_larb_get/put

2021-09-28 Thread Yong Wu
After adding device_link between the iommu consumer and smi-larb,
the pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. we can get rid of mtk_smi_larb_get/put.

CC: Matthias Brugger 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Krzysztof Kozlowski 
Acked-by: Matthias Brugger 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/memory/mtk-smi.c   | 14 --
 include/soc/mediatek/smi.h | 20 
 2 files changed, 34 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index c5fb51f73b34..7c61c924e220 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -134,20 +134,6 @@ static void mtk_smi_clk_disable(const struct mtk_smi *smi)
clk_disable_unprepare(smi->clk_apb);
 }
 
-int mtk_smi_larb_get(struct device *larbdev)
-{
-   int ret = pm_runtime_resume_and_get(larbdev);
-
-   return (ret < 0) ? ret : 0;
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
-
-void mtk_smi_larb_put(struct device *larbdev)
-{
-   pm_runtime_put_sync(larbdev);
-}
-EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
-
 static int
 mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 {
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 15e3397cec58..11f7d6b59642 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -19,26 +19,6 @@ struct mtk_smi_larb_iommu {
unsigned char  bank[32];
 };
 
-/*
- * mtk_smi_larb_get: Enable the power domain and clocks for this local arbiter.
- *   It also initialize some basic setting(like iommu).
- * mtk_smi_larb_put: Disable the power domain and clocks for this local 
arbiter.
- * Both should be called in non-atomic context.
- *
- * Returns 0 if successful, negative on failure.
- */
-int mtk_smi_larb_get(struct device *larbdev);
-void mtk_smi_larb_put(struct device *larbdev);
-
-#else
-
-static inline int mtk_smi_larb_get(struct device *larbdev)
-{
-   return 0;
-}
-
-static inline void mtk_smi_larb_put(struct device *larbdev) { }
-
 #endif
 
 #endif
-- 
2.18.0



[PATCH v8 09/12] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put

2021-09-28 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the vcodec device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Tiffany Lin 
CC: Irui Wang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Tiffany Lin 
Reviewed-by: Dafna Hirschfeld 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 37 +++-
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  |  3 --
 .../platform/mtk-vcodec/mtk_vcodec_enc.c  |  1 -
 .../platform/mtk-vcodec/mtk_vcodec_enc_pm.c   | 44 +++
 4 files changed, 10 insertions(+), 75 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 6038db96f71c..d0bf9aa3b29d 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -8,14 +8,12 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_vcodec_dec_pm.h"
 #include "mtk_vcodec_util.h"
 
 int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
 {
-   struct device_node *node;
struct platform_device *pdev;
struct mtk_vcodec_pm *pm;
struct mtk_vcodec_clk *dec_clk;
@@ -26,18 +24,7 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
pm = >pm;
pm->mtkdev = mtkdev;
dec_clk = >vdec_clk;
-   node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
-   if (!node) {
-   mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
-   return -1;
-   }
 
-   pdev = of_find_device_by_node(node);
-   of_node_put(node);
-   if (WARN_ON(!pdev)) {
-   return -1;
-   }
-   pm->larbvdec = >dev;
pdev = mtkdev->plat_dev;
pm->dev = >dev;
 
@@ -47,14 +34,11 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
dec_clk->clk_info = devm_kcalloc(>dev,
dec_clk->clk_num, sizeof(*clk_info),
GFP_KERNEL);
-   if (!dec_clk->clk_info) {
-   ret = -ENOMEM;
-   goto put_device;
-   }
+   if (!dec_clk->clk_info)
+   return -ENOMEM;
} else {
mtk_v4l2_err("Failed to get vdec clock count");
-   ret = -EINVAL;
-   goto put_device;
+   return -EINVAL;
}
 
for (i = 0; i < dec_clk->clk_num; i++) {
@@ -63,29 +47,24 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
"clock-names", i, _info->clk_name);
if (ret) {
mtk_v4l2_err("Failed to get clock name id = %d", i);
-   goto put_device;
+   return ret;
}
clk_info->vcodec_clk = devm_clk_get(>dev,
clk_info->clk_name);
if (IS_ERR(clk_info->vcodec_clk)) {
mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
clk_info->clk_name);
-   ret = PTR_ERR(clk_info->vcodec_clk);
-   goto put_device;
+   return PTR_ERR(clk_info->vcodec_clk);
}
}
 
pm_runtime_enable(>dev);
return 0;
-put_device:
-   put_device(pm->larbvdec);
-   return ret;
 }
 
 void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
 {
pm_runtime_disable(dev->pm.dev);
-   put_device(dev->pm.larbvdec);
 }
 
 int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
@@ -122,11 +101,6 @@ void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
}
}
 
-   ret = mtk_smi_larb_get(pm->larbvdec);
-   if (ret) {
-   mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
-   goto error;
-   }
return;
 
 error:
@@ -139,7 +113,6 @@ void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
struct mtk_vcodec_clk *dec_clk = >vdec_clk;
int i = 0;
 
-   mtk_smi_larb_put(pm->larbvdec);
for (i = dec_clk->clk_num - 1; i >= 0; i--)
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 }
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index c6c7672fecfb..64b73dd880ce 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -189,10 +189,7 @@ struct mtk_vcodec_clk {
  */
 struct mtk_vcodec_pm {
struct mtk_vcodec_clk   vdec_clk;
-   struct device   *larbvdec;
-
struct mtk_vcodec_clk   venc_clk;
-   struct device   *larbvenc;
  

[PATCH v8 08/12] drm/mediatek: Get rid of mtk_smi_larb_get/put

2021-09-28 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the drm device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: CK Hu 
CC: Philipp Zabel 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Chun-Kuang Hu 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 10 --
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 36 ++---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |  1 -
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  5 +--
 4 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 455ea23c6130..445c30cc823f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -12,7 +12,6 @@
 #include 
 
 #include 
-#include 
 
 #include 
 #include 
@@ -643,22 +642,14 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
-   ret = mtk_smi_larb_get(comp->larb_dev);
-   if (ret) {
-   DRM_ERROR("Failed to get larb: %d\n", ret);
-   return;
-   }
-
ret = pm_runtime_resume_and_get(comp->dev);
if (ret < 0) {
-   mtk_smi_larb_put(comp->larb_dev);
DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
return;
}
 
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
-   mtk_smi_larb_put(comp->larb_dev);
pm_runtime_put(comp->dev);
return;
}
@@ -695,7 +686,6 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
-   mtk_smi_larb_put(comp->larb_dev);
ret = pm_runtime_put(comp->dev);
if (ret < 0)
DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 99cbf44463e4..48642e814370 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -414,37 +414,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct 
drm_device *drm,
return ret;
 }
 
-static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp 
*comp,
-   struct device *dev)
-{
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", 
node);
-   return -EINVAL;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   return -EPROBE_DEFER;
-   }
-   of_node_put(larb_node);
-   comp->larb_dev = _pdev->dev;
-
-   return 0;
-}
-
 int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
  enum mtk_ddp_comp_id comp_id)
 {
struct platform_device *comp_pdev;
enum mtk_ddp_comp_type type;
struct mtk_ddp_comp_dev *priv;
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
int ret;
+#endif
 
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -460,16 +438,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct 
mtk_ddp_comp *comp,
}
comp->dev = _pdev->dev;
 
-   /* Only DMA capable components need the LARB property */
-   if (type == MTK_DISP_OVL ||
-   type == MTK_DISP_OVL_2L ||
-   type == MTK_DISP_RDMA ||
-   type == MTK_DISP_WDMA) {
-   ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
-   if (ret)
-   return ret;
-   }
-
if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS ||
type == MTK_DISP_CCORR ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index bb914d976cf5..1b582262b682 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -70,7 +70,6 @@ struct mtk_ddp_comp_funcs {
 struct mtk_ddp_comp {
struct device *dev;
int irq;
-   struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
 };
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index aec39724ebeb..c234293fc2c3 100644
--- a/drivers/g

[PATCH v8 07/12] drm/mediatek: Add pm runtime support for ovl and rdma

2021-09-28 Thread Yong Wu
From: Yongqiang Niu 

Prepare for smi cleaning up "mediatek,larb".

Display use the dispsys device to call pm_rumtime_get_sync before.
This patch add pm_runtime_xx with ovl and rdma device whose nodes has
"iommus" property, then display could help pm_runtime_get for smi via
ovl or rdma device.

CC: CK Hu 
Signed-off-by: Yongqiang Niu 
Signed-off-by: Yong Wu 
(Yong: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync)
Acked-by: Chun-Kuang Hu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c  |  8 +++-
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c |  9 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c  | 13 -
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 5326989d5206..716eac6831f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -414,9 +415,13 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_ovl_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -424,6 +429,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 static int mtk_disp_ovl_remove(struct platform_device *pdev)
 {
component_del(>dev, _disp_ovl_component_ops);
+   pm_runtime_disable(>dev);
 
return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c 
b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 75d7f45579e2..251f034acb09 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mtk_disp_drv.h"
@@ -327,9 +328,13 @@ static int mtk_disp_rdma_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, priv);
 
+   pm_runtime_enable(dev);
+
ret = component_add(dev, _disp_rdma_component_ops);
-   if (ret)
+   if (ret) {
+   pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+   }
 
return ret;
 }
@@ -338,6 +343,8 @@ static int mtk_disp_rdma_remove(struct platform_device 
*pdev)
 {
component_del(>dev, _disp_rdma_component_ops);
 
+   pm_runtime_disable(>dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 5f81489fc60c..455ea23c6130 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -649,9 +649,17 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc 
*crtc,
return;
}
 
+   ret = pm_runtime_resume_and_get(comp->dev);
+   if (ret < 0) {
+   mtk_smi_larb_put(comp->larb_dev);
+   DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", 
ret);
+   return;
+   }
+
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
mtk_smi_larb_put(comp->larb_dev);
+   pm_runtime_put(comp->dev);
return;
}
 
@@ -664,7 +672,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
 {
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-   int i;
+   int i, ret;
 
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
@@ -688,6 +696,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc 
*crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
mtk_smi_larb_put(comp->larb_dev);
+   ret = pm_runtime_put(comp->dev);
+   if (ret < 0)
+   DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: 
%d\n", ret);
 
mtk_crtc->enabled = false;
 }
-- 
2.18.0



[PATCH v8 06/12] media: mtk-mdp: Get rid of mtk_smi_larb_get/put

2021-09-28 Thread Yong Wu
MediaTek IOMMU has already added the device_link between the consumer
and smi-larb device. If the mdp device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

CC: Minghsiu Tsai 
CC: Houlong Wei 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Reviewed-by: Houlong Wei 
Reviewed-by: Dafna Hirschfeld 
---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 40 ---
 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h |  2 -
 drivers/media/platform/mtk-mdp/mtk_mdp_core.c |  1 -
 3 files changed, 43 deletions(-)

diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
index b3426a551bea..1e3833f1c9ae 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
@@ -9,7 +9,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_comp.h"
 
@@ -18,14 +17,6 @@ void mtk_mdp_comp_clock_on(struct device *dev, struct 
mtk_mdp_comp *comp)
 {
int i, err;
 
-   if (comp->larb_dev) {
-   err = mtk_smi_larb_get(comp->larb_dev);
-   if (err)
-   dev_err(dev,
-   "failed to get larb, err %d. type:%d\n",
-   err, comp->type);
-   }
-
for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
if (IS_ERR(comp->clk[i]))
continue;
@@ -46,17 +37,12 @@ void mtk_mdp_comp_clock_off(struct device *dev, struct 
mtk_mdp_comp *comp)
continue;
clk_disable_unprepare(comp->clk[i]);
}
-
-   if (comp->larb_dev)
-   mtk_smi_larb_put(comp->larb_dev);
 }
 
 int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
  struct mtk_mdp_comp *comp,
  enum mtk_mdp_comp_type comp_type)
 {
-   struct device_node *larb_node;
-   struct platform_device *larb_pdev;
int ret;
int i;
 
@@ -77,32 +63,6 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node 
*node,
break;
}
 
-   /* Only DMA capable components need the LARB property */
-   comp->larb_dev = NULL;
-   if (comp->type != MTK_MDP_RDMA &&
-   comp->type != MTK_MDP_WDMA &&
-   comp->type != MTK_MDP_WROT)
-   return 0;
-
-   larb_node = of_parse_phandle(node, "mediatek,larb", 0);
-   if (!larb_node) {
-   dev_err(dev,
-   "Missing mediadek,larb phandle in %pOF node\n", node);
-   ret = -EINVAL;
-   goto put_dev;
-   }
-
-   larb_pdev = of_find_device_by_node(larb_node);
-   if (!larb_pdev) {
-   dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
-   of_node_put(larb_node);
-   ret = -EPROBE_DEFER;
-   goto put_dev;
-   }
-   of_node_put(larb_node);
-
-   comp->larb_dev = _pdev->dev;
-
return 0;
 
 put_dev:
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h 
b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
index 7897766c96bb..ae41dd3cd72a 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
@@ -26,14 +26,12 @@ enum mtk_mdp_comp_type {
  * @node:  list node to track sibing MDP components
  * @dev_node:  component device node
  * @clk:   clocks required for component
- * @larb_dev:  SMI device required for component
  * @type:  component type
  */
 struct mtk_mdp_comp {
struct list_headnode;
struct device_node  *dev_node;
struct clk  *clk[2];
-   struct device   *larb_dev;
enum mtk_mdp_comp_type  type;
 };
 
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
index 976aa1f4829b..70a8eab16863 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
@@ -17,7 +17,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_mdp_core.h"
 #include "mtk_mdp_m2m.h"
-- 
2.18.0



[PATCH v8 05/12] media: mtk-jpeg: Get rid of mtk_smi_larb_get/put

2021-09-28 Thread Yong Wu
MediaTek IOMMU has already added device_link between the consumer
and smi-larb device. If the jpg device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

After removing the larb_get operations, then mtk_jpeg_clk_init is
also unnecessary. Remove it too.

CC: Rick Chang 
CC: Xia Jiang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Rick Chang 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 45 +--
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h   |  2 -
 2 files changed, 2 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index a89c7b206eef..4fea2c512434 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -22,7 +22,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_jpeg_enc_hw.h"
 #include "mtk_jpeg_dec_hw.h"
@@ -1055,10 +1054,6 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
int ret;
 
-   ret = mtk_smi_larb_get(jpeg->larb);
-   if (ret)
-   dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
-
ret = clk_bulk_prepare_enable(jpeg->variant->num_clks,
  jpeg->variant->clks);
if (ret)
@@ -1069,7 +1064,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
clk_bulk_disable_unprepare(jpeg->variant->num_clks,
   jpeg->variant->clks);
-   mtk_smi_larb_put(jpeg->larb);
 }
 
 static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
@@ -1284,35 +1278,6 @@ static struct clk_bulk_data mtk_jpeg_clocks[] = {
{ .id = "jpgenc" },
 };
 
-static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
-{
-   struct device_node *node;
-   struct platform_device *pdev;
-   int ret;
-
-   node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0);
-   if (!node)
-   return -EINVAL;
-   pdev = of_find_device_by_node(node);
-   if (WARN_ON(!pdev)) {
-   of_node_put(node);
-   return -EINVAL;
-   }
-   of_node_put(node);
-
-   jpeg->larb = >dev;
-
-   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
-   jpeg->variant->clks);
-   if (ret) {
-   dev_err(>dev, "failed to get jpeg clock:%d\n", ret);
-   put_device(>dev);
-   return ret;
-   }
-
-   return 0;
-}
-
 static void mtk_jpeg_job_timeout_work(struct work_struct *work)
 {
struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1333,11 +1298,6 @@ static void mtk_jpeg_job_timeout_work(struct work_struct 
*work)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
-static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
-{
-   put_device(jpeg->larb);
-}
-
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
struct mtk_jpeg_dev *jpeg;
@@ -1376,7 +1336,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_req_irq;
}
 
-   ret = mtk_jpeg_clk_init(jpeg);
+   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
+   jpeg->variant->clks);
if (ret) {
dev_err(>dev, "Failed to init clk, err %d\n", ret);
goto err_clk_init;
@@ -1442,7 +1403,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
v4l2_device_unregister(>v4l2_dev);
 
 err_dev_register:
-   mtk_jpeg_clk_release(jpeg);
 
 err_clk_init:
 
@@ -1460,7 +1420,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
video_device_release(jpeg->vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(>v4l2_dev);
-   mtk_jpeg_clk_release(jpeg);
 
return 0;
 }
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 595f7f10c9fd..3e4811a41ba2 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -85,7 +85,6 @@ struct mtk_jpeg_variant {
  * @alloc_ctx: videobuf2 memory allocator's context
  * @vdev:  video device node for jpeg mem2mem mode
  * @reg_base:  JPEG registers mapping
- * @larb:  SMI device
  * @job_timeout_work:  IRQ timeout structure
  * @variant:   driver variant to be used
  */
@@ -99,7 +98,6 @@ struct mtk_jpeg_dev {
void*alloc_ctx;
struct video_device *vdev;
void __iomem*reg_base;
-   struct device   *larb;
struct delayed_work job_timeout_work;
const struct mtk_jpeg_variant *variant;
 };
-- 
2.18.0



[PATCH v8 04/12] iommu/mediatek: Add device_link between the consumer and the larb devices

2021-09-28 Thread Yong Wu
MediaTek IOMMU-SMI diagram is like below. all the consumer connect with
smi-larb, then connect with smi-common.

M4U
 |
smi-common
 |
  -
  | |...
  | |
larb1 larb2
  | |
vdec   venc

When the consumer works, it should enable the smi-larb's power which
also need enable the smi-common's power firstly.

Thus, First of all, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

This patch adds device_link between the consumer and the larbs.

When device_link_add, I add the flag DL_FLAG_STATELESS to avoid calling
pm_runtime_xx to keep the original status of clocks. It can avoid two
issues:
1) Display HW show fastlogo abnormally reported in [1]. At the beggining,
all the clocks are enabled before entering kernel, but the clocks for
display HW(always in larb0) will be gated after clk_enable and clk_disable
called from device_link_add(->pm_runtime_resume) and rpm_idle. The clock
operation happened before display driver probe. At that time, the display
HW will be abnormal.

2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to skip
pm_runtime_xx to avoid the deadlock.

Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
device_link_removed should be added explicitly.

[1] https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
[2] https://lore.kernel.org/patchwork/patch/1086569/

Suggested-by: Tomasz Figa 
Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/iommu/mtk_iommu.c| 22 ++
 drivers/iommu/mtk_iommu_v1.c | 20 +++-
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d5848f78a677..a2fa55899434 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -560,22 +560,44 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_data *data;
+   struct device_link *link;
+   struct device *larbdev;
+   unsigned int larbid;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return ERR_PTR(-ENODEV); /* Not a iommu client device */
 
data = dev_iommu_priv_get(dev);
 
+   /*
+* Link the consumer device with the smi-larb device(supplier)
+* The device in each a larb is a independent HW. thus only link
+* one larb here.
+*/
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   larbdev = data->larb_imu[larbid].dev;
+   link = device_link_add(dev, larbdev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link)
+   dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
return >iommu;
 }
 
 static void mtk_iommu_release_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   struct mtk_iommu_data *data;
+   struct device *larbdev;
+   unsigned int larbid;
 
if (!fwspec || fwspec->ops != _iommu_ops)
return;
 
+   data = dev_iommu_priv_get(dev);
+   larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+   larbdev = data->larb_imu[larbid].dev;
+   device_link_remove(dev, larbdev);
+
iommu_fwspec_free(dev);
 }
 
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 4d7809432239..e6f13459470e 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -423,7 +423,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct of_phandle_args iommu_spec;
struct mtk_iommu_data *data;
-   int err, idx = 0;
+   int err, idx = 0, larbid;
+   struct device_link *link;
+   struct device *larbdev;
 
/*
 * In the deferred case, free the existed fwspec.
@@ -453,6 +455,14 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
 
data = dev_iommu_priv_get(dev);
 
+   /* Link the consumer device with the smi-larb device(supplier) */
+   larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
+   larbdev = data->larb_imu[larbid].dev;
+   link = device_link_add(dev, larbdev,
+  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+   if (!link)
+   dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
+
return >iommu;
 }
 
@@ -473,10 +483,18 @@ static void mtk_iommu_probe_finalize(struct device *dev)
 static void mtk_iommu_release_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   struct mtk_iommu_data *data;
+   struct device *larbdev;
+   unsigned int larbid;
 
if (!fwspec || fwspec->ops != _iommu_ops)
   

[PATCH v8 03/12] iommu/mediatek: Add probe_defer for smi-larb

2021-09-28 Thread Yong Wu
Prepare for adding device_link.

The iommu consumer should use device_link to connect with the
smi-larb(supplier). then the smi-larb should run before the iommu
consumer. Here we delay the iommu driver until the smi driver is ready,
then all the iommu consumers always are after the smi driver.

When there is no this patch, if some consumer drivers run before
smi-larb, the supplier link_status is DL_DEV_NO_DRIVER(0) in the
device_link_add, then device_links_driver_bound will use WARN_ON
to complain that the link_status of supplier is not right.

device_is_bound may be more elegant here. but it is not allowed to
EXPORT from https://lore.kernel.org/patchwork/patch/1334670/.

Signed-off-by: Yong Wu 
Tested-by: Frank Wunderlich  # BPI-R2/MT7623
---
 drivers/iommu/mtk_iommu.c| 2 +-
 drivers/iommu/mtk_iommu_v1.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d837adfd1da5..d5848f78a677 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -844,7 +844,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
id = i;
 
plarbdev = of_find_device_by_node(larbnode);
-   if (!plarbdev) {
+   if (!plarbdev || !plarbdev->dev.driver) {
of_node_put(larbnode);
return -EPROBE_DEFER;
}
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 1467ba1e4417..4d7809432239 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -602,7 +602,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}
 
plarbdev = of_find_device_by_node(larbnode);
-   if (!plarbdev) {
+   if (!plarbdev || !plarbdev->dev.driver) {
of_node_put(larbnode);
return -EPROBE_DEFER;
}
-- 
2.18.0



[PATCH v8 02/12] iommu/mediatek-v1: Free the existed fwspec if the master dev already has

2021-09-28 Thread Yong Wu
When the iommu master device enters of_iommu_xlate, the ops may be
NULL(iommu dev is defered), then it will initialize the fwspec here:

[] (dev_iommu_fwspec_set) from []
(iommu_fwspec_init+0xbc/0xd4)
[] (iommu_fwspec_init) from []
(of_iommu_xlate+0x7c/0x12c)
[] (of_iommu_xlate) from []
(of_iommu_configure+0x144/0x1e8)

BUT the mtk_iommu_v1.c only supports arm32, the probing flow still is a bit
weird. We always expect create the fwspec internally. otherwise it will
enter here and return fail.

static int mtk_iommu_create_mapping(struct device *dev,
struct of_phandle_args *args)
{
...
if (!fwspec) {

} else if (dev_iommu_fwspec_get(dev)->ops != _iommu_ops) {
>>>>>>>>>>Enter here. return fail.<<<<<<<<<<<<
return -EINVAL;
}
...
}

Thus, Free the existed fwspec if the master device already has fwspec.

This issue is reported at:
https://lore.kernel.org/linux-mediatek/trinity-7d9ebdc9-4849-4d93-bfb5-429dcb4ee449-1626253158870@3c-app-gmx-bs01/

Reported-by: Frank Wunderlich 
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu_v1.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index be22fcf988ce..1467ba1e4417 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -425,6 +425,15 @@ static struct iommu_device *mtk_iommu_probe_device(struct 
device *dev)
struct mtk_iommu_data *data;
int err, idx = 0;
 
+   /*
+* In the deferred case, free the existed fwspec.
+* Always initialize the fwspec internally.
+*/
+   if (fwspec) {
+   iommu_fwspec_free(dev);
+   fwspec = dev_iommu_fwspec_get(dev);
+   }
+
while (!of_parse_phandle_with_args(dev->of_node, "iommus",
   "#iommu-cells",
   idx, _spec)) {
-- 
2.18.0



[PATCH v8 01/12] dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW

2021-09-28 Thread Yong Wu
After adding device_link between the consumer with the smi-larbs,
if the consumer call its owner pm_runtime_get(_sync), the
pm_runtime_get(_sync) of smi-larb and smi-common will be called
automatically. Thus, the consumer don't need the property.

And IOMMU also know which larb this consumer connects with from
iommu id in the "iommus=" property.

Signed-off-by: Yong Wu 
Reviewed-by: Rob Herring 
Reviewed-by: Evan Green 
---
 .../bindings/display/mediatek/mediatek,disp.txt  | 9 -
 .../devicetree/bindings/media/mediatek-jpeg-decoder.yaml | 9 -
 .../devicetree/bindings/media/mediatek-jpeg-encoder.yaml | 9 -
 Documentation/devicetree/bindings/media/mediatek-mdp.txt | 8 
 .../devicetree/bindings/media/mediatek-vcodec.txt| 4 
 5 files changed, 39 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
index fbb59c9ddda6..867bd82e2f03 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
@@ -61,8 +61,6 @@ Required properties (DMA function blocks):
"mediatek,-disp-rdma"
"mediatek,-disp-wdma"
   the supported chips are mt2701, mt8167 and mt8173.
-- larb: Should contain a phandle pointing to the local arbiter device as 
defined
-  in 
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
 - iommus: Should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
   for details.
@@ -91,7 +89,6 @@ ovl0: ovl@1400c000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL0>;
iommus = < M4U_PORT_DISP_OVL0>;
-   mediatek,larb = <>;
 };
 
 ovl1: ovl@1400d000 {
@@ -101,7 +98,6 @@ ovl1: ovl@1400d000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_OVL1>;
iommus = < M4U_PORT_DISP_OVL1>;
-   mediatek,larb = <>;
 };
 
 rdma0: rdma@1400e000 {
@@ -111,7 +107,6 @@ rdma0: rdma@1400e000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA0>;
iommus = < M4U_PORT_DISP_RDMA0>;
-   mediatek,larb = <>;
mediatek,rdma-fifosize = <8192>;
 };
 
@@ -122,7 +117,6 @@ rdma1: rdma@1400f000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA1>;
iommus = < M4U_PORT_DISP_RDMA1>;
-   mediatek,larb = <>;
 };
 
 rdma2: rdma@1401 {
@@ -132,7 +126,6 @@ rdma2: rdma@1401 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_RDMA2>;
iommus = < M4U_PORT_DISP_RDMA2>;
-   mediatek,larb = <>;
 };
 
 wdma0: wdma@14011000 {
@@ -142,7 +135,6 @@ wdma0: wdma@14011000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA0>;
iommus = < M4U_PORT_DISP_WDMA0>;
-   mediatek,larb = <>;
 };
 
 wdma1: wdma@14012000 {
@@ -152,7 +144,6 @@ wdma1: wdma@14012000 {
power-domains = < MT8173_POWER_DOMAIN_MM>;
clocks = < CLK_MM_DISP_WDMA1>;
iommus = < M4U_PORT_DISP_WDMA1>;
-   mediatek,larb = <>;
 };
 
 color0: color@14013000 {
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
index 9b87f036f178..052e752157b4 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
@@ -42,13 +42,6 @@ properties:
   power-domains:
 maxItems: 1
 
-  mediatek,larb:
-$ref: '/schemas/types.yaml#/definitions/phandle'
-description: |
-  Must contain the local arbiters in the current Socs, see
-  
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
-  for details.
-
   iommus:
 maxItems: 2
 description: |
@@ -63,7 +56,6 @@ required:
   - clocks
   - clock-names
   - power-domains
-  - mediatek,larb
   - iommus
 
 additionalProperties: false
@@ -83,7 +75,6 @@ examples:
   clock-names = "jpgdec-smi",
 "jpgdec";
   power-domains = < MT2701_POWER_DOMAIN_ISP>;
-  mediatek,larb = <>;
   iommus = < MT2701_M4U_PORT_JPGDEC_WDMA>,
< MT2701_M4U_PORT_JPGDEC_BSDMA>;
 };
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
index fcd9b829e036..8bfdfdfaba59 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/me

[PATCH v8 00/12] Clean up "mediatek,larb"

2021-09-28 Thread Yong Wu
MediaTek IOMMU block diagram always like below:

M4U
 |
smi-common
 |
  -
  | |  ...
  | |
larb1 larb2
  | |
vdec   venc

All the consumer connect with smi-larb, then connect with smi-common.

When the consumer works, it should enable the smi-larb's power which also
need enable the smi-common's power firstly.

Thus, Firstly, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.

After adding the device_link, then "mediatek,larb" property can be removed.
the iommu consumer don't need call the mtk_smi_larb_get/put to enable
the power and clock of smi-larb and smi-common.

About the MM dt-binding/dtsi patches, I guess they should go together, thus
I don't split them for each a MM module and each a SoC.

Base on a jpeg dtbing patchset[1] that already got the necessary R-b.

[1] 
https://lore.kernel.org/linux-mediatek/20210702102304.3346429-1-hsi...@chromium.org/

Change notes:
v8: 1) Rebase on v5.15-rc1.
2) Don't rebase the below mdp patchset that may still need more discuss.

https://lore.kernel.org/linux-mediatek/20210709022324.1607884-1-ei...@chromium.org/
3) Add Frank's Tested-by. Remove Dafna's Tested-by as he requested.

v7: 
https://lore.kernel.org/linux-mediatek/20210730025238.22456-1-yong...@mediatek.com/
1) Fix a arm32 boot fail issue. reported from Frank.
2) Add a return fail in the mtk drm. suggested by Dafna.

v6: 
https://lore.kernel.org/linux-mediatek/20210714025626.5528-1-yong...@mediatek.com/
1) rebase on v5.14-rc1.
2) Fix the issue commented in v5 from Dafna and Hsin-Yi.
3) Remove the patches about using pm_runtime_resume_and_get since they have
   already been merged by other patches.

v5: 
https://lore.kernel.org/linux-mediatek/20210410091128.31823-1-yong...@mediatek.com/
1) Base v5.12-rc2.
2) Remove changing the mtk-iommu to module_platform_driver patch, It have 
already been a
independent patch.

v4: 
https://lore.kernel.org/linux-mediatek/1590826218-23653-1-git-send-email-yong...@mediatek.com/
 
base on v5.7-rc1.
  1) Move drm PM patch before smi patchs.
  2) Change builtin_platform_driver to module_platform_driver since we may need
 build as module.
  3) Rebase many patchset as above.

v3: 
https://lore.kernel.org/linux-iommu/1567503456-24725-1-git-send-email-yong...@mediatek.com/
1) rebase on v5.3-rc1 and the latest mt8183 patchset.
2) Use device_is_bound to check whether the driver is ready from Matthias.  
  
3) Add DL_FLAG_STATELESS flag when calling device_link_add and explain the
   reason in the commit message[3/14].
4) Add a display patch[12/14] into this series. otherwise it may affect
   display HW fastlogo even though it don't happen in mt8183.
   
v2: 
https://lore.kernel.org/linux-iommu/1560171313-28299-1-git-send-email-yong...@mediatek.com/
   1) rebase on v5.2-rc1.
   2) Move adding device_link between the consumer and smi-larb into
iommu_add_device from Robin.
   3) add DL_FLAG_AUTOREMOVE_CONSUMER even though the smi is built-in from Evan.
   4) Remove the shutdown callback in iommu.   

v1: 
https://lore.kernel.org/linux-iommu/1546318276-18993-1-git-send-email-yong...@mediatek.com/

Yong Wu (11):
  dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW
  iommu/mediatek-v1: Free the existed fwspec if the master dev already
has
  iommu/mediatek: Add probe_defer for smi-larb
  iommu/mediatek: Add device_link between the consumer and the larb
devices
  media: mtk-jpeg: Get rid of mtk_smi_larb_get/put
  media: mtk-mdp: Get rid of mtk_smi_larb_get/put
  drm/mediatek: Get rid of mtk_smi_larb_get/put
  media: mtk-vcodec: Get rid of mtk_smi_larb_get/put
  memory: mtk-smi: Get rid of mtk_smi_larb_get/put
  arm: dts: mediatek: Get rid of mediatek,larb for MM nodes
  arm64: dts: mediatek: Get rid of mediatek,larb for MM nodes

Yongqiang Niu (1):
  drm/mediatek: Add pm runtime support for ovl and rdma

 .../display/mediatek/mediatek,disp.txt|  9 
 .../bindings/media/mediatek-jpeg-decoder.yaml |  9 
 .../bindings/media/mediatek-jpeg-encoder.yaml |  9 
 .../bindings/media/mediatek-mdp.txt   |  8 
 .../bindings/media/mediatek-vcodec.txt|  4 --
 arch/arm/boot/dts/mt2701.dtsi |  2 -
 arch/arm/boot/dts/mt7623n.dtsi|  5 ---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi  | 16 ---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi  |  6 ---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c   |  8 +++-
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c  |  9 +++-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c   | 15 ---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c   | 36 +--
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h   |  1 -
 drivers/gpu/drm/mediatek/mtk_drm_drv.c|  5 +--
 drivers/iommu/mtk_iommu.c | 24 +-
 drivers/iommu/mtk_iommu_v1.c

[PATCH v7 05/12] media: mtk-jpeg: Get rid of mtk_smi_larb_get/put

2021-07-30 Thread Yong Wu
MediaTek IOMMU has already added device_link between the consumer
and smi-larb device. If the jpg device call the pm_runtime_get_sync,
the smi-larb's pm_runtime_get_sync also be called automatically.

After removing the larb_get operations, then mtk_jpeg_clk_init is
also unnecessary. Remove it too.

CC: Rick Chang 
CC: Xia Jiang 
Signed-off-by: Yong Wu 
Reviewed-by: Evan Green 
Acked-by: Rick Chang 
Reviewed-by: Dafna Hirschfeld 
Tested-by: Dafna Hirschfeld  # on mt8173
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 45 +--
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h   |  2 -
 2 files changed, 2 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index a89c7b206eef..4fea2c512434 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -22,7 +22,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "mtk_jpeg_enc_hw.h"
 #include "mtk_jpeg_dec_hw.h"
@@ -1055,10 +1054,6 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
int ret;
 
-   ret = mtk_smi_larb_get(jpeg->larb);
-   if (ret)
-   dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
-
ret = clk_bulk_prepare_enable(jpeg->variant->num_clks,
  jpeg->variant->clks);
if (ret)
@@ -1069,7 +1064,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
clk_bulk_disable_unprepare(jpeg->variant->num_clks,
   jpeg->variant->clks);
-   mtk_smi_larb_put(jpeg->larb);
 }
 
 static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
@@ -1284,35 +1278,6 @@ static struct clk_bulk_data mtk_jpeg_clocks[] = {
{ .id = "jpgenc" },
 };
 
-static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
-{
-   struct device_node *node;
-   struct platform_device *pdev;
-   int ret;
-
-   node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0);
-   if (!node)
-   return -EINVAL;
-   pdev = of_find_device_by_node(node);
-   if (WARN_ON(!pdev)) {
-   of_node_put(node);
-   return -EINVAL;
-   }
-   of_node_put(node);
-
-   jpeg->larb = >dev;
-
-   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
-   jpeg->variant->clks);
-   if (ret) {
-   dev_err(>dev, "failed to get jpeg clock:%d\n", ret);
-   put_device(>dev);
-   return ret;
-   }
-
-   return 0;
-}
-
 static void mtk_jpeg_job_timeout_work(struct work_struct *work)
 {
struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1333,11 +1298,6 @@ static void mtk_jpeg_job_timeout_work(struct work_struct 
*work)
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
-static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
-{
-   put_device(jpeg->larb);
-}
-
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
struct mtk_jpeg_dev *jpeg;
@@ -1376,7 +1336,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
goto err_req_irq;
}
 
-   ret = mtk_jpeg_clk_init(jpeg);
+   ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks,
+   jpeg->variant->clks);
if (ret) {
dev_err(>dev, "Failed to init clk, err %d\n", ret);
goto err_clk_init;
@@ -1442,7 +1403,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
v4l2_device_unregister(>v4l2_dev);
 
 err_dev_register:
-   mtk_jpeg_clk_release(jpeg);
 
 err_clk_init:
 
@@ -1460,7 +1420,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
video_device_release(jpeg->vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(>v4l2_dev);
-   mtk_jpeg_clk_release(jpeg);
 
return 0;
 }
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h 
b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 595f7f10c9fd..3e4811a41ba2 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -85,7 +85,6 @@ struct mtk_jpeg_variant {
  * @alloc_ctx: videobuf2 memory allocator's context
  * @vdev:  video device node for jpeg mem2mem mode
  * @reg_base:  JPEG registers mapping
- * @larb:  SMI device
  * @job_timeout_work:  IRQ timeout structure
  * @variant:   driver variant to be used
  */
@@ -99,7 +98,6 @@ struct mtk_jpeg_dev {
void*alloc_ctx;
struct video_device *vdev;
void __iomem*reg_base;
-   struct device   *larb;
struct delayed_work job_timeout_work;
const struct mtk_jpeg_variant *variant;
 };
-- 
2.18.0



  1   2   >