[PATCH v2 8/9] mailbox: mediatek: Add CMDQ secure mailbox driver

Jason-JH Lin (林睿祥) Jason-JH.Lin at mediatek.com
Tue Oct 24 23:20:13 PDT 2023


Hi Angelo,

Thanks for the reviews.

On Mon, 2023-10-23 at 12:48 +0200, AngeloGioacchino Del Regno wrote:
> Il 23/10/23 06:37, Jason-JH.Lin ha scritto:
> > To support secure video path feature, GCE have to read/write
> > registgers
> > in the secure world. GCE will enable the secure access permission
> > to the
> > HW who wants to access the secure content buffer.
> > 
> > Add CMDQ secure mailbox driver to make CMDQ client user is able to
> > sending their HW settings to the secure world. So that GCE can
> > execute
> > all instructions to configure HW in the secure world.
> > 
> > Signed-off-by: Jason-JH.Lin <jason-jh.lin at mediatek.com>
> 
> This driver needs to be cleaned up quite a bit, and I'd expect this
> to take a few
> versions before being upstreamable.
> 
Sure, it's hard to make it upstreamable. It will get better and better
after your reviews. :)

> > ---
> >   drivers/mailbox/Makefile                      |    2 +-
> >   drivers/mailbox/mtk-cmdq-sec-mailbox.c        | 1102
> > +++++++++++++++++
> >   drivers/mailbox/mtk-cmdq-sec-tee.c            |  202 +++
> >   include/linux/mailbox/mtk-cmdq-mailbox.h      |    2 +
> >   .../linux/mailbox/mtk-cmdq-sec-iwc-common.h   |  293 +++++
> >   include/linux/mailbox/mtk-cmdq-sec-mailbox.h  |   83 ++
> >   include/linux/mailbox/mtk-cmdq-sec-tee.h      |   31 +
> >   7 files changed, 1714 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/mailbox/mtk-cmdq-sec-mailbox.c
> >   create mode 100644 drivers/mailbox/mtk-cmdq-sec-tee.c
> >   create mode 100644 include/linux/mailbox/mtk-cmdq-sec-iwc-
> > common.h
> >   create mode 100644 include/linux/mailbox/mtk-cmdq-sec-mailbox.h
> >   create mode 100644 include/linux/mailbox/mtk-cmdq-sec-tee.h
> > 
> > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> > index fc9376117111..82da2f4ee81a 100644
> > --- a/drivers/mailbox/Makefile
> > +++ b/drivers/mailbox/Makefile
> > @@ -51,7 +51,7 @@ obj-$(CONFIG_STM32_IPCC) 	+= stm32-ipcc.o
> >   
> >   obj-$(CONFIG_MTK_ADSP_MBOX)	+= mtk-adsp-mailbox.o
> >   
> > -obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o
> > +obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o mtk-cmdq-
> > sec-mailbox.o mtk-cmdq-sec-tee.o
> >   
> >   obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o
> >   
> > diff --git a/drivers/mailbox/mtk-cmdq-sec-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-sec-mailbox.c
> > new file mode 100644
> > index 000000000000..dac867386cf1
> > --- /dev/null
> > +++ b/drivers/mailbox/mtk-cmdq-sec-mailbox.c
> > @@ -0,0 +1,1102 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2019 MediaTek Inc.
> > +
> 
> Fix comment style please:
> 
> // SPDX...
> /*
>   * Copyright ...
>   */
> 
OK, I'll fix this.

> > +#include <linux/clk.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/io.h>
> > +#include <linux/mailbox_controller.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/sched/clock.h>
> > +#include <linux/timer.h>
> > +
> > +#include <linux/mailbox/mtk-cmdq-sec-mailbox.h>
> > +
> > +#define CMDQ_THR_BASE		(0x100)
> > +#define CMDQ_THR_SIZE		(0x80)
> 
> Those two definitions are the same as in mtk-cmdq-mailbox.c: please
> avoid code
> duplication around, it's harder to maintain.

OK, I'll move this to header file.

> 
> > +#define CMDQ_THR_EXEC_CNT_PA	(0x28)
> > +
> > +#define CMDQ_BUF_ALLOC_SIZE		(PAGE_SIZE)
> > +#define CMDQ_TIMEOUT_DEFAULT		(1000)
> > +#define CMDQ_NO_TIMEOUT			(0xffffffff)
> > +#define ADDR_METADATA_MAX_COUNT_ORIGIN	(8)
> > +
> > +/*
> > + * CMDQ secure context struct
> > + * note it is not global data, each process has its own CMDQ sec
> > context
> > + */
> 
> This structure is practically fully documented: please use kerneldoc
> at this point.
> 
OK, I'll refine these structures here.
By the way, is there any tools can scan the structures or function that
are met to kernel doc?

> > +struct cmdq_sec_context {
> > +	struct list_head		listEntry;
> 
> listEntry -> list_entry or listentry - no camelcase please.
> 
> > +
> > +	/* basic info */
> > +	u32				tgid; /* tgid of process context */
> > +	u32				referCount; /* reference count for
> > open cmdq device node */
> > +
> 
> referCount -> refcount?
> 
> > +	/* iwc state */
> > +	enum cmdq_iwc_state_enum	state;
> 
> iwc_state
> 
> > +
> > +	/* iwc information */
> > +	void				*iwc_msg; /* message buffer
> > */
> > +
> > +	struct cmdq_sec_tee_context	tee; /* trustzone parameters */
> 
> tee_ctx
> 
> > +};
> > +
> > +struct cmdq_sec_task {
> > +	struct list_head	list_entry;
> > +	dma_addr_t		pa_base;
> > +	struct cmdq_sec_thread	*thread;
> > +	struct cmdq_pkt		*pkt;
> > +	u64			exec_time;
> > +	struct work_struct	exec_work;
> > +
> > +	bool			resetExecCnt;
> 
> Again no camelcase - here and everywhere else.
> 
> Also, I see a pattern in all of the _sec_ structures: those seem to
> be the same
> as the non-sec ones, as defined in mtk-cmdq-mailbox, but with more
> params.
> 
> I understand the memory concerns, but there's an easy way out of
> this... we could
> get this done like:
> 
> struct cmdq_sec_task {
> 	struct cmdq_task	tsk;
> 
> 	/* Secure CMDQ */
> 	u32			wait_cookie;
> 	s32			scenario;
> 	u64			engine_flag;
> 	u64			trigger;
> }
> 
> ...and this can be done for all of the _sec_ variants of the cmdq
> mbox structs
> as far as I can see.

OK, Thanks for the advices.
I'll reuse the same part of struct cmdq_task.

> > +	u32			waitCookie;
> > +
> > +	u64			engineFlag;
> > +	s32			scenario;
> > +	u64			trigger;
> > +};
> > +
> > +struct cmdq_sec_thread {
> > +	struct mbox_chan	*chan;
> > +	void __iomem		*base;
> > +	struct list_head	task_list;
> > +	struct timer_list	timeout;
> > +	u32			timeout_ms;
> > +	struct work_struct	timeout_work;
> > +	u32			priority;
> > +	u32			idx;
> > +	bool			occupied;
> > +
> > +	/* following part only secure ctrl */
> > +	u32			wait_cookie;
> > +	u32			next_cookie;
> > +	u32			task_cnt;
> > +	struct workqueue_struct	*task_exec_wq;
> > +};
> > +
> > +/**
> 
> This is not valid kerneldoc.

OK, I'll refine it.

> 
> > + * shared memory between normal and secure world
> > + */
> > +struct cmdq_sec_shared_mem {
> > +	void		*va;
> > +	dma_addr_t	pa;
> > +	u32		size;
> > +};
> > +
> > +struct cmdq_sec {
> > +	struct mbox_controller		mbox;
> > +	void __iomem			*base;
> > +	phys_addr_t			base_pa;
> > +	u32				hwid;
> > +	u32				gce_num;
> > +	struct clk_bulk_data		*clocks;
> > +	u32				thread_nr;
> > +	struct cmdq_sec_thread		*thread;
> > +	struct cmdq_client		*clt;
> > +	struct cmdq_pkt			*clt_pkt;
> > +
> > +	atomic_t			path_res;
> > +	struct cmdq_sec_shared_mem	*shared_mem;
> > +	struct cmdq_sec_context		*context;
> > +	struct iwcCmdqCancelTask_t	cancel;
> > +
> > +	struct workqueue_struct		*timeout_wq;
> > +	u64				sec_invoke;
> > +	u64				sec_done;
> > +
> > +	bool				notify_run;
> > +	struct work_struct		irq_notify_work;
> > +	struct workqueue_struct		*notify_wq;
> > +	u32				cmdq_event;
> > +	/* mutex for cmdq_sec_thread excuting cmdq_sec_task */
> > +	struct mutex			exec_lock;
> > +};
> > +
> > +static atomic_t cmdq_path_res = ATOMIC_INIT(0);
> > +
> > +static int cmdq_sec_task_submit(struct cmdq_sec *cmdq, struct
> > cmdq_sec_task *task,
> > +				const u32 iwc_cmd, const u32 thrd_idx,
> > void *data);
> > +
> > +static inline void cmdq_sec_setup_tee_context_base(struct
> > cmdq_sec_context *context)
> 
> You don't need this function, as it's just wrapping over another one:
> you can just
> call cmdq_sec_setup_tee_context.

OK, I'll remove this wrapping function.

> 
> > +{
> > +	cmdq_sec_setup_tee_context(&context->tee);
> > +}
> > +
> > +static inline int cmdq_sec_init_context_base(struct
> > cmdq_sec_context *context)
> > +{
> > +	int status;
> > +
> > +	status = cmdq_sec_init_context(&context->tee);
> > +	if (status < 0)
> > +		return status;
> 
> if (a < 0) return a;
> else return a;
> 
> really? :-)
> 
Oh, this is not correct...

> Besides, again, you don't need this wrapper function.
> 
OK, I'll remove this wrapping function and avoid the wrong status
checking. Thanks!

> > +
> > +	return status;
> > +}
> > +
> > +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt)
> > +{
> > +	struct cmdq_client *cl = (struct cmdq_client *)pkt->cl;
> > +	struct cmdq_sec_thread *thread = ((struct mbox_chan *)(cl-
> > >chan))->con_priv;
> > +	struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct
> > cmdq_sec, mbox);
> > +	struct cmdq_operand left, right;
> > +	dma_addr_t addr;
> > +
> > +	if (!thread->occupied || !cmdq->shared_mem)
> > +		return -EFAULT;
> > +
> > +	pr_debug("%s %d: pkt:%p thread:%u gce:%#lx",
> 
> All those pr_xxxx shall become dev_debug, dev_err, etc.

OK, I'll change them.

> 
> > +		 __func__, __LINE__, pkt, thread->idx, (unsigned
> > long)cmdq->base_pa);
> > +
> > +	addr = (u32)(cmdq->base_pa + CMDQ_THR_BASE +
> > +		CMDQ_THR_SIZE * thread->idx + CMDQ_THR_EXEC_CNT_PA);
> > +
> > +	cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_HIGH(addr));
> > +	cmdq_pkt_read_s(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_LOW(addr),
> > CMDQ_THR_SPR_IDX1);
> > +
> > +	left.reg = true;
> > +	left.idx = CMDQ_THR_SPR_IDX1;
> > +	right.reg = false;
> > +	right.value = 1;
> > +	cmdq_pkt_logic_command(pkt, CMDQ_LOGIC_ADD, CMDQ_THR_SPR_IDX1,
> > &left, &right);
> > +
> > +	addr = cmdq->shared_mem->pa + CMDQ_SEC_SHARED_THR_CNT_OFFSET +
> > +		thread->idx * sizeof(u32);
> 
> Fits in one line.

OK. Thanks!

> 
> > +
> > +	cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_HIGH(addr));
> > +	cmdq_pkt_write_s(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_LOW(addr),
> > CMDQ_THR_SPR_IDX1);
> > +	cmdq_pkt_set_event(pkt, cmdq->cmdq_event);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(cmdq_sec_insert_backup_cookie);
> > +
> > +static int cmdq_sec_realloc_addr_list(struct cmdq_pkt *pkt, const
> > u32 count)
> > +{
> > +	struct cmdq_sec_data *sec_data = (struct cmdq_sec_data *)pkt-
> > >sec_data;
> > +	void *prev = (void *)(unsigned long)sec_data->addrMetadatas,
> > *curr;
> > +
> > +	if (count <= sec_data->addrMetadataMaxCount)
> > +		return 0;
> > +
> > +	curr = kcalloc(count, sizeof(*sec_data), GFP_KERNEL);
> > +	if (!curr)
> > +		return -ENOMEM;
> > +
> > +	if (count && sec_data->addrMetadatas)
> > +		memcpy(curr, prev, sizeof(*sec_data) * sec_data-
> > >addrMetadataMaxCount);
> > +
> > +	kfree(prev);
> > +
> > +	sec_data->addrMetadatas = (uintptr_t)curr;
> > +	sec_data->addrMetadataMaxCount = count;
> > +	return 0;
> > +}
> > +
> > +static int cmdq_sec_check_sec(struct cmdq_pkt *pkt)
> 
> This is not just a check: it is *allocating* memory, so please either
> find a better
> name for this function, or just make sure that the sec_data is
> already allocated
> before calling into functions that are calling this one, as I can
> foresee memory
> leaks because of confusion deriving from this function.

OK, I'll rename it to cmdq_sec_pkt_create_sec_data() and add another
cmdq_sec_pkt_destory_sec_data() to free it.

> 
> > +{
> > +	struct cmdq_sec_data *sec_data;
> > +
> > +	if (pkt->sec_data)
> > +		return 0;
> > +
> > +	sec_data = kzalloc(sizeof(*sec_data), GFP_KERNEL);
> > +	if (!sec_data)
> > +		return -ENOMEM;
> > +
> > +	pkt->sec_data = (void *)sec_data;
> > +
> > +	return 0;
> > +}
> > +
> > +static int cmdq_sec_append_metadata(struct cmdq_pkt *pkt,
> > +				    const enum
> > cmdq_iwc_addr_metadata_type type,
> > +				    const u64 base, const u32 offset,
> > const u32 size,
> > +				    const u32 port)
> > +{
> > +	struct cmdq_sec_data *sec_data;
> > +	struct iwcCmdqAddrMetadata_t *meta;
> 
> No camelcase please.

OK, I'll rename it.

> 
> > +	int idx, max, ret;
> > +
> > +	pr_debug("[%s %d] pkt:%p type:%u base:%#llx offset:%#x size:%#x
> > port:%#x",
> > +		 __func__, __LINE__, pkt, type, base, offset, size,
> > port);
> > +
> > +	ret = cmdq_sec_check_sec(pkt);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	sec_data = (struct cmdq_sec_data *)pkt->sec_data;
> > +	idx = sec_data->addrMetadataCount;
> > +	if (idx >= CMDQ_IWC_MAX_ADDR_LIST_LENGTH) {
> > +		pr_err("idx:%u reach over:%u", idx,
> > CMDQ_IWC_MAX_ADDR_LIST_LENGTH);
> > +		return -EFAULT;
> > +	}
> > +
> > +	if (!sec_data->addrMetadataMaxCount)
> > +		max = ADDR_METADATA_MAX_COUNT_ORIGIN;
> > +	else if (idx >= sec_data->addrMetadataMaxCount)
> > +		max = sec_data->addrMetadataMaxCount * 2;
> > +	else
> > +		max = sec_data->addrMetadataMaxCount;
> > +
> > +	ret = cmdq_sec_realloc_addr_list(pkt, max);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (!sec_data->addrMetadatas) {
> > +		pr_info("addrMetadatas is missing");
> > +
> > +		meta = kzalloc(sizeof(*meta), GFP_KERNEL);
> > +		if (!meta)
> > +			return -ENOMEM;
> > +
> > +		sec_data->addrMetadatas = (uintptr_t)(void *)meta;
> > +	}
> > +	meta = (struct iwcCmdqAddrMetadata_t *)(uintptr_t)sec_data-
> > >addrMetadatas;
> > +
> > +	meta[idx].instrIndex = pkt->cmd_buf_size / CMDQ_INST_SIZE - 1;
> > +	meta[idx].type = type;
> > +	meta[idx].baseHandle = base;
> > +	meta[idx].offset = offset;
> > +	meta[idx].size = size;
> > +	meta[idx].port = port;
> > +	sec_data->addrMetadataCount += 1;
> > +	return 0;
> > +}
> > +
> > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, const u64
> > dapc_engine,
> > +			  const u64 port_sec_engine, const enum
> > cmdq_sec_scenario scenario)
> > +{
> > +	struct cmdq_sec_data *sec_data;
> > +	int ret;
> > +
> > +	if (!pkt) {
> > +		pr_err("invalid pkt:%p", pkt);
> > +		return -EINVAL;
> > +	}
> > +
> > +	ret = cmdq_sec_check_sec(pkt);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	pr_debug("[%s %d] pkt:%p sec_data:%p dapc:%llu port_sec:%llu
> > scen:%u",
> > +		 __func__, __LINE__, pkt, pkt->sec_data, dapc_engine,
> > port_sec_engine, scenario);
> > +
> > +	sec_data = (struct cmdq_sec_data *)pkt->sec_data;
> > +	sec_data->enginesNeedDAPC |= dapc_engine;
> > +	sec_data->enginesNeedPortSecurity |= port_sec_engine;
> > +	sec_data->scenario = scenario;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(cmdq_sec_pkt_set_data);
> > +
> > +int cmdq_sec_pkt_write(struct cmdq_pkt *pkt, u32 addr, u64 base,
> > +		       const enum cmdq_iwc_addr_metadata_type type,
> > +		       const u32 offset, const u32 size, const u32
> > port)
> > +{
> > +	int ret;
> > +
> > +	ret = cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX0, addr);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = cmdq_pkt_write_s_reg_value(pkt, CMDQ_THR_SPR_IDX0,
> > (u32)base);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return cmdq_sec_append_metadata(pkt, type, base, offset, size,
> > port);
> > +}
> > +EXPORT_SYMBOL(cmdq_sec_pkt_write);
> > +
> > +static u32 cmdq_sec_get_cookie(struct cmdq_sec *cmdq, u32 idx)
> > +{
> > +	return *(u32 *)(cmdq->shared_mem->va +
> > +		CMDQ_SEC_SHARED_THR_CNT_OFFSET + idx * sizeof(u32));
> > +}
> > +
> > +static void cmdq_sec_task_done(struct cmdq_sec_task *task, int
> > sta)
> > +{
> > +	struct cmdq_cb_data data;
> > +
> > +	data.sta = sta;
> > +	data.pkt = task->pkt;
> > +
> > +	pr_debug("%s task:%p pkt:%p err:%d",
> > +		 __func__, task, task->pkt, sta);
> > +
> > +	mbox_chan_received_data(task->thread->chan, &data);
> > +
> > +	list_del_init(&task->list_entry);
> > +	kfree(task);
> > +}
> > +
> > +static bool cmdq_sec_irq_handler(struct cmdq_sec_thread *thread,
> > const u32 cookie, const int err)
> > +{
> > +	struct cmdq_sec_task *task, *temp, *cur_task = NULL;
> > +	struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct
> > cmdq_sec, mbox);
> > +	unsigned long flags;
> > +	int done;
> > +
> > +	spin_lock_irqsave(&thread->chan->lock, flags);
> > +	if (thread->wait_cookie <= cookie)
> > +		done = cookie - thread->wait_cookie + 1;
> > +	else if (thread->wait_cookie == (cookie + 1) %
> > CMDQ_MAX_COOKIE_VALUE)
> > +		done = 0;
> > +	else
> > +		done = CMDQ_MAX_COOKIE_VALUE - thread->wait_cookie + 1
> > +
> > +			cookie + 1;
> > +
> > +	list_for_each_entry_safe(task, temp, &thread->task_list,
> > list_entry) {
> > +		if (!done)
> > +			break;
> > +
> > +		cmdq_sec_task_done(task, err);
> > +
> > +		if (thread->task_cnt)
> > +			thread->task_cnt -= 1;
> > +
> > +		done--;
> > +	}
> > +
> > +	cur_task = list_first_entry_or_null(&thread->task_list,
> > +					    struct cmdq_sec_task,
> > list_entry);
> > +
> > +	if (err && cur_task) {
> > +		spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +
> > +		/* for error task, cancel, callback and done */
> > +		memset(&cmdq->cancel, 0, sizeof(cmdq->cancel));
> > +		cmdq_sec_task_submit(cmdq, cur_task,
> > CMD_CMDQ_IWC_CANCEL_TASK,
> > +				     thread->idx, &cmdq->cancel);
> > +
> > +		cmdq_sec_task_done(task, err);
> > +
> > +		spin_lock_irqsave(&thread->chan->lock, flags);
> > +
> > +		task = list_first_entry_or_null(&thread->task_list,
> > +						struct cmdq_sec_task,
> > list_entry);
> > +		if (cur_task == task)
> > +			cmdq_sec_task_done(cur_task, err);
> > +		else
> > +			pr_err("task list changed");
> > +
> > +		/*
> > +		 * error case stop all task for secure,
> > +		 * since secure tdrv always remove all when cancel
> > +		 */
> > +		while (!list_empty(&thread->task_list)) {
> > +			cur_task = list_first_entry(&thread->task_list,
> > +						    struct
> > cmdq_sec_task, list_entry);
> > +
> > +			cmdq_sec_task_done(cur_task, -ECONNABORTED);
> > +		}
> > +	} else if (err) {
> > +		pr_debug("error but all task done, check notify
> > callback");
> > +	}
> > +
> > +	if (list_empty(&thread->task_list)) {
> > +		thread->wait_cookie = 0;
> > +		thread->next_cookie = 0;
> > +		thread->task_cnt = 0;
> > +		__raw_writel(0, (void __iomem *)cmdq->shared_mem->va +
> > +			     CMDQ_SEC_SHARED_THR_CNT_OFFSET +
> > +			     thread->idx * sizeof(u32));
> > +		spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +		del_timer(&thread->timeout);
> > +		return true;
> > +	}
> > +
> > +	thread->wait_cookie = cookie % CMDQ_MAX_COOKIE_VALUE + 1;
> > +
> > +	mod_timer(&thread->timeout, jiffies + msecs_to_jiffies(thread-
> > >timeout_ms));
> > +	spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +
> > +	return false;
> > +}
> > +
> > +static void cmdq_sec_irq_notify_work(struct work_struct
> > *work_item)
> > +{
> > +	struct cmdq_sec *cmdq = container_of(work_item, struct
> > cmdq_sec, irq_notify_work);
> > +	int i;
> > +
> > +	mutex_lock(&cmdq->exec_lock);
> > +
> > +	for (i = 0; i < CMDQ_MAX_SECURE_THREAD_COUNT; i++) {
> > +		struct cmdq_sec_thread *thread = &cmdq-
> > >thread[CMDQ_MIN_SECURE_THREAD_ID + i];
> > +		u32 cookie = cmdq_sec_get_cookie(cmdq, thread->idx);
> > +
> > +		if (cookie < thread->wait_cookie || !thread->task_cnt)
> > +			continue;
> > +
> > +		cmdq_sec_irq_handler(thread, cookie, 0);
> > +	}
> > +
> > +	mutex_unlock(&cmdq->exec_lock);
> > +}
> > +
> > +static void cmdq_sec_irq_notify_callback(struct mbox_client *cl,
> > void *mssg)
> > +{
> > +	struct cmdq_cb_data *data = (struct cmdq_cb_data *)mssg;
> > +	struct cmdq_sec *cmdq = container_of(((struct cmdq_client
> > *)data->pkt->cl)->chan->mbox,
> > +					     struct cmdq_sec, mbox);
> > +
> 
> 	if (work_pending...) {
> 		dev_dbg
> 		return;
> 	}
> 
> 	queue_work
> 

It's much better. I'll change this. Thanks!

> > +	if (!work_pending(&cmdq->irq_notify_work))
> > +		queue_work(cmdq->notify_wq, &cmdq->irq_notify_work);
> > +	else
> > +		pr_debug("%s last notify callback working", __func__);
> > +}
> > +
> > +static int cmdq_sec_irq_notify_start(struct cmdq_sec *cmdq)
> > +{
> > +	int err;
> > +
> > +	if (cmdq->notify_run)
> > +		return 0;
> > +
> > +	if (!cmdq->clt_pkt) {
> > +		cmdq->clt = cmdq_mbox_create(cmdq->mbox.dev, 0);
> > +		if (!cmdq->clt || IS_ERR(cmdq->clt)) {
> > +			pr_err("clt mbox_create failed clt:%p
> > index:%d",
> > +			       cmdq->clt, CMDQ_SEC_IRQ_THREAD);
> > +			return -EINVAL;
> > +		}
> > +		cmdq->clt->client.rx_callback =
> > cmdq_sec_irq_notify_callback;
> > +
> > +		cmdq->clt_pkt = cmdq_pkt_create(cmdq->clt,
> > CMDQ_BUF_ALLOC_SIZE);
> > +		if (!cmdq->clt_pkt || IS_ERR(cmdq->clt_pkt)) {
> > +			pr_err("clt_pkt cmdq_pkt_create failed pkt:%p
> > index:%d",
> > +			       cmdq->clt_pkt, CMDQ_SEC_IRQ_THREAD);
> > +			return -EINVAL;
> > +		}
> > +
> > +		INIT_WORK(&cmdq->irq_notify_work,
> > cmdq_sec_irq_notify_work);
> > +	}
> > +
> > +	cmdq_pkt_wfe(cmdq->clt_pkt, cmdq->cmdq_event, true);
> > +	cmdq_pkt_finalize_loop(cmdq->clt_pkt);
> > +	dma_sync_single_for_device(cmdq->mbox.dev,
> > +				   cmdq->clt_pkt->pa_base,
> > +				   cmdq->clt_pkt->cmd_buf_size,
> > +				   DMA_TO_DEVICE);
> > +	err = mbox_send_message(cmdq->clt->chan, cmdq->clt_pkt);
> > +	mbox_client_txdone(cmdq->clt->chan, 0);
> > +	if (err < 0) {
> > +		pr_err("%s failed:%d", __func__, err);
> > +		cmdq_pkt_destroy(cmdq->clt_pkt);
> > +		cmdq_mbox_destroy(cmdq->clt);
> 
> 		return err;
> 	}
> 	cmdq->notify_run = true;
> 
> > +	} else {
> > +		cmdq->notify_run = true;
> > +		pr_debug("%s success!", __func__);
> > +	}
> > +
> > +	return err;
> 
> return 0 here
> 

OK, I'll change this. Thanks!

> > +}
> > +
> > +static int cmdq_sec_session_init(struct cmdq_sec_context *context)
> > +{
> > +	int err = 0;
> > +
> > +	if (context->state >= IWC_SES_OPENED) {
> > +		pr_debug("session opened:%u", context->state);
> > +		return err;
> 
> 		return 0;
> 
> > +	}
> > +
> > +	switch (context->state) {
> > +	case IWC_INIT:
> > +		err = cmdq_sec_init_context_base(context);
> > +		if (err)
> 
> 		if (err)
> 			return err;
> 
> > +			break;
> > +		context->state = IWC_CONTEXT_INITED;
> > +	fallthrough;
> > +	case IWC_CONTEXT_INITED:
> > +		if (context->iwc_msg) {
> > +			pr_err("iwcMessage not NULL:%p", context-
> > >iwc_msg);
> > +			err = -EINVAL;
> 
> return -EINVAL;
> 
> > +			break;
> > +		}
> > +
> > +		err = cmdq_sec_allocate_wsm(&context->tee, &context-
> > >iwc_msg,
> > +					    sizeof(struct
> > iwcCmdqMessage_t));
> > +		if (err)
> > +			break;
> 
> return err
> 
> > +
> > +		context->state = IWC_WSM_ALLOCATED;
> > +	fallthrough;
> > +	case IWC_WSM_ALLOCATED:
> > +		err = cmdq_sec_open_session(&context->tee, context-
> > >iwc_msg);
> > +		if (err)
> > +			break;
> 
> return err
> 
> > +
> > +		context->state = IWC_SES_OPENED;
> > +	fallthrough;
> > +	default:
> > +		break;
> > +	}
> 
> 	return 0;
> 

OK' I'll change these return err logic. Thanks!

> > +	return err;
> > +}
> > +
> > +static int cmdq_sec_fill_iwc_msg(struct cmdq_sec_context *context,
> > +				 struct cmdq_sec_task *task, u32
> > thrd_idx)
> > +{
> > +	struct iwcCmdqMessage_t *iwc_msg = NULL;
> > +	struct cmdq_sec_data *data = (struct cmdq_sec_data *)task->pkt-
> > >sec_data;
> > +	u32 size = 0, offset = 0, *instr;
> > +
> > +	iwc_msg = (struct iwcCmdqMessage_t *)context->iwc_msg;
> > +
> > +	if (task->pkt->cmd_buf_size + 4 * CMDQ_INST_SIZE >
> > CMDQ_TZ_CMD_BLOCK_SIZE) {
> > +		pr_err("task:%p size:%zu > %u",
> > +		       task, task->pkt->cmd_buf_size,
> > CMDQ_TZ_CMD_BLOCK_SIZE);
> > +		return -EFAULT;
> > +	}
> > +
> > +	if (thrd_idx == CMDQ_INVALID_THREAD) {
> > +		iwc_msg->command.commandSize = 0;
> > +		iwc_msg->command.metadata.addrListLength = 0;
> > +		return 0;
> 
> if invalid thread, return 0?! Are you sure?!

Oh, There is a cmd will use the invalid thread to send a message.

But I shouldn't just return 0 for all cmd with invalid thread.
I'll refine this. Thanks!

> 
> > +	}
> > +
> 
> 	if (iwc_msg->command.size == 0 && task->pkt->cmd_buf_size == 0)
> {
> 		dev_dbg(...... command size is zero)
> 
> 		return (something);
> 	}
> 
> > +	iwc_msg->command.thread = thrd_idx;
> > +	iwc_msg->command.scenario = task->scenario;
> > +	iwc_msg->command.engineFlag = task->engineFlag;
> > +	size = task->pkt->cmd_buf_size;
> > +	memcpy(iwc_msg->command.pVABase + offset, task->pkt->va_base,
> > size);
> > +	iwc_msg->command.commandSize += size;
> > +	offset += size / 4;
> > +
> > +	if (iwc_msg->command.commandSize == 0) {
> > +		pr_err("%s %d: commandSize is 0\n", __func__,
> > __LINE__);
> 
> So this being zero is valid? Again, are you sure?
> 
Oh, this may be the test code which I forgot to remove.
I'll remove this check. Thanks!

> > +		return 0;
> > +	}
> > +
> > +	instr = &iwc_msg->command.pVABase[iwc_msg->command.commandSize
> > / 4 - 4];
> > +	if (instr[0] == 0x1 && instr[1] == 0x40000000)
> 
> Please define this, I guess that instr[] is a 64-bits instruction, is
> it?
> 
Each GCE instruction is 64-bits, but we usually verify them by each 32-
bits. In this case, I think checking 64-bits is better.

> So this could be... #define SOMETHING 0x140000000ULL
> ...but however you choose to define it is fine, just .. define it
> please :-)
> 

OK, I'll add an EOC(end of command) define for that.

> > +		instr[0] = 0;
> > +	else
> > +		pr_err("%s %d: find EOC failed: %#x %#x",
> > +		       __func__, __LINE__, instr[1], instr[0]);
> > +
> > +	iwc_msg->command.waitCookie = task->waitCookie;
> > +	iwc_msg->command.resetExecCnt = task->resetExecCnt;
> > +
> > +	if (data->addrMetadataCount) {
> > +		iwc_msg->command.metadata.addrListLength = data-
> > >addrMetadataCount;
> > +		memcpy(iwc_msg->command.metadata.addrList,
> > +		       (u32 *)(unsigned long)data->addrMetadatas,
> > +		       data->addrMetadataCount * sizeof(struct
> > iwcCmdqAddrMetadata_t));
> > +	}
> > +
> > +	iwc_msg->command.metadata.enginesNeedDAPC = data-
> > >enginesNeedDAPC;
> > +	iwc_msg->command.metadata.enginesNeedPortSecurity =
> > +		data->enginesNeedPortSecurity;
> > +	iwc_msg->command.hNormalTask = (unsigned long)task->pkt;
> > +
> > +	return 0;
> > +}
> > +
> > +static int cmdq_sec_session_send(struct cmdq_sec_context *context,
> > +				 struct cmdq_sec_task *task, const u32
> > iwc_cmd,
> > +				 const u32 thrd_idx, struct cmdq_sec
> > *cmdq)
> > +{
> > +	int err = 0;
> > +	u64 cost;
> > +	struct iwcCmdqMessage_t *iwc_msg = NULL;
> > +
> > +	iwc_msg = (struct iwcCmdqMessage_t *)context->iwc_msg;
> > +
> > +	memset(iwc_msg, 0, sizeof(*iwc_msg));
> > +	iwc_msg->cmd = iwc_cmd;
> > +	iwc_msg->cmdq_id = cmdq->hwid;
> > +	iwc_msg->command.thread = thrd_idx;
> > +
> > +	switch (iwc_cmd) {
> > +	case CMD_CMDQ_IWC_SUBMIT_TASK:
> > +		err = cmdq_sec_fill_iwc_msg(context, task, thrd_idx);
> > +		if (err)
> > +			return err;
> > +		break;
> > +	case CMD_CMDQ_IWC_CANCEL_TASK:
> > +		iwc_msg->cancelTask.waitCookie = task->waitCookie;
> > +		iwc_msg->cancelTask.thread = thrd_idx;
> > +		break;
> > +	case CMD_CMDQ_IWC_PATH_RES_ALLOCATE:
> > +		if (!cmdq->shared_mem || !cmdq->shared_mem->va) {
> > +			pr_err("%s %d: shared_mem is NULL", __func__,
> > __LINE__);
> > +			return -EFAULT;
> > +		}
> > +		iwc_msg->pathResource.size = cmdq->shared_mem->size;
> > +		iwc_msg->pathResource.shareMemoyPA = cmdq->shared_mem-
> > >pa;
> > +		iwc_msg->pathResource.useNormalIRQ = 1;
> > +		break;
> > +	default:
> > +		break;
> > +	}
> > +
> > +	cmdq->sec_invoke = sched_clock();
> > +	pr_debug("%s execute cmdq:%p task:%lx command:%u thread:%u
> > cookie:%d",
> > +		 __func__, cmdq, (unsigned long)task, iwc_cmd,
> > thrd_idx,
> > +		 task ? task->waitCookie : -1);
> > +
> > +	/* send message */
> > +	err = cmdq_sec_execute_session(&context->tee, iwc_cmd,
> > CMDQ_TIMEOUT_DEFAULT);
> > +
> > +	cmdq->sec_done = sched_clock();
> > +	cost = div_u64(cmdq->sec_done - cmdq->sec_invoke, 1000000);
> > +	if (cost >= CMDQ_TIMEOUT_DEFAULT)
> > +		pr_err("%s execute timeout cmdq:%p task:%lx
> > cost:%lluus",
> > +		       __func__, cmdq, (unsigned long)task, cost);
> > +	else
> > +		pr_debug("%s execute done cmdq:%p task:%lx
> > cost:%lluus",
> > +			 __func__, cmdq, (unsigned long)task, cost);
> > +
> 
> 	if (err)
> 		return err;
> 
> 	context->state = IWC_SES_ON_TRANSACTED;
> 	return 0;

OK, I'll change this. Thanks!

> 
> > +	if (err == 0)
> > +		context->state = IWC_SES_ON_TRANSACTED;
> > +
> > +	return err;
> > +}
> > +
> > +static int cmdq_sec_session_reply(const u32 iwc_cmd, struct
> > iwcCmdqMessage_t *iwc_msg,
> > +				  void *data, struct cmdq_sec_task
> > *task)
> > +{
> > +	struct iwcCmdqCancelTask_t *cancel = data;
> > +	struct cmdq_sec_data *sec_data = task->pkt->sec_data;
> > +
> > +	if (iwc_cmd == CMD_CMDQ_IWC_SUBMIT_TASK) {
> 
> 	if (iwc_cmd == CMD_CMDQ_IWC_SUBMIT_TASK && iwc_msg->rsp < 0) {
> 		....
> 	} else if (...) {
> 		....
> 	}
> 
> 	return ...
> 

OK, I'll change this. Thanks!

> > +		if (iwc_msg->rsp < 0) {
> > +			/* submit fail case copy status */
> > +			memcpy(&sec_data->sec_status, &iwc_msg-
> > >secStatus,
> > +			       sizeof(sec_data->sec_status));
> > +			sec_data->response = iwc_msg->rsp;
> > +		}
> > +	} else if (iwc_cmd == CMD_CMDQ_IWC_CANCEL_TASK && cancel) {
> > +		/* cancel case only copy cancel result */
> > +		memcpy(cancel, &iwc_msg->cancelTask, sizeof(*cancel));
> > +	}
> > +
> > +	return iwc_msg->rsp;
> > +}
> > +
> > +static int cmdq_sec_task_submit(struct cmdq_sec *cmdq, struct
> > cmdq_sec_task *task,
> > +				const u32 iwc_cmd, const u32 thrd_idx,
> > void *data)
> > +{
> > +	struct cmdq_sec_context *context;
> > +	int err;
> > +
> > +	do {
> > +		if (!cmdq->context) {
> > +			context = kzalloc(sizeof(*cmdq->context),
> > GFP_ATOMIC);
> > +			if (!context) {
> > +				err = -ENOMEM;
> > +				break;
> > +			}
> > +			cmdq->context = context;
> > +			cmdq->context->state = IWC_INIT;
> > +			cmdq->context->tgid = current->tgid;
> > +		}
> > +
> > +		if (cmdq->context->state == IWC_INIT)
> > +			cmdq_sec_setup_tee_context_base(cmdq->context);
> > +
> > +		err = cmdq_sec_session_init(cmdq->context);
> > +		if (err) {
> > +			pr_err("%s %d: cmdq_sec_session_init fail",
> > __func__, __LINE__);
> > +			break;
> > +		}
> > +
> > +		err = cmdq_sec_irq_notify_start(cmdq);
> > +		if (err < 0) {
> > +			pr_err("%s %d: cmdq_sec_irq_notify_start fail",
> > __func__, __LINE__);
> > +			break;
> > +		}
> > +
> > +		err = cmdq_sec_session_send(cmdq->context, task,
> > iwc_cmd, thrd_idx, cmdq);
> > +		if (err)
> > +			pr_err("%s %d: cmdq_sec_session_send fail:
> > %d\n", __func__, __LINE__, err);
> > +		else
> > +			err = cmdq_sec_session_reply(iwc_cmd, cmdq-
> > >context->iwc_msg, data, task);
> > +	} while (0);
> 
> Seriously? do { ... } while(0) ?!?!?!
> 
> No!!!!
> 

OK, I'll change this like the above checking logic. Thanks!

> > +
> > +	if (err)
> > +		pr_err("%s %d: sec invoke err:%d task:%p thread:%u
> > gce:%#lx",
> > +		       __func__, __LINE__, err, task, thrd_idx,
> > (unsigned long)cmdq->base_pa);
> > +
> > +	return err;
> > +}
> > +
> > +static int cmdq_sec_suspend(struct device *dev)
> > +{
> > +	struct cmdq_sec *cmdq = dev_get_drvdata(dev);
> > +
> > +	clk_bulk_disable_unprepare(cmdq->gce_num, cmdq->clocks);
> > +	return 0;
> > +}
> > +
> > +static int cmdq_sec_resume(struct device *dev)
> > +{
> > +	struct cmdq_sec *cmdq = dev_get_drvdata(dev);
> > +
> > +	WARN_ON(clk_bulk_prepare_enable(cmdq->gce_num, cmdq->clocks));
> > +	return 0;
> > +}
> > +
> > +static const struct dev_pm_ops cmdq_sec_pm_ops = {
> > +	.suspend = cmdq_sec_suspend,
> > +	.resume = cmdq_sec_resume,
> > +};
> > +
> > +static void cmdq_sec_task_exec_work(struct work_struct *work_item)
> > +{
> > +	struct cmdq_sec_task *task = container_of(work_item, struct
> > cmdq_sec_task, exec_work);
> > +	struct cmdq_sec *cmdq = container_of(task->thread->chan->mbox,
> > struct cmdq_sec, mbox);
> > +	struct cmdq_sec_data *data;
> > +	unsigned long flags;
> > +	int err;
> > +
> > +	pr_debug("%s gce:%#lx task:%p pkt:%p thread:%u",
> > +		 __func__, (unsigned long)cmdq->base_pa, task, task-
> > >pkt, task->thread->idx);
> > +
> > +	if (!task->pkt->sec_data) {
> > +		pr_err("pkt:%p without sec_data", task->pkt);
> > +		return;
> > +	}
> > +	data = (struct cmdq_sec_data *)task->pkt->sec_data;
> > +
> > +	mutex_lock(&cmdq->exec_lock);
> > +
> > +	spin_lock_irqsave(&task->thread->chan->lock, flags);
> > +	if (!task->thread->task_cnt) {
> > +		mod_timer(&task->thread->timeout, jiffies +
> > +			msecs_to_jiffies(task->thread->timeout_ms));
> > +		task->thread->wait_cookie = 1;
> > +		task->thread->next_cookie = 1;
> > +		task->thread->task_cnt = 0;
> > +		__raw_writel(0, (void __iomem *)cmdq->shared_mem->va +
> > +			     CMDQ_SEC_SHARED_THR_CNT_OFFSET +
> > +			     task->thread->idx * sizeof(u32));
> > +	}
> > +
> > +	task->resetExecCnt = task->thread->task_cnt ? false : true;
> > +	task->waitCookie = task->thread->next_cookie;
> > +	task->thread->next_cookie = (task->thread->next_cookie + 1) %
> > CMDQ_MAX_COOKIE_VALUE;
> > +	list_add_tail(&task->list_entry, &task->thread->task_list);
> > +	task->thread->task_cnt += 1;
> > +	spin_unlock_irqrestore(&task->thread->chan->lock, flags);
> > +	task->trigger = sched_clock();
> > +
> > +	if (!atomic_cmpxchg(&cmdq_path_res, 0, 1)) {
> > +		err = cmdq_sec_task_submit(cmdq, NULL,
> > CMD_CMDQ_IWC_PATH_RES_ALLOCATE,
> > +					   CMDQ_INVALID_THREAD, NULL);
> > +		if (err) {
> > +			atomic_set(&cmdq_path_res, 0);
> > +			goto task_err_callback;
> > +		}
> > +	}
> > +
> > +	if (task->thread->task_cnt > CMDQ_MAX_TASK_IN_SECURE_THREAD) {
> > +		pr_err("task_cnt:%u cannot more than %u task:%p thrd-
> > idx:%u",
> > +		       task->thread->task_cnt,
> > CMDQ_MAX_TASK_IN_SECURE_THREAD,
> > +		       task, task->thread->idx);
> > +		err = -EMSGSIZE;
> > +		goto task_err_callback;
> > +	}
> > +
> > +	err = cmdq_sec_task_submit(cmdq, task,
> > CMD_CMDQ_IWC_SUBMIT_TASK, task->thread->idx, NULL);
> > +	if (err)
> > +		pr_err("task submit CMD_CMDQ_IWC_SUBMIT_TASK failed:%d
> > gce:%#lx task:%p thread:%u",
> > +		       err, (unsigned long)cmdq->base_pa, task, task-
> > >thread->idx);
> > +
> > +task_err_callback:
> 
> end:

OK, I'll change it.

> 
> > +	if (err) {
> > +		struct cmdq_cb_data cb_data;
> > +
> > +		cb_data.sta = err;
> > +		cb_data.pkt = task->pkt;
> > +		mbox_chan_received_data(task->thread->chan, &cb_data);
> > +
> > +		spin_lock_irqsave(&task->thread->chan->lock, flags);
> > +		if (!task->thread->task_cnt)
> > +			pr_err("thread:%u task_cnt:%u cannot below
> > zero",
> > +			       task->thread->idx, task->thread-
> > >task_cnt);
> > +		else
> > +			task->thread->task_cnt -= 1;
> > +
> > +		task->thread->next_cookie = (task->thread->next_cookie
> > - 1 +
> > +			CMDQ_MAX_COOKIE_VALUE) % CMDQ_MAX_COOKIE_VALUE;
> > +		list_del(&task->list_entry);
> > +		pr_debug("gce:%#lx err:%d task:%p pkt:%p thread:%u
> > task_cnt:%u wait_cookie:%u next_cookie:%u",
> > +			 (unsigned long)cmdq->base_pa, err, task, task-
> > >pkt,
> > +			 task->thread->idx, task->thread->task_cnt,
> > +			 task->thread->wait_cookie, task->thread-
> > >next_cookie);
> > +		spin_unlock_irqrestore(&task->thread->chan->lock,
> > flags);
> > +		kfree(task);
> > +	}
> > +	mutex_unlock(&cmdq->exec_lock);
> > +}
> > +
> > +static int cmdq_sec_mbox_send_data(struct mbox_chan *chan, void
> > *data)
> > +{
> > +	struct cmdq_pkt *pkt = (struct cmdq_pkt *)data;
> > +	struct cmdq_sec_data *sec_data = (struct cmdq_sec_data *)pkt-
> > >sec_data;
> > +	struct cmdq_sec_thread *thread = (struct cmdq_sec_thread
> > *)chan->con_priv;
> > +	struct cmdq_sec_task *task;
> > +
> > +	if (!sec_data)
> > +		return -EINVAL;
> > +
> > +	task = kzalloc(sizeof(*task), GFP_ATOMIC);
> > +	if (!task)
> > +		return -ENOMEM;
> > +
> > +	task->pkt = pkt;
> > +	task->thread = thread;
> > +	task->scenario = sec_data->scenario;
> > +	task->engineFlag = sec_data->enginesNeedDAPC | sec_data-
> > >enginesNeedPortSecurity;
> > +
> > +	INIT_WORK(&task->exec_work, cmdq_sec_task_exec_work);
> > +	queue_work(thread->task_exec_wq, &task->exec_work);
> > +	return 0;
> > +}
> > +
> > +static void cmdq_sec_thread_timeout(struct timer_list *t)
> > +{
> > +	struct cmdq_sec_thread *thread = from_timer(thread, t,
> > timeout);
> > +	struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct
> > cmdq_sec, mbox);
> > +
> > +	if (!work_pending(&thread->timeout_work))
> > +		queue_work(cmdq->timeout_wq, &thread->timeout_work);
> > +}
> > +
> > +static void cmdq_sec_task_timeout_work(struct work_struct
> > *work_item)
> > +{
> > +	struct cmdq_sec_thread *thread = container_of(work_item, struct
> > cmdq_sec_thread,
> > +						      timeout_work);
> > +	struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct
> > cmdq_sec, mbox);
> > +	struct cmdq_sec_task *task;
> > +	unsigned long flags;
> > +	u64 duration;
> > +	u32 cookie;
> > +
> > +	mutex_lock(&cmdq->exec_lock);
> > +
> > +	spin_lock_irqsave(&thread->chan->lock, flags);
> > +	if (list_empty(&thread->task_list)) {
> > +		pr_err("thread:%u task_list is empty", thread->idx);
> > +		spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +		goto done;
> > +	}
> > +
> > +	task = list_first_entry(&thread->task_list, struct
> > cmdq_sec_task, list_entry);
> > +	duration = div_u64(sched_clock() - task->trigger, 1000000);
> > +	if (duration < thread->timeout_ms) {
> > +		mod_timer(&thread->timeout, jiffies +
> > +			  msecs_to_jiffies(thread->timeout_ms -
> > duration));
> > +		spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +		goto done;
> > +	}
> > +
> > +	cookie = cmdq_sec_get_cookie(cmdq, thread->idx);
> > +	spin_unlock_irqrestore(&thread->chan->lock, flags);
> > +
> > +	pr_err("%s duration:%llu cookie:%u thread:%u",
> > +	       __func__, duration, cookie, thread->idx);
> > +	cmdq_sec_irq_handler(thread, cookie, -ETIMEDOUT);
> > +
> > +done:
> > +	mutex_unlock(&cmdq->exec_lock);
> > +}
> > +
> > +static int cmdq_sec_mbox_startup(struct mbox_chan *chan)
> > +{
> > +	struct cmdq_sec_thread *thread = (struct cmdq_sec_thread
> > *)chan->con_priv;
> > +	char name[20];
> > +
> > +	timer_setup(&thread->timeout, cmdq_sec_thread_timeout, 0);
> > +
> > +	INIT_WORK(&thread->timeout_work, cmdq_sec_task_timeout_work);
> > +	snprintf(name, sizeof(name), "task_exec_wq_%u", thread->idx);
> > +	thread->task_exec_wq = create_singlethread_workqueue(name);
> > +	thread->occupied = true;
> > +	return 0;
> > +}
> > +
> > +static void cmdq_sec_mbox_shutdown(struct mbox_chan *chan)
> > +{
> > +	struct cmdq_sec_thread *thread = (struct cmdq_sec_thread
> > *)chan->con_priv;
> > +
> > +	thread->occupied = false;
> > +}
> > +
> > +static int cmdq_sec_mbox_flush(struct mbox_chan *chan, unsigned
> > long timeout)
> > +{
> > +	struct cmdq_sec_thread *thread = (struct cmdq_sec_thread
> > *)chan->con_priv;
> > +	struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct
> > cmdq_sec, mbox);
> > +	int i;
> > +
> > +	mutex_lock(&cmdq->exec_lock);
> > +
> > +	if (list_empty(&thread->task_list))
> 
> if (list_empty..) {
> 	mutex_unlock(...)
> 	return 0;
> }
> 

OK, I'll change this. Thanks!

> > +		goto out;
> > +
> > +	for (i = 0; i < CMDQ_MAX_SECURE_THREAD_COUNT; i++) {
> > +		struct cmdq_sec_thread *thread = &cmdq-
> > >thread[CMDQ_MIN_SECURE_THREAD_ID + i];
> > +		u32 cookie = cmdq_sec_get_cookie(cmdq, thread->idx);
> > +
> > +		if (cookie < thread->wait_cookie || !thread->task_cnt)
> > +			continue;
> > +
> > +		cmdq_sec_irq_handler(thread, cookie, -ECONNABORTED);
> > +	}
> > +
> > +out:
> > +	mutex_unlock(&cmdq->exec_lock);
> > +	return 0;
> > +}
> > +
> > +static bool cmdq_sec_mbox_last_tx_done(struct mbox_chan *chan)
> > +{
> > +	return true;
> 
> Noupe. This is a hack.
> 
> You want to do some check here to return if the last TX is done, you
> can't
> just return true and call it a day.
> 

Since we use TXDONE_BY_ACK, we can remove this function implement.
So I'll remove this in the next version. 

> > +}
> > +
> > +static const struct mbox_chan_ops cmdq_sec_mbox_chan_ops = {
> > +	.send_data = cmdq_sec_mbox_send_data,
> > +	.startup = cmdq_sec_mbox_startup,
> > +	.shutdown = cmdq_sec_mbox_shutdown,
> > +	.flush = cmdq_sec_mbox_flush,
> > +	.last_tx_done = cmdq_sec_mbox_last_tx_done,
> > +};
> > +
> > +static struct mbox_chan *cmdq_sec_mbox_of_xlate(struct
> > mbox_controller *mbox,
> > +						const struct
> > of_phandle_args *sp)
> > +{
> > +	struct cmdq_sec_thread *thread;
> > +	int idx = sp->args[0];
> > +
> > +	if (mbox->num_chans <= idx) {
> > +		pr_err("invalid thrd-idx:%u", idx);
> > +		return ERR_PTR(-EINVAL);
> > +	}
> > +
> > +	thread = (struct cmdq_sec_thread *)mbox->chans[idx].con_priv;
> > +	thread->chan = &mbox->chans[idx];
> > +	thread->timeout_ms = CMDQ_NO_TIMEOUT;
> > +	thread->priority = sp->args[1];
> > +
> > +	return &mbox->chans[idx];
> > +}
> > +
> > +static int cmdq_sec_probe(struct platform_device *pdev)
> > +{
> > +	int i, err;
> > +	struct cmdq_sec *cmdq;
> > +	struct cmdq_sec_plat *plat_data;
> > +	struct device *dev = &pdev->dev;
> > +
> > +	plat_data = (struct cmdq_sec_plat *)pdev->dev.platform_data;
> > +	if (!plat_data) {
> > +		dev_err(dev, "no valid platform data!\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
> > +	if (!cmdq)
> > +		return -ENOMEM;
> > +
> > +	cmdq->base_pa = plat_data->base_pa;
> > +	cmdq->base = plat_data->base;
> > +	cmdq->thread_nr = plat_data->thread_nr;
> > +	cmdq->gce_num = plat_data->gce_num;
> > +	cmdq->clocks = devm_kcalloc(dev, cmdq->gce_num,
> > +				    sizeof(struct clk_bulk_data),
> > GFP_KERNEL);
> > +	if (!cmdq->clocks)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0 ; i < cmdq->gce_num; i++)
> > +		cmdq->clocks[i] = plat_data->clocks[i];
> > +
> > +	cmdq->hwid = plat_data->hwid;
> > +	cmdq->cmdq_event = plat_data->cmdq_event;
> > +
> > +	cmdq->mbox.dev = plat_data->gce_dev;
> > +	cmdq->mbox.chans = devm_kcalloc(dev, cmdq->thread_nr,
> > +					sizeof(*cmdq->mbox.chans),
> > GFP_KERNEL);
> > +	if (!cmdq->mbox.chans)
> > +		return -ENOMEM;
> > +
> > +	cmdq->mbox.ops = &cmdq_sec_mbox_chan_ops;
> > +	cmdq->mbox.num_chans = cmdq->thread_nr;
> > +	cmdq->mbox.of_xlate = cmdq_sec_mbox_of_xlate;
> > +
> > +	/* make use of TXDONE_BY_ACK */
> > +	cmdq->mbox.txdone_irq = false;
> > +	cmdq->mbox.txdone_poll = false;
> > +
> > +	cmdq->thread = devm_kcalloc(dev, cmdq->thread_nr,
> > +				    sizeof(*cmdq->thread), GFP_KERNEL);
> > +	if (!cmdq->thread)
> > +		return -ENOMEM;
> > +
> > +	mutex_init(&cmdq->exec_lock);
> > +	for (i = 0; i < cmdq->thread_nr; i++) {
> > +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
> > CMDQ_THR_SIZE * i;
> > +		INIT_LIST_HEAD(&cmdq->thread[i].task_list);
> > +		cmdq->thread[i].idx = i;
> > +		cmdq->thread[i].occupied = false;
> > +		cmdq->mbox.chans[i].con_priv = (void *)&cmdq-
> > >thread[i];
> > +	}
> > +
> > +	cmdq->notify_wq =
> > create_singlethread_workqueue("mtk_cmdq_sec_notify_wq");
> > +	cmdq->timeout_wq =
> > create_singlethread_workqueue("mtk_cmdq_sec_timeout_wq");
> > +	err = devm_mbox_controller_register(dev, &cmdq->mbox);
> > +	if (err)
> > +		return err;
> > +
> > +	cmdq->shared_mem = devm_kzalloc(dev, sizeof(*cmdq->shared_mem), 
> > GFP_KERNEL);
> > +	if (!cmdq->shared_mem)
> > +		return -ENOMEM;
> > +
> > +	cmdq->shared_mem->va = dma_alloc_coherent(dev, PAGE_SIZE,
> > +						  &cmdq->shared_mem-
> > >pa, GFP_KERNEL);
> > +	cmdq->shared_mem->size = PAGE_SIZE;
> > +
> > +	platform_set_drvdata(pdev, cmdq);
> > +	WARN_ON(clk_bulk_prepare_enable(cmdq->gce_num, cmdq->clocks));
> > +
> > +	return 0;
> > +}
> > +
> > +static int cmdq_sec_remove(struct platform_device *pdev)
> > +{
> > +	struct cmdq_sec *cmdq = platform_get_drvdata(pdev);
> > +
> > +	if (cmdq->context)
> > +		cmdq_sec_free_wsm(&cmdq->context->tee, &cmdq->context-
> > >iwc_msg);
> > +
> > +	mbox_controller_unregister(&cmdq->mbox);
> > +
> > +	clk_bulk_disable_unprepare(cmdq->gce_num, cmdq->clocks);
> > +	return 0;
> > +}
> > +
> > +static struct platform_driver cmdq_sec_drv = {
> > +	.probe = cmdq_sec_probe,
> > +	.remove = cmdq_sec_remove,
> > +	.driver = {
> > +		.name = "mtk_cmdq_sec",
> 
> "mtk-cmdq-secure"
> 
OK, I'll change it.

> > +		.pm = &cmdq_sec_pm_ops,
> > +	},
> > +};
> > +
> > +static int __init cmdq_sec_init(void)
> > +{
> > +	int err;
> > +
> > +	err = platform_driver_register(&cmdq_sec_drv);
> > +	if (err)
> > +		pr_err("platform_driver_register failed:%d", err);
> > +	return err;
> > +}
> > +
> > +arch_initcall(cmdq_sec_init);
> 
> Do you *really* need this to be an arch_initcall?! That's a bit
> early, and I don't
> really see any reason for this.

OK, It needs to be later than cmdq mailbox driver (subsys_initcall) and
earlier than user driver (module_initcall).

So I think it should be rootfs_initcall() here to ensure it can be
earlier than all the user drivers.

> 
> > +
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/mailbox/mtk-cmdq-sec-tee.c
> > b/drivers/mailbox/mtk-cmdq-sec-tee.c
> > new file mode 100644
> > index 000000000000..e42e9dba343c
> > --- /dev/null
> > +++ b/drivers/mailbox/mtk-cmdq-sec-tee.c
> > @@ -0,0 +1,202 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2019 MediaTek Inc.
> 
> // SPDX...
> /*
>   * Copyright..
>   */
> 

OK, I'll change it. Thanks!

> 
> > +
> > +#include <linux/math64.h>
> > +#include <linux/sched/clock.h>
> > +
> > +#include <linux/mailbox/mtk-cmdq-sec-tee.h>
> > +#include <linux/soc/mediatek/mtk-cmdq.h>
> > +
> > +/* lock to protect atomic secure task execution */
> > +static DEFINE_MUTEX(cmdq_sec_exec_lock);
> > +
> > +static void cmdq_sec_lock_secure_path(void)
> > +{
> > +	mutex_lock(&cmdq_sec_exec_lock);
> > +	smp_mb();	/*memory barrier*/
> 
> I'm sure that you don't need a memory barrier after locking this
> mutex.
> 
> Besides, you don't need this function at all: just call mutex_lock
> and mutex_unlock
> where appropriate.
> 
> > +}
> > +
> > +static void cmdq_sec_unlock_secure_path(void)
> > +{
> > +	mutex_unlock(&cmdq_sec_exec_lock);
> > +}

OK, I'll remove these 2 wrapping functions.

> > +
> > +void cmdq_sec_setup_tee_context(struct cmdq_sec_tee_context *tee)
> > +{
> > +	/* 09010000 0000 0000 0000000000000000 */
> > +	memset(tee->uuid, 0, sizeof(tee->uuid));
> > +	tee->uuid[0] = 0x9;
> > +	tee->uuid[1] = 0x1;
> > +}
> > +EXPORT_SYMBOL(cmdq_sec_setup_tee_context);
> > +
> > +#if IS_ENABLED(CONFIG_TEE)
> 
> Can this driver really work if CONFIG_TEE=n ?!
> 
> I guess it wouldn't, so this is not right at all. The solution is to
> depend on
> CONFIG_TEE to *even compile* this driver....

Yes, I'll remove this and add a dependency to Makefile. Thanks!

> > +static int tee_dev_match(struct tee_ioctl_version_data *t, const
> > void *v)
> > +{
> > +#if IS_ENABLED(CONFIG_OPTEE)
> > +	if (t->impl_id == TEE_IMPL_ID_OPTEE)
> > +		return 1;
> > +#endif
> > +	return 0;
> > +}
> > +#endif
> > +
> 
> ..snip..
> 
> > diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h
> > b/include/linux/mailbox/mtk-cmdq-mailbox.h
> > index fdda995a69ce..997a75c529fb 100644
> > --- a/include/linux/mailbox/mtk-cmdq-mailbox.h
> > +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
> > @@ -7,6 +7,7 @@
> >   #ifndef __MTK_CMDQ_MAILBOX_H__
> >   #define __MTK_CMDQ_MAILBOX_H__
> >   
> > +#include <linux/mailbox_controller.h>
> 
> Why are you adding this header?
> 
> No implicit inclusions in drivers please.
> 
Because I include <mtk-cmdq-mailbox.h> in mtk-cmdq-sec-mailbox.h and
cmdq_get_shift_pa() will use the `struct mbox_chan * chan` as
parameters.

So I add this to avoid the build fail in mtk-cmdq-sec-mailbox.
I think I should split it to another patch.

> >   #include <linux/platform_device.h>
> >   #include <linux/slab.h>
> >   #include <linux/types.h>
> > @@ -77,6 +78,7 @@ struct cmdq_pkt {
> >   	size_t			buf_size; /* real buffer size */
> >   	void			*cl;
> >   	bool			loop;
> > +	void			*sec_data;
> >   };
> >   
> >   struct cmdq_sec_plat {
> > diff --git a/include/linux/mailbox/mtk-cmdq-sec-iwc-common.h
> > b/include/linux/mailbox/mtk-cmdq-sec-iwc-common.h
> > new file mode 100644
> > index 000000000000..addc515df279
> > --- /dev/null
> > +++ b/include/linux/mailbox/mtk-cmdq-sec-iwc-common.h
> > @@ -0,0 +1,293 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> > + */
> > +
> > +#ifndef __CMDQ_SEC_IWC_COMMON_H__
> > +#define __CMDQ_SEC_IWC_COMMON_H__
> > +
> > +/*
> > + * shared DRAM
> > + * bit x = 1 means thread x raise IRQ
> > + */
> > +#define CMDQ_SEC_SHARED_IRQ_RAISED_OFFSET	0
> > +#define CMDQ_SEC_SHARED_THR_CNT_OFFSET		0x100
> > +#define CMDQ_SEC_SHARED_TASK_VA_OFFSET		0x200
> > +#define CMDQ_SEC_SHARED_OP_OFFSET		0x300
> > +#define CMDQ_SEC_SHARED_SUSPEND_CNT		0x304
> > +#define CMDQ_SEC_SHARED_RESET_CNT		0x308
> > +
> > +/* commanad buffer & metadata */
> > +#define CMDQ_TZ_CMD_BLOCK_SIZE		(20 << 12) /* MDP
> > readback may request 20 pages */
> > +#define CMDQ_IWC_MAX_CMD_LENGTH		(CMDQ_TZ_CMD_BLOCK_SIZE
> > / 4)
> > +
> > +#define CMDQ_IWC_MAX_ADDR_LIST_LENGTH	(30)
> > +
> > +#define CMDQ_IWC_CLIENT_NAME		(16)
> > +
> > +#define CMDQ_SEC_MESSAGE_INST_LEN	(8)
> > +#define CMDQ_SEC_DISPATCH_LEN		(8)
> > +#define CMDQ_MAX_READBACK_ENG		(8)
> > +
> > +/*
> > + * Command IDs for normal world(TLC or linux kernel) to secure
> > world
> > + */
> > +/* submit current task */
> > +#define CMD_CMDQ_IWC_SUBMIT_TASK	(1)
> > +/* (not used)release resource in secure path per session */
> 
> If this is unused, it shouldn't be here at all.
> 
> Also, you don't need those parenthesis, remove.
> 
> > +#define CMD_CMDQ_IWC_RES_RELEASE	(2)

OK, I'll remove this unused definition.

> > +/* cancel current task */
> > +#define CMD_CMDQ_IWC_CANCEL_TASK	(3)
> > +/* create global resource for secure path */
> > +#define CMD_CMDQ_IWC_PATH_RES_ALLOCATE	(4)
> > +/* destroy globacl resource for secure path */
> > +#define CMD_CMDQ_IWC_PATH_RES_RELEASE	(5)
> > +
> > +/*
> > + * ERROR code number (ERRNO)
> > + * note the error result returns negative value, i.e, -(ERRNO)
> > + */
> > +#define CMDQ_ERR_NOMEM					(12) /*
> > out of memory */
> > +#define CMDQ_ERR_FAULT					(14) /*
> > bad address */
> > +
> > +#define CMDQ_ERR_ADDR_CONVERT_HANDLE_2_PA		(1000)
> > +#define CMDQ_ERR_ADDR_CONVERT_ALLOC_MVA			(1100)
> > +#define CMDQ_ERR_ADDR_CONVERT_ALLOC_MVA_N2S		(1101)
> > +#define CMDQ_ERR_ADDR_CONVERT_FREE_MVA			(1200)
> > +#define CMDQ_ERR_PORT_CONFIG				(1300)
> > +
> > +/* param check */
> > +#define CMDQ_ERR_UNKNOWN_ADDR_METADATA_TYPE		(1400)
> > +#define CMDQ_ERR_TOO_MANY_SEC_HANDLE			(1401)
> > +/* security check */
> > +#define CMDQ_ERR_SECURITY_INVALID_INSTR			(1500)
> > +#define CMDQ_ERR_SECURITY_INVALID_SEC_HANDLE		(1501)
> > +#define CMDQ_ERR_SECURITY_INVALID_DAPC_FALG		(1502)
> > +#define CMDQ_ERR_INSERT_DAPC_INSTR_FAILED		(1503)
> > +#define CMDQ_ERR_INSERT_PORT_SECURITY_INSTR_FAILED	(1504)
> > +#define CMDQ_ERR_INVALID_SECURITY_THREAD		(1505)
> > +#define CMDQ_ERR_PATH_RESOURCE_NOT_READY		(1506)
> > +#define CMDQ_ERR_NULL_TASK				(1507)
> > +#define CMDQ_ERR_SECURITY_INVALID_SOP			(1508)
> > +#define CMDQ_ERR_SECURITY_INVALID_SEC_PORT_FALG		(1511)
> > +
> 
> Fully documented enumeration, but no kerneldoc? :-)
> 

I'll refine it by kerneldoc.

> > +enum cmdq_iwc_addr_metadata_type {
> > +	CMDQ_IWC_H_2_PA		= 0, /* sec handle to sec PA */
> > +	CMDQ_IWC_H_2_MVA	= 1, /* sec handle to sec MVA */
> > +	CMDQ_IWC_NMVA_2_MVA	= 2, /* map normal MVA to secure world */
> > +	CMDQ_IWC_PH_2_MVA	= 3, /* protected handle to sec MVA */
> > +};
> > +
> > +enum cmdq_sec_engine_enum {
> > +	/* MDP */
> > +	CMDQ_SEC_MDP_RDMA0		= 0,
> > +	CMDQ_SEC_MDP_RDMA1		= 1,
> > +	CMDQ_SEC_MDP_WDMA		= 2,
> > +	CMDQ_SEC_MDP_RDMA2		= 3,
> > +	CMDQ_SEC_MDP_RDMA3		= 4,
> > +	CMDQ_SEC_MDP_WROT0		= 5,
> > +	CMDQ_SEC_MDP_WROT1		= 6,
> > +	CMDQ_SEC_MDP_WROT2		= 7,
> > +	CMDQ_SEC_MDP_WROT3		= 8,
> > +	CMDQ_SEC_MDP_HDR0		= 9,
> > +	CMDQ_SEC_MDP_HDR1		= 10,
> > +	CMDQ_SEC_MDP_HDR2		= 11,
> > +	CMDQ_SEC_MDP_HDR3		= 12,
> > +	CMDQ_SEC_MDP_AAL0		= 13,
> > +	CMDQ_SEC_MDP_AAL1		= 14,
> > +	CMDQ_SEC_MDP_AAL2		= 15,
> > +	CMDQ_SEC_MDP_AAL3		= 16,
> > +
> > +	/* DISP (VDOSYS0) */
> > +	CMDQ_SEC_DISP_RDMA0		= 17,
> > +	CMDQ_SEC_DISP_RDMA1		= 18,
> > +	CMDQ_SEC_DISP_WDMA0		= 19,
> > +	CMDQ_SEC_DISP_WDMA1		= 20,
> > +	CMDQ_SEC_DISP_OVL0		= 21,
> > +	CMDQ_SEC_DISP_OVL1		= 22,
> > +	CMDQ_SEC_DISP_OVL2		= 23,
> > +	CMDQ_SEC_DISP_2L_OVL0		= 24,
> > +	CMDQ_SEC_DISP_2L_OVL1		= 25,
> > +	CMDQ_SEC_DISP_2L_OVL2		= 26,
> > +
> > +	/* DSIP (VDOSYS1) */
> > +	CMDQ_SEC_VDO1_DISP_RDMA_L0	= 27,
> > +	CMDQ_SEC_VDO1_DISP_RDMA_L1	= 28,
> > +	CMDQ_SEC_VDO1_DISP_RDMA_L2	= 29,
> > +	CMDQ_SEC_VDO1_DISP_RDMA_L3	= 30,
> > +
> > +	/* VENC */
> > +	CMDQ_SEC_VENC_BSDMA		= 31,
> > +	CMDQ_SEC_VENC_CUR_LUMA		= 32,
> > +	CMDQ_SEC_VENC_CUR_CHROMA	= 33,
> > +	CMDQ_SEC_VENC_REF_LUMA		= 34,
> > +	CMDQ_SEC_VENC_REF_CHROMA	= 35,
> > +	CMDQ_SEC_VENC_REC		= 36,
> > +	CMDQ_SEC_VENC_SUB_R_LUMA	= 37,
> > +	CMDQ_SEC_VENC_SUB_W_LUMA	= 38,
> > +	CMDQ_SEC_VENC_SV_COMV		= 39,
> > +	CMDQ_SEC_VENC_RD_COMV		= 40,
> > +	CMDQ_SEC_VENC_NBM_RDMA		= 41,
> > +	CMDQ_SEC_VENC_NBM_WDMA		= 42,
> > +	CMDQ_SEC_VENC_NBM_RDMA_LITE	= 43,
> > +	CMDQ_SEC_VENC_NBM_WDMA_LITE	= 44,
> > +	CMDQ_SEC_VENC_FCS_NBM_RDMA	= 45,
> > +	CMDQ_SEC_VENC_FCS_NBM_WDMA	= 46,
> > +
> > +	CMDQ_SEC_MAX_ENG_COUNT		/* keep in the end */
> > +};
> > +
> > +/*
> > + * IWC message
> 
> kerneldoc please

OK. Thanks!
> 
> > + */
> > +struct iwcCmdqAddrMetadata_t {
> 
> ...and no camelcase.
> 
OK, I'll fix it. Thanks!

> > +	/*
> > +	 * [IN] index of instruction
> > +	 * Update its arg_b value to real PA/MVA in secure world
> > +	 */
> > +	u32 instrIndex;
> > +
> 
> 
> ..snip..
> 
> > diff --git a/include/linux/mailbox/mtk-cmdq-sec-mailbox.h
> > b/include/linux/mailbox/mtk-cmdq-sec-mailbox.h
> > new file mode 100644
> > index 000000000000..17ee0ae646ab
> > --- /dev/null
> > +++ b/include/linux/mailbox/mtk-cmdq-sec-mailbox.h
> > @@ -0,0 +1,83 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> > + */
> > +
> > +#ifndef __MTK_CMDQ_SEC_MAILBOX_H__
> > +#define __MTK_CMDQ_SEC_MAILBOX_H__
> > +
> > +#include <linux/kernel.h>
> > +
> > +#include <linux/mailbox/mtk-cmdq-mailbox.h>
> > +#include <linux/mailbox/mtk-cmdq-sec-iwc-common.h>
> > +#include <linux/mailbox/mtk-cmdq-sec-tee.h>
> > +#include <linux/soc/mediatek/mtk-cmdq.h>
> > +
> > +#define CMDQ_INVALID_THREAD		(-1)
> > +#define CMDQ_MAX_TASK_IN_SECURE_THREAD	(16)
> > +#define CMDQ_SEC_IRQ_THREAD		(15)
> > +
> > +/* This define should sync with cmdq_sec_def.h in secure world */
> > +#define CMDQ_MIN_SECURE_THREAD_ID	(8)
> 
> As you wrote, this shall be in sync with secure world, so this will
> either break
> at the next SoC, or at the next secure world update.
> 
> This means that those definitions shall be in platform data for this
> driver.

Oh yes! I'll try to use platform data to refine this.
Thanks for your advice.

> 
> > +#define CMDQ_MAX_SECURE_THREAD_ID	(10)
> > +#define CMDQ_MAX_SECURE_THREAD_COUNT	(CMDQ_MAX_SECURE_THREAD
> > _ID - CMDQ_MIN_SECURE_THREAD_ID)
> > +
> > +/* Max value of CMDQ_THR_EXEC_CMD_CNT (value starts from 0) */
> > +#define CMDQ_MAX_COOKIE_VALUE           (0xffff)
> > +
> > +enum cmdq_sec_scenario {
> > +	CMDQ_SEC_PRIMARY_DISP		= 1,
> > +	CMDQ_SEC_SUB_DISP		= 4,
> > +	CMDQ_SEC_PRIMARY_DISP_DISABLE	= 18,
> > +	CMDQ_SEC_SUB_DISP_DISABLE	= 19,
> > +
> > +	CMDQ_MAX_SEC_COUNT	/* keep in the end */
> > +};
> > +
> > +/* Inter-world communication state */
> > +enum cmdq_iwc_state_enum {
> > +	IWC_INIT,
> > +	IWC_CONTEXT_INITED,
> > +	IWC_WSM_ALLOCATED,
> > +	IWC_SES_OPENED,
> > +	IWC_SES_ON_TRANSACTED,
> > +
> > +	IWC_STATE_END_OF_ENUM,
> 
> Usually "END_OF_ENUM" is "MAX", so rename this to IWC_STATE_MAX
> 
OK, I'll change it.

> > +};
> > +
> > +/*
> 
> kerneldoc please.
> 
OK. Thanks!

> > + * Address metadata, used to translate secure buffer PA
> > + * related instruction in secure world.
> > + */
> > +struct cmdq_sec_data {
> > +	u32 addrMetadataCount;	/* [IN] count of element in
> > addrList */
> > +	u64 addrMetadatas;		/* [IN] array of
> > iwcCmdqAddrMetadata_t */
> > +	u32 addrMetadataMaxCount;	/* [Reserved] */
> > +
> > +	enum cmdq_sec_scenario scenario;
> > +
> > +	u64 enginesNeedDAPC;
> > +	u64 enginesNeedPortSecurity;
> > +
> > +	/*
> > +	 * [Reserved]
> > +	 * This is task index in thread's tasklist for CMDQ driver
> > usage.
> > +	 * Not for client. -1 means not in tasklist.
> > +	 */
> > +	s32 waitCookie;
> > +	/* [Reserved] reset HW thread in secure world */
> > +	bool resetExecCnt;
> > +
> > +	/* [OUT] response */
> > +	s32 response;
> > +	struct iwcCmdqSecStatus_t sec_status;
> > +};
> > +
> 
> Please document all those functions that you're exporting with
> kerneldoc.
> 

OK, Thanks!

> > +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt);
> > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, const u64
> > dapc_engine,
> > +			  const u64 port_sec_engine, const enum
> > cmdq_sec_scenario scenario);
> > +int cmdq_sec_pkt_write(struct cmdq_pkt *pkt, u32 addr, u64 base,
> > +		       const enum cmdq_iwc_addr_metadata_type type,
> > +		       const u32 offset, const u32 size, const u32
> > port);
> > +
> > +#endif /* __MTK_CMDQ_SEC_MAILBOX_H__ */
> > diff --git a/include/linux/mailbox/mtk-cmdq-sec-tee.h
> > b/include/linux/mailbox/mtk-cmdq-sec-tee.h
> > new file mode 100644
> > index 000000000000..77090921cdf6
> > --- /dev/null
> > +++ b/include/linux/mailbox/mtk-cmdq-sec-tee.h
> > @@ -0,0 +1,31 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2019 MediaTek Inc.
> > + */
> > +
> > +#ifndef __MTK_CMDQ_SEC_TEE_H__
> > +#define __MTK_CMDQ_SEC_TEE_H__
> > +
> > +#include <linux/types.h>
> > +#include <linux/delay.h>
> > +#include <linux/tee_drv.h>
> > +
> > +/* context for tee vendor */
> 
> kerneldoc please.
> 
OK, Thanks!

> > +struct cmdq_sec_tee_context {
> > +	/* Universally Unique Identifier of secure world */
> > +	u8			uuid[TEE_IOCTL_UUID_LEN];
> > +	struct tee_context	*tee_context; /* basic context */
> > +	u32			session; /* session handle */
> > +	struct tee_shm		*shared_mem; /* shared memory */
> > +};
> > +
> 
> Also here, please document those functions.
> 
OK, Thanks!

> > +void cmdq_sec_setup_tee_context(struct cmdq_sec_tee_context *tee);
> > +int cmdq_sec_init_context(struct cmdq_sec_tee_context *tee);
> > +int cmdq_sec_deinit_context(struct cmdq_sec_tee_context *tee);
> > +int cmdq_sec_allocate_wsm(struct cmdq_sec_tee_context *tee, void
> > **wsm_buffer, u32 size);
> > +int cmdq_sec_free_wsm(struct cmdq_sec_tee_context *tee, void
> > **wsm_buffer);
> > +int cmdq_sec_open_session(struct cmdq_sec_tee_context *tee, void
> > *wsm_buffer);
> > +int cmdq_sec_close_session(struct cmdq_sec_tee_context *tee);
> > +int cmdq_sec_execute_session(struct cmdq_sec_tee_context *tee, u32
> > cmd, s32 timeout_ms);
> > +
> > +#endif	/* __MTK_CMDQ_SEC_TEE_H__ */
> 
> 
> 
> Regards,
> Angelo

These patches are porting from the other platform which is not strongly
follow the upstream coding style. And we are asked to send the upstream
patch in a hurry schedule. Although I've remove a lot of unused code
and simplify some code flow, it still has a lot of trivial problems.
I really appreciate you taking the time to review this patch.
Thanks again!

Regards,
Jason-JH.Lin



More information about the Linux-mediatek mailing list